HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine
PVOID m_SCEContext; // status change callback routine context
BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress
- EHCI_PORT_STATUS m_PortStatus[16]; // port status
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
// set command
VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
//
// Initialize the UsbQueue now that we have an AdapterObject.
//
- Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL);
+ Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, &m_Lock);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Initialize the UsbQueue\n");
StopController();
//
- // Reset the device. Bit is set to 0 on completion.
- //
- GetCommandRegister(&UsbCmd);
- UsbCmd.HCReset = TRUE;
- SetCommandRegister(&UsbCmd);
-
- //
- // Check that the controller reset
- //
- for (FailSafe = 100; FailSafe > 1; FailSafe--)
- {
- KeStallExecutionProcessor(10);
- GetCommandRegister(&UsbCmd);
- if (!UsbCmd.HCReset)
- {
- break;
- }
- }
-
- //
- // If the controller did not reset then fail
- //
- if (UsbCmd.HCReset)
- {
- DPRINT1("EHCI ERROR: Controller failed to reset. Hardware problem!\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- //
- // Disable Interrupts and clear status
+ // Enable Interrupts and start execution
//
- EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, 0);
- EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, 0x0000001f);
+ EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
+ /*| EHCI_USBINTR_FLROVR*/ | EHCI_USBINTR_PC);
//
// Assign the AsyncList Register
//
GetCommandRegister(&UsbCmd);
UsbCmd.PeriodicEnable = TRUE;
- UsbCmd.AsyncEnable = TRUE; //FIXME: Need USB Memory Manager
-
UsbCmd.IntThreshold = 1;
- // FIXME: Set framelistsize when periodic is implemented.
SetCommandRegister(&UsbCmd);
- //
- // Enable Interrupts and start execution
- //
- EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
- /*| EHCI_USBINTR_FLROVR*/ | EHCI_USBINTR_PC);
-
+ GetCommandRegister(&UsbCmd);
UsbCmd.Run = TRUE;
SetCommandRegister(&UsbCmd);
//
EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1);
+ //
+ // Enable async
+ //
+ GetCommandRegister(&UsbCmd);
+ UsbCmd.AsyncEnable = TRUE; //FIXME: Need USB Memory Manager
+ // FIXME: Set framelistsize when periodic is implemented.
+ SetCommandRegister(&UsbCmd);
+
DPRINT1("EHCI Started!\n");
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
+ //
+ // check slow speed line before reset
+ //
if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
{
DPRINT1("Non HighSpeed device. Releasing Ownership\n");
return STATUS_DEVICE_NOT_CONNECTED;
}
+ ASSERT(PortStatus & EHCI_PRT_CONNECTED);
+
//
// Reset and clean enable
//
PortStatus &= ~EHCI_PRT_RESET;
EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
- KeStallExecutionProcessor(100);
+ 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);
//
- // Check that the port reset
+ // check slow speed line after reset
//
- PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
- if (PortStatus & EHCI_PRT_RESET)
+ if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
{
- DPRINT1("Port did not reset\n");
- return STATUS_RETRY;
+ DPRINT1("Non HighSpeed device. Releasing Ownership\n");
+ EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), EHCI_PRT_RELEASEOWNERSHIP);
+ return STATUS_DEVICE_NOT_CONNECTED;
}
+ //
+ // this must be enabled now
+ //
+ ASSERT(PortStatus & EHCI_PRT_ENABLED);
+
return STATUS_SUCCESS;
}
OUT USHORT *PortStatus,
OUT USHORT *PortChange)
{
-#if 0
ULONG Value;
USHORT Status = 0, Change = 0;
}
}
- // Get Speed. If SlowSpeedLine flag is there then its a slow speed device
- if (Value & EHCI_PRT_SLOWSPEEDLINE)
- Status |= USB_PORT_STATUS_LOW_SPEED;
- else
- Status |= USB_PORT_STATUS_HIGH_SPEED;
-
// Get Connected Status
if (Value & EHCI_PRT_CONNECTED)
+ {
Status |= USB_PORT_STATUS_CONNECT;
+ // Get Speed. If SlowSpeedLine flag is there then its a slow speed device
+ if (Value & EHCI_PRT_SLOWSPEEDLINE)
+ Status |= USB_PORT_STATUS_LOW_SPEED;
+ else
+ Status |= USB_PORT_STATUS_HIGH_SPEED;
+ }
+
// Get Enabled Status
if (Value & EHCI_PRT_ENABLED)
Status |= USB_PORT_STATUS_ENABLE;
Status |= USB_PORT_STATUS_OVER_CURRENT;
// In a reset state?
- if (Value & EHCI_PRT_RESET)
+ if ((Value & EHCI_PRT_RESET) || m_ResetInProgress[PortId])
+ {
Status |= USB_PORT_STATUS_RESET;
+ Change |= USB_PORT_STATUS_RESET;
+ }
//
// FIXME: Is the Change here correct?
*PortStatus = Status;
*PortChange = Change;
-#else
- *PortStatus = m_PortStatus[PortId].PortStatus;
- *PortChange = m_PortStatus[PortId].PortChange;
-#endif
+
return STATUS_SUCCESS;
}
if (PortId > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL;
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
-
if (Status == C_PORT_RESET)
{
- if (Value & EHCI_PRT_RESET)
- {
- Value &= ~EHCI_PRT_RESET;
- EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
- KeStallExecutionProcessor(100);
- }
-
- Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
//
// update port status
//
- m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_RESET;
- if (Value & EHCI_PRT_ENABLED)
- m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE;
- else
- {
- DPRINT1("Port is not enabled.\n");
- }
+ m_ResetInProgress[PortId] = FALSE;
}
if (Status == C_PORT_CONNECTION)
{
- // FIXME: Make sure its the Connection and Enable Change status.
- Value |= EHCI_PRT_CONNECTSTATUSCHANGE;
- Value |= EHCI_PRT_ENABLEDSTATUSCHANGE;
+ 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);
-
- m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_CONNECT;
}
return STATUS_SUCCESS;
if (Feature == PORT_RESET)
{
- if (Value & EHCI_PRT_SLOWSPEEDLINE)
- {
- DPRINT1("Non HighSpeed device. Releasing Ownership\n");
- }
-
ResetPort(PortId);
//
// update cached settings
//
- m_PortStatus[PortId].PortChange |= USB_PORT_STATUS_RESET;
- m_PortStatus[PortId].PortStatus &= ~USB_PORT_STATUS_ENABLE;
+ m_ResetInProgress[PortId] = TRUE;
//
// is there a status change callback
//
// controller reported error
//
+ DPRINT1("CStatus %x\n", CStatus);
Status = STATUS_UNSUCCESSFUL;
PC_ASSERT(FALSE);
+ return;
}
//
//
if (PortStatus & EHCI_PRT_CONNECTSTATUSCHANGE)
{
- //
- // Clear the port change status
- //
- //This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_CONNECTSTATUSCHANGE);
-
if (PortStatus & EHCI_PRT_CONNECTED)
{
DPRINT1("Device connected on port %d\n", i);
continue;
}
}
-
- //
- // update port status flags
- //
- This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
- This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_CONNECT;
- This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT;
}
else
{
DPRINT1("Device disconnected on port %d\n", i);
-
- //
- // update port status flags
- //
- This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_HIGH_SPEED;
- This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_CONNECT;
- This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT;
}
-
+
//
// is there a status change callback
//