]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
MdeModulePkg/Xhci: Remove TRB when canceling Async Int Transfer
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / XhciSched.c
index 372702d3f08239f11432dbf549595530db420e27..9e34faf2637d8031b275fd93872c856dfc6f8033 100644 (file)
@@ -2,7 +2,7 @@
 \r
   XHCI transfer scheduling routines.\r
 \r
-Copyright (c) 2011 - 2012, 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
@@ -47,10 +47,6 @@ XhcCreateCmdTrb (
   Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;\r
   Urb->TrbEnd             = Urb->TrbStart;\r
 \r
-  Urb->EvtRing     = &Xhc->EventRing;\r
-  XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-  Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
   return Urb;\r
 }\r
 \r
@@ -106,16 +102,14 @@ XhcCmdTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
-\r
   Status  = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);\r
-  *EvtTrb = Urb->EvtTrbStart;\r
+  *EvtTrb = Urb->EvtTrb;\r
 \r
   if (Urb->Result == EFI_USB_NOERROR) {\r
     Status = EFI_SUCCESS;\r
   }\r
 \r
-  FreePool (Urb);\r
+  XhcFreeUrb (Xhc, Urb);\r
 \r
 ON_EXIT:\r
   return Status;\r
@@ -182,10 +176,39 @@ XhcCreateUrb (
 \r
   Status = XhcCreateTransferTrb (Xhc, Urb);\r
   ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status));\r
+    FreePool (Urb);\r
+    Urb = NULL;\r
+  }\r
 \r
   return Urb;\r
 }\r
 \r
