]> 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 d6210255f4dcae47a9a5ccb6b077e419f92cc531..bdd9c27db562aa204b120247be751269e27d2bec 100644 (file)
@@ -1,23 +1,18 @@
-/** @file  \r
+/** @file\r
   The Ehci controller driver.\r
 \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
+  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
   Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached\r
-  to the EHCI controller before the UHCI driver attaches to the companion UHCI controller. \r
-  This way avoids the control transfer on a shared port between EHCI and companion host\r
-  controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.\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
-Copyright (c) 2006 - 2009, 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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -88,7 +83,7 @@ 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
   DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
 \r
@@ -121,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
@@ -133,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
@@ -191,8 +203,8 @@ ON_EXIT:
 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
@@ -310,9 +322,9 @@ EhcSetState (
 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
@@ -344,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
@@ -469,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
@@ -598,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
@@ -964,7 +991,6 @@ EhcAsyncInterruptTransfer (
   URB                     *Urb;\r
   EFI_TPL                 OldTpl;\r
   EFI_STATUS              Status;\r
-  UINT8                   *Data;\r
 \r
   //\r
   // Validate parameters\r
@@ -1013,16 +1039,7 @@ EhcAsyncInterruptTransfer (
 \r
   EhcAckAllInterrupt (Ehc);\r
 \r
-  Data = AllocatePool (DataLength);\r
-\r
-  if (Data == NULL) {\r
-    DEBUG ((EFI_D_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
@@ -1030,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
@@ -1040,20 +1054,10 @@ EhcAsyncInterruptTransfer (
           );\r
 \r
   if (Urb == NULL) {\r
-    DEBUG ((EFI_D_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
@@ -1118,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
@@ -1183,6 +1183,7 @@ EhcSyncInterruptTransfer (
     Status = EFI_SUCCESS;\r
   }\r
 \r
+  EhcFreeUrb (Ehc, Urb);\r
 ON_EXIT:\r
   Ehc->PciIo->Flush (Ehc->PciIo);\r
   gBS->RestoreTPL (OldTpl);\r
@@ -1363,7 +1364,7 @@ EhcDriverBindingSupported (
   // Test whether the controller belongs to Ehci type\r
   //\r
   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)\r
-      || ((UsbClassCReg.PI != PCI_IF_EHCI) && (UsbClassCReg.PI !=PCI_IF_UHCI))) {\r
+      || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
   }\r
@@ -1379,11 +1380,135 @@ 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
 \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 if created,\r
@@ -1392,8 +1517,9 @@ ON_EXIT:
 **/\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
@@ -1427,6 +1553,7 @@ EhcCreateUsb2Hc (
   Ehc->Usb2Hc.MinorRevision             = 0x0;\r
 \r
   Ehc->PciIo                 = PciIo;\r
+  Ehc->DevicePath            = DevicePath;\r
   Ehc->OriginalPciAttributes = OriginalPciAttributes;\r
 \r
   InitializeListHead (&Ehc->AsyncIntTransfers);\r
@@ -1437,12 +1564,22 @@ EhcCreateUsb2Hc (
 \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
+                  TPL_NOTIFY,\r
                   EhcMonitorAsyncRequests,\r
                   Ehc,\r
                   &Ehc->PollTimer\r
@@ -1460,7 +1597,7 @@ EhcCreateUsb2Hc (
   One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
 \r
   @param  Event                   Pointer to this event\r
-  @param  Context                 Event hanlder private data\r
+  @param  Context                 Event handler private data\r
 \r
 **/\r
 VOID\r
@@ -1476,11 +1613,9 @@ EhcExitBootService (
   Ehc = (USB2_HC_DEV *) Context;\r
 \r
   //\r
-  // Stop the Host Controller\r
+  // Reset the Host Controller\r
   //\r
-  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
-\r
-  return;\r
+  EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
 }\r
 \r
 \r
@@ -1516,14 +1651,15 @@ EhcDriverBindingStart (
   EFI_HANDLE              *HandleBuffer;\r
   UINTN                   NumberOfHandles;\r
   UINTN                   Index;\r
-  UINTN                   UhciSegmentNumber;\r
-  UINTN                   UhciBusNumber;\r
-  UINTN                   UhciDeviceNumber;\r
-  UINTN                   UhciFunctionNumber;\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
@@ -1541,6 +1677,19 @@ EhcDriverBindingStart (
     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
@@ -1564,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
@@ -1594,19 +1743,19 @@ EhcDriverBindingStart (
     goto CLOSE_PCIIO;\r
   }\r
   //\r
-  // determine if the device is UHCI host controller or not. If yes, then find out the \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 driver attaches to UHCI host controller.\r
+  // UHCI or OHCI driver attaches to UHCI or OHCI host controller.\r
   //\r
-  if ((UsbClassCReg.PI == PCI_IF_UHCI) &&\r
-       (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && \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
-                    &UhciSegmentNumber,\r
-                    &UhciBusNumber,\r
-                    &UhciDeviceNumber,\r
-                    &UhciFunctionNumber\r
+                    &CompanionSegmentNumber,\r
+                    &CompanionBusNumber,\r
+                    &CompanionDeviceNumber,\r
+                    &CompanionFunctionNumber\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       goto CLOSE_PCIIO;\r
@@ -1647,8 +1796,8 @@ EhcDriverBindingStart (
         goto CLOSE_PCIIO;\r
       }\r
 \r
-      if ((UsbClassCReg.PI == PCI_IF_EHCI) &&\r
-           (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && \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
@@ -1664,7 +1813,7 @@ EhcDriverBindingStart (
         // 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 == UhciBusNumber) {\r
+        if (EhciBusNumber == CompanionBusNumber) {\r
           gBS->CloseProtocol (\r
                     Controller,\r
                     &gEfiPciIoProtocolGuid,\r
@@ -1682,7 +1831,7 @@ EhcDriverBindingStart (
   //\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
     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));\r
@@ -1691,6 +1840,26 @@ EhcDriverBindingStart (
     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
@@ -1704,13 +1873,16 @@ EhcDriverBindingStart (
   }\r
 \r
   //\r
-  // Robustnesss improvement such as for UoL\r
+  // Robustnesss improvement such as for Duet platform\r
   // Default is not required.\r
   //\r
   if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
     EhcClearLegacySupport (Ehc);\r
   }\r
-  EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+\r
+  if (!EhcIsDebugPortInUse (Ehc, NULL)) {\r
+    EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+  }\r
 \r
   Status = EhcInitHC (Ehc);\r
 \r
@@ -1806,7 +1978,7 @@ 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
@@ -1853,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
@@ -1870,6 +2035,13 @@ 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
@@ -1884,6 +2056,12 @@ EhcDriverBindingStop (
     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