]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / EhciSched.c
index 936a855f12c1b68423f8dd9a043eaa1f234cd4e8..fea6f47f4c04146e85cae140a9689dde97527403 100644 (file)
@@ -2,8 +2,8 @@
 \r
   EHCI transfer scheduling routines.\r
 \r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2018, 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
 http://opensource.org/licenses/bsd-license.php\r
@@ -34,11 +34,12 @@ EhcCreateHelpQ (
   EHC_QH                  *Qh;\r
   QH_HW                   *QhHw;\r
   EHC_QTD                 *Qtd;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\r
 \r
   //\r
   // Create an inactive Qtd to terminate the short packet read.\r
   //\r
-  Qtd = EhcCreateQtd (Ehc, NULL, 0, QTD_PID_INPUT, 0, 64);\r
+  Qtd = EhcCreateQtd (Ehc, NULL, NULL, 0, QTD_PID_INPUT, 0, 64);\r
 \r
   if (Qtd == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -68,10 +69,12 @@ EhcCreateHelpQ (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  PciAddr           = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));\r
   QhHw              = &Qh->QhHw;\r
-  QhHw->HorizonLink = QH_LINK (QhHw, EHC_TYPE_QH, FALSE);\r
+  QhHw->HorizonLink = QH_LINK (PciAddr + OFFSET_OF(EHC_QH, QhHw), EHC_TYPE_QH, FALSE);\r
   QhHw->Status      = QTD_STAT_HALTED;\r
   QhHw->ReclaimHead = 1;\r
+  Qh->NextQh        = Qh;\r
   Ehc->ReclaimHead  = Qh;\r
 \r
   //\r
@@ -114,8 +117,8 @@ EhcInitSched (
   UINTN                 Pages;\r
   UINTN                 Bytes;\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
@@ -156,10 +159,17 @@ EhcInitSched (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Ehc->PeriodFrameHost  = Buf;\r
-  Ehc->PeriodFrame      = (VOID *) ((UINTN) PhyAddr);\r
+  Ehc->PeriodFrame      = Buf;\r
   Ehc->PeriodFrameMap   = Map;\r
-  Ehc->High32bitAddr    = EHC_HIGH_32BIT (PhyAddr);\r
+\r
+  //\r
+  // Program the FRAMELISTBASE register with the low 32 bit addr\r
+  //\r
+  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));\r
+  //\r
+  // Program the CTRLDSSEGMENT register with the high 32 bit addr\r
+  //\r
+  EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, EHC_HIGH_32BIT (PhyAddr));\r
 \r
   //\r
   // Init memory pool management then create the helper\r
@@ -168,38 +178,73 @@ EhcInitSched (
   //\r
   Ehc->MemPool = UsbHcInitMemPool (\r
                    PciIo,\r
-                   EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT),\r
-                   Ehc->High32bitAddr\r
+                   Ehc->Support64BitDma,\r
+                   EHC_HIGH_32BIT (PhyAddr)\r
                    );\r
 \r
   if (Ehc->MemPool == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit1;\r
   }\r
 \r
   Status = EhcCreateHelpQ (Ehc);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ErrorExit;\r
   }\r
 \r
   //\r
   // Initialize the frame list entries then set the registers\r
   //\r
