[USBOHCI]
[reactos.git] / drivers / usb / usbohci / hardware.cpp
index e935c41..cc35707 100644 (file)
@@ -120,7 +120,6 @@ protected:
     POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor;                                 // iso endpoint descriptor
     POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT];        // endpoints for interrupt / iso transfers
     ULONG m_NumberOfPorts;                                                             // number of ports
-    OHCI_PORT_STATUS m_PortStatus[OHCI_MAX_PORT_COUNT];                                // port change status
     PDMAMEMORYMANAGER m_MemoryManager;                                                 // memory manager
     HD_INIT_CALLBACK* m_SCECallBack;                                                   // status change callback routine
     PVOID m_SCEContext;                                                                // status change callback routine context
@@ -874,10 +873,10 @@ CUSBHardwareDevice::StopController(void)
     //
     // alignment check
     //
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET, 0xFFFFFFFF);
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET), 0xFFFFFFFF);
     Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET));
-    DPRINT1("HcHCCA Alignment %x\n", Control);
-    ASSERT((Control & 0xFFFFFFF0) == 0xFFFFFFF0);
+    //ASSERT((m_HCCAPhysicalAddress.QuadPart & Control) == Control);
+
 
     //
     // check context
@@ -1114,7 +1113,6 @@ CUSBHardwareDevice::GetPortStatus(
     Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
     DPRINT("GetPortStatus PortId %x Value %x\n", PortId, Value);
 
-
     // connected
     if (Value & OHCI_RH_PORTSTATUS_CCS)
         *PortStatus |= USB_PORT_STATUS_CONNECT;
@@ -1127,9 +1125,9 @@ CUSBHardwareDevice::GetPortStatus(
     if (Value & OHCI_RH_PORTSTATUS_PES)
         *PortStatus |= USB_PORT_STATUS_ENABLE;
 
-    // port enabled
+    // port disconnect or hardware error
     if (Value & OHCI_RH_PORTSTATUS_PESC)
-        *PortChange |= USB_PORT_STATUS_ENABLE;
+        *PortChange |= USB_PORT_STATUS_CONNECT;
 
     // port suspend
     if (Value & OHCI_RH_PORTSTATUS_PSS)
@@ -1139,14 +1137,21 @@ CUSBHardwareDevice::GetPortStatus(
     if (Value & OHCI_RH_PORTSTATUS_PSSC)
         *PortChange |= USB_PORT_STATUS_ENABLE;
 
-    // port reset
-    if (Value & OHCI_RH_PORTSTATUS_PSS)
+    // port reset started (change bit only set at completion)
+    if (Value & OHCI_RH_PORTSTATUS_PRS)
+    {
         *PortStatus |= USB_PORT_STATUS_RESET;
+        *PortChange |= USB_PORT_STATUS_RESET;
+    }
 
-    // port reset
+    // port reset ended (change bit only set at completion)
     if (Value & OHCI_RH_PORTSTATUS_PRSC)
         *PortChange |= USB_PORT_STATUS_RESET;
 
+    // low speed device
+    if (Value & OHCI_RH_PORTSTATUS_LSDA)
+        *PortStatus |= USB_PORT_STATUS_LOW_SPEED;
+
     return STATUS_SUCCESS;
 }
 
@@ -1206,7 +1211,6 @@ CUSBHardwareDevice::ClearPortStatus(
         //
         // sanity checks
         //
-        ASSERT((Value & OHCI_RH_PORTSTATUS_PRS) == 0);
         ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC));
 
         //
@@ -1214,49 +1218,24 @@ CUSBHardwareDevice::ClearPortStatus(
         //
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC);
 
-        //
-        // read status register
-        //
-        Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
-
-        //
-        // reset complete bit should be cleared
-        //
-        ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC) == 0);
-
-        //
-        // update port status
-        //
-        m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_RESET;
-
         //
         // sanity check
         //
         ASSERT((Value & OHCI_RH_PORTSTATUS_PES));
-
-        //
-        // port is enabled
-        //
-        m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE;
-
-        //
-        // re-enable root hub change
-        //
-        Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET));
-        WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), Value | OHCI_ROOT_HUB_STATUS_CHANGE);
-
     }
 
-    if (Status == C_PORT_CONNECTION)
+    if (Status == C_PORT_CONNECTION || Status == C_PORT_ENABLE)
     {
         //
-        // clear bit
+        // clear bits
         //
-        WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_CSC);
-        m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_CONNECT;
+        WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_CSC | OHCI_RH_PORTSTATUS_PESC);
     }
 
-
+    //
+    // re-enable root hub change
+    //
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
 
     return STATUS_SUCCESS;
 }
@@ -1287,10 +1266,39 @@ CUSBHardwareDevice::SetPortFeature(
     }
     else if (Feature == PORT_POWER)
     {
+        LARGE_INTEGER Timeout;
+
         //
         // enable power
         //
         WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PPS);
+
+        //
+        // read descriptor A for the delay data
+        //
+        Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET));
+
+        //
+        // compute the delay
+        //
+        Timeout.QuadPart = OHCI_RH_GET_POWER_ON_TO_POWER_GOOD_TIME(Value);
+
+        //
+        // delay is multiplied by 2 ms
+        //
+        Timeout.QuadPart *= 2;
+        DPRINT1("Waiting %d milliseconds for port power up\n", Timeout.LowPart);
+
+        //
+        // convert to 100 ns units (absolute)
+        //
+        Timeout.QuadPart *= -10000;
+
+        //
+        // perform the wait
+        //
+        KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
+
         return STATUS_SUCCESS;
     }
     else if (Feature == PORT_SUSPEND)
@@ -1318,12 +1326,6 @@ CUSBHardwareDevice::SetPortFeature(
         //
         KeStallExecutionProcessor(100);
 
-        //
-        // update cached settings
-        //
-        m_PortStatus[PortId].PortChange |= USB_PORT_STATUS_RESET;
-        m_PortStatus[PortId].PortStatus &= ~USB_PORT_STATUS_ENABLE;
-
         //
         // is there a status change callback
         //
@@ -1497,10 +1499,6 @@ InterruptServiceRoutine(
 
     if (Status & OHCI_ROOT_HUB_STATUS_CHANGE) 
     {
-        //
-        // new device has arrived
-        //
-
         //
         // disable interrupt as it will fire untill the port has been reset
         //
@@ -1590,21 +1588,6 @@ OhciDefferedRoutine(
                     // enable port
                     //
                     WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_RH_PORT_STATUS(Index)), OHCI_RH_PORTSTATUS_PES);
-
-
-                    //
-                    // store change
-                    //
-                    This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_CONNECT;
-                    This->m_PortStatus[Index].PortChange |= USB_PORT_STATUS_CONNECT;
-
-                    if ((PortStatus & OHCI_RH_PORTSTATUS_LSDA))
-                    {
-                        //
-                        // low speed device connected
-                        //
-                        This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_LOW_SPEED;
-                    }
                 }
                 else
                 {
@@ -1612,13 +1595,6 @@ OhciDefferedRoutine(
                     // device disconnected
                     //
                     DPRINT1("Device disconnected at Port %x\n", Index);
-
-                    //
-                    // update port status flags
-                    //
-                    This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_LOW_SPEED;
-                    This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_CONNECT;
-                    This->m_PortStatus[Index].PortChange |= USB_PORT_STATUS_CONNECT;
                 }
 
                 //