]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
index e37cf719d7fcb9dc3a2a7a28cacd9b5471949640..bdd9c27db562aa204b120247be751269e27d2bec 100644 (file)
@@ -1,22 +1,18 @@
 /** @file\r
+  The Ehci controller driver.\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
+  EhciDxe driver is responsible for managing the behavior of EHCI controller.\r
+  It implements the interfaces of monitoring the status of all ports and transferring\r
+  Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.\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
+  Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached\r
+  to the EHCI controller before a UHCI or OHCI driver attaches to the companion UHCI or\r
+  OHCI controller.  This way avoids the control transfer on a shared port between EHCI\r
+  and companion host controller when UHCI or OHCI gets attached earlier than EHCI and a\r
+  USB 2.0 device inserts.\r
 \r
-Module Name:\r
-\r
-    Ehci.c\r
-\r
-Abstract:\r
-\r
-\r
-Revision History\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -43,21 +39,29 @@ USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
   {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}\r
 };\r
 \r
+EFI_DRIVER_BINDING_PROTOCOL\r
+gEhciDriverBinding = {\r
+  EhcDriverBindingSupported,\r
+  EhcDriverBindingStart,\r
+  EhcDriverBindingStop,\r
+  0x30,\r
+  NULL,\r
+  NULL\r
+};\r
 \r
 /**\r
-  Retrieves the capablility of root hub ports.\r
+  Retrieves the capability of root hub ports.\r
 \r
-  @param  This                 This EFI_USB_HC_PROTOCOL instance.\r
-  @param  MaxSpeed             Max speed supported by the controller\r
-  @param  PortNumber           Number of the root hub ports.\r
-  @param  Is64BitCapable       Whether the controller supports 64-bit memory\r
-                               addressing.\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  MaxSpeed              Max speed supported by the controller.\r
+  @param  PortNumber            Number of the root hub ports.\r
+  @param  Is64BitCapable        Whether the controller supports 64-bit memory\r
+                                addressing.\r
 \r
-  @return EFI_SUCCESS           : host controller capability were retrieved successfully.\r
-  @return EFI_INVALID_PARAMETER : Either of the three capability pointer is NULL\r
+  @retval EFI_SUCCESS           Host controller capability were retrieved successfully.\r
+  @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcGetCapability (\r
@@ -79,9 +83,9 @@ EhcGetCapability (
 \r
   *MaxSpeed       = EFI_USB_SPEED_HIGH;\r
   *PortNumber     = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);\r
-  *Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);\r
+  *Is64BitCapable = (UINT8) Ehc->Support64BitDma;\r
 \r
-  EHC_DEBUG (("EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
+  DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
 \r
   gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
@@ -91,17 +95,16 @@ EhcGetCapability (
 /**\r
   Provides software reset for the USB host controller.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  Attributes           A bit mask of the reset operation to perform.\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  Attributes            A bit mask of the reset operation to perform.\r
 \r
-  @return EFI_SUCCESS           : The reset operation succeeded.\r
-  @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
-  @return EFI_UNSUPPOURTED      : The type of reset specified by Attributes is\r
-  @return not currently supported by the host controller.\r
-  @return EFI_DEVICE_ERROR      : Host controller isn't halted to reset.\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
+                                not currently supported by the host controller.\r
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcReset (\r
@@ -113,8 +116,20 @@ EhcReset (
   EFI_TPL                 OldTpl;\r
   EFI_STATUS              Status;\r
 \r
+  Ehc = EHC_FROM_THIS (This);\r
+\r
+  if (Ehc->DevicePath != NULL) {\r
+    //\r
+    // Report Status Code to indicate reset happens\r
+    //\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),\r
+      Ehc->DevicePath\r
+      );\r
+  }\r
+\r
   OldTpl  = gBS->RaiseTPL (EHC_TPL);\r
-  Ehc     = EHC_FROM_THIS (This);\r
 \r
   switch (Attributes) {\r
   case EFI_USB_HC_RESET_GLOBAL:\r
@@ -125,6 +140,11 @@ EhcReset (
     //\r
     // Host Controller must be Halt when Reset it\r
     //\r
+    if (EhcIsDebugPortInUse (Ehc, NULL)) {\r
+      Status = EFI_SUCCESS;\r
+      goto ON_EXIT;\r
+    }\r
+\r
     if (!EhcIsHalt (Ehc)) {\r
       Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
 \r
@@ -161,7 +181,7 @@ EhcReset (
   }\r
 \r
 ON_EXIT:\r
-  EHC_DEBUG (("EhcReset: exit status %r\n", Status));\r
+  DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));\r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
@@ -170,22 +190,21 @@ ON_EXIT:
 /**\r
   Retrieve the current state of the USB host controller.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                Variable to return the current host controller\r
-                               state.\r
+  @param  This                   This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  State                  Variable to return the current host controller\r
+                                 state.\r
 \r
-  @return EFI_SUCCESS           : Host controller state was returned in State.\r
-  @return EFI_INVALID_PARAMETER : State is NULL.\r
-  @return EFI_DEVICE_ERROR      : An error was encountered while attempting to\r
-  @return retrieve the host controller's current state.\r
+  @retval EFI_SUCCESS            Host controller state was returned in State.\r
+  @retval EFI_INVALID_PARAMETER  State is NULL.\r
+  @retval EFI_DEVICE_ERROR       An error was encountered while attempting to\r
+                                 retrieve the host controller's current state.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcGetState (\r
-  IN  CONST EFI_USB2_HC_PROTOCOL  *This,\r
-  OUT       EFI_USB_HC_STATE      *State\r
+  IN   EFI_USB2_HC_PROTOCOL  *This,\r
+  OUT  EFI_USB_HC_STATE      *State\r
   )\r
 {\r
   EFI_TPL                 OldTpl;\r
@@ -206,7 +225,7 @@ EhcGetState (
 \r
   gBS->RestoreTPL (OldTpl);\r
 \r
-  EHC_DEBUG (("EhcGetState: current state %d\n", *State));\r
+  DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -214,16 +233,15 @@ EhcGetState (
 /**\r
   Sets the USB host controller to a specific state.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                The state of the host controller that will be set.\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  State                 The state of the host controller that will be set.\r
 \r
-  @return EFI_SUCCESS           : The USB host controller was successfully placed\r
-  @return in the state specified by State.\r
-  @return EFI_INVALID_PARAMETER : State is invalid.\r
-  @return EFI_DEVICE_ERROR      : Failed to set the state due to device error.\r
+  @retval EFI_SUCCESS           The USB host controller was successfully placed\r
+                                in the state specified by State.\r
+  @retval EFI_INVALID_PARAMETER State is invalid.\r
+  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcSetState (\r
@@ -281,7 +299,7 @@ EhcSetState (
     Status = EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  EHC_DEBUG (("EhcSetState: exit status %r\n", Status));\r
+  DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));\r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
@@ -290,24 +308,23 @@ EhcSetState (
 /**\r
   Retrieves the current status of a USB root hub port.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber           The root hub port to retrieve the state from.   This\r
-                               value is zero-based.\r
-  @param  PortStatus           Variable to receive the port state\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  PortNumber            The root hub port to retrieve the state from.\r
+                                This value is zero-based.\r
+  @param  PortStatus            Variable to receive the port state.\r
 \r
-  @return EFI_SUCCESS           : The status of the USB root hub port specified\r
-  @return by PortNumber was returned in PortStatus.\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @retval EFI_SUCCESS           The status of the USB root hub port specified.\r
+                                by PortNumber was returned in PortStatus.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid.\r
+  @retval EFI_DEVICE_ERROR      Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcGetRootHubPortStatus (\r
-  IN  CONST EFI_USB2_HC_PROTOCOL  *This,\r
-  IN  CONST UINT8                 PortNumber,\r
-  OUT       EFI_USB_PORT_STATUS   *PortStatus\r
+  IN   EFI_USB2_HC_PROTOCOL  *This,\r
+  IN   UINT8                 PortNumber,\r
+  OUT  EFI_USB_PORT_STATUS   *PortStatus\r
   )\r
 {\r
   USB2_HC_DEV             *Ehc;\r
@@ -339,6 +356,10 @@ EhcGetRootHubPortStatus (
   PortStatus->PortStatus        = 0;\r
   PortStatus->PortChangeStatus  = 0;\r
 \r
+  if (EhcIsDebugPortInUse (Ehc, &PortNumber)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
   State                         = EhcReadOpReg (Ehc, Offset);\r
 \r
   //\r
@@ -382,16 +403,15 @@ ON_EXIT:
 /**\r
   Sets a feature for the specified root hub port.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber           Root hub port to set.\r
-  @param  PortFeature          Feature to set\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  PortNumber            Root hub port to set.\r
+  @param  PortFeature           Feature to set.\r
 \r
-  @return EFI_SUCCESS           : The feature specified by PortFeature was set\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was set.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+  @retval EFI_DEVICE_ERROR      Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcSetRootHubPortFeature (\r
@@ -450,7 +470,7 @@ EhcSetRootHubPortFeature (
       Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);\r
 \r
       if (EFI_ERROR (Status)) {\r
-        EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
+        DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
         break;\r
       }\r
     }\r
@@ -465,9 +485,12 @@ EhcSetRootHubPortFeature (
 \r
   case EfiUsbPortPower:\r
     //\r
-    // Not supported, ignore the operation\r
+    // Set port power bit when PPC is 1\r
     //\r
-    Status = EFI_SUCCESS;\r
+    if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {\r
+      State |= PORTSC_POWER;\r
+      EhcWriteOpReg (Ehc, Offset, State);\r
+    }\r
     break;\r
 \r
   case EfiUsbPortOwner:\r
@@ -480,7 +503,7 @@ EhcSetRootHubPortFeature (
   }\r
 \r
 ON_EXIT:\r
-  EHC_DEBUG (("EhcSetRootHubPortFeature: exit status %r\n", Status));\r
+  DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));\r
 \r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
@@ -490,19 +513,18 @@ ON_EXIT:
 /**\r
   Clears a feature for the specified root hub port.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber           Specifies the root hub port whose feature is\r
-                               requested to be cleared.\r
-  @param  PortFeature          Indicates the feature selector associated with the\r
-                               feature clear request.\r
+  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  PortNumber            Specifies the root hub port whose feature is\r
+                                requested to be cleared.\r
+  @param  PortFeature           Indicates the feature selector associated with the\r
+                                feature clear request.\r
 \r
-  @return EFI_SUCCESS           : The feature specified by PortFeature was cleared\r
-  @return for the USB root hub port specified by PortNumber.\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\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
+  @retval EFI_DEVICE_ERROR      Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcClearRootHubPortFeature (\r
@@ -595,6 +617,14 @@ EhcClearRootHubPortFeature (
     break;\r
 \r
   case EfiUsbPortPower:\r
+    //\r
+    // Clear port power bit when PPC is 1\r
+    //\r
+    if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {\r
+      State &= ~PORTSC_POWER;\r
+      EhcWriteOpReg (Ehc, Offset, State);\r
+    }\r
+    break;\r
   case EfiUsbPortSuspendChange:\r
   case EfiUsbPortResetChange:\r
     //\r
@@ -608,7 +638,7 @@ EhcClearRootHubPortFeature (
   }\r
 \r
 ON_EXIT:\r
-  EHC_DEBUG (("EhcClearRootHubPortFeature: exit status %r\n", Status));\r
+  DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));\r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
@@ -617,28 +647,27 @@ ON_EXIT:
 /**\r
   Submits control transfer to a target USB device.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        The target device address\r
-  @param  DeviceSpeed          Target device speed.\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
-  @param  Data                 Data buffer to be transmitted or received from USB\r
-                               device.\r
-  @param  DataLength           The size (in bytes) of the data buffer\r
-  @param  TimeOut              Indicates the maximum timeout, in millisecond,\r
-  @param  Translator           Transaction translator to be used by this device.\r
-  @param  TransferResult       Return the result of this control transfer.\r
-\r
-  @return EFI_SUCCESS           : Transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  : The transfer failed due to lack of resources.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_TIMEOUT           : Transfer failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      : Transfer failed due to host controller or device error.\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         The target device address.\r
+  @param  DeviceSpeed           Target device speed.\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
+  @param  Data                  Data buffer to be transmitted or received from USB\r
+                                device.\r
+  @param  DataLength            The size (in bytes) of the data buffer.\r
+  @param  TimeOut               Indicates the maximum timeout, in millisecond.\r
+  @param  Translator            Transaction translator to be used by this device.\r
+  @param  TransferResult        Return the result of this control transfer.\r
+\r
+  @retval EFI_SUCCESS           Transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           Transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcControlTransfer (\r
@@ -700,7 +729,7 @@ EhcControlTransfer (
   *TransferResult = EFI_USB_ERR_SYSTEM;\r
 \r
   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
-    EHC_ERROR (("EhcControlTransfer: HC halted at entrance\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));\r
 \r
     EhcAckAllInterrupt (Ehc);\r
     goto ON_EXIT;\r
@@ -736,7 +765,7 @@ EhcControlTransfer (
           );\r
 \r
   if (Urb == NULL) {\r
-    EHC_ERROR (("EhcControlTransfer: failed to create URB"));\r
+    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));\r
 \r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
@@ -765,7 +794,7 @@ ON_EXIT:
   gBS->RestoreTPL (OldTpl);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
   }\r
 \r
   return Status;\r
@@ -775,35 +804,33 @@ ON_EXIT:
 /**\r
   Submits bulk transfer to a bulk endpoint of a USB device.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address\r
-  @param  EndPointAddress      Endpoint number and its direction in bit 7. .\r
-  @param  DeviceSpeed          Device speed, Low speed device doesn't support  bulk\r
-                               transfer.\r
-  @param  MaximumPacketLength  Maximum packet size the endpoint is capable of\r
-                               sending or receiving.\r
-  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.\r
-  @param  Data                 Array of pointers to the buffers of data to transmit\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
+  @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk\r
+                                transfer.\r
+  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of\r
+                                sending or receiving.\r
+  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.\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\r
-                               use                        of the subsequent bulk\r
-                               transfer.\r
-  @param  Translator           A pointr to the transaction translator data.\r
-  @param  TimeOut              Indicates the maximum time, in millisecond, which\r
-                               the transfer is allowed to complete.\r
-  @param  TransferResult       A pointer to the detailed result information of the\r
-                               bulk transfer.\r
-\r
-  @return EFI_SUCCESS           : The transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  : The transfer failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_TIMEOUT           : The transfer failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      : The transfer failed due to host controller error.\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\r
+                                use of the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in millisecond, which\r
+                                the transfer is allowed to complete.\r
+  @param  Translator            A pointr to the transaction translator data.\r
+  @param  TransferResult        A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcBulkTransfer (\r
@@ -851,7 +878,7 @@ EhcBulkTransfer (
   Status          = EFI_DEVICE_ERROR;\r
 \r
   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
-    EHC_ERROR (("EhcBulkTransfer: HC is halted\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));\r
 \r
     EhcAckAllInterrupt (Ehc);\r
     goto ON_EXIT;\r
@@ -881,7 +908,7 @@ EhcBulkTransfer (
           );\r
 \r
   if (Urb == NULL) {\r
-    EHC_ERROR (("EhcBulkTransfer: failed to create URB\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));\r
 \r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
@@ -907,7 +934,7 @@ ON_EXIT:
   gBS->RestoreTPL (OldTpl);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
   }\r
 \r
   return Status;\r
@@ -918,32 +945,31 @@ ON_EXIT:
   Submits an asynchronous interrupt transfer to an\r
   interrupt endpoint of a USB device.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address\r
-  @param  EndPointAddress      Endpoint number and its direction encoded in bit 7\r
-  @param  DeviceSpeed          Indicates device speed.\r
-  @param  MaximumPacketLength  Maximum packet size the target endpoint is capable\r
-  @param  IsNewTransfer        If TRUE, to submit an new asynchronous interrupt\r
-                               transfer If FALSE, to remove the specified\r
-                               asynchronous interrupt\r
-  @param  DataToggle           On input, the initial data toggle to use; on output,\r
-                               it is updated to indicate the next data toggle\r
-  @param  PollingInterval      The he interval, in milliseconds, that the transfer\r
-                               is polled.\r
-  @param  DataLength           The length of data to receive at the rate specified\r
-                               by  PollingInterval.\r
-  @param  Translator           Transaction translator to use.\r
-  @param  CallBackFunction     Function to call at the rate specified by\r
-                               PollingInterval\r
-  @param  Context              Context to CallBackFunction.\r
-\r
-  @return EFI_SUCCESS           : The request has been successfully submitted or canceled.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_OUT_OF_RESOURCES  : The request failed due to a lack of resources.\r
-  @return EFI_DEVICE_ERROR      : The transfer failed due to host controller error.\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7\r
+  @param  DeviceSpeed           Indicates device speed.\r
+  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable\r
+  @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt\r
+                                transfer If FALSE, to remove the specified\r
+                                asynchronous interrupt.\r
+  @param  DataToggle            On input, the initial data toggle to use; on output,\r
+                                it is updated to indicate the next data toggle.\r
+  @param  PollingInterval       The he interval, in milliseconds, that the transfer\r
+                                is polled.\r
+  @param  DataLength            The length of data to receive at the rate specified\r
+                                by  PollingInterval.\r
+  @param  Translator            Transaction translator to use.\r
+  @param  CallBackFunction      Function to call at the rate specified by\r
+                                PollingInterval.\r
+  @param  Context               Context to CallBackFunction.\r
+\r
+  @retval EFI_SUCCESS           The request has been successfully submitted or canceled.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcAsyncInterruptTransfer (\r
@@ -965,7 +991,6 @@ EhcAsyncInterruptTransfer (
   URB                     *Urb;\r
   EFI_TPL                 OldTpl;\r
   EFI_STATUS              Status;\r
-  UINT8                   *Data;\r
 \r
   //\r
   // Validate parameters\r
@@ -998,14 +1023,14 @@ EhcAsyncInterruptTransfer (
   if (!IsNewTransfer) {\r
     Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);\r
 \r
-    EHC_DEBUG (("EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));\r
+    DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));\r
     goto ON_EXIT;\r
   }\r
 \r
   Status = EFI_SUCCESS;\r
 \r
   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
-    EHC_ERROR (("EhcAsyncInterruptTransfer: HC is halt\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));\r
     EhcAckAllInterrupt (Ehc);\r
 \r
     Status = EFI_DEVICE_ERROR;\r
@@ -1014,16 +1039,7 @@ EhcAsyncInterruptTransfer (
 \r
   EhcAckAllInterrupt (Ehc);\r
 \r
-  Data = AllocatePool (DataLength);\r
-\r
-  if (Data == NULL) {\r
-    EHC_ERROR (("EhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
-\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Urb = EhcCreateUrb (\r
+  Urb = EhciInsertAsyncIntTransfer (\r
           Ehc,\r
           DeviceAddress,\r
           EndPointAddress,\r
@@ -1031,9 +1047,6 @@ EhcAsyncInterruptTransfer (
           *DataToggle,\r
           MaximumPacketLength,\r
           Translator,\r
-          EHC_INT_TRANSFER_ASYNC,\r
-          NULL,\r
-          Data,\r
           DataLength,\r
           CallBackFunction,\r
           Context,\r
@@ -1041,20 +1054,10 @@ EhcAsyncInterruptTransfer (
           );\r
 \r
   if (Urb == NULL) {\r
-    EHC_ERROR (("EhcAsyncInterruptTransfer: failed to create URB\n"));\r
-\r
-    gBS->FreePool (Data);\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // New asynchronous transfer must inserted to the head.\r
-  // Check the comments in EhcMoniteAsyncRequests\r
-  //\r
-  EhcLinkQhToPeriod (Ehc, Urb->Qh);\r
-  InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);\r
-\r
 ON_EXIT:\r
   Ehc->PciIo->Flush (Ehc->PciIo);\r
   gBS->RestoreTPL (OldTpl);\r
@@ -1067,30 +1070,29 @@ ON_EXIT:
   Submits synchronous interrupt transfer to an interrupt endpoint\r
   of a USB device.\r
 \r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address\r
-  @param  EndPointAddress      Endpoint number and its direction encoded in bit 7\r
-  @param  DeviceSpeed          Indicates device speed.\r
-  @param  MaximumPacketLength  Maximum packet size the target endpoint is capable\r
-                               of sending or receiving.\r
-  @param  Data                 Buffer of data that will be transmitted to  USB\r
-                               device or received from USB device.\r
-  @param  DataLength           On input, the size, in bytes, of the data buffer; On\r
-                               output, the number of bytes transferred.\r
-  @param  DataToggle           On input, the initial data toggle to use; on output,\r
-                               it is updated to indicate the next data toggle\r
-  @param  TimeOut              Maximum time, in second, to complete\r
-  @param  Translator           Transaction translator to use.\r
-  @param  TransferResult       Variable to receive the transfer result\r
-\r
-  @return EFI_SUCCESS           The transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
-  @return EFI_TIMEOUT           The transfer failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      The failed due to host controller or device error\r
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7\r
+  @param  DeviceSpeed           Indicates device speed.\r
+  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable\r
+                                of sending or receiving.\r
+  @param  Data                  Buffer of data that will be transmitted to  USB\r
+                                device or received from USB device.\r
+  @param  DataLength            On input, the size, in bytes, of the data buffer; On\r
+                                output, the number of bytes transferred.\r
+  @param  DataToggle            On input, the initial data toggle to use; on output,\r
+                                it is updated to indicate the next data toggle.\r
+  @param  TimeOut               Maximum time, in second, to complete.\r
+  @param  Translator            Transaction translator to use.\r
+  @param  TransferResult        Variable to receive the transfer result.\r
+\r
+  @return EFI_SUCCESS           The transfer was completed successfully.\r
+  @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
+  @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @return EFI_TIMEOUT           The transfer failed due to timeout.\r
+  @return EFI_DEVICE_ERROR      The failed due to host controller or device error\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcSyncInterruptTransfer (\r
@@ -1120,10 +1122,6 @@ EhcSyncInterruptTransfer (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!EHCI_IS_DATAIN (EndPointAddress)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1141,7 +1139,7 @@ EhcSyncInterruptTransfer (
   Status          = EFI_DEVICE_ERROR;\r
 \r
   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
-    EHC_ERROR (("EhcSyncInterruptTransfer: HC is halt\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));\r
 \r
     EhcAckAllInterrupt (Ehc);\r
     goto ON_EXIT;\r
@@ -1167,7 +1165,7 @@ EhcSyncInterruptTransfer (
           );\r
 \r
   if (Urb == NULL) {\r
-    EHC_ERROR (("EhcSyncInterruptTransfer: failed to create URB\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));\r
 \r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
@@ -1185,12 +1183,13 @@ EhcSyncInterruptTransfer (
     Status = EFI_SUCCESS;\r
   }\r
 \r
+  EhcFreeUrb (Ehc, Urb);\r
 ON_EXIT:\r
   Ehc->PciIo->Flush (Ehc->PciIo);\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
   }\r
 \r
   return Status;\r
@@ -1201,8 +1200,8 @@ ON_EXIT:
   Submits isochronous transfer to a target USB device.\r
 \r
   @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address\r
-  @param  EndPointAddress      End point address with its direction\r
+  @param  DeviceAddress        Target device address.\r
+  @param  EndPointAddress      End point address with its direction.\r
   @param  DeviceSpeed          Device speed, Low speed device doesn't support this\r
                                type.\r
   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of\r
@@ -1211,14 +1210,13 @@ ON_EXIT:
   @param  Data                 Array of pointers to the buffers of data that will\r
                                be transmitted to USB device or received from USB\r
                                device.\r
-  @param  DataLength           The size, in bytes, of the data buffer\r
+  @param  DataLength           The size, in bytes, of the data buffer.\r
   @param  Translator           Transaction translator to use.\r
-  @param  TransferResult       Variable to receive the transfer result\r
+  @param  TransferResult       Variable to receive the transfer result.\r
 \r
-  @return EFI_UNSUPPORTED : Isochronous transfer is unsupported.\r
+  @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcIsochronousTransfer (\r
@@ -1242,8 +1240,8 @@ EhcIsochronousTransfer (
   Submits Async isochronous transfer to a target USB device.\r
 \r
   @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address\r
-  @param  EndPointAddress      End point address with its direction\r
+  @param  DeviceAddress        Target device address.\r
+  @param  EndPointAddress      End point address with its direction.\r
   @param  DeviceSpeed          Device speed, Low speed device doesn't support this\r
                                type.\r
   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of\r
@@ -1252,16 +1250,15 @@ EhcIsochronousTransfer (
   @param  Data                 Array of pointers to the buffers of data that will\r
                                be transmitted to USB device or received from USB\r
                                device.\r
-  @param  DataLength           The size, in bytes, of the data buffer\r
+  @param  DataLength           The size, in bytes, of the data buffer.\r
   @param  Translator           Transaction translator to use.\r
-  @param  IsochronousCallBack  Function to be called when the transfer complete\r
+  @param  IsochronousCallBack  Function to be called when the transfer complete.\r
   @param  Context              Context passed to the call back function as\r
-                               parameter\r
+                               parameter.\r
 \r
-  @return EFI_UNSUPPORTED : Isochronous transfer isn't supported\r
+  @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EhcAsyncIsochronousTransfer (\r
@@ -1281,29 +1278,22 @@ EhcAsyncIsochronousTransfer (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+  Entry point for EFI drivers.\r
+\r
+  @param  ImageHandle       EFI_HANDLE.\r
+  @param  SystemTable       EFI_SYSTEM_TABLE.\r
+\r
+  @return EFI_SUCCESS       Success.\r
+          EFI_DEVICE_ERROR  Fail.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EhcDriverEntryPoint (\r
   IN EFI_HANDLE           ImageHandle,\r
   IN EFI_SYSTEM_TABLE     *SystemTable\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Entry point for EFI drivers.\r
-\r
-Arguments:\r
-\r
-  ImageHandle - EFI_HANDLE\r
-  SystemTable - EFI_SYSTEM_TABLE\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS         Success\r
-  EFI_DEVICE_ERROR    Fail\r
-\r
---*/\r
 {\r
   return EfiLibInstallDriverBindingComponentName2 (\r
            ImageHandle,\r
@@ -1322,11 +1312,11 @@ Returns:
   be supported.\r
 \r
   @param  This                 Protocol instance pointer.\r
-  @param  Controlle            Handle of device to test\r
-  @param  RemainingDevicePath  Not used\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
 \r
-  @return EFI_SUCCESS         : This driver supports this device.\r
-  @return EFI_UNSUPPORTED     : This driver does not support this device.\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1360,7 +1350,7 @@ EhcDriverBindingSupported (
   Status = PciIo->Pci.Read (\r
                         PciIo,\r
                         EfiPciIoWidthUint8,\r
-                        EHC_PCI_CLASSC,\r
+                        PCI_CLASSCODE_OFFSET,\r
                         sizeof (USB_CLASSC) / sizeof (UINT8),\r
                         &UsbClassCReg\r
                         );\r
@@ -1373,9 +1363,8 @@ EhcDriverBindingSupported (
   //\r
   // Test whether the controller belongs to Ehci type\r
   //\r
-  if ((UsbClassCReg.BaseCode     != PCI_CLASS_SERIAL) ||\r
-      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
-      (UsbClassCReg.PI           != EHC_PCI_CLASSC_PI)) {\r
+  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)\r
+      || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
   }\r
@@ -1391,22 +1380,146 @@ ON_EXIT:
   return Status;\r
 }\r
 \r
+/**\r
+  Get the usb debug port related information.\r
+\r
+  @param  Ehc                The EHCI device.\r
+\r
+  @retval RETURN_SUCCESS     Get debug port number, bar and offset successfully.\r
+  @retval Others             The usb host controller does not supported usb debug port capability.\r
+\r
+**/\r
+EFI_STATUS\r
+EhcGetUsbDebugPortInfo (\r
+  IN  USB2_HC_DEV     *Ehc\r
+ )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT16              PciStatus;\r
+  UINT8               CapabilityPtr;\r
+  UINT8               CapabilityId;\r
+  UINT16              DebugPort;\r
+  EFI_STATUS          Status;\r
+\r
+  ASSERT (Ehc->PciIo != NULL);\r
+  PciIo = Ehc->PciIo;\r
+\r
+  //\r
+  // Detect if the EHCI host controller support Capaility Pointer.\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        PCI_PRIMARY_STATUS_OFFSET,\r
+                        sizeof (UINT16),\r
+                        &PciStatus\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {\r
+    //\r
+    // The Pci Device Doesn't Support Capability Pointer.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get Pointer To Capability List\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        PCI_CAPBILITY_POINTER_OFFSET,\r
+                        1,\r
+                        &CapabilityPtr\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Find Capability ID 0xA, Which Is For Debug Port\r
+  //\r
+  while (CapabilityPtr != 0) {\r
+    Status = PciIo->Pci.Read (\r
+                          PciIo,\r
+                          EfiPciIoWidthUint8,\r
+                          CapabilityPtr,\r
+                          1,\r
+                          &CapabilityId\r
+                          );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {\r
+      break;\r
+    }\r
+\r
+    Status = PciIo->Pci.Read (\r
+                          PciIo,\r
+                          EfiPciIoWidthUint8,\r
+                          CapabilityPtr + 1,\r
+                          1,\r
+                          &CapabilityPtr\r
+                          );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // No Debug Port Capability Found\r
+  //\r
+  if (CapabilityPtr == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get The Base Address Of Debug Port Register In Debug Port Capability Register\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                        Ehc->PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        CapabilityPtr + 2,\r
+                        sizeof (UINT16),\r
+                        &DebugPort\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Ehc->DebugPortOffset = DebugPort & 0x1FFF;\r
+  Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);\r
+  Ehc->DebugPortNum    = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
-  Create and initialize a USB2_HC_DEV\r
+  Create and initialize a USB2_HC_DEV.\r
 \r
-  @param  PciIo                  The PciIo on this device\r
-  @param  OriginalPciAttributes  Original PCI attributes\r
+  @param  PciIo                  The PciIo on this device.\r
+  @param  DevicePath             The device path of host controller.\r
+  @param  OriginalPciAttributes  Original PCI attributes.\r
 \r
-  @return The allocated and initialized USB2_HC_DEV structure\r
-  @return if created, otherwise NULL.\r
+  @return  The allocated and initialized USB2_HC_DEV structure if created,\r
+           otherwise NULL.\r
 \r
 **/\r
-STATIC\r
 USB2_HC_DEV *\r
 EhcCreateUsb2Hc (\r
-  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
-  IN UINT64               OriginalPciAttributes\r
+  IN EFI_PCI_IO_PROTOCOL       *PciIo,\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN UINT64                    OriginalPciAttributes\r
   )\r
 {\r
   USB2_HC_DEV             *Ehc;\r
@@ -1436,10 +1549,11 @@ EhcCreateUsb2Hc (
   Ehc->Usb2Hc.GetRootHubPortStatus      = EhcGetRootHubPortStatus;\r
   Ehc->Usb2Hc.SetRootHubPortFeature     = EhcSetRootHubPortFeature;\r
   Ehc->Usb2Hc.ClearRootHubPortFeature   = EhcClearRootHubPortFeature;\r
-  Ehc->Usb2Hc.MajorRevision             = 0x1;\r
-  Ehc->Usb2Hc.MinorRevision             = 0x1;\r
+  Ehc->Usb2Hc.MajorRevision             = 0x2;\r
+  Ehc->Usb2Hc.MinorRevision             = 0x0;\r
 \r
   Ehc->PciIo                 = PciIo;\r
+  Ehc->DevicePath            = DevicePath;\r
   Ehc->OriginalPciAttributes = OriginalPciAttributes;\r
 \r
   InitializeListHead (&Ehc->AsyncIntTransfers);\r
@@ -1448,15 +1562,25 @@ EhcCreateUsb2Hc (
   Ehc->HcCapParams    = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);\r
   Ehc->CapLen         = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;\r
 \r
-  EHC_DEBUG (("EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));\r
+  DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));\r
+\r
+  //\r
+  // EHCI Controllers with a CapLen of 0 are ignored.\r
+  //\r
+  if (Ehc->CapLen == 0) {\r
+    gBS->FreePool (Ehc);\r
+    return NULL;\r
+  }\r
+\r
+  EhcGetUsbDebugPortInfo (Ehc);\r
 \r
   //\r
   // Create AsyncRequest Polling Timer\r
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  EhcMoniteAsyncRequests,\r
+                  TPL_NOTIFY,\r
+                  EhcMonitorAsyncRequests,\r
                   Ehc,\r
                   &Ehc->PollTimer\r
                   );\r
@@ -1469,18 +1593,43 @@ EhcCreateUsb2Hc (
   return Ehc;\r
 }\r
 \r
+/**\r
+  One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
+\r
+  @param  Event                   Pointer to this event\r
+  @param  Context                 Event handler private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EhcExitBootService (\r
+  EFI_EVENT                      Event,\r
+  VOID                           *Context\r
+  )\r
+\r
+{\r
+  USB2_HC_DEV   *Ehc;\r
+\r
+  Ehc = (USB2_HC_DEV *) Context;\r
+\r
+  //\r
+  // Reset the Host Controller\r
+  //\r
+  EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+}\r
+\r
 \r
 /**\r
-  Starting the Usb EHCI Driver\r
+  Starting the Usb EHCI Driver.\r
 \r
   @param  This                 Protocol instance pointer.\r
-  @param  Controller           Handle of device to test\r
-  @param  RemainingDevicePath  Not used\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
 \r
-  @return EFI_SUCCESS          supports this device.\r
-  @return EFI_UNSUPPORTED      do not support this device.\r
-  @return EFI_DEVICE_ERROR     : cannot be started due to device Error\r
-  @return EFI_OUT_OF_RESOURCES : cannot allocate resources\r
+  @return EFI_SUCCESS          supports this device.\r
+  @return EFI_UNSUPPORTED      do not support this device.\r
+  @return EFI_DEVICE_ERROR     cannot be started due to device Error.\r
+  @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1494,9 +1643,23 @@ EhcDriverBindingStart (
   EFI_STATUS              Status;\r
   USB2_HC_DEV             *Ehc;\r
   EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  EFI_PCI_IO_PROTOCOL     *Instance;\r
   UINT64                  Supports;\r
   UINT64                  OriginalPciAttributes;\r
   BOOLEAN                 PciAttributesSaved;\r
+  USB_CLASSC              UsbClassCReg;\r
+  EFI_HANDLE              *HandleBuffer;\r
+  UINTN                   NumberOfHandles;\r
+  UINTN                   Index;\r
+  UINTN                   CompanionSegmentNumber;\r
+  UINTN                   CompanionBusNumber;\r
+  UINTN                   CompanionDeviceNumber;\r
+  UINTN                   CompanionFunctionNumber;\r
+  UINTN                   EhciSegmentNumber;\r
+  UINTN                   EhciBusNumber;\r
+  UINTN                   EhciDeviceNumber;\r
+  UINTN                   EhciFunctionNumber;\r
+  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1511,10 +1674,22 @@ EhcDriverBindingStart (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to open PCI_IO\n"));\r
-    return EFI_DEVICE_ERROR;\r
+    return Status;\r
   }\r
 \r
+  //\r
+  // Open Device Path Protocol for on USB host controller\r
+  //\r
+  HcDevicePath = NULL;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &HcDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
   PciAttributesSaved = FALSE;\r
   //\r
   // Save original PCI attributes\r
@@ -1538,7 +1713,7 @@ EhcDriverBindingStart (
                     &Supports\r
                     );\r
   if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE;\r
+    Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
     Status = PciIo->Attributes (\r
                       PciIo,\r
                       EfiPciIoAttributeOperationEnable,\r
@@ -1548,22 +1723,143 @@ EhcDriverBindingStart (
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to enable controller\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));\r
+    goto CLOSE_PCIIO;\r
+  }\r
+\r
+  //\r
+  // Get the Pci device class code.\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        PCI_CLASSCODE_OFFSET,\r
+                        sizeof (USB_CLASSC) / sizeof (UINT8),\r
+                        &UsbClassCReg\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto CLOSE_PCIIO;\r
+  }\r
+  //\r
+  // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the\r
+  // companion usb ehci host controller and force EHCI driver get attached to it before\r
+  // UHCI or OHCI driver attaches to UHCI or OHCI host controller.\r
+  //\r
+  if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI || UsbClassCReg.ProgInterface == PCI_IF_OHCI) &&\r
+       (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&\r
+       (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {\r
+    Status = PciIo->GetLocation (\r
+                    PciIo,\r
+                    &CompanionSegmentNumber,\r
+                    &CompanionBusNumber,\r
+                    &CompanionDeviceNumber,\r
+                    &CompanionFunctionNumber\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto CLOSE_PCIIO;\r
+    }\r
+\r
+    Status = gBS->LocateHandleBuffer (\r
+                    ByProtocol,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    NULL,\r
+                    &NumberOfHandles,\r
+                    &HandleBuffer\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto CLOSE_PCIIO;\r
+    }\r
+\r
+    for (Index = 0; Index < NumberOfHandles; Index++) {\r
+      //\r
+      // Get the device path on this handle\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                    HandleBuffer[Index],\r
+                    &gEfiPciIoProtocolGuid,\r
+                    (VOID **)&Instance\r
+                    );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = Instance->Pci.Read (\r
+                    Instance,\r
+                    EfiPciIoWidthUint8,\r
+                    PCI_CLASSCODE_OFFSET,\r
+                    sizeof (USB_CLASSC) / sizeof (UINT8),\r
+                    &UsbClassCReg\r
+                    );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_UNSUPPORTED;\r
+        goto CLOSE_PCIIO;\r
+      }\r
+\r
+      if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&\r
+           (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&\r
+           (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {\r
+        Status = Instance->GetLocation (\r
+                    Instance,\r
+                    &EhciSegmentNumber,\r
+                    &EhciBusNumber,\r
+                    &EhciDeviceNumber,\r
+                    &EhciFunctionNumber\r
+                    );\r
+        if (EFI_ERROR (Status)) {\r
+          goto CLOSE_PCIIO;\r
+        }\r
+        //\r
+        // Currently, the judgment on the companion usb host controller is through the\r
+        // same bus number, which may vary on different platform.\r
+        //\r
+        if (EhciBusNumber == CompanionBusNumber) {\r
+          gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+          EhcDriverBindingStart(This, HandleBuffer[Index], NULL);\r
+        }\r
+      }\r
+    }\r
+    Status = EFI_NOT_FOUND;\r
     goto CLOSE_PCIIO;\r
   }\r
 \r
   //\r
   // Create then install USB2_HC_PROTOCOL\r
   //\r
-  Ehc = EhcCreateUsb2Hc (PciIo, OriginalPciAttributes);\r
+  Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);\r
 \r
   if (Ehc == NULL) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to create USB2_HC\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));\r
 \r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto CLOSE_PCIIO;\r
   }\r
 \r
+  //\r
+  // Enable 64-bit DMA support in the PCI layer if this controller\r
+  // supports it.\r
+  //\r
+  if (EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT)) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+                      NULL\r
+                      );\r
+    if (!EFI_ERROR (Status)) {\r
+      Ehc->Support64BitDma = TRUE;\r
+    } else {\r
+      DEBUG ((EFI_D_WARN,\r
+        "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",\r
+        __FUNCTION__, Controller, Status));\r
+    }\r
+  }\r
+\r
   Status = gBS->InstallProtocolInterface (\r
                   &Controller,\r
                   &gEfiUsb2HcProtocolGuid,\r
@@ -1572,20 +1868,26 @@ EhcDriverBindingStart (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
     goto FREE_POOL;\r
   }\r
 \r
   //\r
-  // Robustnesss improvement such as for UoL\r
+  // Robustnesss improvement such as for Duet platform\r
+  // Default is not required.\r
   //\r
-  EhcClearLegacySupport (Ehc);\r
-  EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+  if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
+    EhcClearLegacySupport (Ehc);\r
+  }\r
+\r
+  if (!EhcIsDebugPortInUse (Ehc, NULL)) {\r
+    EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+  }\r
 \r
   Status = EhcInitHC (Ehc);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to init host controller\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));\r
     goto UNINSTALL_USBHC;\r
   }\r
 \r
@@ -1595,12 +1897,27 @@ EhcDriverBindingStart (
   Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
+    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
 \r
     EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
     goto UNINSTALL_USBHC;\r
   }\r
 \r
+  //\r
+  // Create event to stop the HC when exit boot service.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  EhcExitBootService,\r
+                  Ehc,\r
+                  &gEfiEventExitBootServicesGuid,\r
+                  &Ehc->ExitBootServiceEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto UNINSTALL_USBHC;\r
+  }\r
+\r
   //\r
   // Install the component name protocol, don't fail the start\r
   // because of something for display.\r
@@ -1621,7 +1938,7 @@ EhcDriverBindingStart (
     );\r
 \r
 \r
-  EHC_DEBUG (("EhcDriverBindingStart: EHCI started for controller @ %x\n", Controller));\r
+  DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));\r
   return EFI_SUCCESS;\r
 \r
 UNINSTALL_USBHC:\r
@@ -1637,7 +1954,7 @@ FREE_POOL:
   gBS->FreePool (Ehc);\r
 \r
 CLOSE_PCIIO:\r
-  if (PciAttributesSaved == TRUE) {\r
+  if (PciAttributesSaved) {\r
     //\r
     // Restore original PCI attributes\r
     //\r
@@ -1661,16 +1978,16 @@ CLOSE_PCIIO:
 \r
 \r
 /**\r
-  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  Stop this driver on ControllerHandle. Support stopping any child handles\r
   created by this driver.\r
 \r
   @param  This                 Protocol instance pointer.\r
-  @param  Controller           Handle of device to stop driver on\r
-  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer\r
+  @param  Controller           Handle of device to stop driver on.\r
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
   @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
 \r
-  @return EFI_SUCCESS         Success\r
-  @return EFI_DEVICE_ERROR    Fail\r
+  @return EFI_SUCCESS          Success.\r
+  @return EFI_DEVICE_ERROR     Fail.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1708,13 +2025,6 @@ EhcDriverBindingStop (
   Ehc   = EHC_FROM_THIS (Usb2Hc);\r
   PciIo = Ehc->PciIo;\r
 \r
-  //\r
-  // Stop AsyncRequest Polling timer then stop the EHCI driver\r
-  // and uninstall the EHCI protocl.\r
-  //\r
-  gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);\r
-  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
-\r
   Status = gBS->UninstallProtocolInterface (\r
                   Controller,\r
                   &gEfiUsb2HcProtocolGuid,\r
@@ -1725,16 +2035,33 @@ EhcDriverBindingStop (
     return Status;\r
   }\r
 \r
+  //\r
+  // Stop AsyncRequest Polling timer then stop the EHCI driver\r
+  // and uninstall the EHCI protocl.\r
+  //\r
+  gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);\r
+  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
+\r
   if (Ehc->PollTimer != NULL) {\r
     gBS->CloseEvent (Ehc->PollTimer);\r
   }\r
 \r
+  if (Ehc->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (Ehc->ExitBootServiceEvent);\r
+  }\r
+\r
   EhcFreeSched (Ehc);\r
 \r
-  if (Ehc->ControllerNameTable) {\r
+  if (Ehc->ControllerNameTable != NULL) {\r
     FreeUnicodeStringTable (Ehc->ControllerNameTable);\r
   }\r
 \r
+  //\r
+  // Disable routing of all ports to EHCI controller, so all ports are\r
+  // routed back to the UHCI or OHCI controller.\r
+  //\r
+  EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);\r
+\r
   //\r
   // Restore original PCI attributes\r
   //\r
@@ -1757,12 +2084,3 @@ EhcDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_DRIVER_BINDING_PROTOCOL\r
-gEhciDriverBinding = {\r
-  EhcDriverBindingSupported,\r
-  EhcDriverBindingStart,\r
-  EhcDriverBindingStop,\r
-  0x10,\r
-  NULL,\r
-  NULL\r
-};\r