-  Desc = (UINT32 *) Ehc->PeriodFrame;\r
+  Ehc->PeriodFrameHost      = AllocateZeroPool (EHC_FRAME_LEN * sizeof (UINTN));\r
+  if (Ehc->PeriodFrameHost == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
+  }\r
+\r
+  PciAddr  = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));\r
 \r
   for (Index = 0; Index < EHC_FRAME_LEN; Index++) {\r
-    Desc[Index] = QH_LINK (Ehc->PeriodOne, EHC_TYPE_QH, FALSE);\r
+    //\r
+    // Store the pci bus address of the QH in period frame list which will be accessed by pci bus master.\r
+    //\r
+    ((UINT32 *)(Ehc->PeriodFrame))[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+    //\r
+    // Store the host address of the QH in period frame list which will be accessed by host.\r
+    //\r
+    ((UINTN *)(Ehc->PeriodFrameHost))[Index] = (UINTN)Ehc->PeriodOne;\r
   }\r
 \r
-  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame));\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 (EHC_QH));\r
+  EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));\r
   return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  if (Ehc->PeriodOne != NULL) {\r
+    UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));\r
+    Ehc->PeriodOne = NULL;\r
+  }\r
+\r
+  if (Ehc->ReclaimHead != NULL) {\r
+    UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));\r
+    Ehc->ReclaimHead = NULL;\r
+  }\r
+\r
+  if (Ehc->ShortReadStop != NULL) {\r
+    UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));\r
+    Ehc->ShortReadStop = NULL;\r
+  }\r
+\r
+ErrorExit1:\r
+  PciIo->FreeBuffer (PciIo, Pages, Buf);\r
+  PciIo->Unmap (PciIo, Map);\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -208,8 +253,6 @@ EhcInitSched (
 \r
   @param  Ehc                   The EHCI device.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcFreeSched (\r
@@ -250,11 +293,16 @@ EhcFreeSched (
     PciIo->FreeBuffer (\r
              PciIo,\r
              EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE),\r
-             Ehc->PeriodFrameHost\r
+             Ehc->PeriodFrame\r
              );\r
 \r
     Ehc->PeriodFrame = NULL;\r
   }\r
+\r
+  if (Ehc->PeriodFrameHost != NULL) {\r
+    FreePool (Ehc->PeriodFrameHost);\r
+    Ehc->PeriodFrameHost = NULL;\r
+  }\r
 }\r
 \r
 \r
@@ -268,8 +316,6 @@ EhcFreeSched (
   @param  Ehc                   The EHCI device.\r
   @param  Qh                    The queue head to link.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcLinkQhToAsync (\r
@@ -278,6 +324,7 @@ EhcLinkQhToAsync (
   )\r
 {\r
   EHC_QH                  *Head;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\r
 \r
   //\r
   // Append the queue head after the reclaim header, then\r
@@ -289,8 +336,10 @@ EhcLinkQhToAsync (
   Qh->NextQh              = Head->NextQh;\r
   Head->NextQh            = Qh;\r
 \r
-  Qh->QhHw.HorizonLink    = QH_LINK (Head, EHC_TYPE_QH, FALSE);;\r
-  Head->QhHw.HorizonLink  = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
+  PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh->NextQh, sizeof (EHC_QH));\r
+  Qh->QhHw.HorizonLink    = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+  PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));\r
+  Head->QhHw.HorizonLink  = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
 }\r
 \r
 \r
@@ -301,8 +350,6 @@ EhcLinkQhToAsync (
   @param  Ehc                   The EHCI device.\r
   @param  Qh                    The queue head to unlink.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcUnlinkQhFromAsync (\r
@@ -312,6 +359,7 @@ EhcUnlinkQhFromAsync (
 {\r
   EHC_QH                  *Head;\r
   EFI_STATUS              Status;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\r
 \r
   ASSERT (Ehc->ReclaimHead->NextQh == Qh);\r
 \r
@@ -325,7 +373,8 @@ EhcUnlinkQhFromAsync (
   Head->NextQh            = Qh->NextQh;\r
   Qh->NextQh              = NULL;\r
 \r
-  Head->QhHw.HorizonLink  = QH_LINK (Head, EHC_TYPE_QH, FALSE);\r
+  PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));\r
+  Head->QhHw.HorizonLink  = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
 \r
   //\r
   // Set and wait the door bell to synchronize with the hardware\r
@@ -346,8 +395,6 @@ EhcUnlinkQhFromAsync (
   @param  Ehc                   The EHCI device.\r
   @param  Qh                    The queue head to link.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcLinkQhToPeriod (\r
@@ -355,20 +402,18 @@ EhcLinkQhToPeriod (
   IN EHC_QH               *Qh\r
   )\r
 {\r
-  UINT32                  *Frames;\r
   UINTN                   Index;\r
   EHC_QH                  *Prev;\r
   EHC_QH                  *Next;\r
-\r
-  Frames = Ehc->PeriodFrame;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\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
+    ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));\r
+    Next  = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];\r
     Prev  = NULL;\r
 \r
     //\r
@@ -416,7 +461,8 @@ EhcLinkQhToPeriod (
       Prev->NextQh            = Qh;\r
 \r
       Qh->QhHw.HorizonLink    = Prev->QhHw.HorizonLink;\r
-      Prev->QhHw.HorizonLink  = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
+      PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));\r
+      Prev->QhHw.HorizonLink  = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
       break;\r
     }\r
 \r
@@ -427,14 +473,18 @@ EhcLinkQhToPeriod (
     //\r
     if (Qh->NextQh == NULL) {\r
       Qh->NextQh              = Next;\r
-      Qh->QhHw.HorizonLink    = QH_LINK (Next, EHC_TYPE_QH, FALSE);\r
+      PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Next, sizeof (EHC_QH));\r
+      Qh->QhHw.HorizonLink    = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
     }\r
 \r
+    PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));\r
+\r
     if (Prev == NULL) {\r
-      Frames[Index] = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
+      ((UINT32*)Ehc->PeriodFrame)[Index]     = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+      ((UINTN*)Ehc->PeriodFrameHost)[Index]  = (UINTN)Qh;\r
     } else {\r
       Prev->NextQh            = Qh;\r
-      Prev->QhHw.HorizonLink  = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
+      Prev->QhHw.HorizonLink  = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
     }\r
   }\r
 }\r
