Author: janderwald
Date: Sat Feb 25 03:28:17 2012
New Revision: 55849

URL: http://svn.reactos.org/svn/reactos?rev=55849&view=rev
Log:
[USBEHCI]
- Fix reset port sequence #2
- Clear unwanted bits
- Fix wait time as in spec
- Wait max 500ms for the reset bit to clear, otherwise restart the reset 
sequence
- Check if work item is currently queued

Modified:
    trunk/reactos/drivers/usb/usbehci/hardware.cpp

Modified: trunk/reactos/drivers/usb/usbehci/hardware.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hardware.cpp?rev=55849&r1=55848&r2=55849&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hardware.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hardware.cpp [iso-8859-1] Sat Feb 25 
03:28:17 2012
@@ -123,6 +123,7 @@
     PVOID m_SCEContext;                                                        
        // status change callback routine context
     BOOLEAN m_DoorBellRingInProgress;                                          
        // door bell ring in progress
     WORK_QUEUE_ITEM m_StatusChangeWorkItem;                                    
        // work item for status change callback
+    ULONG m_WorkItemActive;                                                    
        // work item status
     ULONG m_SyncFramePhysAddr;                                                 
        // periodic frame list physical address
     BUS_INTERFACE_STANDARD m_BusInterface;                                     
        // pci bus interface
 
@@ -973,13 +974,13 @@
     // Reset and clean enable
     //
     PortStatus |= EHCI_PRT_RESET;
-    PortStatus &= ~EHCI_PRT_ENABLED;
+    PortStatus &= EHCI_PORTSC_DATAMASK;
     EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
 
     //
-    // delay is 20 ms for port reset as per USB 2.0 spec
-    //
-    Timeout.QuadPart = 20;
+    // delay is 50 ms for port reset as per USB 2.0 spec
+    //
+    Timeout.QuadPart = 50;
     DPRINT1("Waiting %d milliseconds for port reset\n", Timeout.LowPart);
 
     //
@@ -1077,7 +1078,7 @@
     ULONG PortId,
     ULONG Status)
 {
-    ULONG Value;
+    ULONG Value, WaitTime, ResetComplete;
     LARGE_INTEGER Timeout;
 
     DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", 
PortId, Status);
@@ -1087,32 +1088,43 @@
 
     if (Status == C_PORT_RESET)
     {
-        //
-        // Clear reset
-        //
-        Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-        Value &= ~EHCI_PRT_RESET;
-        EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
-
         do
         {
-            //
-            // wait
-            //
-            KeStallExecutionProcessor(100);
-            
-            //
-            // Check that the port reset
-            //
+            // wait for completion
+            ResetComplete = FALSE;
+
+            // Clear reset
             Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-            if (!(Value & EHCI_PRT_RESET))
-                break;
-        } while (TRUE);
+            Value &= (EHCI_PORTSC_DATAMASK | EHCI_PRT_ENABLED);
+            Value &= ~EHCI_PRT_RESET;
+            EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
+
+            for(WaitTime = 0; WaitTime < 500; WaitTime += 20)
+            {
+                // wait
+                KeStallExecutionProcessor(20);
+
+                // Check that the port reset
+                Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+
+                // is complete
+                if (!(Value & EHCI_PRT_RESET))
+                {
+                    // check for bogus value
+                    if (Value == MAXULONG)
+                        continue;
+
+                    // reset done
+                    ResetComplete = TRUE;
+                    break;
+                }
+            }
+        } while (!ResetComplete);
 
         //
         // delay is 10 ms
         //
-        Timeout.QuadPart = 10;
+        Timeout.QuadPart = 50;
         DPRINT1("Waiting %d milliseconds for port to recover after reset\n", 
Timeout.LowPart);
 
         //
@@ -1129,32 +1141,31 @@
         // check slow speed line after reset
         //
         Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-        if (Value & EHCI_PRT_SLOWSPEEDLINE)
+
+        // did the reset complete successfully
+        if (Value != MAXULONG)
         {
-            DPRINT1("Non HighSpeed device. Releasing Ownership\n");
+            if (Value & EHCI_PRT_ENABLED || !(Value & EHCI_PRT_CONNECTED) || 
Value & EHCI_PRT_CONNECTSTATUSCHANGE)
+            {
+                // successfully reset port
+                DPRINT1("Port is back up after reset\n");
+                return STATUS_SUCCESS;
+            }
+
+            // either the port failed to reset
+            // or it is a full speed / low speed device
+            // release control to companion controller
+            DPRINT("[USBEHCI] Failed to reset port Id %x PortStatus %x 
releasing ownership\n", PortId, Value);
+
+            // re-read register
+            Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+
+            // releaseing ownership
             EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value | 
EHCI_PRT_RELEASEOWNERSHIP);
             return STATUS_DEVICE_NOT_CONNECTED;
-        }
-
-        //
-        // this will be enabled now since we're high-speed
-        //
-        do
-        {
-            //
-            // wait
-            //
-            KeStallExecutionProcessor(100);
-
-            //
-            // Check that the port is enabled
-            //
-            Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-            if (Value & EHCI_PRT_ENABLED)
-                break;
-        } while (TRUE);
-
-        DPRINT1("Port is back up after reset\n");
+       }
+
+
     }
     else if (Status == C_PORT_CONNECTION)
     {
@@ -1515,6 +1526,9 @@
         //
         if (QueueSCEWorkItem && This->m_SCECallBack != NULL)
         {
+            // work item is now active
+            This->m_WorkItemActive = TRUE;
+
             //
             // queue work item for processing
             //
@@ -1545,6 +1559,8 @@
         This->m_SCECallBack(This->m_SCEContext);
     }
 
+    // work item is completed
+    This->m_WorkItemActive = FALSE;
 }
 
 NTSTATUS


Reply via email to