]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciPei / EhciSched.c
index 8e9dad12d2adef1401ee98d6f60de7db8d25b86a..8eb432dfc31d5466df66fce81e20a9a2b1befd75 100644 (file)
@@ -2,16 +2,9 @@
 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
 which is used to enable recovery function from USB Drivers.\r
 \r
-Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
-  \r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions\r
-of the BSD License which accompanies this distribution.  The\r
-full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -19,7 +12,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 /**\r
   Create helper QTD/QH for the EHCI device.\r
-  \r
+\r
   @param  Ehc         The EHCI device.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for helper QTD/QH.\r
@@ -95,7 +88,7 @@ EhcCreateHelpQ (
 \r
 /**\r
   Initialize the schedule data structure such as frame list.\r
-  \r
+\r
   @param  Ehc                   The EHCI device to init schedule data for.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to init schedule data.\r
@@ -107,11 +100,13 @@ EhcInitSched (
   IN PEI_USB2_HC_DEV      *Ehc\r
   )\r
 {\r
+  VOID                  *Buf;\r
   EFI_PHYSICAL_ADDRESS  PhyAddr;\r
   VOID                  *Map;\r
   UINTN                 Index;\r
   UINT32                *Desc;\r
   EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  PciAddr;\r
 \r
   //\r
   // First initialize the periodical schedule data:\r
@@ -124,15 +119,19 @@ EhcInitSched (
   // The Frame List ocupies 4K bytes,\r
   // and must be aligned on 4-Kbyte boundaries.\r
   //\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
+             Ehc->IoMmu,\r
              1,\r
-             &PhyAddr\r
+             &Buf,\r
+             &PhyAddr,\r
+             &Map\r
              );\r
 \r
-  Map = NULL;\r
-  Ehc->PeriodFrameHost  = (VOID *)(UINTN)PhyAddr;\r
-  Ehc->PeriodFrame      = (VOID *)(UINTN)PhyAddr;\r
+  if (EFI_ERROR (Status) || (Buf == NULL)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ehc->PeriodFrame      = Buf;\r
   Ehc->PeriodFrameMap   = Map;\r
   Ehc->High32bitAddr    = EHC_HIGH_32BIT (PhyAddr);\r
 \r
@@ -156,31 +155,32 @@ EhcInitSched (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   //\r
   // Initialize the frame list entries then set the registers\r
   //\r
   Desc = (UINT32 *) Ehc->PeriodFrame;\r
-\r
+  PciAddr  = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
   for (Index = 0; Index < EHC_FRAME_LEN; Index++) {\r
-    Desc[Index] = QH_LINK (Ehc->PeriodOne, EHC_TYPE_QH, FALSE);\r
+    Desc[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
   }\r
 \r
-  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame));\r
+  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));\r
 \r
   //\r
   // Second initialize the asynchronous schedule:\r
   // Only need to set the AsynListAddr register to\r
   // the reclamation header\r
   //\r
-  EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (Ehc->ReclaimHead));\r
+  PciAddr  = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
+  EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
   Free the schedule data. It may be partially initialized.\r
-  \r
-  @param  Ehc   The EHCI device. \r
+\r
+  @param  Ehc   The EHCI device.\r
 \r
 **/\r
 VOID\r
@@ -192,26 +192,27 @@ EhcFreeSched (
   EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, 0);\r
 \r
   if (Ehc->PeriodOne != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
     Ehc->PeriodOne = NULL;\r
   }\r
 \r
   if (Ehc->ReclaimHead != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
     Ehc->ReclaimHead = NULL;\r
   }\r
 \r
   if (Ehc->ShortReadStop != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (PEI_EHC_QTD));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ShortReadStop, sizeof (PEI_EHC_QTD));\r
     Ehc->ShortReadStop = NULL;\r
   }\r
 \r
   if (Ehc->MemPool != NULL) {\r
-    UsbHcFreeMemPool (Ehc->MemPool);\r
+    UsbHcFreeMemPool (Ehc, Ehc->MemPool);\r
     Ehc->MemPool = NULL;\r
   }\r
 \r
   if (Ehc->PeriodFrame != NULL) {\r
+    IoMmuFreeBuffer (Ehc->IoMmu, 1, Ehc->PeriodFrame, Ehc->PeriodFrameMap);\r
     Ehc->PeriodFrame = NULL;\r
   }\r
 }\r
