]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
SourceLevelDebugPkg DebugUsb3: Re-Support IOMMU
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Common.c
index 37f49ad822f56fb6668bb17d4794db0481e9568d..fb9ca84fc7bc09d649b0ebf896521e920df49ac2 100644 (file)
 \r
 #include "DebugCommunicationLibUsb3Internal.h"\r
 \r
-//\r
-// The global variable which can be used after memory is ready.\r
-//\r
-USB3_DEBUG_PORT_HANDLE     mDebugCommunicationLibUsb3DebugPortHandle;\r
-\r
 UINT16   mString0Desc[] = {\r
   //  String Descriptor Type + Length\r
   ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,\r
@@ -150,6 +145,28 @@ XhcSetDebugRegBit (
   XhcWriteDebugReg (Handle, Offset, Data);\r
 }\r
 \r
+/**\r
+  Clear one bit of the debug register while keeping other bits.\r
+\r
+  @param  Handle       Debug port handle.\r
+  @param  Offset       The offset of the debug register.\r
+  @param  Bit          The bit mask of the register to clear.\r
+\r
+**/\r
+VOID\r
+XhcClearDebugRegBit (\r
+  IN USB3_DEBUG_PORT_HANDLE   *Handle,\r
+  IN UINT32                   Offset,\r
+  IN UINT32                   Bit\r
+  )\r
+{\r
+  UINT32                  Data;\r
+\r
+  Data  = XhcReadDebugReg (Handle, Offset);\r
+  Data  &= ~Bit;\r
+  XhcWriteDebugReg (Handle, Offset, Data);\r
+}\r
+\r
 /**\r
   Program and eanble XHCI MMIO base address.\r
 \r
@@ -199,7 +216,7 @@ UpdateXhcResource (
   IN EFI_PHYSICAL_ADDRESS                   XhciMmioBase\r
   )\r
 {\r
-  if ((Handle == NULL) || (Handle->XhciMmioBase == XhciMmioBase)) {\r
+  if (Handle == NULL) {\r
     return;\r
   }\r
 \r
@@ -236,6 +253,14 @@ CalculateUsbDebugPortMmioBase (
   EFI_PHYSICAL_ADDRESS            CapabilityPointer;\r
   UINT8                           CapLength;\r
 \r
+  if (Handle->Initialized != USB3DBG_UNINITIALIZED) {\r
+    if (Handle->Initialized == USB3DBG_NO_DBG_CAB) {\r
+      return RETURN_UNSUPPORTED;\r
+    } else {\r
+      return RETURN_SUCCESS;\r
+    }\r
+  }\r
+\r
   VendorId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_VENDOR_ID_OFFSET);\r
   DeviceId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_DEVICE_ID_OFFSET);\r
   \r
@@ -288,6 +313,7 @@ CalculateUsbDebugPortMmioBase (
   Handle->DebugCapabilityBase   = CapabilityPointer;\r
   Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;\r
   Handle->XhciOpRegister        = Handle->XhciMmioBase + CapLength;\r
+  Handle->DebugSupport = TRUE;\r
   Handle->Initialized = USB3DBG_DBG_CAB;\r
   return RETURN_SUCCESS;\r
 \r
@@ -326,6 +352,9 @@ NeedReinitializeHardware(
   Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);\r
   if ((Dcctrl & BIT0) == 0) {\r
     Result = TRUE;\r
+  } else if (!Handle->Ready) {\r
+    Handle->Ready = TRUE;\r
+    Handle->Initialized = USB3DBG_ENABLED;\r
   }\r
 \r
   return Result;\r
@@ -677,6 +706,13 @@ InitializeUsbDebugHardware (
     MicroSecondDelay (10 * 1000);\r
   }\r
 \r
+  //\r
+  // Clear DCE bit and LSE bit in DCCTRL\r
+  //\r
+  if ((XhcReadDebugReg (Handle, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {\r
+    XhcClearDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);\r
+  }\r
+\r
   //\r
   // Construct the buffer for read, poll and write.\r
   //\r
@@ -745,6 +781,73 @@ Enable:
   return Status;\r
 }\r
 \r
+/**\r
+  Discover and initialize usb debug port.\r
+\r
+  @param Handle                 Debug port handle.\r
+\r
+**/\r
+VOID\r
+DiscoverInitializeUsbDebugPort (\r
+  IN USB3_DEBUG_PORT_HANDLE     *Handle\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_PHYSICAL_ADDRESS          XhciMmioBase;\r
+\r
+  //\r
+  // Read 64-bit MMIO base address\r
+  //\r
+  XhciMmioBase = ProgramXhciBaseAddress ();\r
+  Handle->XhciMmioBase = XhciMmioBase;\r
+\r
+  Status = CalculateUsbDebugPortMmioBase (Handle);\r
+  if (!RETURN_ERROR (Status)) {\r
+    UpdateXhcResource (Handle, XhciMmioBase);\r
+    if (NeedReinitializeHardware (Handle)) {\r
+      InitializeUsbDebugHardware (Handle);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Set USB3 debug instance address.\r
+\r
+  @param[in] Instance           Debug port instance.\r
+\r
+**/  \r
+VOID\r
+SetUsb3DebugPortInstance (\r
+  IN USB3_DEBUG_PORT_HANDLE     *Instance\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS          *AddrPtr;\r
+\r
+  AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();\r
+  ASSERT (AddrPtr != NULL);\r
+  *AddrPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) Instance;\r
+}\r
+\r
+/**\r
+  Return USB3 debug instance address.\r
+\r
+**/  \r
+USB3_DEBUG_PORT_HANDLE *\r
+GetUsb3DebugPortInstance (\r
+  VOID\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS          *AddrPtr;\r
+  USB3_DEBUG_PORT_HANDLE        *Instance;\r
+\r
+  AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();\r
+  ASSERT (AddrPtr != NULL);\r
+\r
+  Instance = (USB3_DEBUG_PORT_HANDLE *) (UINTN) *AddrPtr;\r
+\r
+  return Instance;\r
+}\r
+\r
 /**\r
   Read data from debug device and save the data in buffer.\r
 \r
@@ -772,7 +875,6 @@ DebugPortReadBuffer (
   )\r
 {\r
   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;\r
-  RETURN_STATUS             Status;\r
   UINT8                     Index;\r
   UINT8                     *Data;\r
 \r
@@ -781,24 +883,27 @@ DebugPortReadBuffer (
   }\r
 \r
   //\r
-  // If Handle is NULL, it means memory is ready for use.\r
-  // Use global variable to store handle value.\r
+  // If Handle is NULL, get own instance.\r
+  // If Handle is not NULL, use it and set the instance.\r
   //\r
-  if (Handle == NULL) {\r
-    UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
+  if (Handle != NULL) {\r
+    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;\r
+    SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
   } else {\r
-    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
+    UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
   }\r
-  \r
-  if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
+  if (UsbDebugPortHandle == NULL) {\r
     return 0;\r
   }\r
-  \r
-  if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
-    Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
-    if (RETURN_ERROR(Status)) {\r
-      return 0;\r
-    }\r
+\r
+  if (UsbDebugPortHandle->InNotify) {\r
+    return 0;\r
+  }\r
+\r
+  DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
+\r
+  if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {\r
+    return 0;\r
   }\r
 \r
   Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;\r
@@ -848,10 +953,8 @@ DebugPortWriteBuffer (
   )\r
 {\r
   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;\r
-  RETURN_STATUS             Status;\r
   UINTN                     Sent;\r
   UINTN                     Total;\r
-  EFI_PHYSICAL_ADDRESS      XhciMmioBase;\r
 \r
   if (NumberOfBytes == 0 || Buffer == NULL) {\r
     return 0;\r
@@ -861,38 +964,34 @@ DebugPortWriteBuffer (
   Total = 0;\r
 \r
   //\r
-  // If Handle is NULL, it means memory is ready for use.\r
-  // Use global variable to store handle value.\r
+  // If Handle is NULL, get own instance.\r
+  // If Handle is not NULL, use it and set the instance.\r
   //\r
-  if (Handle == NULL) {\r
-    UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
+  if (Handle != NULL) {\r
+    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;\r
+    SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
   } else {\r
-    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
+    UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
   }\r
-  \r
-  if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
+  if (UsbDebugPortHandle == NULL) {\r
     return 0;\r
   }\r
 \r
-  //\r
-  // MMIO base address is possible to clear, set it if it is cleared. (XhciMemorySpaceClose in PchUsbCommon.c)\r
-  //\r
-  XhciMmioBase = ProgramXhciBaseAddress ();\r
+  if (UsbDebugPortHandle->InNotify) {\r
+    return 0;\r
+  }\r
 \r
-  UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
+  DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
 \r
-  if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
-    Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
-    if (RETURN_ERROR(Status)) {\r
-      return 0;\r
-    }\r
+  if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {\r
+    return 0;\r
   }\r
 \r
   //\r
   // When host is trying to send data, write will be blocked.\r
   // Poll to see if there is any data sent by host at first.\r
   //\r
-  DebugPortPollBuffer (Handle);\r
+  DebugPortPollBuffer (UsbDebugPortHandle);\r
 \r
   while ((Total < NumberOfBytes)) {\r
     if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {\r
@@ -900,7 +999,7 @@ DebugPortWriteBuffer (
     } else {\r
       Sent = (UINT8)(NumberOfBytes - Total);\r
     }\r
-    Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);\r
+    XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);\r
     Total += Sent;\r
   }\r
   \r
@@ -928,33 +1027,31 @@ DebugPortPollBuffer (
 {\r
   USB3_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;\r
   UINTN                     Length;\r
-  RETURN_STATUS             Status;\r
-  EFI_PHYSICAL_ADDRESS      XhciMmioBase;\r
 \r
   //\r
-  // If Handle is NULL, it means memory is ready for use.\r
-  // Use global variable to store handle value.\r
+  // If Handle is NULL, get own instance.\r
+  // If Handle is not NULL, use it and set the instance.\r
   //\r
-  if (Handle == NULL) {\r
-    UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
+  if (Handle != NULL) {\r
+    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;\r
+    SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
   } else {\r
-    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
+    UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
+  }\r
+  if (UsbDebugPortHandle == NULL) {\r
+    return FALSE;\r
   }\r
 \r
-  if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
-    return 0;\r
+  if (UsbDebugPortHandle->InNotify) {\r
+    return FALSE;\r
   }\r
 \r
-  XhciMmioBase = ProgramXhciBaseAddress ();\r
-  UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
-  \r
-  if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
-    Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
-    if (RETURN_ERROR(Status)) {\r
-      return FALSE;\r
-    }\r
+  DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
+\r
+  if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {\r
+    return FALSE;\r
   }\r
-  \r
+\r
   //\r
   // If the data buffer is not empty, then return TRUE directly.\r
   // Otherwise initialize a usb read transaction and read data to internal data buffer.\r
@@ -967,7 +1064,7 @@ DebugPortPollBuffer (
   // Read data as much as we can\r
   //\r
   Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
-  XhcDataTransfer (Handle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);\r
+  XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);\r
 \r
   if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
     return FALSE;\r
@@ -1015,8 +1112,6 @@ DebugPortInitialize (
   IN DEBUG_PORT_CONTINUE  Function\r
   )\r
 {\r
-  RETURN_STATUS             Status;\r
-  USB3_DEBUG_PORT_HANDLE    Handle;\r
   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;\r
 \r
   //\r
@@ -1025,40 +1120,19 @@ DebugPortInitialize (
   ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));\r
 \r
   if (Function == NULL && Context != NULL) {\r
-    UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Context;\r
-  } else {\r
-    ZeroMem(&Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
-    UsbDebugPortHandle = &Handle;\r
+    SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE *) Context);\r
+    return (DEBUG_PORT_HANDLE) Context;\r
   }\r
-\r
-  if (Function == NULL && Context != NULL) {\r
-    return (DEBUG_PORT_HANDLE *) Context;\r
+  UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
+  if (UsbDebugPortHandle == NULL) {\r
+    return NULL;\r
   }\r
-  \r
-  //\r
-  // Read 64-bit MMIO base address\r
-  //\r
-  UsbDebugPortHandle->XhciMmioBase = ProgramXhciBaseAddress ();\r
 \r
-  Status = CalculateUsbDebugPortMmioBase (UsbDebugPortHandle);\r
-  if (RETURN_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-\r
-  if (NeedReinitializeHardware(&Handle)) {\r
-    Status = InitializeUsbDebugHardware (&Handle);\r
-    if (RETURN_ERROR(Status)) {\r
-      goto Exit;\r
-    }\r
-  }\r
-\r
-Exit:\r
+  DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
 \r
   if (Function != NULL) {\r
-    Function (Context, &Handle);\r
-  } else {\r
-    CopyMem(&mDebugCommunicationLibUsb3DebugPortHandle, &Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
+    Function (Context, (DEBUG_PORT_HANDLE) UsbDebugPortHandle);\r
   }\r
 \r
-  return (DEBUG_PORT_HANDLE)(UINTN)&mDebugCommunicationLibUsb3DebugPortHandle;\r
+  return (DEBUG_PORT_HANDLE) UsbDebugPortHandle;\r
 }\r