[USBEHCI_NEW]

- Add flags for Port Status Control Register and remove structiures for Port Status Control Register.
- Remove USB Status Register and use the flags instead.
- Remove functions that are not used and never will be.
- Implement InterruptServiceRoutine and Deffered Procedure Routine.
- Partially implement port status change to detect device insert and removal.

svn path=/branches/usb-bringup/; revision=51366
This commit is contained in:
Michael Martin 2011-04-16 05:55:02 +00:00
parent 9b44c5121d
commit acbd41ebf5
2 changed files with 151 additions and 102 deletions

View file

@ -18,6 +18,13 @@ InterruptServiceRoutine(
IN PKINTERRUPT Interrupt, IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext); IN PVOID ServiceContext);
VOID NTAPI
EhciDefferedRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
class CUSBHardwareDevice : public IUSBHardwareDevice class CUSBHardwareDevice : public IUSBHardwareDevice
{ {
public: public:
@ -58,6 +65,7 @@ public:
// friend function // friend function
friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
// constructor / destructor // constructor / destructor
CUSBHardwareDevice(IUnknown *OuterUnknown){} CUSBHardwareDevice(IUnknown *OuterUnknown){}
@ -71,24 +79,17 @@ protected:
PDEVICE_OBJECT m_NextDeviceObject; PDEVICE_OBJECT m_NextDeviceObject;
KSPIN_LOCK m_Lock; KSPIN_LOCK m_Lock;
PKINTERRUPT m_Interrupt; PKINTERRUPT m_Interrupt;
KDPC m_IntDpcObject;
PULONG m_Base; PULONG m_Base;
PDMA_ADAPTER m_Adapter; PDMA_ADAPTER m_Adapter;
ULONG m_MapRegisters; ULONG m_MapRegisters;
PQUEUE_HEAD AsyncListQueueHead; PQUEUE_HEAD m_AsyncListQueueHead;
EHCI_CAPS m_Capabilities; EHCI_CAPS m_Capabilities;
VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
VOID SetStatusRegister(PEHCI_USBSTS_CONTENT UsbSts);
VOID GetStatusRegister(PEHCI_USBSTS_CONTENT UsbSts);
//VOID SetPortRegister(PEHCI_USBPORTSC_CONTENT UsbPort);
//VOID GetPortRegister(PEHCI_USBPORTSC_CONTENT UsbPort);
ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset); ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset);
ULONG EHCI_READ_REGISTER_USHORT(ULONG Offset);
ULONG EHCI_READ_REGISTER_UCHAR(ULONG Offset);
VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value); VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value);
VOID EHCI_WRITE_REGISTER_USHORT(ULONG Offset, ULONG Value);
VOID EHCI_WRITE_REGISTER_UCHAR(ULONG Offset, ULONG Value);
}; };
//================================================================================================= //=================================================================================================
@ -152,59 +153,18 @@ CUSBHardwareDevice::GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
*Register = READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBCMD)); *Register = READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBCMD));
} }
VOID
CUSBHardwareDevice::SetStatusRegister(PEHCI_USBSTS_CONTENT UsbSts)
{
PULONG Register;
Register = (PULONG)UsbSts;
WRITE_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBSTS), *Register);
}
VOID
CUSBHardwareDevice::GetStatusRegister(PEHCI_USBSTS_CONTENT UsbSts)
{
PULONG CmdRegister;
CmdRegister = (PULONG)UsbSts;
*CmdRegister = READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBSTS));
}
ULONG ULONG
CUSBHardwareDevice::EHCI_READ_REGISTER_ULONG(ULONG Offset) CUSBHardwareDevice::EHCI_READ_REGISTER_ULONG(ULONG Offset)
{ {
return READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset)); return READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset));
} }
ULONG
CUSBHardwareDevice::EHCI_READ_REGISTER_USHORT(ULONG Offset)
{
return READ_REGISTER_USHORT((PUSHORT)((ULONG)m_Base + Offset));
}
ULONG
CUSBHardwareDevice::EHCI_READ_REGISTER_UCHAR(ULONG Offset)
{
return READ_REGISTER_UCHAR((PUCHAR)((ULONG)m_Base + Offset));
}
VOID VOID
CUSBHardwareDevice::EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value) CUSBHardwareDevice::EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value)
{ {
WRITE_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset), Value); WRITE_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset), Value);
} }
VOID
CUSBHardwareDevice::EHCI_WRITE_REGISTER_USHORT(ULONG Offset, ULONG Value)
{
WRITE_REGISTER_USHORT((PUSHORT)((ULONG)m_Base + Offset), Value);
}
VOID
CUSBHardwareDevice::EHCI_WRITE_REGISTER_UCHAR(ULONG Offset, ULONG Value)
{
WRITE_REGISTER_UCHAR((PUCHAR)((ULONG)m_Base + Offset), Value);
}
NTSTATUS NTSTATUS
CUSBHardwareDevice::PnpStart( CUSBHardwareDevice::PnpStart(
PCM_RESOURCE_LIST RawResources, PCM_RESOURCE_LIST RawResources,
@ -228,6 +188,10 @@ CUSBHardwareDevice::PnpStart(
{ {
case CmResourceTypeInterrupt: case CmResourceTypeInterrupt:
{ {
KeInitializeDpc(&m_IntDpcObject,
EhciDefferedRoutine,
this);
Status = IoConnectInterrupt(&m_Interrupt, Status = IoConnectInterrupt(&m_Interrupt,
InterruptServiceRoutine, InterruptServiceRoutine,
(PVOID)this, (PVOID)this,
@ -324,7 +288,7 @@ CUSBHardwareDevice::PnpStart(
// //
// FIXME: Create a QueueHead that will always be the address of the AsyncList // FIXME: Create a QueueHead that will always be the address of the AsyncList
// //
AsyncListQueueHead = NULL; m_AsyncListQueueHead = NULL;
// //
// Start the controller // Start the controller
@ -381,20 +345,19 @@ NTSTATUS
CUSBHardwareDevice::StartController(void) CUSBHardwareDevice::StartController(void)
{ {
EHCI_USBCMD_CONTENT UsbCmd; EHCI_USBCMD_CONTENT UsbCmd;
EHCI_USBSTS_CONTENT UsbSts; ULONG UsbSts, FailSafe;
LONG FailSafe;
// //
// Stop the controller if its running // Stop the controller if its running
// //
GetStatusRegister(&UsbSts); UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
if (UsbSts.HCHalted) if (!(UsbSts & EHCI_STS_HALT))
StopController(); StopController();
// //
// Reset the device. Bit is set to 0 on completion. // Reset the device. Bit is set to 0 on completion.
// //
SetCommandRegister(&UsbCmd); GetCommandRegister(&UsbCmd);
UsbCmd.HCReset = TRUE; UsbCmd.HCReset = TRUE;
SetCommandRegister(&UsbCmd); SetCommandRegister(&UsbCmd);
@ -438,7 +401,7 @@ CUSBHardwareDevice::StartController(void)
UsbCmd.AsyncEnable = FALSE; //FIXME: Need USB Memory Manager UsbCmd.AsyncEnable = FALSE; //FIXME: Need USB Memory Manager
UsbCmd.IntThreshold = 1; UsbCmd.IntThreshold = 1;
// FIXME: Set framlistsize when periodic is implemented. // FIXME: Set framelistsize when periodic is implemented.
SetCommandRegister(&UsbCmd); SetCommandRegister(&UsbCmd);
// //
@ -456,15 +419,15 @@ CUSBHardwareDevice::StartController(void)
for (FailSafe = 100; FailSafe > 1; FailSafe--) for (FailSafe = 100; FailSafe > 1; FailSafe--)
{ {
KeStallExecutionProcessor(10); KeStallExecutionProcessor(10);
GetStatusRegister(&UsbSts); UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
if (!UsbSts.HCHalted) if (!(UsbSts & EHCI_STS_HALT))
{ {
break; break;
} }
} }
if (!UsbSts.HCHalted) if (UsbSts & EHCI_STS_HALT)
{ {
DPRINT1("Could not start execution on the controller\n"); DPRINT1("Could not start execution on the controller\n");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
@ -482,8 +445,7 @@ NTSTATUS
CUSBHardwareDevice::StopController(void) CUSBHardwareDevice::StopController(void)
{ {
EHCI_USBCMD_CONTENT UsbCmd; EHCI_USBCMD_CONTENT UsbCmd;
EHCI_USBSTS_CONTENT UsbSts; ULONG UsbSts, FailSafe;
LONG FailSafe;
// //
// Disable Interrupts and stop execution // Disable Interrupts and stop execution
@ -496,14 +458,14 @@ CUSBHardwareDevice::StopController(void)
for (FailSafe = 100; FailSafe > 1; FailSafe--) for (FailSafe = 100; FailSafe > 1; FailSafe--)
{ {
KeStallExecutionProcessor(10); KeStallExecutionProcessor(10);
GetStatusRegister(&UsbSts); UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
if (UsbSts.HCHalted) if (UsbSts & EHCI_STS_HALT)
{ {
break; break;
} }
} }
if (!UsbSts.HCHalted) if (!(UsbSts & EHCI_STS_HALT))
{ {
DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n"); DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
@ -557,8 +519,114 @@ InterruptServiceRoutine(
IN PKINTERRUPT Interrupt, IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext) IN PVOID ServiceContext)
{ {
UNIMPLEMENTED CUSBHardwareDevice *This;
return FALSE; ULONG CStatus;
This = (CUSBHardwareDevice*) ServiceContext;
CStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR);
//
// Check that it belongs to EHCI
//
if (!CStatus)
return FALSE;
//
// Clear the Status
//
This->EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, CStatus);
if (CStatus & EHCI_STS_FATAL)
{
This->StopController();
DPRINT1("EHCI: Host System Error!\n");
return TRUE;
}
if (CStatus & EHCI_ERROR_INT)
{
DPRINT1("EHCI Status = 0x%x\n", CStatus);
}
if (CStatus & EHCI_STS_HALT)
{
DPRINT1("Host Error Unexpected Halt\n");
// FIXME: Reset controller\n");
return TRUE;
}
KeInsertQueueDpc(&This->m_IntDpcObject, This, (PVOID)CStatus);
return TRUE;
}
VOID NTAPI
EhciDefferedRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
CUSBHardwareDevice *This;
ULONG CStatus, PortStatus, i;
This = (CUSBHardwareDevice*) SystemArgument1;
CStatus = (ULONG) SystemArgument2;
if (CStatus & EHCI_STS_PCD)
{
for (i = 0; i < This->m_Capabilities.HCSParams.PortCount; i++)
{
PortStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * i));
//
// Device connected or removed
//
if (PortStatus & EHCI_PRT_CONNECTSTATUSCHAGE)
{
//
// Clear the port change status
//
This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus & EHCI_PRT_CONNECTSTATUSCHAGE);
if (PortStatus & EHCI_PRT_CONNECTED)
{
DPRINT1("Device connected on port %d\n", i);
//
//FIXME: Determine device speed
//
if (This->m_Capabilities.HCSParams.CHCCount)
{
if (PortStatus & EHCI_PRT_ENABLED)
{
DPRINT1("Misbeaving controller. Port should be disabled at this point\n");
}
if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
{
DPRINT1("Non HighSeped device connected. Release ownership\n");
This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), EHCI_PRT_RELEASEOWNERSHIP);
continue;
}
//
// FIXME: Is a port reset needed, or does hub driver request this?
//
}
}
else
{
DPRINT1("Device disconnected on port %d\n", i);
}
//
// FIXME: This needs to be saved somewhere
//
}
}
}
return;
} }
NTSTATUS NTSTATUS

View file

@ -42,6 +42,22 @@
#define EHCI_STS_ASS 0x8000 #define EHCI_STS_ASS 0x8000
#define EHCI_ERROR_INT (EHCI_STS_FATAL | EHCI_STS_ERR) #define EHCI_ERROR_INT (EHCI_STS_FATAL | EHCI_STS_ERR)
//
// Port Register Flags
//
#define EHCI_PRT_CONNECTED 0x01
#define EHCI_PRT_CONNECTSTATUSCHAGE 0x02
#define EHCI_PRT_ENABLED 0x04
#define EHCI_PRT_ENABLEDSTATUSCHANGE 0x08
#define EHCI_PRT_OVERCURRENTACTIVE 0x10
#define EHCI_PRT_OVERCURRENTCHANGE 0x20
#define EHCI_PRT_FORCERESUME 0x40
#define EHCI_PRT_SUSPEND 0x80
#define EHCI_PRT_RESET 0x100
#define EHCI_PRT_SLOWSPEEDLINE 0x400
#define EHCI_PRT_POWER 0x1000
#define EHCI_PRT_RELEASEOWNERSHIP 0x2000
// //
// Terminate Pointer used for QueueHeads and Element Transfer Descriptors to mark Pointers as the end // Terminate Pointer used for QueueHeads and Element Transfer Descriptors to mark Pointers as the end
// //
@ -202,41 +218,6 @@ typedef struct _EHCI_USBCMD_CONTENT
ULONG Reserved2 : 8; ULONG Reserved2 : 8;
} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT; } EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
//
// Status register content
//
typedef struct _EHCI_USBSTS_CONTENT
{
ULONG USBInterrupt:1;
ULONG ErrorInterrupt:1;
ULONG DetectChangeInterrupt:1;
ULONG FrameListRolloverInterrupt:1;
ULONG HostSystemErrorInterrupt:1;
ULONG AsyncAdvanceInterrupt:1;
ULONG Reserved:6;
ULONG HCHalted:1;
ULONG Reclamation:1;
ULONG PeriodicScheduleStatus:1;
ULONG AsynchronousScheduleStatus:1;
} EHCI_USBSTS_CONTENT, *PEHCI_USBSTS_CONTENT;
typedef struct _EHCI_USBPORTSC_CONTENT
{
ULONG CurrentConnectStatus:1;
ULONG ConnectStatusChange:1;
ULONG PortEnabled:1;
ULONG PortEnableChanged:1;
ULONG OverCurrentActive:1;
ULONG OverCurrentChange:1;
ULONG ForcePortResume:1;
ULONG Suspend:1;
ULONG PortReset:1;
ULONG Reserved:1;
ULONG LineStatus:2;
ULONG PortPower:1;
ULONG PortOwner:1;
} EHCI_USBPORTSC_CONTENT, *PEHCI_USBPORTSC_CONTENT;
typedef struct _EHCI_HCS_CONTENT typedef struct _EHCI_HCS_CONTENT
{ {
ULONG PortCount : 4; ULONG PortCount : 4;