]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
Enhance DebugCommunicationLibUsb to reset the debug port when the PORT_ENABLE bit...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb / DebugCommunicationLibUsb.c
index 7fb671eb4b31368ff55a9a14b9589911ed409f51..54aaa71d750b55028572b687c8f4db13744410b4 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
@@ -99,6 +99,15 @@ typedef struct _USB_DEBUG_PORT_REGISTER {
   UINT8          Reserved3;\r
 }USB_DEBUG_PORT_REGISTER;\r
 \r
+//\r
+// The state machine of usb debug port\r
+//\r
+#define USBDBG_NO_DEV        0   // No device present at debug port\r
+#define USBDBG_NO_DBG_CAB    1   // The device attached is not usb debug cable\r
+#define USBDBG_DBG_CAB       2   // The device attached is usb debug cable\r
+#define USBDBG_INIT_DONE     4   // The usb debug cable device is initialized\r
+#define USBDBG_RESET         8   // The system is reset\r
+\r
 #pragma pack(1)\r
 //\r
 // The internal data structure of DEBUG_PORT_HANDLE, which stores some\r
@@ -109,7 +118,7 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
   // The usb debug port memory BAR number in EHCI configuration space.\r
   //\r
   UINT8        DebugPortBarNumber;\r
-  BOOLEAN      Initialized;\r
+  UINT8        Initialized;\r
   //\r
   // The offset of usb debug port registers in EHCI memory range.\r
   //\r
@@ -117,11 +126,11 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
   //\r
   // The usb debug port memory BAR address.\r
   //\r
-  UINT       UsbDebugPortMemoryBase;\r
+  UINT32       UsbDebugPortMemoryBase;\r
   //\r
   // The EHCI memory BAR address.\r
   //\r
-  UINT       EhciMemoryBase;\r
+  UINT32       EhciMemoryBase;\r
   //\r
   // The Bulk In endpoint toggle bit.\r
   //\r
@@ -138,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
@@ -146,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
@@ -164,9 +231,29 @@ CalculateUsbDebugPortBar (
  )\r
 {\r
   UINT16     PciStatus;\r
+  UINT16     VendorId;\r
+  UINT16     DeviceId;\r
+  UINT8      ProgInterface;\r
+  UINT8      SubClassCode;\r
+  UINT8      BaseCode;\r
   UINT8      CapabilityPtr;\r
   UINT8      CapabilityId;\r
 \r
+  VendorId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_VENDOR_ID_OFFSET);\r
+  DeviceId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_DEVICE_ID_OFFSET);\r
+  \r
+  if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  ProgInterface = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET);\r
+  SubClassCode  = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);\r
+  BaseCode      = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);\r
+  \r
+  if ((ProgInterface != PCI_IF_EHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
   //\r
   // Enable Ehci Host Controller MMIO Space.\r
   //\r
@@ -269,7 +356,17 @@ UsbDebugPortIn (
   //\r
   // Wait for completing the request\r
   //\r
-  while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);\r
+  while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {\r
+    if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
+       != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
+      return RETURN_DEVICE_ERROR;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Clearing DONE bit by writing 1\r
+  //\r
+  MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);\r
 \r
   //\r
   // Check if the request is executed successfully or not.\r
@@ -360,7 +457,17 @@ UsbDebugPortOut (
   //\r
   // Wait for completing the request\r
   //\r
-  while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0);\r
+  while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0) {\r
+    if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
+       != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
+      return RETURN_DEVICE_ERROR;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Clearing DONE bit by writing 1\r
+  //\r
+  MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);\r
 \r
   //\r
   // Check if the request is executed successfully or not.\r
@@ -478,8 +585,8 @@ NeedReinitializeHardware(
   )\r
 {\r
   UINT16                  PciCmd;\r
-  UINT                  UsbDebugPortMemoryBase;\r
-  UINT                  EhciMemoryBase;\r
+  UINT32                  UsbDebugPortMemoryBase;\r
+  UINT32                  EhciMemoryBase;\r
   BOOLEAN                 Status;\r
   USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
 \r
@@ -502,15 +609,23 @@ NeedReinitializeHardware(
   //\r
   PciCmd    = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
   if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
+    PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
+    PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
     Status = TRUE;\r
   }\r
 \r
   //\r
-  // Check if the debug port is enabled and owned by myself.\r
+  // If the owner and in_use bit is not set, it means system is doing cold/warm boot or EHCI host controller is reset by system software.\r
   //\r
-  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
-  if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) &\r
-       (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) == 0) {\r
+  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
+  if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE))\r
+       != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) {\r
+    Status = TRUE;\r
+  }\r
+\r
+  if (Handle->Initialized == USBDBG_RESET) {\r
+    Status = TRUE;\r
+  } else if (Handle->Initialized != USBDBG_INIT_DONE) {\r
     Status = TRUE;\r
   }\r
   return Status;\r
