]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c
MdeModulePkg/PciBusDxe: dispatch option ROMs for foreign architectures
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciPei / UhcPeim.c
index 368b75d75304b817b7981eb41115b144b4567d9f..b897c3f82ce6e61734ddadb39639d86f5871ae96 100644 (file)
@@ -2,21 +2,86 @@
 PEIM to produce gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
 which is used to enable recovery function from USB Drivers.\r
 \r
-Copyright (c) 2006 - 2014, 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) 2006 - 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
 #include "UhcPeim.h"\r
 \r
+/**\r
+  Stop the host controller.\r
+\r
+  @param  Uhc           The UHCI device.\r
+  @param  Timeout       Max time allowed.\r
+\r
+  @retval EFI_SUCCESS   The host controller is stopped.\r
+  @retval EFI_TIMEOUT   Failed to stop the host controller.\r
+\r
+**/\r
+EFI_STATUS\r
+UhciStopHc (\r
+  IN USB_UHC_DEV        *Uhc,\r
+  IN UINTN              Timeout\r
+  )\r
+{\r
+  UINT16                CommandContent;\r
+  UINT16                UsbSts;\r
+  UINTN                 Index;\r
+\r
+  CommandContent = USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBCMD);\r
+  CommandContent &= USBCMD_RS;\r
+  USBWritePortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBCMD, CommandContent);\r
+\r
+  //\r
+  // ensure the HC is in halt status after send the stop command\r
+  // Timeout is in us unit.\r
+  //\r
+  for (Index = 0; Index < (Timeout / 50) + 1; Index++) {\r
+    UsbSts = USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBSTS);\r
+\r
+    if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    MicroSecondDelay (50);\r
+  }\r
+\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  One notified function to stop the Host Controller at the end of PEI\r
+\r
+  @param[in]  PeiServices        Pointer to PEI Services Table.\r
+  @param[in]  NotifyDescriptor   Pointer to the descriptor for the Notification event that\r
+                                 caused this function to execute.\r
+  @param[in]  Ppi                Pointer to the PPI data associated with this function.\r
+\r
+  @retval     EFI_SUCCESS  The function completes successfully\r
+  @retval     others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UhcEndOfPei (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,\r
+  IN VOID                       *Ppi\r
+  )\r
+{\r
+  USB_UHC_DEV   *Uhc;\r
+\r
+  Uhc = PEI_RECOVERY_USB_UHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);\r
+\r
+  //\r
+  // Stop the Host Controller\r
+  //\r
+  UhciStopHc (Uhc, 1000 * 1000);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Initializes Usb Host Controller.\r
 \r
@@ -98,6 +163,7 @@ UhcPeimEntry (
 \r
     UhcDev = (USB_UHC_DEV *) ((UINTN) TempPtr);\r
     UhcDev->Signature   = USB_UHC_DEV_SIGNATURE;\r
+    IoMmuInit (&UhcDev->IoMmu);\r
     UhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;\r
 \r
     //\r
@@ -133,6 +199,12 @@ UhcPeimEntry (
       continue;\r
     }\r
 \r
+    UhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+    UhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;\r
+    UhcDev->EndOfPeiNotifyList.Notify = UhcEndOfPei;\r
+\r
+    PeiServicesNotifyPpi (&UhcDev->EndOfPeiNotifyList);\r
+\r
     Index++;\r
   }\r
 \r
