]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / Uhci.c
index 0fc633d8bbfaeb5ce91785b0d213a88debb26ed5..3ec5ecf0e4132549f565671419243e7edb27f979 100644 (file)
@@ -1,43 +1,37 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 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
-\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
-\r
-Module Name:\r
-\r
-  Uhci.c\r
-\r
-Abstract:\r
-\r
   The UHCI driver model and HC protocol routines.\r
 \r
-Revision History\r
-\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Uhci.h"\r
 \r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
+  UhciDriverBindingSupported,\r
+  UhciDriverBindingStart,\r
+  UhciDriverBindingStop,\r
+  0x20,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
 /**\r
   Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  @param  Attributes           A bit mask of the reset operation to perform.  See\r
-                               below for a list of the supported bit mask values.\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  Attributes             A bit mask of the reset operation to perform.  See\r
+                                 below for a list of the supported bit mask values.\r
 \r
-  @return EFI_SUCCESS           : The reset operation succeeded.\r
-  @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
-  @return EFI_UNSUPPORTED       : This type of reset is not currently supported\r
-  @return EFI_DEVICE_ERROR      : Other errors\r
+  @return EFI_SUCCESS            The reset operation succeeded.\r
+  @return EFI_INVALID_PARAMETER  Attributes is not valid.\r
+  @return EFI_UNSUPPORTED        This type of reset is not currently supported.\r
+  @return EFI_DEVICE_ERROR       Other errors.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2Reset (\r
@@ -53,7 +47,18 @@ Uhci2Reset (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Uhc     = UHC_FROM_USB2_HC_PROTO (This);\r
+  Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
+\r
+  if (Uhc->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
+      Uhc->DevicePath\r
+      );\r
+  }\r
 \r
   OldTpl  = gBS->RaiseTPL (UHCI_TPL);\r
 \r
@@ -112,20 +117,19 @@ ON_INVAILD_PARAMETER:
 /**\r
   Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                Variable to receive current device state\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  State                  Variable to receive current device state.\r
 \r
-  @return EFI_SUCCESS           : The state is returned\r
-  @return EFI_INVALID_PARAMETER : State is not valid.\r
-  @return EFI_DEVICE_ERROR      : Other errors2006\r
+  @return EFI_SUCCESS            The state is returned.\r
+  @return EFI_INVALID_PARAMETER  State is not valid.\r
+  @return EFI_DEVICE_ERROR       Other errors.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2GetState (\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
   USB_HC_DEV          *Uhc;\r
@@ -141,7 +145,7 @@ Uhci2GetState (
   UsbCmd  = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
   UsbSts  = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);\r
 \r
-  if (UsbCmd & USBCMD_EGSM) {\r
+  if ((UsbCmd & USBCMD_EGSM) !=0 ) {\r
     *State = EfiUsbHcStateSuspend;\r
 \r
   } else if ((UsbSts & USBSTS_HCH) != 0) {\r
@@ -158,16 +162,15 @@ Uhci2GetState (
 /**\r
   Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                Indicates the state of the host controller that will\r
-                               be set.\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  State                  Indicates the state of the host controller that will\r
+                                 be set.\r
 \r
-  @return EFI_SUCCESS           : Host controller was successfully placed in the state\r
-  @return EFI_INVALID_PARAMETER : State is invalid.\r
-  @return EFI_DEVICE_ERROR      : Failed to set the state\r
+  @return EFI_SUCCESS            Host controller was successfully placed in the state.\r
+  @return EFI_INVALID_PARAMETER  State is invalid.\r
+  @return EFI_DEVICE_ERROR       Failed to set the state.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2SetState (\r
@@ -265,19 +268,18 @@ ON_EXIT:
 /**\r
   Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance\r
-  @param  MaxSpeed             A pointer to the max speed USB host controller\r
-                               supports.\r
-  @param  PortNumber           A pointer to the number of root hub ports.\r
-  @param  Is64BitCapable       A pointer to an integer to show whether USB host\r
-                               controller supports 64-bit memory addressing.\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  MaxSpeed               A pointer to the max speed USB host controller\r
+                                 supports.\r
+  @param  PortNumber             A pointer to the number of root hub ports.\r
+  @param  Is64BitCapable         A pointer to an integer to show whether USB host\r
+                                 controller supports 64-bit memory addressing.\r
 \r
-  @return EFI_SUCCESS           : capabilities were retrieved successfully.\r
-  @return EFI_INVALID_PARAMETER : MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
-  @return EFI_DEVICE_ERROR      : An error was encountered\r
+  @return EFI_SUCCESS            capabilities were retrieved successfully.\r
+  @return EFI_INVALID_PARAMETER  MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
+  @return EFI_DEVICE_ERROR       An error was encountered.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2GetCapability (\r
@@ -313,14 +315,15 @@ Uhci2GetCapability (
     // returns 0 in this bit if port number is invalid. Also, if\r
     // PciIo IoRead returns error, 0xFFFF is returned to caller.\r
     //\r
-    if (((PortSC & 0x80) != 0) && (PortSC != 0xFFFF)) {\r
-      (*PortNumber)++;\r
+    if (((PortSC & 0x80) == 0) || (PortSC == 0xFFFF)) {\r
+      break;\r
     }\r
+    (*PortNumber)++;\r
   }\r
 \r
   Uhc->RootPorts = *PortNumber;\r
 \r
-  DEBUG ((EFI_D_INFO, "Uhci2GetCapability: %d ports\n", Uhc->RootPorts));\r
+  DEBUG ((EFI_D_INFO, "Uhci2GetCapability: %d ports\n", (UINT32)Uhc->RootPorts));\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -328,23 +331,22 @@ Uhci2GetCapability (
 /**\r
   Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL.\r
-  @param  PortNumber           The port to get status\r
-  @param  PortStatus           A pointer to the current port status bits and  port\r
-                               status change bits.\r
+  @param  This                    A pointer to the EFI_USB2_HC_PROTOCOL.\r
+  @param  PortNumber              The port to get status.\r
+  @param  PortStatus              A pointer to the current port status bits and  port\r
+                                  status change bits.\r
 \r
-  @return EFI_SUCCESS           : status of the USB root hub port was returned in PortStatus.\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @return EFI_SUCCESS             status of the USB root hub port was returned in PortStatus.\r
+  @return EFI_INVALID_PARAMETER   PortNumber is invalid.\r
+  @return EFI_DEVICE_ERROR        Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2GetRootHubPortStatus (\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
   USB_HC_DEV          *Uhc;\r
@@ -367,24 +369,24 @@ Uhci2GetRootHubPortStatus (
 \r
   PortSC                        = UhciReadReg (Uhc->PciIo, Offset);\r
 \r
-  if (PortSC & USBPORTSC_CCS) {\r
+  if ((PortSC & USBPORTSC_CCS) != 0) {\r
     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
   }\r
 \r
-  if (PortSC & USBPORTSC_PED) {\r
+  if ((PortSC & USBPORTSC_PED) != 0) {\r
     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
   }\r
 \r
-  if (PortSC & USBPORTSC_SUSP) {\r
+  if ((PortSC & USBPORTSC_SUSP) != 0) {\r
     DEBUG ((EFI_D_INFO, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber));\r
     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
   }\r
 \r
-  if (PortSC & USBPORTSC_PR) {\r
+  if ((PortSC & USBPORTSC_PR) != 0) {\r
     PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
   }\r
 \r
-  if (PortSC & USBPORTSC_LSDA) {\r
+  if ((PortSC & USBPORTSC_LSDA) != 0) {\r
     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
   }\r
 \r
@@ -393,11 +395,11 @@ Uhci2GetRootHubPortStatus (
   //\r
   PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
 \r
-  if (PortSC & USBPORTSC_CSC) {\r
+  if ((PortSC & USBPORTSC_CSC) != 0) {\r
     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
   }\r
 \r
-  if (PortSC & USBPORTSC_PEDC) {\r
+  if ((PortSC & USBPORTSC_PEDC) != 0) {\r
     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
   }\r
 \r
@@ -408,18 +410,17 @@ Uhci2GetRootHubPortStatus (
 /**\r
   Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
 \r
-  @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL.\r
-  @param  PortNumber           Specifies the root hub port whose feature  is\r
-                               requested to be set.\r
-  @param  PortFeature          Indicates the feature selector associated  with the\r
-                               feature set request.\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL.\r
+  @param  PortNumber             Specifies the root hub port whose feature  is\r
+                                 requested to be set.\r
+  @param  PortFeature            Indicates the feature selector associated  with the\r
+                                 feature set request.\r
 \r
-  @return EFI_SUCCESS           : PortFeature was set for the root port\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @return EFI_SUCCESS            PortFeature was set for the root port.\r
+  @return EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
+  @return EFI_DEVICE_ERROR       Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2SetRootHubPortFeature (\r
@@ -448,7 +449,7 @@ Uhci2SetRootHubPortFeature (
   switch (PortFeature) {\r
   case EfiUsbPortSuspend:\r
     Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
-    if (!(Command & USBCMD_EGSM)) {\r
+    if ((Command & USBCMD_EGSM) == 0) {\r
       //\r
       // if global suspend is not active, can set port suspend\r
       //\r
@@ -488,18 +489,17 @@ Uhci2SetRootHubPortFeature (
 /**\r
   Clears a feature for the specified root hub port according to Uefi 2.0 spec.\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           : PortFeature was cleared for the USB root hub port\r
-  @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @return EFI_SUCCESS            PortFeature was cleared for the USB root hub port.\r
+  @return EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
+  @return EFI_DEVICE_ERROR       Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2ClearRootHubPortFeature (\r
@@ -590,27 +590,27 @@ Uhci2ClearRootHubPortFeature (
 \r
 \r
 /**\r
-  Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
-\r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  Request             : USB device request to send\r
-  TransferDirection   : Data direction of the Data stage in control transfer\r
-  Data                : Data to transmit/receive in data stage\r
-  DataLength          : Length of the data\r
-  TimeOut             : Maximum time, in microseconds, for transfer to complete.\r
-  TransferResult      : Variable to receive the transfer result\r
-\r
-  @return EFI_SUCCESS           : The control transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_TIMEOUT           : Failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
+  Submits control transfer to a target USB device according to UEFI 2.0 spec.\r
+\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress          Target device address.\r
+  @param  DeviceSpeed            Device speed.\r
+  @param  MaximumPacketLength    Maximum packet size of the target endpoint.\r
+  @param  Request                USB device request to send.\r
+  @param  TransferDirection      Data direction of the Data stage in control transfer.\r
+  @param  Data                   Data to transmit/receive in data stage.\r
+  @param  DataLength             Length of the data.\r
+  @param  TimeOut                Maximum time, in microseconds, for transfer to complete.\r
+  @param  Translator             Transaction translator to be used by this device.\r
+  @param  TransferResult         Variable to receive the transfer result.\r
+\r
+  @return EFI_SUCCESS            The control transfer was completed successfully.\r
+  @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.\r
+  @return EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @return EFI_TIMEOUT            Failed due to timeout.\r
+  @return EFI_DEVICE_ERROR       Failed due to host controller or device error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2ControlTransfer (\r
@@ -638,6 +638,7 @@ Uhci2ControlTransfer (
   UINT8                   *DataPhy;\r
   VOID                    *DataMap;\r
   BOOLEAN                 IsSlowDevice;\r
+  UINTN                   TransferDataLength;\r
 \r
   Uhc         = UHC_FROM_USB2_HC_PROTO (This);\r
   TDs         = NULL;\r
@@ -665,10 +666,16 @@ Uhci2ControlTransfer (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
+  if ((TransferDirection != EfiUsbNoData) && (Data == NULL || DataLength == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (TransferDirection == EfiUsbNoData) {\r
+    TransferDataLength = 0;\r
+  } else {\r
+    TransferDataLength = *DataLength;\r
+  }\r
+\r
   *TransferResult = EFI_USB_ERR_SYSTEM;\r
   Status          = EFI_DEVICE_ERROR;\r
 \r
@@ -705,9 +712,11 @@ Uhci2ControlTransfer (
           Uhc,\r
           DeviceAddress,\r
           PktId,\r
+          (UINT8*)Request,\r
           RequestPhy,\r
+          (UINT8*)Data,\r
           DataPhy,\r
-          *DataLength,\r
+          TransferDataLength,\r
           (UINT8) MaximumPacketLength,\r
           IsSlowDevice\r
           );\r
@@ -722,7 +731,7 @@ Uhci2ControlTransfer (
   // the TD to corrosponding queue head, then check\r
   // the execution result\r
   //\r
-  UhciLinkTdToQh (Uhc->CtrlQh, TDs);\r
+  UhciLinkTdToQh (Uhc, Uhc->CtrlQh, TDs);\r
   Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
   UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
 \r
@@ -746,32 +755,30 @@ ON_EXIT:
 }\r
 \r
 \r
-\r
 /**\r
-  Submits bulk transfer to a bulk endpoint of a USB device\r
-\r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  EndPointAddress     : Endpoint number and direction\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
-  Data                : Array of pointers to the buffers of data\r
-  DataLength          : On input, size of the data buffer, On output,\r
-  actually transferred data size.\r
-  DataToggle          : On input, data toggle to use; On output, next data toggle\r
-  Translator          : A pointr to the transaction translator data.\r
-  TimeOut             : Maximum time out, in microseconds\r
-  TransferResult      : Variable to receive transfer result\r
-\r
-  @return EFI_SUCCESS           : The bulk transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_TIMEOUT           : Failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress          Target device address.\r
+  @param  EndPointAddress        Endpoint number and direction.\r
+  @param  DeviceSpeed            Device speed.\r
+  @param  MaximumPacketLength    Maximum packet size of the target endpoint.\r
+  @param  DataBuffersNumber      Number of data buffers prepared for the transfer.\r
+  @param  Data                   Array of pointers to the buffers of data.\r
+  @param  DataLength             On input, size of the data buffer, On output,\r
+                                 actually transferred data size.\r
+  @param  DataToggle             On input, data toggle to use; On output, next data toggle.\r
+  @param  TimeOut                Maximum time out, in microseconds.\r
+  @param  Translator             A pointr to the transaction translator data.\r
+  @param  TransferResult         Variable to receive transfer result.\r
+\r
+  @return EFI_SUCCESS            The bulk transfer was completed successfully.\r
+  @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.\r
+  @return EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @return EFI_TIMEOUT            Failed due to timeout.\r
+  @return EFI_DEVICE_ERROR       Failed due to host controller or device error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2BulkTransfer (\r
@@ -808,11 +815,7 @@ Uhci2BulkTransfer (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (*DataLength == 0) {\r
+  if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL) || (TransferResult == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -844,7 +847,7 @@ Uhci2BulkTransfer (
   // Map the source data buffer for bus master access,\r
   // then create a list of TDs\r
   //\r
-  if (EndPointAddress & 0x80) {\r
+  if ((EndPointAddress & 0x80) != 0) {\r
     Direction = EfiUsbDataIn;\r
   } else {\r
     Direction = EfiUsbDataOut;\r
@@ -862,6 +865,7 @@ Uhci2BulkTransfer (
              DeviceAddress,\r
              EndPointAddress,\r
              PktId,\r
+             (UINT8 *)*Data,\r
              DataPhy,\r
              *DataLength,\r
              DataToggle,\r
@@ -882,7 +886,7 @@ Uhci2BulkTransfer (
   //\r
   BulkQh = Uhc->BulkQh;\r
 \r
-  UhciLinkTdToQh (BulkQh, TDs);\r
+  UhciLinkTdToQh (Uhc, BulkQh, TDs);\r
   Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
   UhciUnlinkTdFromQh (BulkQh, TDs);\r
 \r
@@ -905,27 +909,26 @@ ON_EXIT:
   Submits an asynchronous interrupt transfer to an\r
   interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
 \r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  EndPointAddress     : Endpoint number and direction\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  IsNewTransfer       : If TRUE, submit a new transfer, if FALSE cancel old transfer\r
-  DataToggle          : On input, data toggle to use; On output, next data toggle\r
-  PollingInterval     : Interrupt poll rate in milliseconds\r
-  DataLength          : On input, size of the data buffer, On output,\r
-  actually transferred data size.\r
-  Translator          : A pointr to the transaction translator data.\r
-  CallBackFunction    : Function to call periodically\r
-  Context             : User context\r
-\r
-  @return EFI_SUCCESS           : Transfer was submitted\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_OUT_OF_RESOURCES  : Failed due to a lack of resources.\r
-  @return EFI_DEVICE_ERROR      : Can't read register\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress          Target device address.\r
+  @param  EndPointAddress        Endpoint number and direction.\r
+  @param  DeviceSpeed            Device speed.\r
+  @param  MaximumPacketLength    Maximum packet size of the target endpoint.\r
+  @param  IsNewTransfer          If TRUE, submit a new transfer, if FALSE cancel old transfer.\r
+  @param  DataToggle             On input, data toggle to use; On output, next data toggle.\r
+  @param  PollingInterval        Interrupt poll rate in milliseconds.\r
+  @param  DataLength             On input, size of the data buffer, On output,\r
+                                 actually transferred data size.\r
+  @param  Translator             A pointr to the transaction translator data.\r
+  @param  CallBackFunction       Function to call periodically.\r
+  @param  Context                User context.\r
+\r
+  @return EFI_SUCCESS            Transfer was submitted.\r
+  @return EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @return EFI_OUT_OF_RESOURCES   Failed due to a lack of resources.\r
+  @return EFI_DEVICE_ERROR       Can't read register.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2AsyncInterruptTransfer (\r
@@ -951,7 +954,6 @@ Uhci2AsyncInterruptTransfer (
   EFI_STATUS          Status;\r
   UINT8               *DataPtr;\r
   UINT8               *DataPhy;\r
-  VOID                *DataMap;\r
   UINT8               PktId;\r
 \r
   Uhc       = UHC_FROM_USB2_HC_PROTO (This);\r
@@ -959,7 +961,6 @@ Uhci2AsyncInterruptTransfer (
   IntTds    = NULL;\r
   DataPtr   = NULL;\r
   DataPhy   = NULL;\r
-  DataMap   = NULL;\r
 \r
   IsSlowDevice  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
 \r
@@ -1000,40 +1001,30 @@ Uhci2AsyncInterruptTransfer (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  if ((EndPointAddress & 0x80) == 0) {\r
+    PktId = OUTPUT_PACKET_ID;\r
+  } else {\r
+    PktId = INPUT_PACKET_ID;\r
+  }\r
+\r
   //\r
   // Allocate and map source data buffer for bus master access.\r
   //\r
-  DataPtr = AllocatePool (DataLength);\r
+  DataPtr = UsbHcAllocateMem (Uhc->MemPool, DataLength);\r
 \r
   if (DataPtr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
+  DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Uhc->MemPool, DataPtr, DataLength);\r
 \r
-  //\r
-  // Map the user data then create a queue head and\r
-  // list of TD for it.\r
-  //\r
-  Status = UhciMapUserData (\r
-             Uhc,\r
-             EfiUsbDataIn,\r
-             DataPtr,\r
-             &DataLength,\r
-             &PktId,\r
-             &DataPhy,\r
-             &DataMap\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto FREE_DATA;\r
-  }\r
+  OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
 \r
   Qh = UhciCreateQh (Uhc, PollingInterval);\r
 \r
   if (Qh == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
-    goto UNMAP_DATA;\r
+    goto FREE_DATA;\r
   }\r
 \r
   IntTds = UhciCreateBulkOrIntTds (\r
@@ -1041,6 +1032,7 @@ Uhci2AsyncInterruptTransfer (
              DeviceAddress,\r
              EndPointAddress,\r
              PktId,\r
+             DataPtr,\r
              DataPhy,\r
              DataLength,\r
              DataToggle,\r
@@ -1053,7 +1045,7 @@ Uhci2AsyncInterruptTransfer (
     goto DESTORY_QH;\r
   }\r
 \r
-  UhciLinkTdToQh (Qh, IntTds);\r
+  UhciLinkTdToQh (Uhc, Qh, IntTds);\r
 \r
   //\r
   // Save QH-TD structures to async Interrupt transfer list,\r
@@ -1067,7 +1059,6 @@ Uhci2AsyncInterruptTransfer (
              EndPointAddress,\r
              DataLength,\r
              PollingInterval,\r
-             DataMap,\r
              DataPtr,\r
              CallBackFunction,\r
              Context,\r
@@ -1078,7 +1069,7 @@ Uhci2AsyncInterruptTransfer (
     goto DESTORY_QH;\r
   }\r
 \r
-  UhciLinkQhToFrameList (Uhc->FrameBase, Qh);\r
+  UhciLinkQhToFrameList (Uhc, Qh);\r
 \r
   gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
@@ -1086,11 +1077,8 @@ Uhci2AsyncInterruptTransfer (
 DESTORY_QH:\r
   UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
 \r
-UNMAP_DATA:\r
-  Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
-\r
 FREE_DATA:\r
-  gBS->FreePool (DataPtr);\r
+  UsbHcFreeMem (Uhc->MemPool, DataPtr, DataLength);\r
   Uhc->PciIo->Flush (Uhc->PciIo);\r
 \r
   gBS->RestoreTPL (OldTpl);\r
@@ -1101,28 +1089,27 @@ FREE_DATA:
   Submits synchronous interrupt transfer to an interrupt endpoint\r
   of a USB device according to UEFI 2.0 spec.\r
 \r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  EndPointAddress     : Endpoint number and direction\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
-  Data                : Array of pointers to the buffers of data\r
-  DataLength          : On input, size of the data buffer, On output,\r
-  actually transferred data size.\r
-  DataToggle          : On input, data toggle to use; On output, next data toggle\r
-  TimeOut             : Maximum time out, in microseconds\r
-  Translator          : A pointr to the transaction translator data.\r
-  TransferResult      : Variable to receive transfer result\r
-\r
-  @return EFI_SUCCESS           : The transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
-  @return EFI_TIMEOUT           : Failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
+\r
+  @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress          Target device address.\r
+  @param  EndPointAddress        Endpoint number and direction.\r
+  @param  DeviceSpeed            Device speed.\r
+  @param  MaximumPacketLength    Maximum packet size of the target endpoint.\r
+  @param  Data                   Array of pointers to the buffers of data.\r
+  @param  DataLength             On input, size of the data buffer, On output,\r
+                                 actually transferred data size.\r
+  @param  DataToggle             On input, data toggle to use; On output, next data toggle.\r
+  @param  TimeOut                Maximum time out, in microseconds.\r
+  @param  Translator             A pointr to the transaction translator data.\r
+  @param  TransferResult         Variable to receive transfer result.\r
+\r
+  @return EFI_SUCCESS            The transfer was completed successfully.\r
+  @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.\r
+  @return EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @return EFI_TIMEOUT            Failed due to timeout.\r
+  @return EFI_DEVICE_ERROR       Failed due to host controller or device error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2SyncInterruptTransfer (\r
@@ -1164,10 +1151,6 @@ Uhci2SyncInterruptTransfer (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((EndPointAddress & 0x80) == 0) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1215,6 +1198,7 @@ Uhci2SyncInterruptTransfer (
           DeviceAddress,\r
           EndPointAddress,\r
           PktId,\r
+          (UINT8 *)Data,\r
           DataPhy,\r
           *DataLength,\r
           DataToggle,\r
@@ -1230,7 +1214,7 @@ Uhci2SyncInterruptTransfer (
   }\r
 \r
 \r
-  UhciLinkTdToQh (Uhc->SyncIntQh, TDs);\r
+  UhciLinkTdToQh (Uhc, Uhc->SyncIntQh, TDs);\r
 \r
   Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
 \r
@@ -1253,22 +1237,21 @@ ON_EXIT:
 /**\r
   Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
 \r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  EndPointAddress     : Endpoint number and direction\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
-  Data                : Array of pointers to the buffers of data\r
-  DataLength          : On input, size of the data buffer, On output,\r
-  actually transferred data size.\r
-  Translator          : A pointr to the transaction translator data.\r
-  TransferResult      : Variable to receive transfer result\r
+  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and direction.\r
+  @param  DeviceSpeed           Device speed.\r
+  @param  MaximumPacketLength   Maximum packet size of the target endpoint.\r
+  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.\r
+  @param  Data                  Array of pointers to the buffers of data.\r
+  @param  DataLength            On input, size of the data buffer, On output,\r
+                                actually transferred data size.\r
+  @param  Translator            A pointr to the transaction translator data.\r
+  @param  TransferResult        Variable to receive transfer result.\r
 \r
   @return EFI_UNSUPPORTED\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2IsochronousTransfer (\r
@@ -1291,21 +1274,22 @@ Uhci2IsochronousTransfer (
 /**\r
   Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
 \r
-  This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  DeviceAddress       : Target device address\r
-  EndPointAddress     : Endpoint number and direction\r
-  DeviceSpeed         : Device speed\r
-  MaximumPacketLength : Maximum packet size of the target endpoint\r
-  DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
-  Data                : Array of pointers to the buffers of data\r
-  Translator          : A pointr to the transaction translator data.\r
-  IsochronousCallBack : Function to call when the transfer complete\r
-  Context             : Pass to the call back function as parameter\r
+  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and direction.\r
+  @param  DeviceSpeed           Device speed.\r
+  @param  MaximumPacketLength   Maximum packet size of the target endpoint.\r
+  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.\r
+  @param  Data                  Array of pointers to the buffers of data.\r
+  @param  DataLength            On input, size of the data buffer, On output,\r
+                                actually transferred data size.\r
+  @param  Translator            A pointr to the transaction translator data.\r
+  @param  IsochronousCallBack   Function to call when the transfer complete.\r
+  @param  Context               Pass to the call back function as parameter.\r
 \r
   @return EFI_UNSUPPORTED\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Uhci2AsyncIsochronousTransfer (\r
@@ -1325,29 +1309,22 @@ Uhci2AsyncIsochronousTransfer (
   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
+  @retval EFI_SUCCESS      Driver is successfully loaded.\r
+  @return Others           Failed.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 UhciDriverEntryPoint (\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 : Driver is successfully loaded\r
-    Others      : Failed\r
-\r
---*/\r
 {\r
   return EfiLibInstallDriverBindingComponentName2 (\r
            ImageHandle,\r
@@ -1365,11 +1342,11 @@ UhciDriverEntryPoint (
   ControllerHandle that has UsbHcProtocol installed will be supported.\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         : 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
@@ -1404,7 +1381,7 @@ UhciDriverBindingSupported (
   Status = PciIo->Pci.Read (\r
                         PciIo,\r
                         EfiPciIoWidthUint8,\r
-                        CLASSC_OFFSET,\r
+                        PCI_CLASSCODE_OFFSET,\r
                         sizeof (USB_CLASSC) / sizeof (UINT8),\r
                         &UsbClassCReg\r
                         );\r
@@ -1419,7 +1396,7 @@ UhciDriverBindingSupported (
   //\r
   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
-      (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)\r
+      (UsbClassCReg.ProgInterface != PCI_IF_UHCI)\r
       ) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
@@ -1439,18 +1416,20 @@ ON_EXIT:
 \r
 \r
 /**\r
-  Allocate and initialize the empty UHCI device\r
+  Allocate and initialize the empty UHCI device.\r
 \r
-  @param  PciIo                The PCIIO to use\r
+  @param  PciIo                  The PCIIO to use.\r
+  @param  DevicePath             The device path of host controller.\r
+  @param  OriginalPciAttributes  The original PCI attributes.\r
 \r
-  @return Allocated UHCI device\r
+  @return Allocated UHCI device. If err, return NULL.\r
 \r
 **/\r
-STATIC\r
 USB_HC_DEV *\r
 UhciAllocateDev (\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
   USB_HC_DEV  *Uhc;\r
@@ -1484,6 +1463,7 @@ UhciAllocateDev (
   Uhc->Usb2Hc.MinorRevision             = 0x1;\r
 \r
   Uhc->PciIo                 = PciIo;\r
+  Uhc->DevicePath            = DevicePath;\r
   Uhc->OriginalPciAttributes = OriginalPciAttributes;\r
   Uhc->MemPool               = UsbHcInitMemPool (PciIo, TRUE, 0);\r
 \r
@@ -1496,7 +1476,7 @@ UhciAllocateDev (
 \r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   UhciMonitorAsyncReqList,\r
                   Uhc,\r
                   &Uhc->AsyncIntMonitor\r
@@ -1510,20 +1490,17 @@ UhciAllocateDev (
   return Uhc;\r
 \r
 ON_ERROR:\r
-  gBS->FreePool (Uhc);\r
+  FreePool (Uhc);\r
   return NULL;\r
 }\r
 \r
 \r
 /**\r
-  Free the UHCI device and release its associated resources\r
+  Free the UHCI device and release its associated resources.\r
 \r
-  @param  Uhc                  The UHCI device to release\r
-\r
-  @return None\r
+  @param  Uhc     The UHCI device to release.\r
 \r
 **/\r
-STATIC\r
 VOID\r
 UhciFreeDev (\r
   IN USB_HC_DEV           *Uhc\r
@@ -1533,28 +1510,29 @@ UhciFreeDev (
     gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
   }\r
 \r
+  if (Uhc->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (Uhc->ExitBootServiceEvent);\r
+  }\r
+\r
   if (Uhc->MemPool != NULL) {\r
     UsbHcFreeMemPool (Uhc->MemPool);\r
   }\r
 \r
-  if (Uhc->CtrlNameTable) {\r
+  if (Uhc->CtrlNameTable != NULL) {\r
     FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
   }\r
 \r
-  gBS->FreePool (Uhc);\r
+  FreePool (Uhc);\r
 }\r
 \r
 \r
 /**\r
-  Uninstall all Uhci Interface\r
+  Uninstall all Uhci Interface.\r
 \r
-  @param  Controller           Controller handle\r
+  @param  Controller           Controller handle.\r
   @param  This                 Protocol instance pointer.\r
 \r
-  @return VOID\r
-\r
 **/\r
-STATIC\r
 VOID\r
 UhciCleanDevUp (\r
   IN  EFI_HANDLE           Controller,\r
@@ -1562,19 +1540,24 @@ UhciCleanDevUp (
   )\r
 {\r
   USB_HC_DEV          *Uhc;\r
+  EFI_STATUS          Status;\r
 \r
   //\r
   // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
   //\r
   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
-  UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
 \r
-  gBS->UninstallProtocolInterface (\r
-        Controller,\r
-        &gEfiUsb2HcProtocolGuid,\r
-        &Uhc->Usb2Hc\r
-        );\r
 \r
+  Status = gBS->UninstallProtocolInterface (\r
+                  Controller,\r
+                  &gEfiUsb2HcProtocolGuid,\r
+                  &Uhc->Usb2Hc\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
   UhciFreeAllAsyncReq (Uhc);\r
   UhciDestoryFrameList (Uhc);\r
 \r
@@ -1591,19 +1574,47 @@ UhciCleanDevUp (
   UhciFreeDev (Uhc);\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
+UhcExitBootService (\r
+  EFI_EVENT                      Event,\r
+  VOID                           *Context\r
+  )\r
+{\r
+  USB_HC_DEV   *Uhc;\r
+\r
+  Uhc = (USB_HC_DEV *) Context;\r
+\r
+  //\r
+  // Stop the Host Controller\r
+  //\r
+  UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
+\r
+  //\r
+  // Reset the Host Controller\r
+  //\r
+  UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
+  gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
+}\r
 \r
 /**\r
-  Starting the Usb UHCI Driver\r
+  Starting the Usb UHCI 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
   @retval EFI_SUCCESS          This driver supports this device.\r
   @retval EFI_UNSUPPORTED      This driver does not support this device.\r
-  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error\r
-                               EFI_OUT_OF_RESOURCES- Failed due to resource\r
-                               shortage\r
+  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.\r
+                               EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1620,6 +1631,7 @@ UhciDriverBindingStart (
   UINT64              Supports;\r
   UINT64              OriginalPciAttributes;\r
   BOOLEAN             PciAttributesSaved;\r
+  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;\r
 \r
   //\r
   // Open PCIIO, then enable the EHC device and turn off emulation\r
@@ -1638,6 +1650,19 @@ UhciDriverBindingStart (
     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
@@ -1658,7 +1683,9 @@ UhciDriverBindingStart (
   // Robustnesss improvement such as for UoL\r
   // Default is not required.\r
   //\r
-  // UhciTurnOffUsbEmulation (PciIo);\r
+  if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
+    UhciTurnOffUsbEmulation (PciIo);\r
+  }\r
 \r
   Status = PciIo->Attributes (\r
                     PciIo,\r
@@ -1667,7 +1694,7 @@ UhciDriverBindingStart (
                     &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
@@ -1680,7 +1707,7 @@ UhciDriverBindingStart (
     goto CLOSE_PCIIO;\r
   }\r
 \r
-  Uhc = UhciAllocateDev (PciIo, OriginalPciAttributes);\r
+  Uhc = UhciAllocateDev (PciIo, HcDevicePath, OriginalPciAttributes);\r
 \r
   if (Uhc == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
@@ -1721,6 +1748,21 @@ UhciDriverBindingStart (
     goto FREE_UHC;\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
+                  UhcExitBootService,\r
+                  Uhc,\r
+                  &gEfiEventExitBootServicesGuid,\r
+                  &Uhc->ExitBootServiceEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto UNINSTALL_USBHC;\r
+  }\r
+\r
   //\r
   // Install the component name protocol\r
   //\r
@@ -1749,11 +1791,19 @@ UhciDriverBindingStart (
 \r
   return EFI_SUCCESS;\r
 \r
+UNINSTALL_USBHC:\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         Controller,\r
+         &gEfiUsb2HcProtocolGuid,\r
+         &Uhc->Usb2Hc,\r
+         NULL\r
+         );\r
+\r
 FREE_UHC:\r
   UhciFreeDev (Uhc);\r
 \r
 CLOSE_PCIIO:\r
-  if (PciAttributesSaved == TRUE) {\r
+  if (PciAttributesSaved) {\r
     //\r
     // Restore original PCI attributes\r
     //\r
@@ -1777,12 +1827,12 @@ 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\r
@@ -1831,11 +1881,3 @@ UhciDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
-  UhciDriverBindingSupported,\r
-  UhciDriverBindingStart,\r
-  UhciDriverBindingStop,\r
-  0x20,\r
-  NULL,\r
-  NULL\r
-};\r