@@ -548,127 +663,146 @@ InitializeUsbDebugHardware (
   UINT8                     DebugPortNumber;\r
   UINT8                     Length;\r
 \r
-  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
+  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
   PciCmd      = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
-  UsbHCSParam = (UINT32 *)(Handle->EhciMemoryBase + 0x04);\r
-  UsbCmd      = (UINT32 *)(Handle->EhciMemoryBase + 0x20);\r
-  UsbStatus   = (UINT32 *)(Handle->EhciMemoryBase + 0x24);\r
+  UsbHCSParam = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x04);\r
+  UsbCmd      = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x20);\r
+  UsbStatus   = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x24);\r
 \r
   //\r
-  // initialize the data toggle used by bulk in/out endpoint.\r
+  // Check if the debug port is enabled and owned by myself.\r
   //\r
-  Handle->BulkInToggle  = 0;\r
-  Handle->BulkOutToggle = 0;\r
+  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
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "UsbDbg: Need to reset the host controller. ControlStatus = %08x\n",\r
+      MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)\r
+      ));\r
+    //\r
+    // If the host controller is halted, then reset and restart it.\r
+    //\r
+    if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {\r
+      DEBUG ((EFI_D_INFO, "UsbDbg: Reset the host controller.\n"));\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
-  // Enable Ehci Memory Space Access\r
-  //\r
-  if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
-    PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
-    PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
-  }\r
+      MmioOr32((UINTN)UsbCmd, BIT0);\r
+      // ensure that the host controller is started (HALTED bit must be cleared)\r
+      while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);\r
+    }\r
 \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
-  //\r
-  // ensure that the host controller is reset.\r
-  //\r
-  while (MmioRead32((UINTN)UsbCmd) & BIT1);\r
+    //\r
+    // First get the ownership of port 0.\r
+    //\r
+    MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE);\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
+    MicroSecondDelay (200000);\r
   }\r
-\r
-  //\r
-  // First get the ownership of port 0.\r
-  //\r
-  MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER);\r
-\r
-  MicroSecondDelay (200000);\r
-\r
   //\r
   // Find out which port is used as debug port.\r
   //\r
   DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);\r
   //\r
-  // Should find a non low-speed device is connected\r
+  // Should find a device is connected at debug port\r
   //\r
-  PortStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);\r
-  if (!(MmioRead32((UINTN)PortStatus) & BIT0) || ((MmioRead32((UINTN)PortStatus) & USB_PORT_LINE_STATUS_MASK) == USB_PORT_LINE_STATUS_LS)) {\r
+  PortStatus = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);\r
+  if (!(MmioRead32((UINTN)PortStatus) & BIT0)) {\r
+    Handle->Initialized = USBDBG_NO_DEV;\r
     return RETURN_NOT_FOUND;\r
   }\r
 \r
-  //\r
-  // Reset the debug port\r
-  //\r
-  MmioOr32((UINTN)PortStatus, BIT8);\r
-  MicroSecondDelay (200000);\r
-  MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);\r
-  while (MmioRead32((UINTN)PortStatus) & BIT8);\r
+  if (Handle->Initialized != USBDBG_INIT_DONE ||\r
+      (MmioRead32 ((UINTN) &UsbDebugPortRegister->ControlStatus) & USB_DEBUG_PORT_ENABLE) == 0) {\r
+    DEBUG ((EFI_D_INFO, "UsbDbg: Reset the debug port.\n"));\r
+    //\r
+    // Reset the debug port\r
+    //\r
+    MmioOr32((UINTN)PortStatus, BIT8);\r
+    MicroSecondDelay (500000);\r
+    MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);\r
+    while (MmioRead32((UINTN)PortStatus) & BIT8);\r
 \r
-  //\r
-  // The port enabled bit should be set by HW.\r
-  //\r
-  if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {\r
-    return RETURN_DEVICE_ERROR;\r
-  }\r
+    //\r
+    // The port enabled bit should be set by HW.\r
+    //\r
+    if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {\r
+      Handle->Initialized = USBDBG_NO_DBG_CAB;\r
+      return RETURN_DEVICE_ERROR;\r
+    }\r
 \r
-  //\r
-  // Enable Usb Debug Port Capability\r
-  //\r
-  MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE);\r
+    //\r
+    // Enable Usb Debug Port Capability\r
+    //\r
+    MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE);\r
 \r
-  //\r
-  // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.\r
-  //\r
-  Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);\r
+    //\r
+    // initialize the data toggle used by bulk in/out endpoint.\r
+    //\r
+    Handle->BulkInToggle  = 0;\r
+    Handle->BulkOutToggle = 0;\r
 \r
-  //\r
-  // It's not a dedicated usb debug device, should use address 0 to get debug descriptor.\r
-  //\r
-  Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x0, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);\r
-  if (RETURN_ERROR(Status)) {\r
     //\r
-    // The device is not a usb debug device.\r
+    // set usb debug device address as 0x7F.\r
     //\r
-    return Status;\r
-  }\r
+    Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, NULL, NULL);\r
+    if (RETURN_ERROR(Status)) {\r
+      //\r
+      // The device can not work well.\r
+      //\r
+      Handle->Initialized = USBDBG_NO_DBG_CAB;\r
+      return Status;\r
+    }\r
 \r
