]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeModulePkg: Enable port power if port power control feature is supported by EHCI
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
index aae39b0acbda79f6395bbc78010aca21fa887f32..c141803c388071bab53b82cb7c7ade936e588abf 100644 (file)
@@ -1,9 +1,17 @@
-/** @file\r
-  \r
+/** @file  \r
   The Ehci controller driver.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\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
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+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
@@ -46,12 +54,6 @@ gEhciDriverBinding = {
   NULL\r
 };\r
 \r
-///\r
-/// USB host controller Programming Interface.\r
-///\r
-#define  PCI_CLASSC_PI_UHCI               0x00\r
-#define  PCI_CLASSC_PI_EHCI               0x20\r
-\r
 /**\r
   Retrieves the capability of root hub ports.\r
 \r
@@ -189,8 +191,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
@@ -308,9 +310,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
@@ -467,9 +469,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
@@ -596,6 +601,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
@@ -1347,7 +1360,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
@@ -1361,7 +1374,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 != EHC_PCI_CLASSC_PI) && (UsbClassCReg.PI !=PCI_CLASSC_PI_UHCI))) {\r
+      || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface !=PCI_IF_UHCI))) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
   }\r
@@ -1435,6 +1448,14 @@ 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
   //\r
   // Create AsyncRequest Polling Timer\r
   //\r
@@ -1474,11 +1495,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
@@ -1576,10 +1595,13 @@ EhcDriverBindingStart (
     goto CLOSE_PCIIO;\r
   }\r
 \r
+  //\r
+  // Get the Pci device class code.\r
+  //\r
   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
@@ -1588,8 +1610,12 @@ EhcDriverBindingStart (
     Status = EFI_UNSUPPORTED;\r
     goto CLOSE_PCIIO;\r
   }\r
-\r
-  if ((UsbClassCReg.PI == PCI_CLASSC_PI_UHCI) &&\r
+  //\r
+  // determine if the device is UHCI 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
+  //\r
+  if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI) &&\r
        (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && \r
        (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {\r
     Status = PciIo->GetLocation (\r
@@ -1628,7 +1654,7 @@ EhcDriverBindingStart (
       Status = Instance->Pci.Read (\r
                     Instance,\r
                     EfiPciIoWidthUint8,\r
-                    EHC_PCI_CLASSC,\r
+                    PCI_CLASSCODE_OFFSET,\r
                     sizeof (USB_CLASSC) / sizeof (UINT8),\r
                     &UsbClassCReg\r
                     );\r
@@ -1638,7 +1664,7 @@ EhcDriverBindingStart (
         goto CLOSE_PCIIO;\r
       }\r
 \r
-      if ((UsbClassCReg.PI == PCI_CLASSC_PI_EHCI) &&\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
@@ -1651,6 +1677,10 @@ EhcDriverBindingStart (
         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 == UhciBusNumber) {\r
           gBS->CloseProtocol (\r
                     Controller,\r
@@ -1691,7 +1721,7 @@ 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
@@ -1871,6 +1901,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 controller.\r
+  //\r
+  EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);\r
+\r
   //\r
   // Restore original PCI attributes\r
   //\r