]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciPei / EhciSched.c
index e992d4f287978fe5cb3af410d1782d0a43c610e6..db2406b0d2b8dc24f190636d3fcc9b1e637dcdb4 100644 (file)
@@ -2,16 +2,10 @@
 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
 which is used to enable recovery function from USB Drivers.\r
 \r
-Copyright (c) 2010 - 2013, 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
+Copyright (c) Microsoft Corporation.<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 +13,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
@@ -28,13 +22,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 EFI_STATUS\r
 EhcCreateHelpQ (\r
-  IN PEI_USB2_HC_DEV      *Ehc\r
+  IN PEI_USB2_HC_DEV  *Ehc\r
   )\r
 {\r
-  USB_ENDPOINT            Ep;\r
-  PEI_EHC_QH              *Qh;\r
-  QH_HW                   *QhHw;\r
-  PEI_EHC_QTD             *Qtd;\r
+  USB_ENDPOINT  Ep;\r
+  PEI_EHC_QH    *Qh;\r
+  QH_HW         *QhHw;\r
+  PEI_EHC_QTD   *Qtd;\r
 \r
   //\r
   // Create an inactive Qtd to terminate the short packet read.\r
@@ -45,25 +39,25 @@ EhcCreateHelpQ (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Qtd->QtdHw.Status   = QTD_STAT_HALTED;\r
-  Ehc->ShortReadStop  = Qtd;\r
+  Qtd->QtdHw.Status  = QTD_STAT_HALTED;\r
+  Ehc->ShortReadStop = Qtd;\r
 \r
   //\r
   // Create a QH to act as the EHC reclamation header.\r
   // Set the header to loopback to itself.\r
   //\r
-  Ep.DevAddr    = 0;\r
-  Ep.EpAddr     = 1;\r
-  Ep.Direction  = EfiUsbDataIn;\r
-  Ep.DevSpeed   = EFI_USB_SPEED_HIGH;\r
-  Ep.MaxPacket  = 64;\r
-  Ep.HubAddr    = 0;\r
-  Ep.HubPort    = 0;\r
-  Ep.Toggle     = 0;\r
-  Ep.Type       = EHC_BULK_TRANSFER;\r
-  Ep.PollRate   = 1;\r
-\r
-  Qh            = EhcCreateQh (Ehc, &Ep);\r
+  Ep.DevAddr   = 0;\r
+  Ep.EpAddr    = 1;\r
+  Ep.Direction = EfiUsbDataIn;\r
+  Ep.DevSpeed  = EFI_USB_SPEED_HIGH;\r
+  Ep.MaxPacket = 64;\r
+  Ep.HubAddr   = 0;\r
+  Ep.HubPort   = 0;\r
+  Ep.Toggle    = 0;\r
+  Ep.Type      = EHC_BULK_TRANSFER;\r
+  Ep.PollRate  = 1;\r
+\r
+  Qh = EhcCreateQh (Ehc, &Ep);\r
 \r
   if (Qh == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -78,10 +72,10 @@ EhcCreateHelpQ (
   //\r
   // Create a dummy QH to act as the terminator for periodical schedule\r
   //\r
-  Ep.EpAddr   = 2;\r
-  Ep.Type     = EHC_INT_TRANSFER_SYNC;\r
+  Ep.EpAddr = 2;\r
+  Ep.Type   = EHC_INT_TRANSFER_SYNC;\r
 \r
-  Qh          = EhcCreateQh (Ehc, &Ep);\r
+  Qh = EhcCreateQh (Ehc, &Ep);\r
 \r
   if (Qh == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -95,7 +89,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
@@ -104,14 +98,16 @@ EhcCreateHelpQ (
 **/\r
 EFI_STATUS\r
 EhcInitSched (\r
-  IN PEI_USB2_HC_DEV      *Ehc\r
+  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,17 +120,21 @@ 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
-  Ehc->PeriodFrameMap   = Map;\r
-  Ehc->High32bitAddr    = EHC_HIGH_32BIT (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
   //\r
   // Init memory pool management then create the helper\r
@@ -156,62 +156,64 @@ 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
+  Desc    = (UINT32 *)Ehc->PeriodFrame;\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
 EhcFreeSched (\r
-  IN PEI_USB2_HC_DEV      *Ehc\r
+  IN PEI_USB2_HC_DEV  *Ehc\r
   )\r
 {\r
   EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, 0);\r
   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,48 +224,48 @@ 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
 **/\r
 VOID\r
 EhcLinkQhToAsync (\r
-  IN PEI_USB2_HC_DEV      *Ehc,\r
-  IN PEI_EHC_QH           *Qh\r
+  IN PEI_USB2_HC_DEV  *Ehc,\r
+  IN PEI_EHC_QH       *Qh\r
   )\r
 {\r
-  PEI_EHC_QH               *Head;\r
+  PEI_EHC_QH  *Head;\r
 \r
   //\r
   // Append the queue head after the reclaim header, then\r
   // fix the hardware visiable parts (EHCI R1.0 page 72).\r
   // ReclaimHead is always linked to the EHCI's AsynListAddr.\r
   //\r
-  Head                    = Ehc->ReclaimHead;\r
+  Head = Ehc->ReclaimHead;\r
 \r
-  Qh->NextQh              = Head->NextQh;\r
-  Head->NextQh            = Qh;\r
+  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
+  Qh->QhHw.HorizonLink   = QH_LINK (Head, EHC_TYPE_QH, FALSE);\r
+  Head->QhHw.HorizonLink = QH_LINK (Qh, EHC_TYPE_QH, FALSE);\r
 }\r
 \r
 /**\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
 **/\r
 VOID\r
 EhcUnlinkQhFromAsync (\r
-  IN PEI_USB2_HC_DEV      *Ehc,\r
-  IN PEI_EHC_QH           *Qh\r
+  IN PEI_USB2_HC_DEV  *Ehc,\r
+  IN PEI_EHC_QH       *Qh\r
   )\r
 {\r
-  PEI_EHC_QH              *Head;\r
+  PEI_EHC_QH  *Head;\r
 \r
   ASSERT (Ehc->ReclaimHead->NextQh == Qh);\r
 \r
@@ -272,24 +274,24 @@ EhcUnlinkQhFromAsync (
   // visiable part: Only need to loopback the ReclaimHead. The Qh\r
   // is pointing to ReclaimHead (which is staill in the list).\r
   //\r
-  Head                    = Ehc->ReclaimHead;\r
+  Head = Ehc->ReclaimHead;\r
 \r
-  Head->NextQh            = Qh->NextQh;\r
-  Qh->NextQh              = NULL;\r
+  Head->NextQh = Qh->NextQh;\r
+  Qh->NextQh   = NULL;\r
 \r
-  Head->QhHw.HorizonLink  = QH_LINK (Head, EHC_TYPE_QH, FALSE);\r
+  Head->QhHw.HorizonLink = QH_LINK (Head, EHC_TYPE_QH, FALSE);\r
 \r
   //\r
   // Set and wait the door bell to synchronize with the hardware\r
   //\r
   EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT);\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
@@ -300,32 +302,32 @@ EhcUnlinkQhFromAsync (
 **/\r
 BOOLEAN\r
 EhcCheckUrbResult (\r
-  IN  PEI_USB2_HC_DEV     *Ehc,\r
-  IN  PEI_URB             *Urb\r
+  IN  PEI_USB2_HC_DEV  *Ehc,\r
+  IN  PEI_URB          *Urb\r
   )\r
 {\r
-  EFI_LIST_ENTRY          *Entry;\r
-  PEI_EHC_QTD             *Qtd;\r
-  QTD_HW                  *QtdHw;\r
-  UINT8                   State;\r
-  BOOLEAN                 Finished;\r
+  EFI_LIST_ENTRY  *Entry;\r
+  PEI_EHC_QTD     *Qtd;\r
+  QTD_HW          *QtdHw;\r
+  UINT8           State;\r
+  BOOLEAN         Finished;\r
 \r
   ASSERT ((Ehc != NULL) && (Urb != NULL) && (Urb->Qh != NULL));\r
 \r
-  Finished        = TRUE;\r
-  Urb->Completed  = 0;\r
+  Finished       = TRUE;\r
+  Urb->Completed = 0;\r
 \r
-  Urb->Result     = EFI_USB_NOERROR;\r
+  Urb->Result = EFI_USB_NOERROR;\r
 \r
   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
     Urb->Result |= EFI_USB_ERR_SYSTEM;\r
     goto ON_EXIT;\r
   }\r
 \r
-  EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {\r
+  BASE_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {\r
     Qtd   = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);\r
     QtdHw = &Qtd->QtdHw;\r
-    State = (UINT8) QtdHw->Status;\r
+    State = (UINT8)QtdHw->Status;\r
 \r
     if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {\r
       //\r
@@ -350,16 +352,14 @@ EhcCheckUrbResult (
 \r
       Finished = TRUE;\r
       goto ON_EXIT;\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
     } else {\r
       //\r
       // This QTD is finished OK or met short packet read. Update the\r
@@ -370,7 +370,7 @@ EhcCheckUrbResult (
       }\r
 \r
       if ((QtdHw->TotalBytes != 0) && (QtdHw->Pid == QTD_PID_INPUT)) {\r
-        //EHC_DUMP_QH ((Urb->Qh, "Short packet read", FALSE));\r
+        // EHC_DUMP_QH ((Urb->Qh, "Short packet read", FALSE));\r
 \r
         //\r
         // Short packet read condition. If it isn't a setup transfer,\r
@@ -379,7 +379,6 @@ EhcCheckUrbResult (
         // Status Stage of the setup transfer to get the finial result\r
         //\r
         if (QtdHw->AltNext == QTD_LINK (Ehc->ShortReadStop, FALSE)) {\r
-          \r
           Finished = TRUE;\r
           goto ON_EXIT;\r
         }\r
@@ -397,14 +396,14 @@ ON_EXIT:
   // NOTICE: don't move DT update before the loop, otherwise there is\r
   // a race condition that DT is wrong.\r
   //\r
-  Urb->DataToggle = (UINT8) Urb->Qh->QhHw.DataToggle;\r
+  Urb->DataToggle = (UINT8)Urb->Qh->QhHw.DataToggle;\r
 \r
   return Finished;\r
 }\r
 \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
@@ -416,19 +415,19 @@ ON_EXIT:
 **/\r
 EFI_STATUS\r
 EhcExecTransfer (\r
-  IN  PEI_USB2_HC_DEV     *Ehc,\r
-  IN  PEI_URB             *Urb,\r
-  IN  UINTN               TimeOut\r
+  IN  PEI_USB2_HC_DEV  *Ehc,\r
+  IN  PEI_URB          *Urb,\r
+  IN  UINTN            TimeOut\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  UINTN                   Index;\r
-  UINTN                   Loop;\r
-  BOOLEAN                 Finished;\r
-  BOOLEAN                 InfiniteLoop;\r
-\r
-  Status    = EFI_SUCCESS;\r
-  Loop      = TimeOut * EHC_1_MILLISECOND;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  UINTN       Loop;\r
+  BOOLEAN     Finished;\r
+  BOOLEAN     InfiniteLoop;\r
+\r
+  Status       = EFI_SUCCESS;\r
+  Loop         = TimeOut * EHC_1_MILLISECOND;\r
   Finished     = FALSE;\r
   InfiniteLoop = FALSE;\r
 \r
@@ -458,4 +457,3 @@ EhcExecTransfer (
 \r
   return Status;\r
 }\r
-\r