-  if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {\r
-    return RETURN_DEVICE_ERROR;\r
-  }\r
+    //\r
+    // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.\r
+    //\r
+    Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);\r
 \r
-  //\r
-  // set usb debug device address as 0x7F.\r
-  //\r
-  Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, NULL, NULL);\r
-  if (RETURN_ERROR(Status)) {\r
     //\r
-    // The device can not work well.\r
+    // Get debug descriptor.\r
     //\r
-    return Status;\r
+    Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x7F, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);\r
+    if (RETURN_ERROR(Status)) {\r
+      //\r
+      // The device is not a usb debug device.\r
+      //\r
+      Handle->Initialized = USBDBG_NO_DBG_CAB;\r
+      return Status;\r
+    }\r
+\r
+    if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {\r
+      Handle->Initialized = USBDBG_NO_DBG_CAB;\r
+      return RETURN_DEVICE_ERROR;\r
+    }\r
+\r
+    //\r
+    // enable the usb debug feature.\r
+    //\r
+    Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);\r
+    if (RETURN_ERROR(Status)) {\r
+      //\r
+      // The device can not work well.\r
+      //\r
+      Handle->Initialized = USBDBG_NO_DBG_CAB;\r
+      return Status;\r
+    }\r
+  \r
+    Handle->Initialized = USBDBG_DBG_CAB;\r
   }\r
 \r
   //\r
-  // enable the usb debug feature.\r
+  // Set initialized flag\r
   //\r
-  Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);\r
+  Handle->Initialized = USBDBG_INIT_DONE;\r
 \r
-  return Status;\r
+  return RETURN_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -705,6 +839,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
@@ -724,13 +861,6 @@ DebugPortReadBuffer (
     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
   }\r
 \r
-  //\r
-  // Check if debug port is ready\r
-  //\r
-  if (!UsbDebugPortHandle->Initialized) {\r
-    return 0;\r
-  }\r
-\r
   if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
     if (RETURN_ERROR(Status)) {\r
@@ -738,7 +868,7 @@ DebugPortReadBuffer (
     }\r
   }\r
 \r
-  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
+  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
 \r
   //\r
   // First read data from buffer, then read debug port hw to get received data.\r
@@ -766,14 +896,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
@@ -782,46 +941,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
@@ -876,13 +1033,6 @@ DebugPortWriteBuffer (
     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
   }\r
 \r
-  //\r
-  // Check if debug port is ready\r
-  //\r
-  if (!UsbDebugPortHandle->Initialized) {\r
-    return 0;\r
-  }\r
-\r
   if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
     if (RETURN_ERROR(Status)) {\r
@@ -890,7 +1040,7 @@ DebugPortWriteBuffer (
     }\r
   }\r
 \r
-  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
+  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
 \r
   while ((Total < NumberOfBytes)) {\r
     if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
@@ -955,13 +1105,6 @@ DebugPortPollBuffer (
     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
   }\r
 \r
-  //\r
-  // Check if debug port is ready\r
-  //\r
-  if (!UsbDebugPortHandle->Initialized) {\r
-    return 0;\r
-  }\r
-\r
   if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
     Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
     if (RETURN_ERROR(Status)) {\r
@@ -977,7 +1120,7 @@ DebugPortPollBuffer (
     return TRUE;\r
   }\r
 \r
-  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
+  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
 \r
   UsbDebugPortRegister->TokenPid = INPUT_PID;\r
   if (UsbDebugPortHandle->BulkInToggle == 0) {\r
@@ -1000,7 +1143,12 @@ DebugPortPollBuffer (
   //\r
   // Wait for completing the request\r
   //\r
-  while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);\r
+  while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {\r
+    if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
+       != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
+      return FALSE;\r
+    }\r
+  }\r
 \r
   if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {\r
     return FALSE;\r
@@ -1059,16 +1207,44 @@ DebugPortInitialize (
 {\r
   RETURN_STATUS             Status;\r
   USB_DEBUG_PORT_HANDLE     Handle;\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
-    return (DEBUG_PORT_HANDLE *) Context;\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
-    DEBUG ((EFI_D_ERROR, "USB Debug Port: EHCI host controller does not support debug port capability!\n"));\r
+    DEBUG ((EFI_D_ERROR, "UsbDbg: the pci device pointed by PcdUsbEhciPciAddress is not EHCI host controller or does not support debug port capability!\n"));\r
     goto Exit;\r
   }\r
 \r
@@ -1092,16 +1268,16 @@ DebugPortInitialize (
     Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
   }\r
 \r
-  Status = InitializeUsbDebugHardware (&Handle);\r
-  if (RETURN_ERROR(Status)) {\r
-    DEBUG ((EFI_D_ERROR, "USB Debug Port: Initialization failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
-    goto Exit;\r
-  }\r
+  Handle.Initialized = USBDBG_RESET;\r
 \r
-  //\r
-  // Set debug port initialized successfully flag\r
-  //\r
-  Handle.Initialized = TRUE;\r
+  if (NeedReinitializeHardware(&Handle)) {\r
+    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: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
+      goto Exit;\r
+    }\r
+  }\r
 \r
 Exit:\r
 \r