@@ -447,8 +497,6 @@ EhcLinkQhToPeriod (
   @param  Ehc                   The EHCI device.\r
   @param  Qh                    The queue head to unlink.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcUnlinkQhFromPeriod (\r
@@ -456,20 +504,17 @@ EhcUnlinkQhFromPeriod (
   IN EHC_QH               *Qh\r
   )\r
 {\r
-  UINT32                  *Frames;\r
   UINTN                   Index;\r
   EHC_QH                  *Prev;\r
   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
+    ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));\r
+    This  = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];\r
     Prev  = NULL;\r
 \r
     //\r
@@ -493,7 +538,8 @@ EhcUnlinkQhFromPeriod (
       //\r
       // Qh is the first entry in the frame\r
       //\r
-      Frames[Index] = Qh->QhHw.HorizonLink;\r
+      ((UINT32*)Ehc->PeriodFrame)[Index] = Qh->QhHw.HorizonLink;\r
+      ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh->NextQh;\r
     } else {\r
       Prev->NextQh            = Qh->NextQh;\r
       Prev->QhHw.HorizonLink  = Qh->QhHw.HorizonLink;\r
@@ -523,6 +569,7 @@ EhcCheckUrbResult (
   QTD_HW                  *QtdHw;\r
   UINT8                   State;\r
   BOOLEAN                 Finished;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\r
 \r
   ASSERT ((Ehc != NULL) && (Urb != NULL) && (Urb->Qh != NULL));\r
 \r
@@ -592,14 +639,15 @@ EhcCheckUrbResult (
         // ShortReadStop. If it is a setup transfer, need to check the\r
         // Status Stage of the setup transfer to get the finial result\r
         //\r
-        if (QtdHw->AltNext == QTD_LINK (Ehc->ShortReadStop, FALSE)) {\r
-          DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, break\n"));\r
+        PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));\r
+        if (QtdHw->AltNext == QTD_LINK (PciAddr, FALSE)) {\r
+          DEBUG ((EFI_D_VERBOSE, "EhcCheckUrbResult: Short packet read, break\n"));\r
 \r
           Finished = TRUE;\r
           goto ON_EXIT;\r
         }\r
 \r
-        DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, continue\n"));\r
+        DEBUG ((EFI_D_VERBOSE, "EhcCheckUrbResult: Short packet read, continue\n"));\r
       }\r
     }\r
   }\r
@@ -643,19 +691,30 @@ 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
+  Status       = EFI_SUCCESS;\r
+  Loop         = TimeOut * EHC_1_MILLISECOND;\r
+  Finished     = FALSE;\r
+  InfiniteLoop = FALSE;\r
 \r
