]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeMdeModulePkg/Xhci: Fix a wrong conditional judgment which bring assertion with...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
index c141803c388071bab53b82cb7c7ade936e588abf..787bdc13a022f9cffd4a22f103774ccf8bb001ea 100644 (file)
@@ -10,7 +10,7 @@
   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
+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
@@ -120,9 +120,22 @@ EhcReset (
   USB2_HC_DEV             *Ehc;\r
   EFI_TPL                 OldTpl;\r
   EFI_STATUS              Status;\r
+  UINT32                  DbgCtrlStatus;\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 +146,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
@@ -323,6 +344,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 +366,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
@@ -1390,11 +1419,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
@@ -1403,8 +1556,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
@@ -1438,6 +1592,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
@@ -1455,6 +1610,8 @@ EhcCreateUsb2Hc (
     gBS->FreePool (Ehc);\r
     return NULL;\r
   }\r
+  \r
+  EhcGetUsbDebugPortInfo (Ehc);\r
 \r
   //\r
   // Create AsyncRequest Polling Timer\r
@@ -1541,6 +1698,8 @@ EhcDriverBindingStart (
   UINTN                   EhciBusNumber;\r
   UINTN                   EhciDeviceNumber;\r
   UINTN                   EhciFunctionNumber;\r
+  UINT32                  State;\r
+  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1558,6 +1717,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
@@ -1699,7 +1871,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
@@ -1727,7 +1899,13 @@ EhcDriverBindingStart (
   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