Author: cgutman Date: Fri Jan 27 05:20:37 2012 New Revision: 55231
URL: http://svn.reactos.org/svn/reactos?rev=55231&view=rev Log: [USBOHCI] - Attempt to fix reset race conditions
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Fri Jan 27 05:20:37 2012 @@ -1172,6 +1172,119 @@
if (Status == C_PORT_RESET) { + // + // sanity checks + // + ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC)); + + // + // clear reset bit complete + // + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC); + + // + // sanity check + // + ASSERT((Value & OHCI_RH_PORTSTATUS_PES)); + } + + if (Status == C_PORT_CONNECTION || Status == C_PORT_ENABLE) + { + // + // clear bits + // + 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; +} + + +NTSTATUS +CUSBHardwareDevice::SetPortFeature( + ULONG PortId, + ULONG Feature) +{ + ULONG Value; + + DPRINT1("CUSBHardwareDevice::SetPortFeature PortId %x Feature %x\n", PortId, Feature); + + // + // read port status + // + Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); + + + if (Feature == PORT_ENABLE) + { + // + // enable port + // + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PES); + return STATUS_SUCCESS; + } + 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) + { + // + // enable port + // + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PSS); + return STATUS_SUCCESS; + } + else if (Feature == PORT_RESET) + { + // + // assert + // + ASSERT((Value & OHCI_RH_PORTSTATUS_CCS)); + + // + // reset port + // + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS); + do { // @@ -1191,151 +1304,14 @@ // 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 - // - ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC)); - - // - // clear reset bit complete - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC); - - // - // sanity check - // - ASSERT((Value & OHCI_RH_PORTSTATUS_PES)); - } - - if (Status == C_PORT_CONNECTION || Status == C_PORT_ENABLE) - { - // - // clear bits - // - 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; -} - - -NTSTATUS -CUSBHardwareDevice::SetPortFeature( - ULONG PortId, - ULONG Feature) -{ - ULONG Value; - - DPRINT1("CUSBHardwareDevice::SetPortFeature PortId %x Feature %x\n", PortId, Feature); - - // - // read port status - // - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); - - - if (Feature == PORT_ENABLE) - { - // - // enable port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PES); + // trigger the status change interrupt + // + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE); + return STATUS_SUCCESS; - } - 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) - { - // - // enable port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PSS); - return STATUS_SUCCESS; - } - else if (Feature == PORT_RESET) - { - // - // assert - // - ASSERT((Value & OHCI_RH_PORTSTATUS_CCS)); - - // - // reset port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS); - - // - // wait - // - KeStallExecutionProcessor(100); - - // - // is there a status change callback - // - if (m_SCECallBack != NULL) - { - // - // issue callback - // - m_SCECallBack(m_SCEContext); - } } return STATUS_SUCCESS; }