@@ -222,7 +223,7 @@ EhcFreeSched (
   due to its interfaces. This simplifies the AsynList\r
   management: A reclamation header is always linked to\r
   the AsyncListAddr, the only active QH is appended to it.\r
-  \r
+\r
   @param  Ehc   The EHCI device.\r
   @param  Qh    The queue head to link.\r
 \r
@@ -252,7 +253,7 @@ EhcLinkQhToAsync (
 /**\r
   Unlink a queue head from the asynchronous schedule list.\r
   Need to synchronize with hardware.\r
-  \r
+\r
   @param  Ehc   The EHCI device.\r
   @param  Qh    The queue head to unlink.\r
 \r
@@ -283,171 +284,13 @@ EhcUnlinkQhFromAsync (
   // Set and wait the door bell to synchronize with the hardware\r
   //\r
   EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT);\r
-  \r
-  return;\r
-}\r
-\r
-/**\r
-  Link a queue head for interrupt transfer to the periodic\r
-  schedule frame list. This code is very much the same as\r
-  that in UHCI.\r
-  \r
-  @param  Ehc   The EHCI device.\r
-  @param  Qh    The queue head to link.\r
-\r
-**/\r
-VOID\r
-EhcLinkQhToPeriod (\r
-  IN PEI_USB2_HC_DEV      *Ehc,\r
-  IN PEI_EHC_QH           *Qh\r
-  )\r
-{\r
-  UINT32                  *Frames;\r
-  UINTN                   Index;\r
-  PEI_EHC_QH              *Prev;\r
-  PEI_EHC_QH              *Next;\r
-\r
-  Frames = Ehc->PeriodFrame;\r
-\r
-  for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {\r
-    //\r
-    // First QH can't be NULL because we always keep PeriodOne\r
-    // heads on the frame list\r
-    //\r
-    ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));\r
-    Next  = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);\r
-    Prev  = NULL;\r
-\r
-    //\r
-    // Now, insert the queue head (Qh) into this frame:\r
-    // 1. Find a queue head with the same poll interval, just insert\r
-    //    Qh after this queue head, then we are done.\r
-    //\r
-    // 2. Find the position to insert the queue head into:\r
-    //      Previous head's interval is bigger than Qh's\r
-    //      Next head's interval is less than Qh's\r
-    //    Then, insert the Qh between then\r
-    //\r
-    while (Next->Interval > Qh->Interval) {\r
-      Prev  = Next;\r
-      Next  = Next->NextQh;\r
-    }\r
-\r
-    ASSERT (Next != NULL);\r
-\r
-    //\r
-    // The entry may have been linked into the frame by early insertation.\r
-    // For example: if insert a Qh with Qh.Interval == 4, and there is a Qh\r
-    // with Qh.Interval == 8 on the frame. If so, we are done with this frame.\r
-    // It isn't necessary to compare all the QH with the same interval to\r
-    // Qh. This is because if there is other QH with the same interval, Qh\r
-    // should has been inserted after that at Frames[0] and at Frames[0] it is\r
-    // impossible for (Next == Qh)\r
-    //\r
-    if (Next == Qh) {\r
-      continue;\r
-    }\r
-\r
-    if (Next->Interval == Qh->Interval) {\r
-      //\r
-      // If there is a QH with the same interval, it locates at\r
-      // Frames[0], and we can simply insert it after this QH. We\r
-      // are all done.\r
-      //\r
-      ASSERT ((Index == 0) && (Qh->NextQh == NULL));\r
-\r
-      Prev                    = Next;\r
-      Next                    = Next->NextQh;\r
-\r
-      Qh->NextQh              = Next;\r
-      Prev->NextQh            = Qh;\r
-\r
-      Qh->QhHw.HorizonLink    = Prev->QhHw.HorizonLink;\r
-      Prev->QhHw.HorizonLink  = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
-      break;\r
-    }\r
-    \r
-    //\r
-    // OK, find the right position, insert it in. If Qh's next\r
-    // link has already been set, it is in position. This is\r
-    // guarranted by 2^n polling interval.\r
-    //\r
-    if (Qh->NextQh == NULL) {\r
-      Qh->NextQh              = Next;\r
-      Qh->QhHw.HorizonLink    = QH_LINK (Next, EHC_TYPE_QH, FALSE);\r
-    }\r
-\r
-    if (Prev == NULL) {\r
-      Frames[Index] = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
-    } else {\r
-      Prev->NextQh            = Qh;\r
-      Prev->QhHw.HorizonLink  = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  Unlink an interrupt queue head from the periodic \r
-  schedule frame list.\r
-  \r
-  @param  Ehc   The EHCI device.\r
-  @param  Qh    The queue head to unlink.\r
-\r
-**/\r
-VOID\r
-EhcUnlinkQhFromPeriod (\r
-  IN PEI_USB2_HC_DEV      *Ehc,\r
-  IN PEI_EHC_QH           *Qh\r
-  )\r
-{\r
-  UINT32                  *Frames;\r
-  UINTN                   Index;\r
-  PEI_EHC_QH              *Prev;\r
-  PEI_EHC_QH              *This;\r
-\r
-  Frames = Ehc->PeriodFrame;\r
-\r
-  for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {\r
-    //\r
-    // Frame link can't be NULL because we always keep PeroidOne\r
-    // on the frame list\r
-    //\r
-    ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));\r
-    This  = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);\r
-    Prev  = NULL;\r
-\r
-    //\r
-    // Walk through the frame's QH list to find the\r
-    // queue head to remove\r
-    //\r
-    while ((This != NULL) && (This != Qh)) {\r
-      Prev  = This;\r
-      This  = This->NextQh;\r
-    }\r
-    \r
-    //\r
-    // Qh may have already been unlinked from this frame\r
-    // by early action. See the comments in EhcLinkQhToPeriod.\r
-    //\r
-    if (This == NULL) {\r
-      continue;\r
-    }\r
 \r
-    if (Prev == NULL) {\r
-      //\r
-      // Qh is the first entry in the frame\r
-      //\r
-      Frames[Index] = Qh->QhHw.HorizonLink;\r
-    } else {\r
-      Prev->NextQh            = Qh->NextQh;\r
-      Prev->QhHw.HorizonLink  = Qh->QhHw.HorizonLink;\r
-    }\r
-  }\r
+  return;\r
 }\r
 \r
 /**\r
   Check the URB's execution result and update the URB's\r
-  result accordingly. \r
+  result accordingly.\r
 \r
   @param Ehc   The EHCI device.\r
   @param Urb   The URB to check result.\r
@@ -508,13 +351,13 @@ EhcCheckUrbResult (
 \r
       Finished = TRUE;\r
       goto ON_EXIT;\r
-      \r
+\r
     } else if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {\r
       //\r
       // The QTD is still active, no need to check furthur.\r
       //\r
       Urb->Result |= EFI_USB_ERR_NOTEXECUTE;\r
-      \r
+\r
       Finished = FALSE;\r
       goto ON_EXIT;\r
 \r
@@ -537,7 +380,7 @@ EhcCheckUrbResult (
         // Status Stage of the setup transfer to get the finial result\r
         //\r
         if (QtdHw->AltNext == QTD_LINK (Ehc->ShortReadStop, FALSE)) {\r
-          \r
+\r
           Finished = TRUE;\r
           goto ON_EXIT;\r
         }\r
@@ -562,7 +405,7 @@ ON_EXIT:
 \r
 /**\r
   Execute the transfer by polling the URB. This is a synchronous operation.\r
-  \r
+\r
   @param  Ehc               The EHCI device.\r
   @param  Urb               The URB to execute.\r
   @param  TimeOut           The time to wait before abort, in millisecond.\r
@@ -583,19 +426,29 @@ EhcExecTransfer (
   UINTN                   Index;\r
   UINTN                   Loop;\r
   BOOLEAN                 Finished;\r
+  BOOLEAN                 InfiniteLoop;\r
 \r
   Status    = EFI_SUCCESS;\r
-  Loop      = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1;\r
-  Finished  = FALSE;\r
+  Loop      = TimeOut * EHC_1_MILLISECOND;\r
+  Finished     = FALSE;\r
+  InfiniteLoop = FALSE;\r
+\r
+  //\r
+  // If Timeout is 0, then the caller must wait for the function to be completed\r
+  // until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
+  //\r
+  if (TimeOut == 0) {\r
+    InfiniteLoop = TRUE;\r
+  }\r
 \r
-  for (Index = 0; Index < Loop; Index++) {\r
+  for (Index = 0; InfiniteLoop || (Index < Loop); Index++) {\r
     Finished = EhcCheckUrbResult (Ehc, Urb);\r
 \r
     if (Finished) {\r
       break;\r
     }\r
 \r
-    MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);\r
+    MicroSecondDelay (EHC_1_MICROSECOND);\r
   }\r
 \r
   if (!Finished) {\r
@@ -607,265 +460,3 @@ EhcExecTransfer (
   return Status;\r
 }\r
 \r
-/**\r
-  Delete a single asynchronous interrupt transfer for\r
-  the device and endpoint.\r
-  \r
-  @param  Ehc               The EHCI device.\r
-  @param  DevAddr           The address of the target device.\r
-  @param  EpNum             The endpoint of the target.\r
-  @param  DataToggle        Return the next data toggle to use.\r
-\r
-  @retval EFI_NOT_FOUND     No transfer for the device is found.\r
-  @retval EFI_SUCCESS       An asynchronous transfer is removed.\r
-\r
-**/\r
-EFI_STATUS\r
-EhciDelAsyncIntTransfer (\r
-  IN  PEI_USB2_HC_DEV     *Ehc,\r
-  IN  UINT8               DevAddr,\r
-  IN  UINT8               EpNum,  \r
-  OUT UINT8               *DataToggle\r
-  )\r
-{\r
-  EFI_LIST_ENTRY          *Entry;\r
-  EFI_LIST_ENTRY          *Next;\r
-  PEI_URB                 *Urb;\r
-  EFI_USB_DATA_DIRECTION  Direction;\r
-\r
-  Direction = (((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);\r
-  EpNum    &= 0x0F;\r
-\r
-  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {\r
-    Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);\r
-\r
-    if ((Urb->Ep.DevAddr == DevAddr) && (Urb->Ep.EpAddr == EpNum) && \r
-        (Urb->Ep.Direction == Direction)) {\r
-      //\r
-      // Check the URB status to retrieve the next data toggle\r
-      // from the associated queue head.\r
-      //\r
-      EhcCheckUrbResult (Ehc, Urb);\r
-      *DataToggle = Urb->DataToggle;\r
-\r
-      EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);\r
-      RemoveEntryList (&Urb->UrbList);\r
-\r
-      EhcFreeUrb (Ehc, Urb);\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  Remove all the asynchronous interrutp transfers.\r
-  \r
-  @param  Ehc         The EHCI device.\r
-\r
-**/\r
-VOID\r
-EhciDelAllAsyncIntTransfers (\r
-  IN PEI_USB2_HC_DEV      *Ehc\r
-  )\r
-{\r
-  EFI_LIST_ENTRY          *Entry;\r
-  EFI_LIST_ENTRY          *Next;\r
-  PEI_URB                 *Urb;\r
-\r
-  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {\r
-    Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);\r
-\r
-    EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);\r
-    RemoveEntryList (&Urb->UrbList);\r
-\r
-    EhcFreeUrb (Ehc, Urb);\r
-  }\r
-}\r
-\r
-/**\r
-  Flush data from PCI controller specific address to mapped system \r
-  memory address.\r
-  \r
-  @param  Ehc               The EHCI device.\r
-  @param  Urb               The URB to unmap.\r
-\r
-  @retval EFI_DEVICE_ERROR  Fail to flush data to mapped system memory.\r
-  @retval EFI_SUCCESS       Success to flush data to mapped system memory.\r
-\r
-**/\r
-EFI_STATUS\r
-EhcFlushAsyncIntMap (\r
-  IN  PEI_USB2_HC_DEV     *Ehc,\r
-  IN  PEI_URB             *Urb\r
-  )\r
-{\r
-  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
-\r
-  Urb->DataMap  = NULL;\r
-  PhyAddr       =  (EFI_PHYSICAL_ADDRESS) (UINTN) Urb->Data;\r
-  Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Update the queue head for next round of asynchronous transfer.\r
-\r
-  @param Urb   The URB to update.\r
-\r
-**/\r
-VOID\r
-EhcUpdateAsyncRequest (\r
-  IN PEI_URB              *Urb\r
-  )\r
-{\r
-  EFI_LIST_ENTRY          *Entry;\r
-  PEI_EHC_QTD             *FirstQtd;\r
-  QH_HW                   *QhHw;\r
-  PEI_EHC_QTD             *Qtd;\r
-  QTD_HW                  *QtdHw;\r
-  UINTN                   Index;\r
-\r
-  Qtd = NULL;\r
-\r
-  if (Urb->Result == EFI_USB_NOERROR) {\r
-    FirstQtd = NULL;\r
-\r
-    EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {\r
-      Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);\r
-\r
-      if (FirstQtd == NULL) {\r
-        FirstQtd = Qtd;\r
-      }\r
-      \r
-      //\r
-      // Update the QTD for next round of transfer. Host control\r
-      // may change dt/Total Bytes to Transfer/C_Page/Cerr/Status/\r
-      // Current Offset. These fields need to be updated. DT isn't\r
-      // used by interrupt transfer. It uses DT in queue head.\r
-      // Current Offset is in Page[0], only need to reset Page[0]\r
-      // to initial data buffer.\r
-      //\r
-      QtdHw             = &Qtd->QtdHw;\r
-      QtdHw->Status     = QTD_STAT_ACTIVE;\r
-      QtdHw->ErrCnt     = QTD_MAX_ERR;\r
-      QtdHw->CurPage    = 0;\r
-      QtdHw->TotalBytes = (UINT32) Qtd->DataLen;\r
-      QtdHw->Page[0]    = EHC_LOW_32BIT (Qtd->Data);\r
-    }\r
-    \r
-    //\r
-    // Update QH for next round of transfer. Host control only\r
-    // touch the fields in transfer overlay area. Only need to\r
-    // zero out the overlay area and set NextQtd to the first\r
-    // QTD. DateToggle bit is left untouched.\r
-    //\r
-    QhHw              = &Urb->Qh->QhHw;\r
-    QhHw->CurQtd      = QTD_LINK (0, TRUE);\r
-    QhHw->AltQtd      = 0;\r
-\r
-    QhHw->Status      = 0;\r
-    QhHw->Pid         = 0;\r
-    QhHw->ErrCnt      = 0;\r
-    QhHw->CurPage     = 0;\r
-    QhHw->Ioc         = 0;\r
-    QhHw->TotalBytes  = 0;\r
-\r
-    for (Index = 0; Index < 5; Index++) {\r
-      QhHw->Page[Index]     = 0;\r
-      QhHw->PageHigh[Index] = 0;\r
-    }\r
-\r
-    QhHw->NextQtd = QTD_LINK (FirstQtd, FALSE);\r
-  }\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Remove all the asynchronous interrutp transfers.\r
-  \r
-  @param  Event         Interrupt event.\r
-  @param  Context       Pointer to PEI_USB2_HC_DEV.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EhcMoniteAsyncRequests (\r
-  IN EFI_EVENT            Event,\r
-  IN VOID                 *Context\r
-  )\r
-{\r
-  PEI_USB2_HC_DEV         *Ehc;\r
-  EFI_LIST_ENTRY          *Entry;\r
-  EFI_LIST_ENTRY          *Next;\r
-  BOOLEAN                 Finished;\r
-  UINT8                   *ProcBuf;\r
-  PEI_URB                 *Urb;\r
-  UINTN                   PageNumber;\r
-\r
-  Ehc     = (PEI_USB2_HC_DEV *) Context;\r
-\r
-  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {\r
-    Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);\r
-\r
-    //\r
-    // Check the result of URB execution. If it is still\r
-    // active, check the next one.\r
-    //\r
-    Finished = EhcCheckUrbResult (Ehc, Urb);\r
-\r
-    if (!Finished) {\r
-      continue;\r
-    }\r
-\r
-    //\r
-    // Flush any PCI posted write transactions from a PCI host \r
-    // bridge to system memory.\r
-    //\r
-    EhcFlushAsyncIntMap (Ehc, Urb);\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
-    // round of transfer. Ignore the data of this round.\r
-    //\r
-    ProcBuf = NULL;\r
-\r
-    if (Urb->Result == EFI_USB_NOERROR) {\r
-      ASSERT (Urb->Completed <= Urb->DataLen);\r
-      PageNumber =  Urb->Completed/PAGESIZE +1;\r
-      PeiServicesAllocatePages (\r
-        EfiBootServicesCode,\r
-        PageNumber,\r
-        (EFI_PHYSICAL_ADDRESS *)ProcBuf\r
-        );\r
-      if (ProcBuf == NULL) {\r
-        EhcUpdateAsyncRequest (Urb);\r
-        continue;\r
-      }\r
-\r
-      CopyMem (ProcBuf, Urb->Data, Urb->Completed);\r
-    }\r
-\r
-    EhcUpdateAsyncRequest (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
-    // interrupt transfer which is linked to the head of the\r
-    // list. This function scans from head to tail. So the\r
-    // re-submitted interrupt transfer's callback function\r
-    // will not be called again in this round. Don't touch this\r
-    // URB after the callback, it may have been removed by the\r
-    // callback.\r
-    //\r
-    if (Urb->Callback != NULL) {\r
-      (Urb->Callback) (ProcBuf, Urb->Completed, Urb->Context, Urb->Result);\r
-    }\r
-\r
-    if (ProcBuf != NULL) {\r
-    }\r
-  }\r
-}\r