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/u…
==============================================================================
--- 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;
}