[USBOHCI]
[reactos.git] / drivers / usb / usbohci / hardware.cpp
index cc35707..5dc1981 100644 (file)
@@ -1172,42 +1172,6 @@ CUSBHardwareDevice::ClearPortStatus(
 
     if (Status == C_PORT_RESET)
     {
-        do
-        {
-           //
-           // read port status
-           //
-           Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
-
-           if ((Value & OHCI_RH_PORTSTATUS_PRS)  == 0)
-           {
-               //
-               // reset is complete
-               //
-               break;
-           }
-
-           //
-           // wait a bit
-           //
-           KeStallExecutionProcessor(100);
-
-           //DPRINT1("Value %x Index %lu\n", Value, Index);
-
-        }while(TRUE);
-
-        //
-        // check if reset bit is still set
-        //
-        if (Value & OHCI_RH_PORTSTATUS_PRS)
-        {
-            //
-            // reset failed
-            //
-            DPRINT1("PortId %lu Reset failed\n", PortId);
-            return STATUS_UNSUCCESSFUL;
-        }
-
         //
         // sanity checks
         //
@@ -1227,9 +1191,33 @@ CUSBHardwareDevice::ClearPortStatus(
     if (Status == C_PORT_CONNECTION || Status == C_PORT_ENABLE)
     {
         //
-        // clear bits
+        // clear change bits
         //
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_CSC | OHCI_RH_PORTSTATUS_PESC);
+
+        //
+        // wait for port to stabilize
+        //
+        if (Status == C_PORT_CONNECTION)
+        {
+            LARGE_INTEGER Timeout;
+
+            //
+            // delay is 100 ms
+            //
+            Timeout.QuadPart = 100;
+            DPRINT1("Waiting %d milliseconds for port to stabilize after connection\n", Timeout.LowPart);
+
+            //
+            // convert to 100 ns units (absolute)
+            //
+            Timeout.QuadPart *= -10000;
+
+            //
+            // perform the wait
+            //
+            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
+        }
     }
 
     //
@@ -1311,6 +1299,8 @@ CUSBHardwareDevice::SetPortFeature(
     }
     else if (Feature == PORT_RESET)
     {
+        LARGE_INTEGER Timeout;
+
         //
         // assert
         //
@@ -1321,10 +1311,42 @@ CUSBHardwareDevice::SetPortFeature(
         //
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS);
 
+        do
+        {
+           //
+           // read port status
+           //
+           Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
+
+           if ((Value & OHCI_RH_PORTSTATUS_PRS)  == 0)
+           {
+               //
+               // reset is complete
+               //
+               break;
+           }
+
+           //
+           // wait a bit
+           //
+           KeStallExecutionProcessor(100);
+        }while(TRUE);
+
         //
-        // wait 
+        // delay is 10 ms
         //
-        KeStallExecutionProcessor(100);
+        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
@@ -1336,6 +1358,7 @@ CUSBHardwareDevice::SetPortFeature(
             //
             m_SCECallBack(m_SCEContext);
         }
+        return STATUS_SUCCESS;
     }
     return STATUS_SUCCESS;
 }
@@ -1434,6 +1457,8 @@ InterruptServiceRoutine(
         // the interrupt was not caused by DoneHead update
         // check if something important happened
         //
+        DPRINT1("InterruptStatus %x  InterruptEnable %x\n", READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)), 
+                                                            READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)));
         Status = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)) & READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)) & (~OHCI_WRITEBACK_DONE_HEAD); 
         if (Status == 0)
         {