]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeModulePkg: Fix EHCI module build warning reported by VS2005 tool chain.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
index d6210255f4dcae47a9a5ccb6b077e419f92cc531..5ff9b80560aebd1a6a63021d4812c6017a546f43 100644 (file)
@@ -10,8 +10,8 @@
   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 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2012, 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
@@ -120,6 +120,7 @@ EhcReset (
   USB2_HC_DEV             *Ehc;\r
   EFI_TPL                 OldTpl;\r
   EFI_STATUS              Status;\r
+  UINT32                  DbgCtrlStatus;\r
 \r
   OldTpl  = gBS->RaiseTPL (EHC_TPL);\r
   Ehc     = EHC_FROM_THIS (This);\r
@@ -133,6 +134,14 @@ EhcReset (
     //\r
     // Host Controller must be Halt when Reset it\r
     //\r
+    if (Ehc->DebugPortNum != 0) {\r
+      DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);\r
+      if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {\r
+        Status = EFI_SUCCESS;\r
+        goto ON_EXIT;\r
+      }\r
+    }\r
+\r
     if (!EhcIsHalt (Ehc)) {\r
       Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
 \r
@@ -191,8 +200,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 +319,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
@@ -323,6 +332,7 @@ EhcGetRootHubPortStatus (
   UINTN                   Index;\r
   UINTN                   MapSize;\r
   EFI_STATUS              Status;\r
+  UINT32                  DbgCtrlStatus;\r
 \r
   if (PortStatus == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -344,6 +354,13 @@ EhcGetRootHubPortStatus (
   PortStatus->PortStatus        = 0;\r
   PortStatus->PortChangeStatus  = 0;\r
 \r
+  if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) {\r
+    DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);\r
+    if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
   State                         = EhcReadOpReg (Ehc, Offset);\r
 \r
   //\r
@@ -469,9 +486,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 +618,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
@@ -1363,7 +1391,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))) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
   }\r
@@ -1379,6 +1407,129 @@ 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
@@ -1437,6 +1588,16 @@ 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
@@ -1476,11 +1637,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
@@ -1524,6 +1683,7 @@ EhcDriverBindingStart (
   UINTN                   EhciBusNumber;\r
   UINTN                   EhciDeviceNumber;\r
   UINTN                   EhciFunctionNumber;\r
+  UINT32                  State;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1598,7 +1758,7 @@ EhcDriverBindingStart (
   // 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.PI == PCI_IF_UHCI) &&\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
@@ -1647,7 +1807,7 @@ EhcDriverBindingStart (
         goto CLOSE_PCIIO;\r
       }\r
 \r
-      if ((UsbClassCReg.PI == PCI_IF_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
@@ -1704,13 +1864,19 @@ 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 (Ehc->DebugPortNum != 0) {\r
+    State = EhcReadDbgRegister(Ehc, 0);\r
+    if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {\r
+      EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
+    }\r
+  }\r
 \r
   Status = EhcInitHC (Ehc);\r
 \r
@@ -1884,6 +2050,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