From 69d0df4728277ee06d018b84567539aae131b6f2 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 19 Feb 2012 22:22:45 +0000 Subject: [PATCH] [USBEHCI] - Try to fix reset bugs in my code and remove hacks - Don't clear extra bits when acknowledging a port connect status change [USBOHCI] - Code cleanup - No functional change svn path=/trunk/; revision=55725 --- reactos/drivers/usb/usbehci/hardware.cpp | 177 ++++++++++++----------- reactos/drivers/usb/usbohci/hardware.cpp | 12 +- 2 files changed, 97 insertions(+), 92 deletions(-) diff --git a/reactos/drivers/usb/usbehci/hardware.cpp b/reactos/drivers/usb/usbehci/hardware.cpp index d564c6e0d21..ad3dd00ff5c 100644 --- a/reactos/drivers/usb/usbehci/hardware.cpp +++ b/reactos/drivers/usb/usbehci/hardware.cpp @@ -124,7 +124,6 @@ protected: BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback ULONG m_SyncFramePhysAddr; // periodic frame list physical address - BOOLEAN m_ResetInProgress[16]; // set when a reset is in progress BUS_INTERFACE_STANDARD m_BusInterface; // pci bus interface // read register @@ -957,6 +956,7 @@ CUSBHardwareDevice::ResetPort( return STATUS_UNSUCCESSFUL; PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex)); + // // check slow speed line before reset // @@ -977,37 +977,10 @@ CUSBHardwareDevice::ResetPort( EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus); // - // Wait for reset to start + // delay is 20 ms for port reset as per USB 2.0 spec // - KeStallExecutionProcessor(100); - - // - // Clear reset - // - PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex)); - PortStatus &= ~EHCI_PRT_RESET; - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus); - - do - { - // - // wait - // - KeStallExecutionProcessor(100); - - // - // Check that the port reset - // - PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex)); - if (!(PortStatus & EHCI_PRT_RESET)) - break; - } while (TRUE); - - // - // delay is 10 ms - // - Timeout.QuadPart = 10; - DPRINT1("Waiting %d milliseconds for port to recover after reset\n", Timeout.LowPart); + Timeout.QuadPart = 20; + DPRINT1("Waiting %d milliseconds for port reset\n", Timeout.LowPart); // // convert to 100 ns units (absolute) @@ -1019,37 +992,6 @@ CUSBHardwareDevice::ResetPort( // KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - // - // check slow speed line after reset - // - PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex)); - if (PortStatus & EHCI_PRT_SLOWSPEEDLINE) - { - DPRINT1("Non HighSpeed device. Releasing Ownership\n"); - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), EHCI_PRT_RELEASEOWNERSHIP); - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // this will be enabled now since we're high-speed - // - do - { - // - // 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; } @@ -1110,18 +1052,17 @@ CUSBHardwareDevice::GetPortStatus( Status |= USB_PORT_STATUS_OVER_CURRENT; // In a reset state? - if ((Value & EHCI_PRT_RESET) || m_ResetInProgress[PortId]) + if (Value & EHCI_PRT_RESET) { Status |= USB_PORT_STATUS_RESET; Change |= USB_PORT_STATUS_RESET; } - // - // FIXME: Is the Change here correct? - // + // This indicates a connect or disconnect if (Value & EHCI_PRT_CONNECTSTATUSCHANGE) Change |= USB_PORT_STATUS_CONNECT; + // This is set to indicate a critical port error if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE) Change |= USB_PORT_STATUS_ENABLE; @@ -1137,36 +1078,42 @@ CUSBHardwareDevice::ClearPortStatus( ULONG Status) { ULONG Value; + LARGE_INTEGER Timeout; DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status); 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) { // - // update port status + // Clear reset // - m_ResetInProgress[PortId] = FALSE; - } + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + Value &= ~EHCI_PRT_RESET; + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); - if (Status == C_PORT_CONNECTION && (Value & EHCI_PRT_CONNECTED)) - { - LARGE_INTEGER Timeout; + do + { + // + // wait + // + KeStallExecutionProcessor(100); + + // + // Check that the port reset + // + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + if (!(Value & EHCI_PRT_RESET)) + break; + } while (TRUE); // - // delay is 100 ms + // delay is 10 ms // - Timeout.QuadPart = 100; - DPRINT1("Waiting %d milliseconds for port to stabilize after connection\n", Timeout.LowPart); + Timeout.QuadPart = 10; + DPRINT1("Waiting %d milliseconds for port to recover after reset\n", Timeout.LowPart); // // convert to 100 ns units (absolute) @@ -1177,6 +1124,64 @@ CUSBHardwareDevice::ClearPortStatus( // perform the wait // KeDelayExecutionThread(KernelMode, FALSE, &Timeout); + + // + // check slow speed line after reset + // + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + if (Value & EHCI_PRT_SLOWSPEEDLINE) + { + DPRINT1("Non HighSpeed device. Releasing Ownership\n"); + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), EHCI_PRT_RELEASEOWNERSHIP); + return STATUS_DEVICE_NOT_CONNECTED; + } + + // + // this will be enabled now since we're high-speed + // + do + { + // + // wait + // + KeStallExecutionProcessor(100); + + // + // Check that the port is enabled + // + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + if (Value & EHCI_PRT_ENABLED) + break; + } while (TRUE); + + DPRINT1("Port is back up after reset\n"); + } + else if (Status == C_PORT_CONNECTION) + { + // + // reset status change bits + // + Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); + EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); + + if (Value & EHCI_PRT_CONNECTED) + { + // + // 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); + } } return STATUS_SUCCESS; @@ -1207,13 +1212,11 @@ CUSBHardwareDevice::SetPortFeature( if (Feature == PORT_RESET) { + // + // call the helper + // ResetPort(PortId); - // - // update cached settings - // - m_ResetInProgress[PortId] = TRUE; - // // is there a status change callback // diff --git a/reactos/drivers/usb/usbohci/hardware.cpp b/reactos/drivers/usb/usbohci/hardware.cpp index 332e5b56a64..55181d824ab 100644 --- a/reactos/drivers/usb/usbohci/hardware.cpp +++ b/reactos/drivers/usb/usbohci/hardware.cpp @@ -1138,8 +1138,14 @@ CUSBHardwareDevice::GetPortStatus( // connected if (Value & OHCI_RH_PORTSTATUS_CCS) + { *PortStatus |= USB_PORT_STATUS_CONNECT; + // low speed device + if (Value & OHCI_RH_PORTSTATUS_LSDA) + *PortStatus |= USB_PORT_STATUS_LOW_SPEED; + } + // did a device connect? if (Value & OHCI_RH_PORTSTATUS_CSC) *PortChange |= USB_PORT_STATUS_CONNECT; @@ -1171,10 +1177,6 @@ CUSBHardwareDevice::GetPortStatus( 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; } @@ -1352,7 +1354,7 @@ CUSBHardwareDevice::SetPortFeature( // wait a bit // KeStallExecutionProcessor(100); - }while(TRUE); + } while(TRUE); if (m_SCECallBack != NULL) {