@@ -141,12 +213,12 @@ UhcPeimEntry (
 \r
 /**\r
   Submits control transfer to a target USB device.\r
-  \r
+\r
   @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
   @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
   @param  DeviceAddress          The target device address.\r
   @param  DeviceSpeed            Target device speed.\r
-  @param  MaximumPacketLength    Maximum packet size the default control transfer \r
+  @param  MaximumPacketLength    Maximum packet size the default control transfer\r
                                  endpoint is capable of sending or receiving.\r
   @param  Request                USB device request to send.\r
   @param  TransferDirection      Specifies the data direction for the data stage.\r
@@ -190,9 +262,11 @@ UhcControlTransfer (
   TD_STRUCT   *PtrStatusTD;\r
   EFI_STATUS  Status;\r
   UINT32      DataLen;\r
-  UINT8       *PtrDataSource;\r
-  UINT8       *Ptr;\r
   UINT8       DataToggle;\r
+  UINT8       *RequestPhy;\r
+  VOID        *RequestMap;\r
+  UINT8       *DataPhy;\r
+  VOID        *DataMap;\r
 \r
   UhcDev      = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This);\r
 \r
@@ -216,6 +290,24 @@ UhcControlTransfer (
 \r
   ClearStatusReg (UhcDev, StatusReg);\r
 \r
+  //\r
+  // Map the Request and data for bus master access,\r
+  // then create a list of TD for this transfer\r
+  //\r
+  Status = UhciMapUserRequest (UhcDev, Request, &RequestPhy, &RequestMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = UhciMapUserData (UhcDev, TransferDirection, Data, DataLength, &PktID, &DataPhy, &DataMap);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (RequestMap != NULL) {\r
+      IoMmuUnmap (UhcDev->IoMmu, RequestMap);\r
+    }\r
+    return Status;\r
+  }\r
+\r
   //\r
   // generate Setup Stage TD\r
   //\r
@@ -228,6 +320,7 @@ UhcControlTransfer (
     0,\r
     DeviceSpeed,\r
     (UINT8 *) Request,\r
+    RequestPhy,\r
     (UINT8) sizeof (EFI_USB_DEVICE_REQUEST),\r
     &PtrSetupTD\r
     );\r
@@ -242,38 +335,11 @@ UhcControlTransfer (
   //\r
   //  Data Stage of Control Transfer\r
   //\r
-  switch (TransferDirection) {\r
 \r
-  case EfiUsbDataIn:\r
-    PktID         = INPUT_PACKET_ID;\r
-    PtrDataSource = Data;\r
-    DataLen       = (UINT32) *DataLength;\r
-    Ptr           = PtrDataSource;\r
-    break;\r
-\r
-  case EfiUsbDataOut:\r
-    PktID         = OUTPUT_PACKET_ID;\r
-    PtrDataSource = Data;\r
-    DataLen       = (UINT32) *DataLength;\r
-    Ptr           = PtrDataSource;\r
-    break;\r
-\r
-  //\r
-  // no data stage\r
-  //\r
-  case EfiUsbNoData:\r
-    if (*DataLength != 0) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    PktID         = OUTPUT_PACKET_ID;\r
-    PtrDataSource = NULL;\r
-    DataLen       = 0;\r
-    Ptr           = NULL;\r
-    break;\r
-\r
-  default:\r
-    return EFI_INVALID_PARAMETER;\r
+  if (TransferDirection == EfiUsbNoData) {\r
+    DataLen = 0;\r
+  } else {\r
+    DataLen = (UINT32) *DataLength;\r
   }\r
 \r
   DataToggle  = 1;\r
@@ -297,7 +363,8 @@ UhcControlTransfer (
       UhcDev,\r
       DeviceAddress,\r
       0,\r
-      Ptr,\r
+      Data,\r
+      DataPhy,\r
       PacketSize,\r
       PktID,\r
       DataToggle,\r
@@ -312,7 +379,8 @@ UhcControlTransfer (
     PtrPreTD = PtrTD;\r
 \r
     DataToggle ^= 1;\r
-    Ptr += PacketSize;\r
+    Data = (VOID *) ((UINT8 *) Data + PacketSize);\r
+    DataPhy += PacketSize;\r
     DataLen -= PacketSize;\r
   }\r
 \r
@@ -365,31 +433,36 @@ UhcControlTransfer (
   // if has errors that cause host controller halt, then return EFI_DEVICE_ERROR directly.\r
   //\r
   if (!IsStatusOK (UhcDev, StatusReg)) {\r
-\r
-    ClearStatusReg (UhcDev, StatusReg);\r
     *TransferResult |= EFI_USB_ERR_SYSTEM;\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
   }\r
 \r
   ClearStatusReg (UhcDev, StatusReg);\r
 \r
+  if (DataMap != NULL) {\r
+    IoMmuUnmap (UhcDev->IoMmu, DataMap);\r
+  }\r
+  if (RequestMap != NULL) {\r
+    IoMmuUnmap (UhcDev->IoMmu, RequestMap);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
 /**\r
   Submits bulk transfer to a bulk endpoint of a USB device.\r
-  \r
+\r
   @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
   @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
   @param  DeviceAddress         Target device address.\r
   @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
-  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of \r
+  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of\r
                                 sending or receiving.\r
-  @param  Data                  Array of pointers to the buffers of data to transmit \r
+  @param  Data                  Array of pointers to the buffers of data to transmit\r
                                 from or receive into.\r
   @param  DataLength            The lenght of the data buffer.\r
   @param  DataToggle            On input, the initial data toggle for the transfer;\r
-                                On output, it is updated to to next data toggle to use of \r
+                                On output, it is updated to to next data toggle to use of\r
                                 the subsequent bulk transfer.\r
   @param  TimeOut               Indicates the maximum time, in millisecond, which the\r
                                 transfer is allowed to complete.\r
@@ -431,8 +504,6 @@ UhcBulkTransfer (
   TD_STRUCT               *PtrPreTD;\r
 \r
   UINT8                   PktID;\r
-  UINT8                   *PtrDataSource;\r
-  UINT8                   *Ptr;\r
 \r
   BOOLEAN                 IsFirstTD;\r
 \r
@@ -444,6 +515,9 @@ UhcBulkTransfer (
 \r
   UINT16                  CommandContent;\r
 \r
+  UINT8                   *DataPhy;\r
+  VOID                    *DataMap;\r
+\r
   UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This);\r
 \r
   //\r
@@ -467,7 +541,6 @@ UhcBulkTransfer (
   PtrFirstTD        = NULL;\r
   PtrPreTD          = NULL;\r
   DataLen           = 0;\r
-  Ptr               = NULL;\r
 \r
   ShortPacketEnable = FALSE;\r
 \r
@@ -495,33 +568,24 @@ UhcBulkTransfer (
 \r
   ClearStatusReg (UhcDev, StatusReg);\r
 \r
+  //\r
+  // Map the source data buffer for bus master access,\r
+  // then create a list of TDs\r
+  //\r
   if ((EndPointAddress & 0x80) != 0) {\r
     TransferDirection = EfiUsbDataIn;\r
   } else {\r
     TransferDirection = EfiUsbDataOut;\r
   }\r
 \r
-  switch (TransferDirection) {\r
-\r
-  case EfiUsbDataIn:\r
-    ShortPacketEnable = TRUE;\r
-    PktID             = INPUT_PACKET_ID;\r
-    PtrDataSource     = Data;\r
-    DataLen           = (UINT32) *DataLength;\r
-    Ptr               = PtrDataSource;\r
-    break;\r
-\r
-  case EfiUsbDataOut:\r
-    PktID         = OUTPUT_PACKET_ID;\r
-    PtrDataSource = Data;\r
-    DataLen       = (UINT32) *DataLength;\r
-    Ptr           = PtrDataSource;\r
-    break;\r
+  Status = UhciMapUserData (UhcDev, TransferDirection, Data, DataLength, &PktID, &DataPhy, &DataMap);\r
 \r
-  default:\r
-    break;\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
 \r
+  DataLen = (UINT32) *DataLength;\r
+\r
   PtrQH = UhcDev->BulkQH;\r
 \r
   IsFirstTD = TRUE;\r
@@ -540,7 +604,8 @@ UhcBulkTransfer (
       UhcDev,\r
       DeviceAddress,\r
       EndPointAddress,\r
-      Ptr,\r
+      Data,\r
+      DataPhy,\r
       PacketSize,\r
       PktID,\r
       *DataToggle,\r
@@ -570,7 +635,8 @@ UhcBulkTransfer (
     PtrPreTD = PtrTD;\r
 \r
     *DataToggle ^= 1;\r
-    Ptr += PacketSize;\r
+    Data = (VOID *) ((UINT8 *) Data + PacketSize);\r
+    DataPhy += PacketSize;\r
     DataLen -= PacketSize;\r
   }\r
   //\r
@@ -604,14 +670,16 @@ UhcBulkTransfer (
   // if has errors that cause host controller halt, then return EFI_DEVICE_ERROR directly.\r
   //\r
   if (!IsStatusOK (UhcDev, StatusReg)) {\r
-\r
-    ClearStatusReg (UhcDev, StatusReg);\r
     *TransferResult |= EFI_USB_ERR_SYSTEM;\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
   }\r
 \r
   ClearStatusReg (UhcDev, StatusReg);\r
 \r
+  if (DataMap != NULL) {\r
+    IoMmuUnmap (UhcDev->IoMmu, DataMap);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -619,10 +687,10 @@ UhcBulkTransfer (
   Retrieves the number of root hub ports.\r
 \r
   @param[in]  PeiServices   The pointer to the PEI Services Table.\r
-  @param[in]  This          The pointer to this instance of the \r
+  @param[in]  This          The pointer to this instance of the\r
                             PEI_USB_HOST_CONTROLLER_PPI.\r
-  @param[out] PortNumber    The pointer to the number of the root hub ports.                                \r
-                                \r
+  @param[out] PortNumber    The pointer to the number of the root hub ports.\r
+\r
   @retval EFI_SUCCESS           The port number was retrieved successfully.\r
   @retval EFI_INVALID_PARAMETER PortNumber is NULL.\r
 \r
@@ -664,10 +732,10 @@ UhcGetRootHubPortNumber (
 \r
 /**\r
   Retrieves the current status of a USB root hub port.\r
-  \r
+\r
   @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
   @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
-  @param  PortNumber             The root hub port to retrieve the state from.  \r
+  @param  PortNumber             The root hub port to retrieve the state from.\r
   @param  PortStatus             Variable to receive the port state.\r
 \r
   @retval EFI_SUCCESS            The status of the USB root hub port specified.\r
@@ -757,7 +825,7 @@ UhcGetRootHubPortStatus (
 \r
 /**\r
   Sets a feature for the specified root hub port.\r
-  \r
+\r
   @param  PeiServices           The pointer of EFI_PEI_SERVICES\r
   @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI\r
   @param  PortNumber            Root hub port to set.\r
@@ -833,7 +901,7 @@ UhcSetRootHubPortFeature (
 \r
 /**\r
   Clears a feature for the specified root hub port.\r
-  \r
+\r
   @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
   @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
   @param  PortNumber            Specifies the root hub port whose feature\r
@@ -841,7 +909,7 @@ UhcSetRootHubPortFeature (
   @param  PortFeature           Indicates the feature selector associated with the\r
                                 feature clear request.\r
 \r
-  @retval EFI_SUCCESS            The feature specified by PortFeature was cleared \r
+  @retval EFI_SUCCESS            The feature specified by PortFeature was cleared\r
                                  for the USB root hub port specified by PortNumber.\r
   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
 \r
@@ -1056,7 +1124,7 @@ CreateFrameList (
   ASSERT (UhcDev->BulkQH != NULL);\r
 \r
   //\r
-  //Set the corresponding QH pointer \r
+  //Set the corresponding QH pointer\r
   //\r
   SetQHHorizontalLinkPtr(UhcDev->ConfigQH, UhcDev->BulkQH);\r
   SetQHHorizontalQHorTDSelect (UhcDev->ConfigQH, TRUE);\r
@@ -1079,7 +1147,7 @@ CreateFrameList (
 \r
 /**\r
   Read a 16bit width data from Uhc HC IO space register.\r
-  \r
+\r
   @param  UhcDev  The UHCI device.\r
   @param  Port    The IO space address of the register.\r
 \r
@@ -1097,7 +1165,7 @@ USBReadPortW (
 \r
 /**\r
   Write a 16bit width data into Uhc HC IO space register.\r
-  \r
+\r
   @param  UhcDev  The UHCI device.\r
   @param  Port    The IO space address of the register.\r
   @param  Data    The data written into the register.\r
@@ -1115,7 +1183,7 @@ USBWritePortW (
 \r
 /**\r
   Write a 32bit width data into Uhc HC IO space register.\r
-  \r
+\r
   @param  UhcDev  The UHCI device.\r
   @param  Port    The IO space address of the register.\r
   @param  Data    The data written into the register.\r
@@ -1133,7 +1201,7 @@ USBWritePortDW (
 \r
 /**\r
   Clear the content of UHCI's Status Register.\r
-  \r
+\r
   @param  UhcDev       The UHCI device.\r
   @param  StatusAddr   The IO space address of the register.\r
 \r
@@ -1177,26 +1245,7 @@ IsStatusOK (
   }\r
 }\r
 \r
-/**\r
-  Get Current Frame Number.\r
-\r
-  @param  UhcDev          The UHCI device.\r
-  @param  FrameNumberAddr The address of frame list register.\r
-\r
-  @retval The content of the frame list register.\r
 \r
-**/\r
-UINT16\r
-GetCurrentFrameNumber (\r
-  IN USB_UHC_DEV   *UhcDev,\r
-  IN UINT32        FrameNumberAddr\r
-  )\r
-{\r
-  //\r
-  // Gets value in the USB frame number register.\r
-  //\r
-  return (UINT16) (USBReadPortW (UhcDev, FrameNumberAddr) & 0x03FF);\r
-}\r
 \r
 /**\r
   Set Frame List Base Address.\r
@@ -1274,25 +1323,7 @@ SetQHHorizontalLinkPtr (
   PtrQH->QueueHead.QHHorizontalPtr = (UINT32) (UINTN) PtrNext >> 4;\r
 }\r
 \r
-/**\r
-  Get the horizontal link pointer in QH.\r
-\r
-  @param  PtrQH     Place to store QH_STRUCT pointer.\r
 \r
-  @retval The horizontal link pointer in QH.\r
-\r
-**/\r
-VOID *\r
-GetQHHorizontalLinkPtr (\r
-  IN QH_STRUCT  *PtrQH\r
-  )\r
-{\r
-  //\r
-  // Restore the 28bit address to 32bit address\r
-  // (take 32bit address as an example)\r
-  //\r
-  return (VOID *) (UINTN) ((PtrQH->QueueHead.QHHorizontalPtr) << 4);\r
-}\r
 \r
 /**\r
   Set a QH or TD horizontally to be connected with a specific QH.\r
@@ -1395,25 +1426,7 @@ SetQHVerticalValidorInvalid (
   PtrQH->QueueHead.QHVerticalTerminate = IsValid ? 0 : 1;\r
 }\r
 \r
-/**\r
-  Get the vertical validor bit in QH.\r
-\r
-  @param  PtrQH      Place to store QH_STRUCT pointer.\r
-\r
-  @retval The vertical linker is valid or not.\r
 \r
-**/\r
-BOOLEAN\r
-GetQHHorizontalValidorInvalid (\r
-  IN QH_STRUCT  *PtrQH\r
-  )\r
-{\r
-  //\r
-  // If TRUE, meaning the Horizontal Link Pointer field is valid,\r
-  // else, the field is invalid.\r
-  //\r
-  return (BOOLEAN) (!(PtrQH->QueueHead.QHHorizontalTerminate));\r
-}\r
 \r
 /**\r
   Allocate TD or QH Struct.\r
@@ -1492,7 +1505,8 @@ CreateTD (
   @param  DevAddr      Device address.\r
   @param  Endpoint     Endpoint number.\r
   @param  DeviceSpeed  Device Speed.\r
-  @param  DevRequest   Device reuquest.\r
+  @param  DevRequest   CPU memory address of request structure buffer to transfer.\r
+  @param  RequestPhy   PCI memory address of request structure buffer to transfer.\r
   @param  RequestLen   Request length.\r
   @param  PtrTD        TD_STRUCT generated.\r
 \r
@@ -1507,6 +1521,7 @@ GenSetupStageTD (
   IN  UINT8           Endpoint,\r
   IN  UINT8           DeviceSpeed,\r
   IN  UINT8           *DevRequest,\r
+  IN  UINT8           *RequestPhy,\r
   IN  UINT8           RequestLen,\r
   OUT TD_STRUCT       **PtrTD\r
   )\r
@@ -1583,7 +1598,11 @@ GenSetupStageTD (
 \r
   TdStruct->PtrTDBuffer      = (UINT8 *) DevRequest;\r
   TdStruct->TDBufferLength = RequestLen;\r
-  SetTDDataBuffer (TdStruct);\r
+  //\r
+  // Set the beginning address of the buffer that will be used\r
+  // during the transaction.\r
+  //\r
+  TdStruct->TDData.TDBufferPtr = (UINT32) (UINTN) RequestPhy;\r
 \r
   *PtrTD = TdStruct;\r
 \r
@@ -1596,7 +1615,8 @@ GenSetupStageTD (
   @param  UhcDev       The UHCI device.\r
   @param  DevAddr      Device address.\r
   @param  Endpoint     Endpoint number.\r
-  @param  PtrData      Data buffer.\r
+  @param  PtrData      CPU memory address of user data buffer to transfer.\r
+  @param  DataPhy      PCI memory address of user data buffer to transfer.\r
   @param  Len          Data length.\r
   @param  PktID        PacketID.\r
   @param  Toggle       Data toggle value.\r
@@ -1613,6 +1633,7 @@ GenDataTD (
   IN  UINT8           DevAddr,\r
   IN  UINT8           Endpoint,\r
   IN  UINT8           *PtrData,\r
+  IN  UINT8           *DataPhy,\r
   IN  UINT8           Len,\r
   IN  UINT8           PktID,\r
   IN  UINT8           Toggle,\r
@@ -1700,7 +1721,11 @@ GenDataTD (
 \r
   TdStruct->PtrTDBuffer      = (UINT8 *) PtrData;\r
   TdStruct->TDBufferLength = Len;\r
-  SetTDDataBuffer (TdStruct);\r
+  //\r
+  // Set the beginning address of the buffer that will be used\r
+  // during the transaction.\r
+  //\r
+  TdStruct->TDData.TDBufferPtr = (UINT32) (UINTN) DataPhy;\r
 \r
   *PtrTD = TdStruct;\r
 \r
@@ -1803,7 +1828,11 @@ CreateStatusTD (
 \r
   PtrTDStruct->PtrTDBuffer      = NULL;\r
   PtrTDStruct->TDBufferLength = 0;\r
-  SetTDDataBuffer (PtrTDStruct);\r
+  //\r
+  // Set the beginning address of the buffer that will be used\r
+  // during the transaction.\r
+  //\r
+  PtrTDStruct->TDData.TDBufferPtr = 0;\r
 \r
   *PtrTD = PtrTDStruct;\r
 \r
@@ -1909,26 +1938,7 @@ GetTDLinkPtr (
   return (VOID *) (UINTN) ((PtrTDStruct->TDData.TDLinkPtr) << 4);\r
 }\r
 \r
-/**\r
-  Get the information about whether the Link Pointer field pointing to\r
-  a QH or a TD.\r
-\r
-  @param  PtrTDStruct     Place to store TD_STRUCT pointer.\r
-\r
-  @retval whether the Link Pointer field pointing to a QH or a TD.\r
 \r
-**/\r
-BOOLEAN\r
-IsTDLinkPtrQHOrTD (\r
-  IN  TD_STRUCT *PtrTDStruct\r
-  )\r
-{\r
-  //\r
-  // Get the information about whether the Link Pointer field pointing to\r
-  // a QH or a TD.\r
-  //\r
-  return (BOOLEAN) (PtrTDStruct->TDData.TDLinkPtrQSelect);\r
-}\r
 \r
 /**\r
   Enable/Disable short packet detection mechanism.\r
@@ -2173,25 +2183,6 @@ SetTDTokenPacketID (
   PtrTDStruct->TDData.TDTokenPID = PacketID;\r
 }\r
 \r
-/**\r
-  Set the beginning address of the data buffer that will be used\r
-  during the transaction.\r
-\r
-  @param  PtrTDStruct   Place to store TD_STRUCT pointer.\r
-\r
-**/\r
-VOID\r
-SetTDDataBuffer (\r
-  IN  TD_STRUCT *PtrTDStruct\r
-  )\r
-{\r
-  //\r
-  // Set the beginning address of the data buffer that will be used\r
-  // during the transaction.\r
-  //\r
-  PtrTDStruct->TDData.TDBufferPtr = (UINT32) (UINTN) (PtrTDStruct->PtrTDBuffer);\r
-}\r
-\r
 /**\r
   Detect whether the TD is active.\r
 \r
@@ -2773,25 +2764,29 @@ CreateMemoryBlock (
   )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_PHYSICAL_ADDRESS  TempPtr;\r
+  UINT8                 *TempPtr;\r
   UINTN                 MemPages;\r
   UINT8                 *Ptr;\r
+  VOID                  *Mapping;\r
+  EFI_PHYSICAL_ADDRESS  MappedAddr;\r
 \r
   //\r
   // Memory Block uses MemoryBlockSizeInPages pages,\r
   // memory management header and bit array use 1 page\r
   //\r
   MemPages = MemoryBlockSizeInPages + 1;\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesData,\r
+  Status = IoMmuAllocateBuffer (\r
+             UhcDev->IoMmu,\r
              MemPages,\r
-             &TempPtr\r
+             (VOID **) &TempPtr,\r
+             &MappedAddr,\r
+             &Mapping\r
              );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  if (EFI_ERROR (Status) || (TempPtr == NULL)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Ptr = (UINT8 *) ((UINTN) TempPtr);\r
+  Ptr = TempPtr;\r
 \r
   ZeroMem (Ptr, MemPages * EFI_PAGE_SIZE);\r
 \r
@@ -2810,7 +2805,7 @@ CreateMemoryBlock (
   //\r
   // Memory block initial address\r
   //\r
-  Ptr = (UINT8 *) ((UINTN) TempPtr);\r
+  Ptr = TempPtr;\r
   Ptr += EFI_PAGE_SIZE;\r
   (*MemoryHeader)->MemoryBlockPtr = Ptr;\r
   //\r
@@ -3120,7 +3115,7 @@ UhcFreePool (
       StartBitPos   = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) % 8);\r
 \r
       //\r
-      // reset associated bits in bit arry\r
+      // reset associated bits in bit array\r
       //\r
       for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {\r
 \r
@@ -3163,57 +3158,138 @@ InsertMemoryHeaderToList (
   }\r
 }\r
 \r
+\r
+\r
+\r
+\r
 /**\r
-  Judge the memory block in the memory header is empty or not.\r
+  Map address of request structure buffer.\r
 \r
-  @param  MemoryHeaderPtr   A pointer to the memory header list.\r
+  @param  Uhc                The UHCI device.\r
+  @param  Request            The user request buffer.\r
+  @param  MappedAddr         Mapped address of request.\r
+  @param  Map                Identificaion of this mapping to return.\r
 \r
-  @retval Whether the memory block in the memory header is empty or not.\r
+  @return EFI_SUCCESS        Success.\r
+  @return EFI_DEVICE_ERROR   Fail to map the user request.\r
 \r
 **/\r
-BOOLEAN\r
-IsMemoryBlockEmptied (\r
-  IN MEMORY_MANAGE_HEADER  *MemoryHeaderPtr\r
+EFI_STATUS\r
+UhciMapUserRequest (\r
+  IN  USB_UHC_DEV         *Uhc,\r
+  IN  OUT VOID            *Request,\r
+  OUT UINT8               **MappedAddr,\r
+  OUT VOID                **Map\r
   )\r
 {\r
-  UINTN Index;\r
+  EFI_STATUS            Status;\r
+  UINTN                 Len;\r
+  EFI_PHYSICAL_ADDRESS  PhyAddr;\r
+\r
+  Len    = sizeof (EFI_USB_DEVICE_REQUEST);\r
+  Status = IoMmuMap (\r
+             Uhc->IoMmu,\r
+             EdkiiIoMmuOperationBusMasterRead,\r
+             Request,\r
+             &Len,\r
+             &PhyAddr,\r
+             Map\r
+             );\r
 \r
-  for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r
-    if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r
-      return FALSE;\r
-    }\r
+  if (!EFI_ERROR (Status)) {\r
+    *MappedAddr = (UINT8 *) (UINTN) PhyAddr;\r
   }\r
 \r
-  return TRUE;\r
+  return Status;\r
 }\r
 \r
 /**\r
-  remove a memory header from list.\r
+  Map address of user data buffer.\r
+\r
+  @param  Uhc                The UHCI device.\r
+  @param  Direction          Direction of the data transfer.\r
+  @param  Data               The user data buffer.\r
+  @param  Len                Length of the user data.\r
+  @param  PktId              Packet identificaion.\r
+  @param  MappedAddr         Mapped address to return.\r
+  @param  Map                Identificaion of this mapping to return.\r
 \r
-  @param  FirstMemoryHeader   A pointer to the memory header list.\r
-  @param  FreeMemoryHeader    A memory header to be removed into the list.\r
+  @return EFI_SUCCESS        Success.\r
+  @return EFI_DEVICE_ERROR   Fail to map the user data.\r
 \r
 **/\r
-VOID\r
-DelinkMemoryBlock (\r
-  IN MEMORY_MANAGE_HEADER    *FirstMemoryHeader,\r
-  IN MEMORY_MANAGE_HEADER    *FreeMemoryHeader\r
+EFI_STATUS\r
+UhciMapUserData (\r
+  IN  USB_UHC_DEV             *Uhc,\r
+  IN  EFI_USB_DATA_DIRECTION  Direction,\r
+  IN  VOID                    *Data,\r
+  IN  OUT UINTN               *Len,\r
+  OUT UINT8                   *PktId,\r
+  OUT UINT8                   **MappedAddr,\r
+  OUT VOID                    **Map\r
   )\r
 {\r
-  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  PhyAddr;\r
 \r
-  if ((FirstMemoryHeader == NULL) || (FreeMemoryHeader == NULL)) {\r
-    return ;\r
-  }\r
+  Status = EFI_SUCCESS;\r
 \r
-  for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
+  switch (Direction) {\r
+  case EfiUsbDataIn:\r
+    //\r
+    // BusMasterWrite means cpu read\r
+    //\r
+    *PktId = INPUT_PACKET_ID;\r
+    Status = IoMmuMap (\r
+               Uhc->IoMmu,\r
+               EdkiiIoMmuOperationBusMasterWrite,\r
+               Data,\r
+               Len,\r
+               &PhyAddr,\r
+               Map\r
+               );\r
 \r
-    if (TempHeaderPtr->Next == FreeMemoryHeader) {\r
-      //\r
-      // Link the before and after\r
-      //\r
-      TempHeaderPtr->Next = FreeMemoryHeader->Next;\r
-      break;\r
+    if (EFI_ERROR (Status)) {\r
+      goto EXIT;\r
     }\r
+\r
+    *MappedAddr = (UINT8 *) (UINTN) PhyAddr;\r
+    break;\r
+\r
+  case EfiUsbDataOut:\r
+    *PktId = OUTPUT_PACKET_ID;\r
+    Status = IoMmuMap (\r
+               Uhc->IoMmu,\r
+               EdkiiIoMmuOperationBusMasterRead,\r
+               Data,\r
+               Len,\r
+               &PhyAddr,\r
+               Map\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto EXIT;\r
+    }\r
+\r
+    *MappedAddr = (UINT8 *) (UINTN) PhyAddr;\r
+    break;\r
+\r
+  case EfiUsbNoData:\r
+    if ((Len != NULL) && (*Len != 0)) {\r
+      Status    = EFI_INVALID_PARAMETER;\r
+      goto EXIT;\r
+    }\r
+\r
+    *PktId      = OUTPUT_PACKET_ID;\r
+    *MappedAddr = NULL;\r
+    *Map        = NULL;\r
+    break;\r
+\r
+  default:\r
+    Status      = EFI_INVALID_PARAMETER;\r
   }\r
+\r
+EXIT:\r
+  return Status;\r
 }\r
+\r