+/**\r
+  Free an allocated URB.\r
+\r
+  @param  Xhc                   The XHCI device.\r
+  @param  Urb                   The URB to free.\r
+\r
+**/\r
+VOID\r
+XhcFreeUrb (\r
+  IN USB_XHCI_INSTANCE    *Xhc,\r
+  IN URB                  *Urb\r
+  )\r
+{\r
+  if ((Xhc == NULL) || (Urb == NULL)) {\r
+    return;\r
+  }\r
+  \r
+  if (Urb->DataMap != NULL) {\r
+    Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);\r
+  }\r
+\r
+  FreePool (Urb);\r
+}\r
+\r
 /**\r
   Create a transfer TRB.\r
 \r
@@ -210,22 +233,51 @@ XhcCreateTransferTrb (
   UINTN                         TotalLen;\r
   UINTN                         Len;\r
   UINTN                         TrbNum;\r
+  EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
+  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  VOID                          *Map;\r
+  EFI_STATUS                    Status;\r
 \r
   SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
   if (SlotId == 0) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  Urb->Finished  = FALSE;\r
+  Urb->StartDone = FALSE;\r
+  Urb->EndDone   = FALSE;\r
+  Urb->Completed = 0;\r
+  Urb->Result    = EFI_USB_NOERROR;\r
+\r
   Dci       = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
   ASSERT (Dci < 32);\r
   EPRing    = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];\r
   Urb->Ring = EPRing;\r
-  OutputContext = (VOID *)(UINTN)Xhc->DCBAA[SlotId];\r
+  OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
   if (Xhc->HcCParams.Data.Csz == 0) {\r
     EPType  = (UINT8) ((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType;\r
   } else {\r
     EPType  = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;\r
   }\r
+  \r
+  if (Urb->Data != NULL) {\r
+    if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
+      MapOp = EfiPciIoOperationBusMasterWrite;\r
+    } else {\r
+      MapOp = EfiPciIoOperationBusMasterRead;\r
+    }\r
+    \r
+    Len = Urb->DataLen;\r
+    Status  = Xhc->PciIo->Map (Xhc->PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+    \r
+    if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+      DEBUG ((EFI_D_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);\r
+    Urb->DataMap  = Map;\r
+  }\r
 \r
   //\r
   // Construct the TRB\r
@@ -234,9 +286,6 @@ XhcCreateTransferTrb (
   Urb->TrbStart = EPRing->RingEnqueue;\r
   switch (EPType) {\r
     case ED_CONTROL_BIDIR:\r
-      Urb->EvtRing     = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
       //\r
       // For control transfer, create SETUP_STAGE_TRB first.\r
       //\r
@@ -246,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
@@ -270,9 +319,9 @@ XhcCreateTransferTrb (
       if (Urb->DataLen > 0) {\r
         XhcSyncTrsRing (Xhc, EPRing);\r
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
-        TrbStart->TrbCtrData.TRBPtrLo  = XHC_LOW_32BIT(Urb->Data);\r
-        TrbStart->TrbCtrData.TRBPtrHi  = XHC_HIGH_32BIT(Urb->Data);\r
-        TrbStart->TrbCtrData.Lenth     = (UINT32) Urb->DataLen;\r
+        TrbStart->TrbCtrData.TRBPtrLo  = XHC_LOW_32BIT(Urb->DataPhy);\r
+        TrbStart->TrbCtrData.TRBPtrHi  = XHC_HIGH_32BIT(Urb->DataPhy);\r
+        TrbStart->TrbCtrData.Length    = (UINT32) Urb->DataLen;\r
         TrbStart->TrbCtrData.TDSize    = 0;\r
         TrbStart->TrbCtrData.IntTarget = 0;\r
         TrbStart->TrbCtrData.ISP       = 1;\r
@@ -325,10 +374,6 @@ XhcCreateTransferTrb (
 \r
     case ED_BULK_OUT:\r
     case ED_BULK_IN:\r
-      Urb->EvtRing     = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
       TotalLen = 0;\r
       Len      = 0;\r
       TrbNum   = 0;\r
@@ -340,9 +385,9 @@ XhcCreateTransferTrb (
           Len = 0x10000;\r
         }\r
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
-        TrbStart->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);\r
-        TrbStart->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
-        TrbStart->TrbNormal.Lenth     = (UINT32) Len;\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.Length    = (UINT32) Len;\r
         TrbStart->TrbNormal.TDSize    = 0;\r
         TrbStart->TrbNormal.IntTarget = 0;\r
         TrbStart->TrbNormal.ISP       = 1;\r
@@ -364,10 +409,6 @@ XhcCreateTransferTrb (
 \r
     case ED_INTERRUPT_OUT:\r
     case ED_INTERRUPT_IN:\r
-      Urb->EvtRing = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
       TotalLen = 0;\r
       Len      = 0;\r
       TrbNum   = 0;\r
@@ -379,9 +420,9 @@ XhcCreateTransferTrb (
           Len = 0x10000;\r
         }\r
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
-        TrbStart->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);\r
-        TrbStart->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
-        TrbStart->TrbNormal.Lenth     = (UINT32) Len;\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.Length    = (UINT32) Len;\r
         TrbStart->TrbNormal.TDSize    = 0;\r
         TrbStart->TrbNormal.IntTarget = 0;\r
         TrbStart->TrbNormal.ISP       = 1;\r
@@ -423,12 +464,24 @@ XhcInitSched (
   )\r
 {\r
   VOID                  *Dcbaa;\r
+  EFI_PHYSICAL_ADDRESS  DcbaaPhy;\r
   UINT64                CmdRing;\r
+  EFI_PHYSICAL_ADDRESS  CmdRingPhy; \r
   UINTN                 Entries;\r
   UINT32                MaxScratchpadBufs;\r
   UINT64                *ScratchBuf;\r
-  UINT64                *ScratchEntryBuf;\r
+  EFI_PHYSICAL_ADDRESS  ScratchPhy;\r
+  UINT64                *ScratchEntry;\r
+  EFI_PHYSICAL_ADDRESS  ScratchEntryPhy;\r
   UINT32                Index;\r
+  UINTN                 *ScratchEntryMap;\r
+  EFI_STATUS            Status;\r
+\r
+  //\r
+  // Initialize memory management.\r
+  //\r
+  Xhc->MemPool = UsbHcInitMemPool (Xhc->PciIo);\r
+  ASSERT (Xhc->MemPool != NULL);\r
 \r
   //\r
   // Program the Max Device Slots Enabled (MaxSlotsEn) field in the CONFIG register (5.4.7)\r
@@ -445,7 +498,7 @@ XhcInitSched (
   // Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'.\r
   //\r
   Entries = (Xhc->MaxSlotsEn + 1) * sizeof(UINT64);\r
-  Dcbaa   = AllocatePages (EFI_SIZE_TO_PAGES (Entries));\r
+  Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries);\r
   ASSERT (Dcbaa != NULL);\r
   ZeroMem (Dcbaa, Entries);\r
 \r
@@ -458,23 +511,59 @@ XhcInitSched (
   Xhc->MaxScratchpadBufs = MaxScratchpadBufs;\r
   ASSERT (MaxScratchpadBufs <= 1023);\r
   if (MaxScratchpadBufs != 0) {\r
-    ScratchBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)), Xhc->PageSize);\r
-    ASSERT (ScratchBuf != NULL);\r
+    //\r
+    // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them\r
+    //\r
+    ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);\r
+    ASSERT (ScratchEntryMap != NULL);\r
+    Xhc->ScratchEntryMap = ScratchEntryMap;\r
+    \r
+    //\r
+    // Allocate the buffer to record the host address for each entry\r
+    //\r
+    ScratchEntry = AllocateZeroPool (sizeof (UINT64) * MaxScratchpadBufs);\r
+    ASSERT (ScratchEntry != NULL);\r
+    Xhc->ScratchEntry = ScratchEntry;\r
+\r
+    ScratchPhy = 0;\r
+    Status = UsbHcAllocateAlignedPages (\r
+               Xhc->PciIo,\r
+               EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),\r
+               Xhc->PageSize,\r
+               (VOID **) &ScratchBuf, \r
+               &ScratchPhy,\r
+               &Xhc->ScratchMap\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
     ZeroMem (ScratchBuf, MaxScratchpadBufs * sizeof (UINT64));\r
     Xhc->ScratchBuf = ScratchBuf;\r
 \r
+    //\r
+    // Allocate each scratch buffer\r
+    //\r
     for (Index = 0; Index < MaxScratchpadBufs; Index++) {\r
-      ScratchEntryBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (Xhc->PageSize), Xhc->PageSize);\r
-      ASSERT (ScratchEntryBuf != NULL);\r
-      ZeroMem (ScratchEntryBuf, Xhc->PageSize);\r
-      *ScratchBuf++   = (UINT64)(UINTN)ScratchEntryBuf;\r
+      ScratchEntryPhy = 0;\r
+      Status = UsbHcAllocateAlignedPages (\r
+                 Xhc->PciIo,\r
+                 EFI_SIZE_TO_PAGES (Xhc->PageSize),\r
+                 Xhc->PageSize,\r
+                 (VOID **) &ScratchEntry[Index],\r
+                 &ScratchEntryPhy,\r
+                 (VOID **) &ScratchEntryMap[Index]\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      ZeroMem ((VOID *)(UINTN)ScratchEntry[Index], Xhc->PageSize);\r
+      //\r
+      // Fill with the PCI device address\r
+      //\r
+      *ScratchBuf++ = ScratchEntryPhy;\r
     }\r
-\r
     //\r
     // The Scratchpad Buffer Array contains pointers to the Scratchpad Buffers. Entry 0 of the\r
     // Device Context Base Address Array points to the Scratchpad Buffer Array.\r
     //\r
-    *(UINT64 *)Dcbaa = (UINT64)(UINTN)Xhc->ScratchBuf;\r
+    *(UINT64 *)Dcbaa = (UINT64)(UINTN) ScratchPhy;\r
   }\r
 \r
   //\r
@@ -486,8 +575,10 @@ XhcInitSched (
   // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
   // So divide it to two 32-bytes width register access.\r
   //\r
-  XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(Xhc->DCBAA));\r
-  XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->DCBAA));\r
+  DcbaaPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Dcbaa, Entries);\r
+  XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(DcbaaPhy));\r
+  XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (DcbaaPhy));\r
+\r
   DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA));\r
 \r
   //\r
@@ -503,14 +594,15 @@ XhcInitSched (
   // So we set RCS as inverted PCS init value to let Command Ring empty\r
   //\r
   CmdRing  = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0;\r
-  ASSERT ((CmdRing & 0x3F) == 0);\r
-  CmdRing |= XHC_CRCR_RCS;\r
+  CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN) CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);\r
+  ASSERT ((CmdRingPhy & 0x3F) == 0);\r
+  CmdRingPhy |= XHC_CRCR_RCS;\r
   //\r
   // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
   // So divide it to two 32-bytes width register access.\r
   //\r
-  XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRing));\r
-  XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRing));\r
+  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
@@ -553,9 +645,6 @@ 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
 \r
@@ -572,42 +661,88 @@ 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
-  ASSERT (!EFI_ERROR(Status));\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
+  }\r
 \r
   //\r
   // 2)Set dequeue pointer\r
   //\r
-  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));\r
-  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (Urb->Ring->RingEnqueue) | Urb->Ring->RingPCS;\r
-  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (Urb->Ring->RingEnqueue);\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
-  ASSERT (!EFI_ERROR(Status));\r
+  Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);\r
+  if (EFI_ERROR(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
   //\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
@@ -626,35 +761,45 @@ CreateEventRing (
 {\r
   VOID                        *Buf;\r
   EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;\r
+  UINTN                       Size;\r
+  EFI_PHYSICAL_ADDRESS        ERSTPhy;\r
+  EFI_PHYSICAL_ADDRESS        DequeuePhy;\r
 \r
   ASSERT (EventRing != NULL);\r
 \r
-  Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER));\r
+  Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;\r
+  Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN) Buf & 0x3F) == 0);\r
-  ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
+  ZeroMem (Buf, Size);\r
 \r
   EventRing->EventRingSeg0    = Buf;\r
   EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;\r
   EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
   EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
+  \r
+  DequeuePhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, Size);\r
+  \r
   //\r
   // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'\r
   // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.\r
   //\r
   EventRing->EventRingCCS = 1;\r
 \r
-  Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER));\r
+  Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER;\r
+  Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN) Buf & 0x3F) == 0);\r
-  ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
+  ZeroMem (Buf, Size);\r
 \r
   ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;\r
   EventRing->ERSTBase   = ERSTBase;\r
-  ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingSeg0);\r
-  ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingSeg0);\r
+  ERSTBase->PtrLo       = XHC_LOW_32BIT (DequeuePhy);\r
+  ERSTBase->PtrHi       = XHC_HIGH_32BIT (DequeuePhy);\r
   ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;\r
 \r
+  ERSTPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, ERSTBase, Size);\r
+\r
   //\r
   // Program the Interrupter Event Ring Segment Table Size (ERSTSZ) register (5.5.2.3.1)\r
   //\r
@@ -672,12 +817,12 @@ CreateEventRing (
   XhcWriteRuntimeReg (\r
     Xhc,\r
     XHC_ERDP_OFFSET,\r
-    XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
+    XHC_LOW_32BIT((UINT64)(UINTN)DequeuePhy)\r
     );\r
   XhcWriteRuntimeReg (\r
     Xhc,\r
     XHC_ERDP_OFFSET + 4,\r
-    XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
+    XHC_HIGH_32BIT((UINT64)(UINTN)DequeuePhy)\r
     );\r
   //\r
   // Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2)\r
@@ -688,12 +833,12 @@ CreateEventRing (
   XhcWriteRuntimeReg (\r
     Xhc,\r
     XHC_ERSTBA_OFFSET,\r
-    XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)\r
+    XHC_LOW_32BIT((UINT64)(UINTN)ERSTPhy)\r
     );\r
   XhcWriteRuntimeReg (\r
     Xhc,\r
     XHC_ERSTBA_OFFSET + 4,\r
-    XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)\r
+    XHC_HIGH_32BIT((UINT64)(UINTN)ERSTPhy)\r
     );\r
   //\r
   // Need set IMAN IE bit to enble the ring interrupt\r
@@ -718,8 +863,9 @@ CreateTransferRing (
 {\r
   VOID                  *Buf;\r
   LINK_TRB              *EndTrb;\r
+  EFI_PHYSICAL_ADDRESS  PhyAddr;\r
 \r
-  Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TrbNum));\r
+  Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN) Buf & 0x3F) == 0);\r
   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
@@ -736,8 +882,9 @@ CreateTransferRing (
   //\r
   EndTrb        = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));\r
   EndTrb->Type  = TRB_TYPE_LINK;\r
-  EndTrb->PtrLo = XHC_LOW_32BIT (Buf);\r
-  EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
+  EndTrb->PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+  EndTrb->PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
   //\r
   // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.\r
   //\r
@@ -762,34 +909,19 @@ XhcFreeEventRing (
   IN  EVENT_RING          *EventRing\r
 )\r
 {\r
-  UINT8                         Index;\r
-  EVENT_RING_SEG_TABLE_ENTRY    *TablePtr;\r
-  VOID                          *RingBuf;\r
-  EVENT_RING_SEG_TABLE_ENTRY    *EventRingPtr;\r
-\r
   if(EventRing->EventRingSeg0 == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   //\r
-  // Get the Event Ring Segment Table base address\r
+  // Free EventRing Segment 0\r
   //\r
-  TablePtr = (EVENT_RING_SEG_TABLE_ENTRY *)(EventRing->ERSTBase);\r
+  UsbHcFreeMem (Xhc->MemPool, EventRing->EventRingSeg0, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
 \r
   //\r
-  // Get all the TRBs Ring and release\r
+  // Free ESRT table\r
   //\r
-  for (Index = 0; Index < ERST_NUMBER; Index++) {\r
-    EventRingPtr = TablePtr + Index;\r
-    RingBuf      = (VOID *)(UINTN)(EventRingPtr->PtrLo | LShiftU64 ((UINT64)EventRingPtr->PtrHi, 32));\r
-\r
-    if(RingBuf != NULL) {\r
-      FreePages (RingBuf, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER));\r
-      ZeroMem (EventRingPtr, sizeof (EVENT_RING_SEG_TABLE_ENTRY));\r
-    }\r
-  }\r
-\r
-  FreePages (TablePtr, EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER));\r
+  UsbHcFreeMem (Xhc->MemPool, EventRing->ERSTBase, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -804,64 +936,123 @@ XhcFreeSched (
   IN USB_XHCI_INSTANCE    *Xhc\r
   )\r
 {\r
-  UINT32    Index;\r
-  UINT64    *ScratchBuf;\r
-\r
+  UINT32                  Index;\r
+  UINT64                  *ScratchEntry;\r
+  \r
   if (Xhc->ScratchBuf != NULL) {\r
-    ScratchBuf = Xhc->ScratchBuf;\r
+    ScratchEntry = Xhc->ScratchEntry;\r
     for (Index = 0; Index < Xhc->MaxScratchpadBufs; Index++) {\r
-      FreeAlignedPages ((VOID*)(UINTN)*ScratchBuf++, EFI_SIZE_TO_PAGES (Xhc->PageSize));\r
+      //\r
+      // Free Scratchpad Buffers\r
+      //\r
+      UsbHcFreeAlignedPages (Xhc->PciIo, (VOID*)(UINTN)ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);\r
     }\r
-    FreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)));\r
+    //\r
+    // Free Scratchpad Buffer Array\r
+    //\r
+    UsbHcFreeAlignedPages (Xhc->PciIo, Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);\r
+    FreePool (Xhc->ScratchEntryMap);\r
+    FreePool (Xhc->ScratchEntry);\r
+  }\r
+\r
+  if (Xhc->CmdRing.RingSeg0 != NULL) {\r
+    UsbHcFreeMem (Xhc->MemPool, Xhc->CmdRing.RingSeg0, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);\r
+    Xhc->CmdRing.RingSeg0 = NULL;\r
   }\r
+  \r
+  XhcFreeEventRing (Xhc,&Xhc->EventRing);\r
 \r
   if (Xhc->DCBAA != NULL) {\r
-    FreePages (Xhc->DCBAA, EFI_SIZE_TO_PAGES((Xhc->MaxSlotsEn + 1) * sizeof(UINT64)));\r
+    UsbHcFreeMem (Xhc->MemPool, Xhc->DCBAA, (Xhc->MaxSlotsEn + 1) * sizeof(UINT64));\r
     Xhc->DCBAA = NULL;\r
   }\r
+  \r
+  //\r
+  // Free memory pool at last\r
+  //\r
+  if (Xhc->MemPool != NULL) {\r
+    UsbHcFreeMemPool (Xhc->MemPool);\r
+    Xhc->MemPool = NULL;\r
+  }\r
+}\r
 \r
-  if (Xhc->CmdRing.RingSeg0 != NULL){\r
-    FreePages (Xhc->CmdRing.RingSeg0, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER));\r
-    Xhc->CmdRing.RingSeg0 = NULL;\r
+/**\r
+  Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.\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
+\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
+IsAsyncIntTrb (\r
+  IN  USB_XHCI_INSTANCE   *Xhc,\r
+  IN  TRB_TEMPLATE        *Trb,\r
+  OUT URB                 **Urb\r
+  )\r
+{\r
+  LIST_ENTRY              *Entry;\r
+  LIST_ENTRY              *Next;\r
+  TRB_TEMPLATE            *CheckedTrb;\r
+  URB                     *CheckedUrb;\r
+  UINTN                   Index;\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
+      //\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
+        CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;\r
+      }\r
+    }\r
   }\r
 \r
-  XhcFreeEventRing (Xhc,&Xhc->EventRing);\r
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Check if it is ring TRB.\r
+  Check if the Trb is a transaction of the URB.\r
 \r
-  @param Ring   The transfer ring\r
-  @param Trb    The TRB to check if it's in the transfer ring\r
+  @param Trb    The TRB to be checked\r
+  @param Urb    The transfer ring to be checked.\r
 \r
-  @retval TRUE  It is in the ring\r
-  @retval FALSE It is not in the ring\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
 IsTransferRingTrb (\r
-  IN  TRANSFER_RING       *Ring,\r
-  IN  TRB_TEMPLATE        *Trb\r
+  IN  TRB_TEMPLATE        *Trb,\r
+  IN  URB                 *Urb\r
   )\r
 {\r
-  BOOLEAN       Flag;\r
-  TRB_TEMPLATE  *Trb1;\r
+  TRB_TEMPLATE  *CheckedTrb;\r
   UINTN         Index;\r
 \r
-  Trb1 = Ring->RingSeg0;\r
-  Flag = FALSE;\r
+  CheckedTrb = Urb->Ring->RingSeg0;\r
 \r
-  ASSERT (Ring->TrbNumber == CMD_RING_TRB_NUMBER || Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
+  ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
 \r
-  for (Index = 0; Index < Ring->TrbNumber; Index++) {\r
-    if (Trb == Trb1) {\r
-      Flag = TRUE;\r
-      break;\r
+  for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {\r
+    if (Trb == CheckedTrb) {\r
+      return TRUE;\r
     }\r
-    Trb1++;\r
+    CheckedTrb++;\r
   }\r
 \r
-  return Flag;\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -874,44 +1065,50 @@ 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
   )\r
 {\r
-  BOOLEAN                 StartDone;\r
-  BOOLEAN                 EndDone;\r
   EVT_TRB_TRANSFER        *EvtTrb;\r
   TRB_TEMPLATE            *TRBPtr;\r
   UINTN                   Index;\r
   UINT8                   TRBType;\r
   EFI_STATUS              Status;\r
+  URB                     *AsyncUrb;\r
+  URB                     *CheckedUrb;\r
+  UINT64                  XhcDequeue;\r
+  UINT32                  High;\r
+  UINT32                  Low;\r
+  EFI_PHYSICAL_ADDRESS    PhyAddr;\r
 \r
   ASSERT ((Xhc != NULL) && (Urb != NULL));\r
 \r
-  Urb->Completed  = 0;\r
-  Urb->Result     = EFI_USB_NOERROR;\r
-  Status          = EFI_SUCCESS;\r
-  EvtTrb          = NULL;\r
+  Status   = EFI_SUCCESS;\r
+  AsyncUrb = NULL;\r
+\r
+  if (Urb->Finished) {\r
+    goto EXIT;\r
+  }\r
+\r
+  EvtTrb = NULL;\r
 \r
   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
     Urb->Result |= EFI_USB_ERR_SYSTEM;\r
-    Status       = EFI_DEVICE_ERROR;\r
     goto EXIT;\r
   }\r
 \r
   //\r
-  // Restore the EventRingDequeue and poll the transfer event ring from beginning\r
+  // Traverse the event ring to find out all new events from the previous check.\r
   //\r
-  StartDone = FALSE;\r
-  EndDone   = FALSE;\r
-  Urb->EvtRing->EventRingDequeue = Urb->EvtTrbStart;\r
-  for (Index = 0; Index < Urb->EvtRing->TrbNumber; Index++) {\r
-    XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-    Status = XhcCheckNewEvent (Xhc, Urb->EvtRing, ((TRB_TEMPLATE **)&EvtTrb));\r
+  XhcSyncEventRing (Xhc, &Xhc->EventRing);\r
+  for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {\r
+    Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));\r
     if (Status == EFI_NOT_READY) {\r
-      Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
+      //\r
+      // All new events are handled, return directly.\r
+      //\r
       goto EXIT;\r
     }\r
 \r
@@ -921,81 +1118,115 @@ XhcCheckUrbResult (
     if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {\r
       continue;\r
     }\r
+    \r
+    //\r
+    // Need convert pci device address to host address\r
+    //\r
+    PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
+    TRBPtr = (TRB_TEMPLATE *)(UINTN) UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN) PhyAddr, sizeof (TRB_TEMPLATE));\r
 \r
-    TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
-    if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {\r
-      switch (EvtTrb->Completecode) {\r
-        case TRB_COMPLETION_STALL_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_STALL;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
-\r
-        case TRB_COMPLETION_BABBLE_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_BABBLE;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
-\r
-        case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_BUFFER;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
-\r
-        case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
-\r
-        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
-          }\r
-\r
-          TRBType = (UINT8) (TRBPtr->Type);\r
-          if ((TRBType == TRB_TYPE_DATA_STAGE) ||\r
-              (TRBType == TRB_TYPE_NORMAL) ||\r
-              (TRBType == TRB_TYPE_ISOCH)) {\r
-            Urb->Completed += (Urb->DataLen - EvtTrb->Lenth);\r
-          }\r
-\r
-          Status = EFI_SUCCESS;\r
-          break;\r
-\r
-        default:\r
-          DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
-          Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-          Status = EFI_DEVICE_ERROR;\r
-          goto EXIT;\r
-          break;\r
-      }\r
-\r
-      //\r
-      // Only check first and end Trb event address\r
-      //\r
-      if (TRBPtr == Urb->TrbStart) {\r
-        StartDone = TRUE;\r
-      }\r
+    //\r
+    // Update the status of Urb according to the finished event regardless of whether\r
+    // the urb is current checked one or in the XHCI's async transfer list.\r
+    // 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
+      CheckedUrb = Urb;\r
+    } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) {    \r
+      CheckedUrb = AsyncUrb;\r
+    } else {\r
+      continue;\r
+    }\r
+  \r
+    switch (EvtTrb->Completecode) {\r
+      case TRB_COMPLETION_STALL_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_STALL;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        goto EXIT;\r
+\r
+      case TRB_COMPLETION_BABBLE_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_BABBLE;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        goto EXIT;\r
+\r
+      case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_BUFFER;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
+        goto EXIT;\r
+\r
+      case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        goto EXIT;\r
+\r
+      case TRB_COMPLETION_SHORT_PACKET:\r
+      case TRB_COMPLETION_SUCCESS:\r
+        if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
+          DEBUG ((EFI_D_VERBOSE, "XhcCheckUrbResult: short packet happens!\n"));\r
+        }\r
 \r
-      if (TRBPtr == Urb->TrbEnd) {\r
-        EndDone = TRUE;\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 += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length);\r
+        }\r
 \r
-      if (StartDone && EndDone) {\r
         break;\r
-      }\r
+\r
+      default:\r
+        DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
+        CheckedUrb->Finished = TRUE;\r
+        goto EXIT;\r
+    }\r
+\r
+    //\r
+    // Only check first and end Trb event address\r
+    //\r
+    if (TRBPtr == CheckedUrb->TrbStart) {\r
+      CheckedUrb->StartDone = TRUE;\r
+    }\r
+\r
+    if (TRBPtr == CheckedUrb->TrbEnd) {\r
+      CheckedUrb->EndDone = TRUE;\r
+    }\r
+\r
+    if (CheckedUrb->StartDone && CheckedUrb->EndDone) {\r
+      CheckedUrb->Finished = TRUE;\r
+      CheckedUrb->EvtTrb   = (TRB_TEMPLATE *)EvtTrb;\r
     }\r
   }\r
 \r
 EXIT:\r
-  return Status;\r
+\r
+  //\r
+  // Advance event ring to last available entry\r
+  //\r
+  // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+  // So divide it to two 32-bytes width register access.\r
+  //\r
+  Low  = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);\r
+  High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);\r
+  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
+\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->EventRing.EventRingDequeue, sizeof (TRB_TEMPLATE));\r
+\r
+  if ((XhcDequeue & (~0x0F)) != (PhyAddr & (~0x0F))) {\r
+    //\r
+    // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+    // So divide it to two 32-bytes width register access.\r
+    //\r
+    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (PhyAddr) | BIT3);\r
+    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (PhyAddr));\r
+  }\r
+\r
+  return Urb->Finished;\r
 }\r
 \r
 \r
@@ -1022,9 +1253,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
@@ -1039,7 +1271,7 @@ XhcExecTransfer (
   }\r
 \r
   Status = EFI_SUCCESS;\r
-  Loop   = (Timeout * XHC_1_MILLISECOND / XHC_POLL_DELAY) + 1;\r
+  Loop   = Timeout * XHC_1_MILLISECOND;\r
   if (Timeout == 0) {\r
     Loop = 0xFFFFFFFF;\r
   }\r
@@ -1047,11 +1279,18 @@ XhcExecTransfer (
   XhcRingDoorBell (Xhc, SlotId, Dci);\r
 \r
   for (Index = 0; Index < Loop; Index++) {\r
-    Status = XhcCheckUrbResult (Xhc, Urb);\r
-    if ((Status != EFI_NOT_READY)) {\r
+    Finished = XhcCheckUrbResult (Xhc, Urb);\r
+    if (Finished) {\r
       break;\r
     }\r
-    gBS->Stall (XHC_POLL_DELAY);\r
+    gBS->Stall (XHC_1_MICROSECOND);\r
+  }\r
+\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
@@ -1080,6 +1319,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
@@ -1091,9 +1331,18 @@ 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
-      FreePool (Urb);\r
+      XhcFreeUrb (Xhc, Urb);\r
       return EFI_SUCCESS;\r
     }\r
   }\r
@@ -1115,12 +1364,23 @@ 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
-    FreePool (Urb);\r
+    XhcFreeUrb (Xhc, Urb);\r
   }\r
 }\r
 \r
@@ -1151,6 +1411,60 @@ XhcUpdateAsyncRequest (
   }\r
 }\r
 \r
+/**\r
+  Flush data from PCI controller specific address to mapped system\r
+  memory address.\r
+\r
+  @param  Xhc                The XHCI device.\r
+  @param  Urb                The URB to unmap.\r
+\r
+  @retval EFI_SUCCESS        Success to flush data to mapped system memory.\r
+  @retval EFI_DEVICE_ERROR   Fail to flush data to mapped system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+XhcFlushAsyncIntMap (\r
+  IN  USB_XHCI_INSTANCE   *Xhc,\r
+  IN  URB                 *Urb\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
+  EFI_PCI_IO_PROTOCOL           *PciIo;\r
+  UINTN                         Len;\r
+  VOID                          *Map;\r
+\r
+  PciIo = Xhc->PciIo;\r
+  Len   = Urb->DataLen;\r
+\r
+  if (Urb->Ep.Direction == EfiUsbDataIn) {\r
+    MapOp = EfiPciIoOperationBusMasterWrite;\r
+  } else {\r
+    MapOp = EfiPciIoOperationBusMasterRead;\r
+  }\r
+\r
+  if (Urb->DataMap != NULL) {\r
+    Status = PciIo->Unmap (PciIo, Urb->DataMap);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+  }\r
+\r
+  Urb->DataMap = NULL;\r
+\r
+  Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+  if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);\r
+  Urb->DataMap  = Map;\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+  return EFI_DEVICE_ERROR;\r
+}\r
 \r
 /**\r
   Interrupt transfer periodic check handler.\r
@@ -1194,12 +1508,21 @@ XhcMonitorAsyncRequests (
     // Check the result of URB execution. If it is still\r
     // active, check the next one.\r
     //\r
-    Status = XhcCheckUrbResult (Xhc, Urb);\r
+    XhcCheckUrbResult (Xhc, Urb);\r
 \r
-    if (Status == EFI_NOT_READY) {\r
+    if (!Urb->Finished) {\r
       continue;\r
     }\r
 \r
+    //\r
+    // Flush any PCI posted write transactions from a PCI host\r
+    // bridge to system memory.\r
+    //\r
+    Status = XhcFlushAsyncIntMap (Xhc, Urb);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));\r
+    }\r
+\r
     //\r
     // Allocate a buffer then copy the transferred data for user.\r
     // If failed to allocate the buffer, update the URB for next\r
@@ -1219,8 +1542,6 @@ XhcMonitorAsyncRequests (
       CopyMem (ProcBuf, Urb->Data, Urb->Completed);\r
     }\r
 \r
-    XhcUpdateAsyncRequest (Xhc, Urb);\r
-\r
     //\r
     // Leave error recovery to its related device driver. A\r
     // common case of the error recovery is to re-submit the\r
@@ -1244,6 +1565,8 @@ XhcMonitorAsyncRequests (
     if (ProcBuf != NULL) {\r
       gBS->FreePool (ProcBuf);\r
     }\r
+\r
+    XhcUpdateAsyncRequest (Xhc, Urb);\r
   }\r
   gBS->RestoreTPL (OldTpl);\r
 }\r
@@ -1276,6 +1599,10 @@ XhcPollPortStatusChange (
 \r
   Status = EFI_SUCCESS;\r
 \r
+  if ((PortState->PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
   if (ParentRouteChart.Dword == 0) {\r
     RouteChart.Route.RouteString = 0;\r
     RouteChart.Route.RootPortNum = Port + 1;\r
@@ -1290,6 +1617,15 @@ XhcPollPortStatusChange (
     RouteChart.Route.TierNum       = ParentRouteChart.Route.TierNum + 1;\r
   }\r
 \r
+  SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
+  if (SlotId != 0) {\r
+    if (Xhc->HcCParams.Data.Csz == 0) {\r
+      Status = XhcDisableSlotCmd (Xhc, SlotId);\r
+    } else {\r
+      Status = XhcDisableSlotCmd64 (Xhc, SlotId);\r
+    }\r
+  }\r
+\r
   if (((PortState->PortStatus & USB_PORT_STAT_ENABLE) != 0) &&\r
       ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) != 0)) {\r
     //\r
@@ -1307,28 +1643,15 @@ XhcPollPortStatusChange (
     // Execute Enable_Slot cmd for attached device, initialize device context and assign device address.\r
     //\r
     SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
-    if (SlotId == 0) {\r
+    if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) {\r
       if (Xhc->HcCParams.Data.Csz == 0) {\r
         Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
       } else {\r
         Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
       }\r
-      ASSERT_EFI_ERROR (Status);\r
-    }\r
-  } else if ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) == 0) {\r
-    //\r
-    // Device is detached. Disable the allocated device slot and release resource.\r
-    //\r
-    SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
-    if (SlotId != 0) {\r
-      if (Xhc->HcCParams.Data.Csz == 0) {\r
-        Status = XhcDisableSlotCmd (Xhc, SlotId);\r
-      } else {\r
-        Status = XhcDisableSlotCmd64 (Xhc, SlotId);\r
-      }\r
-      ASSERT_EFI_ERROR (Status);\r
     }\r
-  }\r
+  } \r
+\r
   return Status;\r
 }\r
 \r
@@ -1445,10 +1768,6 @@ XhcSyncEventRing (
 {\r
   UINTN               Index;\r
   TRB_TEMPLATE        *EvtTrb1;\r
-  TRB_TEMPLATE        *EvtTrb2;\r
-  UINT64              XhcDequeue;\r
-  UINT32              High;\r
-  UINT32              Low;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
@@ -1456,41 +1775,25 @@ XhcSyncEventRing (
   // Calculate the EventRingEnqueue and EventRingCCS.\r
   // Note: only support single Segment\r
   //\r
-  EvtTrb1 = EvtRing->EventRingSeg0;\r
-  EvtTrb2 = EvtRing->EventRingSeg0;\r
+  EvtTrb1 = EvtRing->EventRingDequeue;\r
 \r
   for (Index = 0; Index < EvtRing->TrbNumber; Index++) {\r
-    if (EvtTrb1->CycleBit != EvtTrb2->CycleBit) {\r
+    if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {\r
       break;\r
     }\r
+\r
     EvtTrb1++;\r
+\r
+    if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+      EvtTrb1 = EvtRing->EventRingSeg0;\r
+      EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;\r
+    }\r
   }\r
 \r
   if (Index < EvtRing->TrbNumber) {\r
     EvtRing->EventRingEnqueue = EvtTrb1;\r
-    EvtRing->EventRingCCS     = (EvtTrb2->CycleBit) ? 1 : 0;\r
   } else {\r
-    EvtRing->EventRingEnqueue = EvtTrb2;\r
-    EvtRing->EventRingCCS     = (EvtTrb2->CycleBit) ? 0 : 1;\r
-  }\r
-\r
-  //\r
-  // Apply the EventRingDequeue to Xhc\r
-  //\r
-  // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
-  // So divide it to two 32-bytes width register access.\r
-  //\r
-  Low  = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);\r
-  High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);\r
-  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
-\r
-  if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {\r
-    //\r
-    // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
-    // So divide it to two 32-bytes width register access.\r
-    //\r
-    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (EvtRing->EventRingDequeue) | BIT3);\r
-    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (EvtRing->EventRingDequeue));\r
+    ASSERT (FALSE);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -1537,7 +1840,7 @@ XhcSyncTrsRing (
       // Toggle PCS maintained by software\r
       //\r
       TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;\r
-      TrsTrb           = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);\r
+      TrsTrb = (TRB_TEMPLATE *) TrsRing->RingSeg0;  // Use host address\r
     }\r
   }\r
 \r
@@ -1579,33 +1882,23 @@ XhcCheckNewEvent (
   OUT TRB_TEMPLATE            **NewEvtTrb\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  TRB_TEMPLATE*EvtTrb;\r
-\r
   ASSERT (EvtRing != NULL);\r
 \r
-  EvtTrb     = EvtRing->EventRingDequeue;\r
   *NewEvtTrb = EvtRing->EventRingDequeue;\r
 \r
   if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {\r
     return EFI_NOT_READY;\r
   }\r
 \r
-  Status = EFI_SUCCESS;\r
-\r
-  if (((EvtTrb->Status >> 24) & 0xFF) != TRB_COMPLETION_SUCCESS) {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
   EvtRing->EventRingDequeue++;\r
   //\r
   // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.\r
   //\r
-  if ((UINTN)EvtRing->EventRingDequeue >=  ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+  if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
     EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;\r
   }\r
 \r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -1692,6 +1985,7 @@ XhcInitializeDeviceSlot (
   UINT8                       SlotId;\r
   UINT8                       ParentSlotId;\r
   DEVICE_CONTEXT              *ParentDeviceContext;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));\r
   CmdTrb.CycleBit = 1;\r
@@ -1703,7 +1997,10 @@ XhcInitializeDeviceSlot (
               XHC_GENERIC_TIMEOUT,\r
               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
               );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status));\r
+    return Status;\r
+  }\r
   ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);\r
   DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));\r
   SlotId = (UINT8)EvtTrb->SlotId;\r
@@ -1719,7 +2016,7 @@ XhcInitializeDeviceSlot (
   // 4.3.3 Device Slot Initialization\r
   // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.\r
   //\r
-  InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT)));\r
+  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT));\r
   ASSERT (InputContext != NULL);\r
   ASSERT (((UINTN) InputContext & 0x3F) == 0);\r
   ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
@@ -1808,13 +2105,18 @@ XhcInitializeDeviceSlot (
   //\r
   // Init the DCS(dequeue cycle state) as the transfer ring's CCS\r
   //\r
-  InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;\r
-  InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+              Xhc->MemPool,\r
+              ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,\r
+              sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+              );\r
+  InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;\r
+  InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
 \r
   //\r
   // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
   //\r
-  OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT)));\r
+  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT));\r
   ASSERT (OutputContext != NULL);\r
   ASSERT (((UINTN) OutputContext & 0x3F) == 0);\r
   ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT));\r
@@ -1824,15 +2126,24 @@ XhcInitializeDeviceSlot (
   // 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with\r
   //    a pointer to the Output Device Context data structure (6.2.1).\r
   //\r
-  Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT));\r
+  //\r
+  // Fill DCBAA with PCI device address\r
+  //\r
+  Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;\r
 \r
   //\r
   // 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
-  CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
-  CmdTrbAddr.PtrHi    = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
+  CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbAddr.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbAddr.CycleBit = 1;\r
   CmdTrbAddr.Type     = TRB_TYPE_ADDRESS_DEV;\r
   CmdTrbAddr.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -1842,12 +2153,11 @@ XhcInitializeDeviceSlot (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
-  DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;\r
-  DEBUG ((EFI_D_INFO, "    Address %d assigned succeefully\n", DeviceAddress));\r
-\r
-  Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
+  if (!EFI_ERROR (Status)) {\r
+    DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;\r
+    DEBUG ((EFI_D_INFO, "    Address %d assigned successfully\n", DeviceAddress));\r
+    Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -1885,6 +2195,7 @@ XhcInitializeDeviceSlot64 (
   UINT8                       SlotId;\r
   UINT8                       ParentSlotId;\r
   DEVICE_CONTEXT_64           *ParentDeviceContext;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));\r
   CmdTrb.CycleBit = 1;\r
@@ -1896,7 +2207,10 @@ XhcInitializeDeviceSlot64 (
               XHC_GENERIC_TIMEOUT,\r
               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
               );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status));\r
+    return Status;\r
+  }\r
   ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);\r
   DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));\r
   SlotId = (UINT8)EvtTrb->SlotId;\r
@@ -1912,7 +2226,7 @@ XhcInitializeDeviceSlot64 (
   // 4.3.3 Device Slot Initialization\r
   // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.\r
   //\r
-  InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));\r
+  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64));\r
   ASSERT (InputContext != NULL);\r
   ASSERT (((UINTN) InputContext & 0x3F) == 0);\r
   ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
@@ -2001,13 +2315,18 @@ XhcInitializeDeviceSlot64 (
   //\r
   // Init the DCS(dequeue cycle state) as the transfer ring's CCS\r
   //\r
-  InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;\r
-  InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+              Xhc->MemPool,\r
+              ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,\r
+              sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+              );\r
+  InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;\r
+  InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
 \r
   //\r
   // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
   //\r
-  OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));\r
+  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64));\r
   ASSERT (OutputContext != NULL);\r
   ASSERT (((UINTN) OutputContext & 0x3F) == 0);\r
   ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));\r
@@ -2017,15 +2336,24 @@ XhcInitializeDeviceSlot64 (
   // 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with\r
   //    a pointer to the Output Device Context data structure (6.2.1).\r
   //\r
-  Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT_64));\r
+  //\r
+  // Fill DCBAA with PCI device address\r
+  //\r
+  Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;\r
 \r
   //\r
   // 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
-  CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
-  CmdTrbAddr.PtrHi    = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
+  CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbAddr.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbAddr.CycleBit = 1;\r
   CmdTrbAddr.Type     = TRB_TYPE_ADDRESS_DEV;\r
   CmdTrbAddr.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2035,13 +2363,11 @@ XhcInitializeDeviceSlot64 (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
-  DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;\r
-  DEBUG ((EFI_D_INFO, "    Address %d assigned succeefully\n", DeviceAddress));\r
-\r
-  Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
-\r
+  if (!EFI_ERROR (Status)) {\r
+    DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;\r
+    DEBUG ((EFI_D_INFO, "    Address %d assigned successfully\n", DeviceAddress));\r
+    Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -2102,7 +2428,10 @@ XhcDisableSlotCmd (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));\r
+    return Status;\r
+  }\r
   //\r
   // Free the slot's device context entry\r
   //\r
@@ -2115,9 +2444,10 @@ XhcDisableSlotCmd (
     if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {\r
       RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;\r
       if (RingSeg != NULL) {\r
-        FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));\r
+        UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
       }\r
       FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+      Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;\r
     }\r
   }\r
 \r
@@ -2127,12 +2457,16 @@ XhcDisableSlotCmd (
     }\r
   }\r
 \r
+  if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting != NULL) {\r
+    FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);\r
+  }\r
+\r
   if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {\r
-    FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT)));\r
+    UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
   }\r
 \r
   if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
-    FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT)));\r
+    UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT));\r
   }\r
   //\r
   // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established\r
@@ -2201,7 +2535,10 @@ XhcDisableSlotCmd64 (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));\r
+    return Status;\r
+  }\r
   //\r
   // Free the slot's device context entry\r
   //\r
@@ -2214,9 +2551,10 @@ XhcDisableSlotCmd64 (
     if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {\r
       RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;\r
       if (RingSeg != NULL) {\r
-        FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));\r
+        UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
       }\r
       FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+      Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;\r
     }\r
   }\r
 \r
@@ -2226,12 +2564,16 @@ XhcDisableSlotCmd64 (
     }\r
   }\r
 \r
+  if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting != NULL) {\r
+    FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);\r
+  }\r
+\r
   if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {\r
-    FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));\r
+    UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
   }\r
 \r
   if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
-    FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));\r
+     UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT_64));\r
   }\r
   //\r
   // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established\r
@@ -2244,6 +2586,369 @@ XhcDisableSlotCmd64 (
   return Status;\r
 }\r
 \r
+/**\r
+  Initialize endpoint context in input context.\r
+\r
+  @param Xhc            The XHCI Instance.\r
+  @param SlotId         The slot id to be configured.\r
+  @param DeviceSpeed    The device's speed.\r
+  @param InputContext   The pointer to the input context.\r
+  @param IfDesc         The pointer to the usb device interface descriptor.\r
+\r
+  @return The maximum device context index of endpoint.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+XhcInitializeEndpointContext (\r
+  IN USB_XHCI_INSTANCE          *Xhc,\r
+  IN UINT8                      SlotId,\r
+  IN UINT8                      DeviceSpeed,\r
+  IN INPUT_CONTEXT              *InputContext,\r
+  IN USB_INTERFACE_DESCRIPTOR   *IfDesc\r
+  )\r
+{\r
+  USB_ENDPOINT_DESCRIPTOR       *EpDesc;\r
+  UINTN                         NumEp;\r
+  UINTN                         EpIndex;\r
+  UINT8                         EpAddr;\r
+  UINT8                         Direction;\r
+  UINT8                         Dci;\r
+  UINT8                         MaxDci;\r
+  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  UINT8                         Interval;\r
+  TRANSFER_RING                 *EndpointTransferRing;\r
+\r
+  MaxDci = 0;\r
+\r
+  NumEp = IfDesc->NumEndpoints;\r
+\r
+  EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
+  for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
+    while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
+      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
+    Dci = XhcEndpointToDci (EpAddr, Direction);\r
+    ASSERT (Dci < 32);\r
+    if (Dci > MaxDci) {\r
+      MaxDci = Dci;\r
+    }\r
+\r
+    InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
+    InputContext->EP[Dci-1].MaxPacketSize     = EpDesc->MaxPacketSize;\r
+\r
+    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+      //\r
+      // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
+      //\r
+      InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+    } else {\r
+      InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+    }\r
+\r
+    switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
+      case USB_ENDPOINT_BULK:\r
+        if (Direction == EfiUsbDataIn) {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
+        }\r
+\r
+        InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+        if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+          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
+        }\r
+\r
+        break;\r
+      case USB_ENDPOINT_ISO:\r
+        if (Direction == EfiUsbDataIn) {\r
+          InputContext->EP[Dci-1].CErr   = 0;\r
+          InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 0;\r
+          InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
+        }\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
+          InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
+        }\r
+        InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+        InputContext->EP[Dci-1].MaxESITPayload   = EpDesc->MaxPacketSize;\r
+        //\r
+        // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+        //\r
+        if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
+          Interval = EpDesc->Interval;\r
+          //\r
+          // Calculate through the bInterval field of Endpoint descriptor.\r
+          //\r
+          ASSERT (Interval != 0);\r
+          InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;\r
+        } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          //\r
+          // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
+          //\r
+          InputContext->EP[Dci-1].Interval         = Interval - 1;\r
+          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+          InputContext->EP[Dci-1].MaxESITPayload   = 0x0002;\r
+          InputContext->EP[Dci-1].MaxBurstSize     = 0x0;\r
+          InputContext->EP[Dci-1].CErr             = 3;\r
+        }\r
+\r
+        if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+          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
+        }\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
+        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
+                Xhc->MemPool,\r
+                ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
+                sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+                );\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
+    EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+  }\r
+\r
+  return MaxDci;\r
+}\r
+\r
+/**\r
+  Initialize endpoint context in input context.\r
+\r
+  @param Xhc            The XHCI Instance.\r
+  @param SlotId         The slot id to be configured.\r
+  @param DeviceSpeed    The device's speed.\r
+  @param InputContext   The pointer to the input context.\r
+  @param IfDesc         The pointer to the usb device interface descriptor.\r
+\r
+  @return The maximum device context index of endpoint.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+XhcInitializeEndpointContext64 (\r
+  IN USB_XHCI_INSTANCE          *Xhc,\r
+  IN UINT8                      SlotId,\r
+  IN UINT8                      DeviceSpeed,\r
+  IN INPUT_CONTEXT_64           *InputContext,\r
+  IN USB_INTERFACE_DESCRIPTOR   *IfDesc\r
+  )\r
+{\r
+  USB_ENDPOINT_DESCRIPTOR       *EpDesc;\r
+  UINTN                         NumEp;\r
+  UINTN                         EpIndex;\r
+  UINT8                         EpAddr;\r
+  UINT8                         Direction;\r
+  UINT8                         Dci;\r
+  UINT8                         MaxDci;\r
+  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  UINT8                         Interval;\r
+  TRANSFER_RING                 *EndpointTransferRing;\r
+\r
+  MaxDci = 0;\r
+\r
+  NumEp = IfDesc->NumEndpoints;\r
+\r
+  EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
+  for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
+    while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
+      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
+    Dci = XhcEndpointToDci (EpAddr, Direction);\r
+    ASSERT (Dci < 32);\r
+    if (Dci > MaxDci) {\r
+      MaxDci = Dci;\r
+    }\r
+\r
+    InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
+    InputContext->EP[Dci-1].MaxPacketSize     = EpDesc->MaxPacketSize;\r
+\r
+    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+      //\r
+      // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
+      //\r
+      InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+    } else {\r
+      InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+    }\r
+\r
+    switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
+      case USB_ENDPOINT_BULK:\r
+        if (Direction == EfiUsbDataIn) {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
+        }\r
+\r
+        InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+        if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+          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
+        }\r
+\r
+        break;\r
+      case USB_ENDPOINT_ISO:\r
+        if (Direction == EfiUsbDataIn) {\r
+          InputContext->EP[Dci-1].CErr   = 0;\r
+          InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 0;\r
+          InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
+        }\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
+          InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
+        } else {\r
+          InputContext->EP[Dci-1].CErr   = 3;\r
+          InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
+        }\r
+        InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+        InputContext->EP[Dci-1].MaxESITPayload   = EpDesc->MaxPacketSize;\r
+        //\r
+        // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+        //\r
+        if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
+          Interval = EpDesc->Interval;\r
+          //\r
+          // Calculate through the bInterval field of Endpoint descriptor.\r
+          //\r
+          ASSERT (Interval != 0);\r
+          InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;\r
+        } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          //\r
+          // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
+          //\r
+          InputContext->EP[Dci-1].Interval         = Interval - 1;\r
+          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+          InputContext->EP[Dci-1].MaxESITPayload   = 0x0002;\r
+          InputContext->EP[Dci-1].MaxBurstSize     = 0x0;\r
+          InputContext->EP[Dci-1].CErr             = 3;\r
+        }\r
+\r
+        if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+          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
+        }\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
+        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
+                Xhc->MemPool,\r
+                ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
+                sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+                );\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
+    EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+  }\r
+\r
+  return MaxDci;\r
+}\r
 \r
 /**\r
   Configure all the device endpoints through XHCI's Configure_Endpoint cmd.\r
@@ -2266,20 +2971,12 @@ XhcSetConfigCmd (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-\r
   USB_INTERFACE_DESCRIPTOR    *IfDesc;\r
-  USB_ENDPOINT_DESCRIPTOR     *EpDesc;\r
   UINT8                       Index;\r
-  UINTN                       NumEp;\r
-  UINTN                       EpIndex;\r
-  UINT8                       EpAddr;\r
-  UINT8                       Direction;\r
   UINT8                       Dci;\r
   UINT8                       MaxDci;\r
-  UINT32                      PhyAddr;\r
-  UINT8                       Interval;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
-  TRANSFER_RING               *EndpointTransferRing;\r
   CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
   INPUT_CONTEXT               *InputContext;\r
   DEVICE_CONTEXT              *OutputContext;\r
@@ -2298,121 +2995,22 @@ XhcSetConfigCmd (
 \r
   IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
   for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {\r
-    while (IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) {\r
+    while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {\r
       IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
     }\r
 \r
-    NumEp = IfDesc->NumEndpoints;\r
-\r
-    EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
-    for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
-      while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
-        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
-      }\r
-\r
-      EpAddr    = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
-      Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
-\r
-      Dci = XhcEndpointToDci (EpAddr, Direction);\r
-      ASSERT (Dci < 32);\r
-      if (Dci > MaxDci) {\r
-        MaxDci = Dci;\r
-      }\r
-\r
-      InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
-      InputContext->EP[Dci-1].MaxPacketSize     = EpDesc->MaxPacketSize;\r
+    if (IfDesc->Length < sizeof (USB_INTERFACE_DESCRIPTOR)) {\r
+      IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+      continue;\r
+    }\r
 \r
-      if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
-        //\r
-        // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
-        //\r
-        InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
-      } else {\r
-        InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
-      }\r
+    Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);\r
+    if (Dci > MaxDci) {\r
+      MaxDci = Dci;\r
+    }\r
 \r
-      switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
-        case USB_ENDPOINT_BULK:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
-          }\r
-\r
-          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-          if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
-            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
-          }\r
-\r
-          break;\r
-        case USB_ENDPOINT_ISO:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 0;\r
-            InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 0;\r
-            InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
-          }\r
-          break;\r
-        case USB_ENDPOINT_INTERRUPT:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
-          }\r
-          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-          InputContext->EP[Dci-1].MaxESITPayload   = EpDesc->MaxPacketSize;\r
-          //\r
-          // Get the bInterval from descriptor and init the the interval field of endpoint context\r
-          //\r
-          if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
-            Interval = EpDesc->Interval;\r
-            //\r
-            // Hard code the interval to MAX first, need calculate through the bInterval field of Endpoint descriptor.\r
-            //\r
-            InputContext->EP[Dci-1].Interval = 6;\r
-          } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
-            Interval = EpDesc->Interval;\r
-            ASSERT (Interval >= 1 && Interval <= 16);\r
-            //\r
-            // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
-            //\r
-            InputContext->EP[Dci-1].Interval         = Interval - 1;\r
-            InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-            InputContext->EP[Dci-1].MaxESITPayload   = 0x0002;\r
-            InputContext->EP[Dci-1].MaxBurstSize     = 0x0;\r
-            InputContext->EP[Dci-1].CErr             = 3;\r
-          }\r
-\r
-          if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
-            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
-          }\r
-          break;\r
-\r
-        case USB_ENDPOINT_CONTROL:\r
-        default:\r
-          ASSERT (0);\r
-          break;\r
-      }\r
-\r
-      PhyAddr  = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
-      PhyAddr &= ~(0x0F);\r
-      PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
-      InputContext->EP[Dci-1].PtrLo = PhyAddr;\r
-      InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
-\r
-      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
-    }\r
-    IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
-  }\r
+    IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+  }\r
 \r
   InputContext->InputControlContext.Dword2 |= BIT0;\r
   InputContext->Slot.ContextEntries         = MaxDci;\r
@@ -2420,8 +3018,9 @@ XhcSetConfigCmd (
   // configure endpoint\r
   //\r
   ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
-  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbCfgEP.CycleBit = 1;\r
   CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
   CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2432,7 +3031,11 @@ XhcSetConfigCmd (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));\r
+  } else {\r
+    Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -2458,20 +3061,12 @@ XhcSetConfigCmd64 (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-\r
   USB_INTERFACE_DESCRIPTOR    *IfDesc;\r
-  USB_ENDPOINT_DESCRIPTOR     *EpDesc;\r
   UINT8                       Index;\r
-  UINTN                       NumEp;\r
-  UINTN                       EpIndex;\r
-  UINT8                       EpAddr;\r
-  UINT8                       Direction;\r
   UINT8                       Dci;\r
   UINT8                       MaxDci;\r
-  UINT32                      PhyAddr;\r
-  UINT8                       Interval;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
-  TRANSFER_RING               *EndpointTransferRing;\r
   CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
   INPUT_CONTEXT_64            *InputContext;\r
   DEVICE_CONTEXT_64           *OutputContext;\r
@@ -2490,146 +3085,600 @@ XhcSetConfigCmd64 (
 \r
   IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
   for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {\r
-    while (IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) {\r
+    while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {\r
       IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
     }\r
 \r
-    NumEp = IfDesc->NumEndpoints;\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
+    }\r
\r
+    IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+  }\r
+\r
+  InputContext->InputControlContext.Dword2 |= BIT0;\r
+  InputContext->Slot.ContextEntries         = MaxDci;\r
+  //\r
+  // configure endpoint\r
+  //\r
+  ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+  PhyAddr  = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
+  CmdTrbCfgEP.CycleBit = 1;\r
+  CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
+  CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
+  DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));\r
+  Status = XhcCmdTransfer (\r
+             Xhc,\r
+             (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+             XHC_GENERIC_TIMEOUT,\r
+             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));\r
+  } else {\r
+    Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Stop endpoint through XHCI's Stop_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           Stop endpoint successfully.\r
+  @retval Others                Failed to stop endpoint.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcStopEndpoint (\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_STOP_ENDPOINT         CmdTrbStopED;\r
+\r
+  DEBUG ((EFI_D_INFO, "XhcStopEndpoint: 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 (&CmdTrbStopED, sizeof (CmdTrbStopED));\r
+  CmdTrbStopED.CycleBit = 1;\r
+  CmdTrbStopED.Type     = TRB_TYPE_STOP_ENDPOINT;\r
+  CmdTrbStopED.EDID     = Dci;\r
+  CmdTrbStopED.SlotId   = SlotId;\r
+  Status = XhcCmdTransfer (\r
+             Xhc,\r
+             (TRB_TEMPLATE *) (UINTN) &CmdTrbStopED,\r
+             XHC_GENERIC_TIMEOUT,\r
+             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status));\r
+  }\r
+\r
+  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
+  @param  Xhc           The XHCI Instance.\r
+  @param  SlotId        The slot id to be configured.\r
+  @param  DeviceSpeed   The device's speed.\r
+  @param  ConfigDesc    The pointer to the usb device configuration descriptor.\r
+  @param  Request       USB device request to send.\r
+\r
+  @retval EFI_SUCCESS   Successfully set interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetInterface (\r
+  IN USB_XHCI_INSTANCE        *Xhc,\r
+  IN UINT8                    SlotId,\r
+  IN UINT8                    DeviceSpeed,\r
+  IN USB_CONFIG_DESCRIPTOR    *ConfigDesc,\r
+  IN EFI_USB_DEVICE_REQUEST   *Request\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDescActive;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDescSet;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDesc;\r
+  USB_ENDPOINT_DESCRIPTOR     *EpDesc;\r
+  UINTN                       NumEp;\r
+  UINTN                       EpIndex;\r
+  UINT8                       EpAddr;\r
+  UINT8                       Direction;\r
+  UINT8                       Dci;\r
+  UINT8                       MaxDci;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
+  VOID                        *RingSeg;\r
+\r
+  CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
+  INPUT_CONTEXT               *InputContext;\r
+  DEVICE_CONTEXT              *OutputContext;\r
+  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  InputContext  = Xhc->UsbDevContext[SlotId].InputContext;\r
+  OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+  //\r
+  // XHCI 4.6.6 Configure Endpoint\r
+  // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+  // Context and Add Context flags as follows:\r
+  // 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop\r
+  // Context and Add Context flags to '0'.\r
+  //\r
+  // Except the interface indicated by Reqeust->Index, no impact to other interfaces.\r
+  // So the default Drop Context and Add Context flags can be '0' to cover 1).\r
+  //\r
+  ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
+  CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));\r
+\r
+  ASSERT (ConfigDesc != NULL);\r
+\r
+  MaxDci = 0;\r
 \r
-    EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
+  IfDescActive = NULL;\r
+  IfDescSet = NULL;\r
+\r
+  IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
+  while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\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
+          // Find out the active interface descriptor.\r
+          //\r
+          IfDescActive = IfDesc;\r
+        } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {\r
+          //\r
+          // Find out the interface descriptor to set.\r
+          //\r
+          IfDescSet = IfDesc;\r
+        }\r
+      }\r
+    }\r
+    IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+  }\r
+\r
+  //\r
+  // XHCI 4.6.6 Configure Endpoint\r
+  // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+  // Context and Add Context flags as follows:\r
+  // 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set\r
+  // the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.\r
+  // 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set\r
+  // the Drop Context flag to '1' and Add Context flag to '0'.\r
+  // 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context\r
+  // and Add Context flags shall be set to '1'.\r
+  //\r
+  // Below codes are to cover 2), 3) and 4).\r
+  //\r
+\r
+  if ((IfDescActive != NULL) && (IfDescSet != NULL)) {\r
+    NumEp = IfDescActive->NumEndpoints;\r
+    EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1);\r
     for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
       while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
         EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
       }\r
 \r
-      EpAddr    = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
-      Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\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
       Dci = XhcEndpointToDci (EpAddr, Direction);\r
       ASSERT (Dci < 32);\r
       if (Dci > MaxDci) {\r
         MaxDci = Dci;\r
       }\r
+      //\r
+      // XHCI 4.3.6 - Setting Alternate Interfaces\r
+      // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.\r
+      //\r
+      Status = XhcStopEndpoint (Xhc, SlotId, Dci);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      //\r
+      // XHCI 4.3.6 - Setting Alternate Interfaces\r
+      // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.\r
+      //\r
+      if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {\r
+        RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;\r
+        if (RingSeg != NULL) {\r
+          UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
+        }\r
+        FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);\r
+        Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;\r
+      }\r
 \r
-      InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
-      InputContext->EP[Dci-1].MaxPacketSize     = EpDesc->MaxPacketSize;\r
+      //\r
+      // Set the Drop Context flag to '1'.\r
+      //\r
+      InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);\r
 \r
-      if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
-        //\r
-        // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
-        //\r
-        InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
-      } else {\r
-        InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
-      }\r
+      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+    }\r
 \r
-      switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
-        case USB_ENDPOINT_BULK:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
-          }\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate\r
+    // Interface setting, to '0'.\r
+    //\r
+    // The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.\r
+    //\r
 \r
-          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-          if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
-            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
-          }\r
-\r
-          break;\r
-        case USB_ENDPOINT_ISO:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 0;\r
-            InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 0;\r
-            InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
-          }\r
-          break;\r
-        case USB_ENDPOINT_INTERRUPT:\r
-          if (Direction == EfiUsbDataIn) {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
-          } else {\r
-            InputContext->EP[Dci-1].CErr   = 3;\r
-            InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
-          }\r
-          InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-          InputContext->EP[Dci-1].MaxESITPayload   = EpDesc->MaxPacketSize;\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 4) For each endpoint enabled by the Configure Endpoint Command:\r
+    //   a. Allocate a Transfer Ring.\r
+    //   b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.\r
+    //   c. Initialize the Endpoint Context data structure.\r
+    //\r
+    Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);\r
+    if (Dci > MaxDci) {\r
+      MaxDci = Dci;\r
+    }\r
+\r
+    InputContext->InputControlContext.Dword2 |= BIT0;\r
+    InputContext->Slot.ContextEntries         = MaxDci;\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 5) Issue and successfully complete a Configure Endpoint Command.\r
+    //\r
+    ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+    PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+    CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+    CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
+    CmdTrbCfgEP.CycleBit = 1;\r
+    CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
+    CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
+    DEBUG ((EFI_D_INFO, "SetInterface: Configure Endpoint\n"));\r
+    Status = XhcCmdTransfer (\r
+               Xhc,\r
+               (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+               XHC_GENERIC_TIMEOUT,\r
+               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "SetInterface: Config Endpoint Failed, Status = %r\n", Status));\r
+    } else {\r
+      //\r
+      // Update the active AlternateSetting.\r
+      //\r
+      Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set interface through XHCI's Configure_Endpoint cmd.\r
+\r
+  @param  Xhc           The XHCI Instance.\r
+  @param  SlotId        The slot id to be configured.\r
+  @param  DeviceSpeed   The device's speed.\r
+  @param  ConfigDesc    The pointer to the usb device configuration descriptor.\r
+  @param  Request       USB device request to send.\r
+\r
+  @retval EFI_SUCCESS   Successfully set interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetInterface64 (\r
+  IN USB_XHCI_INSTANCE        *Xhc,\r
+  IN UINT8                    SlotId,\r
+  IN UINT8                    DeviceSpeed,\r
+  IN USB_CONFIG_DESCRIPTOR    *ConfigDesc,\r
+  IN EFI_USB_DEVICE_REQUEST   *Request\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDescActive;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDescSet;\r
+  USB_INTERFACE_DESCRIPTOR    *IfDesc;\r
+  USB_ENDPOINT_DESCRIPTOR     *EpDesc;\r
+  UINTN                       NumEp;\r
+  UINTN                       EpIndex;\r
+  UINT8                       EpAddr;\r
+  UINT8                       Direction;\r
+  UINT8                       Dci;\r
+  UINT8                       MaxDci;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
+  VOID                        *RingSeg;\r
+\r
+  CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
+  INPUT_CONTEXT_64            *InputContext;\r
+  DEVICE_CONTEXT_64           *OutputContext;\r
+  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  InputContext  = Xhc->UsbDevContext[SlotId].InputContext;\r
+  OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+  //\r
+  // XHCI 4.6.6 Configure Endpoint\r
+  // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+  // Context and Add Context flags as follows:\r
+  // 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop\r
+  // Context and Add Context flags to '0'.\r
+  //\r
+  // Except the interface indicated by Reqeust->Index, no impact to other interfaces.\r
+  // So the default Drop Context and Add Context flags can be '0' to cover 1).\r
+  //\r
+  ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+  CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT_64));\r
+\r
+  ASSERT (ConfigDesc != NULL);\r
+\r
+  MaxDci = 0;\r
+\r
+  IfDescActive = NULL;\r
+  IfDescSet = NULL;\r
+\r
+  IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
+  while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\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
-          // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+          // Find out the active interface descriptor.\r
           //\r
-          if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
-            Interval = EpDesc->Interval;\r
-            //\r
-            // Hard code the interval to MAX first, need calculate through the bInterval field of Endpoint descriptor.\r
-            //\r
-            InputContext->EP[Dci-1].Interval = 6;\r
-          } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
-            Interval = EpDesc->Interval;\r
-            ASSERT (Interval >= 1 && Interval <= 16);\r
-            //\r
-            // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
-            //\r
-            InputContext->EP[Dci-1].Interval         = Interval - 1;\r
-            InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
-            InputContext->EP[Dci-1].MaxESITPayload   = 0x0002;\r
-            InputContext->EP[Dci-1].MaxBurstSize     = 0x0;\r
-            InputContext->EP[Dci-1].CErr             = 3;\r
-          }\r
-\r
-          if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
-            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
-          }\r
-          break;\r
-\r
-        case USB_ENDPOINT_CONTROL:\r
-        default:\r
-          ASSERT (0);\r
-          break;\r
+          IfDescActive = IfDesc;\r
+        } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {\r
+          //\r
+          // Find out the interface descriptor to set.\r
+          //\r
+          IfDescSet = IfDesc;\r
+        }\r
       }\r
-\r
-      PhyAddr  = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
-      PhyAddr &= ~(0x0F);\r
-      PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
-      InputContext->EP[Dci-1].PtrLo = PhyAddr;\r
-      InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
-\r
-      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
     }\r
     IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
   }\r
 \r
-  InputContext->InputControlContext.Dword2 |= BIT0;\r
-  InputContext->Slot.ContextEntries         = MaxDci;\r
   //\r
-  // configure endpoint\r
+  // XHCI 4.6.6 Configure Endpoint\r
+  // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+  // Context and Add Context flags as follows:\r
+  // 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set\r
+  // the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.\r
+  // 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set\r
+  // the Drop Context flag to '1' and Add Context flag to '0'.\r
+  // 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context\r
+  // and Add Context flags shall be set to '1'.\r
   //\r
-  ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
-  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
-  CmdTrbCfgEP.CycleBit = 1;\r
-  CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
-  CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
-  DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));\r
-  Status = XhcCmdTransfer (\r
-             Xhc,\r
-             (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
-             XHC_GENERIC_TIMEOUT,\r
-             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
-             );\r
-  ASSERT_EFI_ERROR(Status);\r
+  // Below codes are to cover 2), 3) and 4).\r
+  //\r
+\r
+  if ((IfDescActive != NULL) && (IfDescSet != NULL)) {\r
+    NumEp = IfDescActive->NumEndpoints;\r
+    EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1);\r
+    for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
+      while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
+        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
+      Dci = XhcEndpointToDci (EpAddr, Direction);\r
+      ASSERT (Dci < 32);\r
+      if (Dci > MaxDci) {\r
+        MaxDci = Dci;\r
+      }\r
+      //\r
+      // XHCI 4.3.6 - Setting Alternate Interfaces\r
+      // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.\r
+      //\r
+      Status = XhcStopEndpoint (Xhc, SlotId, Dci);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      //\r
+      // XHCI 4.3.6 - Setting Alternate Interfaces\r
+      // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.\r
+      //\r
+      if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {\r
+        RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;\r
+        if (RingSeg != NULL) {\r
+          UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
+        }\r
+        FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);\r
+        Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;\r
+      }\r
+\r
+      //\r
+      // Set the Drop Context flag to '1'.\r
+      //\r
+      InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);\r
+\r
+      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+    }\r
+\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate\r
+    // Interface setting, to '0'.\r
+    //\r
+    // The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.\r
+    //\r
+\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 4) For each endpoint enabled by the Configure Endpoint Command:\r
+    //   a. Allocate a Transfer Ring.\r
+    //   b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.\r
+    //   c. Initialize the Endpoint Context data structure.\r
+    //\r
+    Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);\r
+    if (Dci > MaxDci) {\r
+      MaxDci = Dci;\r
+    }\r
+\r
+    InputContext->InputControlContext.Dword2 |= BIT0;\r
+    InputContext->Slot.ContextEntries         = MaxDci;\r
+    //\r
+    // XHCI 4.3.6 - Setting Alternate Interfaces\r
+    // 5) Issue and successfully complete a Configure Endpoint Command.\r
+    //\r
+    ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+    PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+    CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+    CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
+    CmdTrbCfgEP.CycleBit = 1;\r
+    CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
+    CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
+    DEBUG ((EFI_D_INFO, "SetInterface64: Configure Endpoint\n"));\r
+    Status = XhcCmdTransfer (\r
+               Xhc,\r
+               (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+               XHC_GENERIC_TIMEOUT,\r
+               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status));\r
+    } else {\r
+      //\r
+      // Update the active AlternateSetting.\r
+      //\r
+      Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;\r
+    }\r
+  }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.\r
 \r
@@ -2652,6 +3701,7 @@ XhcEvaluateContext (
   CMD_TRB_EVALUATE_CONTEXT    CmdTrbEvalu;\r
   EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
   INPUT_CONTEXT               *InputContext;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
 \r
@@ -2665,8 +3715,9 @@ XhcEvaluateContext (
   InputContext->EP[0].MaxPacketSize         = MaxPacketSize;\r
 \r
   ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));\r
-  CmdTrbEvalu.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbEvalu.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+  CmdTrbEvalu.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbEvalu.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbEvalu.CycleBit = 1;\r
   CmdTrbEvalu.Type     = TRB_TYPE_EVALU_CONTXT;\r
   CmdTrbEvalu.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2677,8 +3728,9 @@ XhcEvaluateContext (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status));\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -2704,6 +3756,7 @@ XhcEvaluateContext64 (
   CMD_TRB_EVALUATE_CONTEXT    CmdTrbEvalu;\r
   EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
   INPUT_CONTEXT_64            *InputContext;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
 \r
@@ -2717,8 +3770,9 @@ XhcEvaluateContext64 (
   InputContext->EP[0].MaxPacketSize         = MaxPacketSize;\r
 \r
   ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));\r
-  CmdTrbEvalu.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbEvalu.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+  CmdTrbEvalu.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbEvalu.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbEvalu.CycleBit = 1;\r
   CmdTrbEvalu.Type     = TRB_TYPE_EVALU_CONTXT;\r
   CmdTrbEvalu.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2729,8 +3783,9 @@ XhcEvaluateContext64 (
              XHC_GENERIC_TIMEOUT,\r
              (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
              );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", Status));\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -2757,11 +3812,11 @@ XhcConfigHubContext (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-\r
   EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
   INPUT_CONTEXT               *InputContext;\r
   DEVICE_CONTEXT              *OutputContext;\r
   CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
   InputContext  = Xhc->UsbDevContext[SlotId].InputContext;\r
@@ -2784,8 +3839,9 @@ XhcConfigHubContext (
   InputContext->Slot.MTT     = MTT;\r
 \r
   ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
-  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbCfgEP.CycleBit = 1;\r
   CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
   CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2796,8 +3852,9 @@ XhcConfigHubContext (
               XHC_GENERIC_TIMEOUT,\r
               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
               );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status));\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -2823,11 +3880,11 @@ XhcConfigHubContext64 (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-\r
   EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
   INPUT_CONTEXT_64            *InputContext;\r
   DEVICE_CONTEXT_64           *OutputContext;\r
   CMD_TRB_CONFIG_ENDPOINT     CmdTrbCfgEP;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
   InputContext  = Xhc->UsbDevContext[SlotId].InputContext;\r
@@ -2850,8 +3907,9 @@ XhcConfigHubContext64 (
   InputContext->Slot.MTT     = MTT;\r
 \r
   ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
-  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (InputContext);\r
-  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (InputContext);\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+  CmdTrbCfgEP.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
+  CmdTrbCfgEP.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
   CmdTrbCfgEP.CycleBit = 1;\r
   CmdTrbCfgEP.Type     = TRB_TYPE_CON_ENDPOINT;\r
   CmdTrbCfgEP.SlotId   = Xhc->UsbDevContext[SlotId].SlotId;\r
@@ -2862,8 +3920,9 @@ XhcConfigHubContext64 (
               XHC_GENERIC_TIMEOUT,\r
               (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
               );\r
-  ASSERT (!EFI_ERROR(Status));\r
-\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcConfigHubContext64: Config Endpoint Failed, Status = %r\n", Status));\r
+  }\r
   return Status;\r
 }\r
 \r