Author: cgutman
Date: Fri Feb 17 03:45:46 2012
New Revision: 55662

URL: http://svn.reactos.org/svn/reactos?rev=55662&view=rev
Log:
[USBOHCI]
- Remove massive hacks from our port reset code
- We now wait for the reset complete interrupt instead of stalling 10ms and 
continuing
- Don't wait for a port to stabilize unless there's actually a device connected
[USBEHCI]
- Fix very long delay between setting the reset bit and clearing it
- Wait for the port to come back enabled before finishing the reset
- Don't wait for a port to stabilize unless there's actually a device connected

Modified:
    trunk/reactos/drivers/usb/usbehci/hardware.cpp
    trunk/reactos/drivers/usb/usbohci/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=55662&r1=55661&r2=55662&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hardware.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hardware.cpp [iso-8859-1] Fri Feb 17 
03:45:46 2012
@@ -977,20 +977,9 @@
     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;
-    DPRINT1("Waiting %d milliseconds for port reset\n", Timeout.LowPart);
-
-    //
-    // convert to 100 ns units (absolute)
-    //
-    Timeout.QuadPart *= -10000;
-
-    //
-    // perform the wait
-    //
-    KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
+    // Wait for reset to start
+    //
+    KeStallExecutionProcessor(100);
 
     //
     // Clear reset
@@ -1042,13 +1031,24 @@
     }
 
     //
-    // this must be enabled now
-    //
-    if (PortStatus & EHCI_PRT_ENABLED)
-    {
-        DPRINT1("Port is not enabled after reset\n");
-        //ASSERT(FALSE);
-    }
+    // this will be enabled now since we're high-speed
+    //
+    do
+    {
+        //
+        // wait
+        //
+        KeStallExecutionProcessor(100);
+
+        //
+        // Check that the port is enabled
+        //
+        PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
+        if (PortStatus & EHCI_PRT_ENABLED)
+            break;
+    } while (TRUE);
+
+    DPRINT1("Port is back up after reset\n");
 
     return STATUS_SUCCESS;
 }
@@ -1143,6 +1143,13 @@
     if (PortId > m_Capabilities.HCSParams.PortCount)
         return STATUS_UNSUCCESSFUL;
 
+    //
+    // reset status change bits
+    //
+    Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+    Value |= EHCI_PRT_CONNECTSTATUSCHANGE | EHCI_PRT_ENABLEDSTATUSCHANGE;
+    EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
+
     if (Status == C_PORT_RESET)
     {
         //
@@ -1151,16 +1158,9 @@
         m_ResetInProgress[PortId] = FALSE;
     }
 
-    if (Status == C_PORT_CONNECTION)
+    if (Status == C_PORT_CONNECTION && (Value & EHCI_PRT_CONNECTED))
     {
         LARGE_INTEGER Timeout;
-
-        //
-        // reset status change bits
-        //
-        Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-        Value |= EHCI_PRT_CONNECTSTATUSCHANGE | EHCI_PRT_ENABLEDSTATUSCHANGE;
-        EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
 
         //
         // delay is 100 ms

Modified: trunk/reactos/drivers/usb/usbohci/hardware.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbohci/hardware.cpp?rev=55662&r1=55661&r2=55662&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Fri Feb 17 
03:45:46 2012
@@ -1193,7 +1193,6 @@
         return STATUS_UNSUCCESSFUL;
 
     Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_RH_PORT_STATUS(PortId)));
-    KeStallExecutionProcessor(100);
 
     if (Status == C_PORT_RESET)
     {
@@ -1223,7 +1222,7 @@
         //
         // wait for port to stabilize
         //
-        if (Status == C_PORT_CONNECTION)
+        if (Status == C_PORT_CONNECTION && (Value & OHCI_RH_PORTSTATUS_CCS))
         {
             LARGE_INTEGER Timeout;
 
@@ -1248,6 +1247,7 @@
     //
     // re-enable root hub change
     //
+    DPRINT1("Enabling status change\n");
     WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
 
     return STATUS_SUCCESS;
@@ -1324,8 +1324,6 @@
     }
     else if (Feature == PORT_RESET)
     {
-        LARGE_INTEGER Timeout;
-
         //
         // assert
         //
@@ -1343,7 +1341,8 @@
            //
            Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 
OHCI_RH_PORT_STATUS(PortId)));
 
-           if ((Value & OHCI_RH_PORTSTATUS_PRS)  == 0)
+           if ((Value & OHCI_RH_PORTSTATUS_PRS) == 0 &&
+               (Value & OHCI_RH_PORTSTATUS_PRSC) != 0)
            {
                //
                // reset is complete
@@ -1357,32 +1356,6 @@
            KeStallExecutionProcessor(100);
         }while(TRUE);
 
-        //
-        // delay is 10 ms
-        //
-        Timeout.QuadPart = 10;
-        DPRINT1("Waiting %d milliseconds for port to recover after reset\n", 
Timeout.LowPart);
-        
-        //
-        // convert to 100 ns units (absolute)
-        //
-        Timeout.QuadPart *= -10000;
-        
-        //
-        // perform the wait
-        //
-        KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
-
-        //
-        // is there a status change callback
-        //
-        if (m_SCECallBack != NULL)
-        {
-            //
-            // issue callback
-            //
-            m_SCECallBack(m_SCEContext);
-        }
         return STATUS_SUCCESS;
     }
     return STATUS_SUCCESS;
@@ -1552,6 +1525,7 @@
         //
         // disable interrupt as it will fire untill the port has been reset
         //
+        DPRINT1("Disabling status change interrupt\n");
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + 
OHCI_INTERRUPT_DISABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
         Acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
     }
@@ -1653,6 +1627,18 @@
                 //
                 QueueSCEWorkItem = TRUE;
             }
+            else if (PortStatus & OHCI_RH_PORTSTATUS_PRSC)
+            {
+                //
+                // This is a port reset complete interrupt
+                //
+                DPRINT1("Port %d completed reset\n", Index);
+
+                //
+                // Queue a work item
+                //
+                QueueSCEWorkItem = TRUE;
+            }
         }
 
         //


Reply via email to