]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
This revision can only work with Intel(c) UDK Debugger Tool version 1.3 or greater...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb / DebugCommunicationLibUsb.c
index aafd52d3c3944975502f5f526f1a1a991c88f8ae..c08d45b7871fe4cecc6e8b6bc1d23d14911e8367 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Port Library implementation based on usb debug port.\r
 \r
-  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -147,6 +147,12 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
   // The data buffer. Maximum length is 8 bytes.\r
   //\r
   UINT8        Data[8];\r
+  //\r
+  // Timter settings\r
+  //\r
+  UINT64       TimerFrequency;\r
+  UINT64       TimerCycle;\r
+  BOOLEAN      TimerCountDown;\r
 } USB_DEBUG_PORT_HANDLE;\r
 #pragma pack()\r
 \r
@@ -155,6 +161,58 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
 //\r
 USB_DEBUG_PORT_HANDLE     mUsbDebugPortHandle;\r
 \r
+/**\r
+  Check if the timer is timeout.\r
+  \r
+  @param[in] UsbDebugPortHandle  Pointer to USB Debug port handle\r
+  @param[in] Timer               The start timer from the begin.\r
+  @param[in] TimeoutTicker       Ticker number need time out.\r
+\r
+  @return TRUE  Timer time out occurs.\r
+  @retval FALSE Timer does not time out.\r
+\r
+**/\r
+BOOLEAN\r
+IsTimerTimeout (\r
+  IN USB_DEBUG_PORT_HANDLE   *UsbDebugPortHandle,\r
+  IN UINT64                  Timer,\r
+  IN UINT64                  TimeoutTicker\r
+  )\r
+{\r
+  UINT64  CurrentTimer;\r
+  UINT64  Delta;\r
+\r
+  CurrentTimer = GetPerformanceCounter ();\r
+\r
+  if (UsbDebugPortHandle->TimerCountDown) {\r
+    //\r
+    // The timer counter counts down.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer < Timer) {\r
+      Delta = Timer - CurrentTimer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);\r
+    }\r
+  } else {\r
+    //\r
+    // The timer counter counts up.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer > Timer) {\r
+      Delta = CurrentTimer - Timer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);\r
+    }\r
+  }\r
\r
+  return (BOOLEAN) (Delta >= TimeoutTicker);\r
+}\r
+\r
 /**\r
   Calculate the usb debug port bar address.\r
 \r
@@ -617,28 +675,21 @@ InitializeUsbDebugHardware (
   if (((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE))\r
        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE)) || (Handle->Initialized == USBDBG_RESET)) {\r
     //\r
-    // If the host controller is not halted, then halt it.\r
-    //\r
-    if ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0) {\r
-      MmioAnd32((UINTN)UsbCmd, (UINT32)~BIT0);\r
-      while ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0);\r
-    }\r
-    //\r
-    // reset the host controller.\r
-    //\r
-    MmioOr32((UINTN)UsbCmd, BIT1);\r
+    // If the host controller is halted, then reset and restart it.\r
     //\r
-    // ensure that the host controller is reset.\r
-    //\r
-    while (MmioRead32((UINTN)UsbCmd) & BIT1);\r
+    if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {\r
+      //\r
+      // reset the host controller.\r
+      //\r
+      MmioOr32((UINTN)UsbCmd, BIT1);\r
+      //\r
+      // ensure that the host controller is reset.\r
+      //\r
+      while ((MmioRead32((UINTN)UsbCmd) & BIT1) != 0);\r
 \r
-    //\r
-    // Start the host controller if it's not running\r
-    //\r
-    if (MmioRead32((UINTN)UsbStatus) & BIT12) {\r
       MmioOr32((UINTN)UsbCmd, BIT0);\r
       // ensure that the host controller is started (HALTED bit must be cleared)\r
-      while (MmioRead32((UINTN)UsbStatus) & BIT12);\r
+      while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);\r
     }\r
 \r
     //\r
@@ -780,6 +831,9 @@ DebugPortReadBuffer (
   UINTN                     Remaining;\r
   UINT8                     Index;\r
   UINT8                     Length;\r
+  UINT64                    Begin;\r
+  UINT64                    TimeoutTicker;\r
+  UINT64                    TimerRound;\r
 \r
   if (NumberOfBytes == 0 || Buffer == NULL) {\r
     return 0;\r
@@ -834,14 +888,43 @@ DebugPortReadBuffer (
   //\r
   // If Timeout is equal to 0, then it means it should always wait until all datum required are received.\r
   //\r
-  if (Timeout == 0) {\r
-    Timeout = 0xFFFFFFFF;\r
+  Begin         = 0;\r
+  TimeoutTicker = 0;  \r
+  TimerRound    = 0;\r
+  if (Timeout != 0) {\r
+    Begin = GetPerformanceCounter ();\r
+    TimeoutTicker = DivU64x32 (\r
+                      MultU64x64 (\r
+                        UsbDebugPortHandle->TimerFrequency,\r
+                        Timeout\r
+                        ),\r
+                      1000000u\r
+                      );\r
+    TimerRound = DivU64x64Remainder (\r
+                   TimeoutTicker,\r
+                   DivU64x32 (UsbDebugPortHandle->TimerCycle, 2),\r
+                   &TimeoutTicker\r
+                   );\r
   }\r
 \r
   //\r
   // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.\r
   //\r
-  while ((Total < NumberOfBytes) && (Timeout != 0)) {\r
+  while (Total < NumberOfBytes) {\r
+    if (Timeout != 0) {\r
+      if (TimerRound == 0) {\r
+        if (IsTimerTimeout (UsbDebugPortHandle, Begin, TimeoutTicker)) {\r
+          //\r
+          // If time out occurs.\r
+          //\r
+          return 0;\r
+        }\r
+      } else {\r
+        if (IsTimerTimeout (UsbDebugPortHandle, Begin, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2))) {\r
+          TimerRound --;\r
+        }\r
+      }\r
+    }\r
     Remaining = NumberOfBytes - Total;\r
     if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
       Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
@@ -850,46 +933,44 @@ DebugPortReadBuffer (
         return Total;\r
       }\r
     } else {\r
-        Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
+      Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
 \r
-        if (RETURN_ERROR(Status)) {\r
-          return Total;\r
-        }\r
+      if (RETURN_ERROR(Status)) {\r
+        return Total;\r
+      }\r
 \r
-        UsbDebugPortHandle->DataCount = Received;\r
+      UsbDebugPortHandle->DataCount = Received;\r
 \r
-        if (Remaining <= Received) {\r
-          Length = (UINT8)Remaining;\r
-        } else {\r
-          Length = (UINT8)Received;\r
-        }\r
+      if (Remaining <= Received) {\r
+        Length = (UINT8)Remaining;\r
+      } else {\r
+        Length = (UINT8)Received;\r
+      }\r
 \r
-        //\r
-        // Copy required data from the data buffer to user buffer.\r
-        //\r
-        for (Index = 0; Index < Length; Index++) {\r
-          (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
-          UsbDebugPortHandle->DataCount--;\r
-        }\r
+      //\r
+      // Copy required data from the data buffer to user buffer.\r
+      //\r
+      for (Index = 0; Index < Length; Index++) {\r
+        (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
+        UsbDebugPortHandle->DataCount--;\r
+      }\r
 \r
-        //\r
-        // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
-        //\r
-        for (Index = 0; Index < Received - Length; Index++) {\r
-          if (Length + Index >= 8) {\r
-            return 0;\r
-          }\r
-          UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
+      //\r
+      // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
+      //\r
+      for (Index = 0; Index < Received - Length; Index++) {\r
+        if (Length + Index >= 8) {\r
+          return 0;\r
         }\r
-        //\r
-        // fixup the real received length in Buffer.\r
-        //\r
-        Received = Length;\r
+        UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
       }\r
-      UsbDebugPortHandle->BulkInToggle ^= 1;\r
-\r
-      Total += Received;\r
-      Timeout -= 100;\r
+      //\r
+      // fixup the real received length in Buffer.\r
+      //\r
+      Received = Length;\r
+    }\r
+    UsbDebugPortHandle->BulkInToggle ^= 1;\r
+    Total += Received;\r
   }\r
 \r
   return Total;\r
@@ -1118,11 +1199,40 @@ DebugPortInitialize (
 {\r
   RETURN_STATUS             Status;\r
   USB_DEBUG_PORT_HANDLE     Handle;\r
-\r  if (Function == NULL && Context != NULL) {\r
-    return (DEBUG_PORT_HANDLE *) Context;\r
+  USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;\r
+  UINT64                    TimerStartValue;\r
+  UINT64                    TimerEndValue;\r
+\r  //\r
+  // Validate the PCD PcdDebugPortHandleBufferSize value \r
+  //\r
+  ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));\r
+\r
+  if (Function == NULL && Context != NULL) {\r
+    UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Context;\r
+  } else {\r
+    ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
+    UsbDebugPortHandle = &Handle;\r
   }\r
 \r
-  ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
+  UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (\r
+                                         &TimerStartValue,\r
+                                         &TimerEndValue\r
+                                         );\r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency  = 0x%lx\n", UsbDebugPortHandle->TimerFrequency)); \r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); \r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue   = 0x%lx\n", TimerEndValue)); \r
+\r
+  if (TimerEndValue < TimerStartValue) {\r
+    UsbDebugPortHandle->TimerCountDown = TRUE;\r
+    UsbDebugPortHandle->TimerCycle     = TimerStartValue - TimerEndValue;\r
+  } else {\r
+    UsbDebugPortHandle->TimerCountDown = FALSE;\r
+    UsbDebugPortHandle->TimerCycle     = TimerEndValue - TimerStartValue;\r
+  }   \r
+\r
+  if (Function == NULL && Context != NULL) {\r
+    return (DEBUG_PORT_HANDLE *) Context;\r
+  }\r
 \r
   Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);\r
   if (RETURN_ERROR (Status)) {\r
@@ -1156,7 +1266,7 @@ DebugPortInitialize (
     DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));\r
     Status = InitializeUsbDebugHardware (&Handle);\r
     if (RETURN_ERROR(Status)) {\r
-      DEBUG ((EFI_D_ERROR, "UsbDbg: Initialization failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
+      DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
       goto Exit;\r
     }\r
   }\r