-  for (Index = 0; Index < Loop; Index++) {\r
+  //\r
+  // According to UEFI spec section 16.2.4, If Timeout is 0, then the caller\r
+  // must wait for the function to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR\r
+  // is returned.\r
+  //\r
+  if (TimeOut == 0) {\r
+    InfiniteLoop = TRUE;\r
+  }\r
+\r
+  for (Index = 0; InfiniteLoop || (Index < Loop); Index++) {\r
     Finished = EhcCheckUrbResult (Ehc, Urb);\r
 \r
     if (Finished) {\r
       break;\r
     }\r
 \r
-    gBS->Stall (EHC_SYNC_POLL_INTERVAL);\r
+    gBS->Stall (EHC_1_MICROSECOND);\r
   }\r
 \r
   if (!Finished) {\r
@@ -734,8 +793,6 @@ EhciDelAsyncIntTransfer (
 \r
   @param  Ehc                   The EHCI device.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhciDelAllAsyncIntTransfers (\r
@@ -815,13 +872,13 @@ ON_ERROR:
 /**\r
   Update the queue head for next round of asynchronous transfer.\r
 \r
+  @param  Ehc                   The EHCI device.\r
   @param  Urb                   The URB to update.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 EhcUpdateAsyncRequest (\r
+  IN  USB2_HC_DEV         *Ehc,\r
   IN URB                  *Urb\r
   )\r
 {\r
@@ -831,6 +888,7 @@ EhcUpdateAsyncRequest (
   EHC_QTD                 *Qtd;\r
   QTD_HW                  *QtdHw;\r
   UINTN                   Index;\r
+  EFI_PHYSICAL_ADDRESS    PciAddr;\r
 \r
   Qtd = NULL;\r
 \r
@@ -857,7 +915,12 @@ EhcUpdateAsyncRequest (
       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
+      // calculate physical address by offset.\r
+      //\r
+      PciAddr = (UINTN)Urb->DataPhy + ((UINTN)Qtd->Data - (UINTN)Urb->Data);\r
+      QtdHw->Page[0]    = EHC_LOW_32BIT (PciAddr);\r
+      QtdHw->PageHigh[0]= EHC_HIGH_32BIT (PciAddr);\r
     }\r
 \r
     //\r
@@ -874,7 +937,7 @@ EhcUpdateAsyncRequest (
     QhHw->Pid         = 0;\r
     QhHw->ErrCnt      = 0;\r
     QhHw->CurPage     = 0;\r
-    QhHw->IOC         = 0;\r
+    QhHw->Ioc         = 0;\r
     QhHw->TotalBytes  = 0;\r
 \r
     for (Index = 0; Index < 5; Index++) {\r
@@ -882,7 +945,8 @@ EhcUpdateAsyncRequest (
       QhHw->PageHigh[Index] = 0;\r
     }\r
 \r
-    QhHw->NextQtd = QTD_LINK (FirstQtd, FALSE);\r
+    PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, FirstQtd, sizeof (EHC_QTD));\r
+    QhHw->NextQtd = QTD_LINK (PciAddr, FALSE);\r
   }\r
 \r
   return ;\r
@@ -895,11 +959,10 @@ EhcUpdateAsyncRequest (
   @param  Event                 Interrupt event.\r
   @param  Context               Pointer to USB2_HC_DEV.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
-EhcMoniteAsyncRequests (\r
+EFIAPI\r
+EhcMonitorAsyncRequests (\r
   IN EFI_EVENT            Event,\r
   IN VOID                 *Context\r
   )\r
@@ -935,7 +998,7 @@ EhcMoniteAsyncRequests (
     //\r
     Status = EhcFlushAsyncIntMap (Ehc, Urb);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "EhcMoniteAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));\r
+      DEBUG ((EFI_D_ERROR, "EhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));\r
     }\r
 \r
     //\r
@@ -951,14 +1014,14 @@ EhcMoniteAsyncRequests (
       ProcBuf = AllocatePool (Urb->Completed);\r
 \r
       if (ProcBuf == NULL) {\r
-        EhcUpdateAsyncRequest (Urb);\r
+        EhcUpdateAsyncRequest (Ehc, Urb);\r
         continue;\r
       }\r
 \r
       CopyMem (ProcBuf, Urb->Data, Urb->Completed);\r
     }\r
 \r
-    EhcUpdateAsyncRequest (Urb);\r
+    EhcUpdateAsyncRequest (Ehc, Urb);\r
 \r
     //\r
     // Leave error recovery to its related device driver. A\r