mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:52:56 +00:00
[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
This commit is contained in:
parent
850d4b4ddf
commit
69d0df4728
2 changed files with 97 additions and 92 deletions
|
@ -124,7 +124,6 @@ protected:
|
||||||
BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress
|
BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress
|
||||||
WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback
|
WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback
|
||||||
ULONG m_SyncFramePhysAddr; // periodic frame list physical address
|
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
|
BUS_INTERFACE_STANDARD m_BusInterface; // pci bus interface
|
||||||
|
|
||||||
// read register
|
// read register
|
||||||
|
@ -957,6 +956,7 @@ CUSBHardwareDevice::ResetPort(
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
|
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
|
||||||
|
|
||||||
//
|
//
|
||||||
// check slow speed line before reset
|
// check slow speed line before reset
|
||||||
//
|
//
|
||||||
|
@ -977,37 +977,10 @@ CUSBHardwareDevice::ResetPort(
|
||||||
EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
|
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);
|
Timeout.QuadPart = 20;
|
||||||
|
DPRINT1("Waiting %d milliseconds for port reset\n", Timeout.LowPart);
|
||||||
//
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// convert to 100 ns units (absolute)
|
// convert to 100 ns units (absolute)
|
||||||
|
@ -1019,37 +992,6 @@ CUSBHardwareDevice::ResetPort(
|
||||||
//
|
//
|
||||||
KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1110,18 +1052,17 @@ CUSBHardwareDevice::GetPortStatus(
|
||||||
Status |= USB_PORT_STATUS_OVER_CURRENT;
|
Status |= USB_PORT_STATUS_OVER_CURRENT;
|
||||||
|
|
||||||
// In a reset state?
|
// In a reset state?
|
||||||
if ((Value & EHCI_PRT_RESET) || m_ResetInProgress[PortId])
|
if (Value & EHCI_PRT_RESET)
|
||||||
{
|
{
|
||||||
Status |= USB_PORT_STATUS_RESET;
|
Status |= USB_PORT_STATUS_RESET;
|
||||||
Change |= USB_PORT_STATUS_RESET;
|
Change |= USB_PORT_STATUS_RESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// This indicates a connect or disconnect
|
||||||
// FIXME: Is the Change here correct?
|
|
||||||
//
|
|
||||||
if (Value & EHCI_PRT_CONNECTSTATUSCHANGE)
|
if (Value & EHCI_PRT_CONNECTSTATUSCHANGE)
|
||||||
Change |= USB_PORT_STATUS_CONNECT;
|
Change |= USB_PORT_STATUS_CONNECT;
|
||||||
|
|
||||||
|
// This is set to indicate a critical port error
|
||||||
if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
|
if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
|
||||||
Change |= USB_PORT_STATUS_ENABLE;
|
Change |= USB_PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
|
@ -1137,36 +1078,42 @@ CUSBHardwareDevice::ClearPortStatus(
|
||||||
ULONG Status)
|
ULONG Status)
|
||||||
{
|
{
|
||||||
ULONG Value;
|
ULONG Value;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
|
||||||
DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
|
DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
|
||||||
|
|
||||||
if (PortId > m_Capabilities.HCSParams.PortCount)
|
if (PortId > m_Capabilities.HCSParams.PortCount)
|
||||||
return STATUS_UNSUCCESSFUL;
|
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)
|
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))
|
do
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Timeout;
|
//
|
||||||
|
// 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;
|
Timeout.QuadPart = 10;
|
||||||
DPRINT1("Waiting %d milliseconds for port to stabilize after connection\n", Timeout.LowPart);
|
DPRINT1("Waiting %d milliseconds for port to recover after reset\n", Timeout.LowPart);
|
||||||
|
|
||||||
//
|
//
|
||||||
// convert to 100 ns units (absolute)
|
// convert to 100 ns units (absolute)
|
||||||
|
@ -1177,6 +1124,64 @@ CUSBHardwareDevice::ClearPortStatus(
|
||||||
// perform the wait
|
// perform the wait
|
||||||
//
|
//
|
||||||
KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
|
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;
|
return STATUS_SUCCESS;
|
||||||
|
@ -1207,13 +1212,11 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
|
|
||||||
if (Feature == PORT_RESET)
|
if (Feature == PORT_RESET)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// call the helper
|
||||||
|
//
|
||||||
ResetPort(PortId);
|
ResetPort(PortId);
|
||||||
|
|
||||||
//
|
|
||||||
// update cached settings
|
|
||||||
//
|
|
||||||
m_ResetInProgress[PortId] = TRUE;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// is there a status change callback
|
// is there a status change callback
|
||||||
//
|
//
|
||||||
|
|
|
@ -1138,8 +1138,14 @@ CUSBHardwareDevice::GetPortStatus(
|
||||||
|
|
||||||
// connected
|
// connected
|
||||||
if (Value & OHCI_RH_PORTSTATUS_CCS)
|
if (Value & OHCI_RH_PORTSTATUS_CCS)
|
||||||
|
{
|
||||||
*PortStatus |= USB_PORT_STATUS_CONNECT;
|
*PortStatus |= USB_PORT_STATUS_CONNECT;
|
||||||
|
|
||||||
|
// low speed device
|
||||||
|
if (Value & OHCI_RH_PORTSTATUS_LSDA)
|
||||||
|
*PortStatus |= USB_PORT_STATUS_LOW_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
// did a device connect?
|
// did a device connect?
|
||||||
if (Value & OHCI_RH_PORTSTATUS_CSC)
|
if (Value & OHCI_RH_PORTSTATUS_CSC)
|
||||||
*PortChange |= USB_PORT_STATUS_CONNECT;
|
*PortChange |= USB_PORT_STATUS_CONNECT;
|
||||||
|
@ -1171,10 +1177,6 @@ CUSBHardwareDevice::GetPortStatus(
|
||||||
if (Value & OHCI_RH_PORTSTATUS_PRSC)
|
if (Value & OHCI_RH_PORTSTATUS_PRSC)
|
||||||
*PortChange |= USB_PORT_STATUS_RESET;
|
*PortChange |= USB_PORT_STATUS_RESET;
|
||||||
|
|
||||||
// low speed device
|
|
||||||
if (Value & OHCI_RH_PORTSTATUS_LSDA)
|
|
||||||
*PortStatus |= USB_PORT_STATUS_LOW_SPEED;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,7 +1354,7 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
// wait a bit
|
// wait a bit
|
||||||
//
|
//
|
||||||
KeStallExecutionProcessor(100);
|
KeStallExecutionProcessor(100);
|
||||||
}while(TRUE);
|
} while(TRUE);
|
||||||
|
|
||||||
if (m_SCECallBack != NULL)
|
if (m_SCECallBack != NULL)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue