From 075cf8cdc9e170aee904f9299a9787f5d960cdfe Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 17 Feb 2012 03:45:46 +0000 Subject: [PATCH] [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 svn path=/trunk/; revision=55662 --- reactos/drivers/usb/usbehci/hardware.cpp | 52 ++++++++++++------------ reactos/drivers/usb/usbohci/hardware.cpp | 48 ++++++++-------------- 2 files changed, 43 insertions(+), 57 deletions(-) diff --git a/reactos/drivers/usb/usbehci/hardware.cpp b/reactos/drivers/usb/usbehci/hardware.cpp index 8ee24e99e2f..d564c6e0d21 100644 --- a/reactos/drivers/usb/usbehci/hardware.cpp +++ b/reactos/drivers/usb/usbehci/hardware.cpp @@ -977,20 +977,9 @@ CUSBHardwareDevice::ResetPort( EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus); // - // delay is 20 ms for port reset as per USB 2.0 spec + // Wait for reset to start // - 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); + KeStallExecutionProcessor(100); // // Clear reset @@ -1042,13 +1031,24 @@ CUSBHardwareDevice::ResetPort( } // - // this must be enabled now + // this will be enabled now since we're high-speed // - if (PortStatus & EHCI_PRT_ENABLED) + do { - DPRINT1("Port is not enabled after reset\n"); - //ASSERT(FALSE); - } + // + // 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 @@ CUSBHardwareDevice::ClearPortStatus( 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,17 +1158,10 @@ CUSBHardwareDevice::ClearPortStatus( 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 // diff --git a/reactos/drivers/usb/usbohci/hardware.cpp b/reactos/drivers/usb/usbohci/hardware.cpp index 8b30b5ca4ee..5c99b516747 100644 --- a/reactos/drivers/usb/usbohci/hardware.cpp +++ b/reactos/drivers/usb/usbohci/hardware.cpp @@ -1193,7 +1193,6 @@ CUSBHardwareDevice::ClearPortStatus( 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 @@ CUSBHardwareDevice::ClearPortStatus( // // 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 @@ CUSBHardwareDevice::ClearPortStatus( // // 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 @@ CUSBHardwareDevice::SetPortFeature( } else if (Feature == PORT_RESET) { - LARGE_INTEGER Timeout; - // // assert // @@ -1343,7 +1341,8 @@ CUSBHardwareDevice::SetPortFeature( // 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 @@ CUSBHardwareDevice::SetPortFeature( 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 @@ InterruptServiceRoutine( // // 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 @@ OhciDefferedRoutine( // 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; + } } //