diff --git a/reactos/drivers/usb/usbehci/common.c b/reactos/drivers/usb/usbehci/common.c
index a3e3df14e40..f03325dc7b8 100644
--- a/reactos/drivers/usb/usbehci/common.c
+++ b/reactos/drivers/usb/usbehci/common.c
@@ -1,3 +1,11 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/common.c
+ * PURPOSE: Common operations in FDO/PDO.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
#define INITGUID
#include "usbehci.h"
diff --git a/reactos/drivers/usb/usbehci/fdo.c b/reactos/drivers/usb/usbehci/fdo.c
index dbee65781b5..59a89718049 100644
--- a/reactos/drivers/usb/usbehci/fdo.c
+++ b/reactos/drivers/usb/usbehci/fdo.c
@@ -1,3 +1,11 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/fdo.c
+ * PURPOSE: USB EHCI device driver.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
/* INCLUDES *******************************************************************/
#include "usbehci.h"
@@ -73,7 +81,7 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
DPRINT("port tmp %x\n", tmp);
-
+ GetDeviceDescriptor(FdoDeviceExtension, 0);
FdoDeviceExtension->ChildDeviceCount++;
CompletePendingRequest(FdoDeviceExtension);
@@ -145,7 +153,7 @@ InterruptService(PKINTERRUPT Interrupt, PVOID ServiceContext)
if (CStatus & EHCI_STS_HALT)
{
- DPRINT("EHCI: Host Controller unexpected halt.\n");
+ DPRINT1("EHCI: Host Controller unexpected halt.\n");
/* FIXME: Reset the controller */
}
diff --git a/reactos/drivers/usb/usbehci/irp.c b/reactos/drivers/usb/usbehci/irp.c
new file mode 100644
index 00000000000..137e3a2fc73
--- /dev/null
+++ b/reactos/drivers/usb/usbehci/irp.c
@@ -0,0 +1,144 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/irp.c
+ * PURPOSE: IRP Handling.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
+
+#include "usbehci.h"
+
+VOID
+RequestCancel (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+ PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+
+ PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+ FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
+
+ KIRQL OldIrql = Irp->CancelIrql;
+ IoReleaseCancelSpinLock(DISPATCH_LEVEL);
+
+ KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->IrpQueueLock);
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+ KeReleaseSpinLock(&FdoDeviceExtension->IrpQueueLock, OldIrql);
+
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+VOID
+QueueRequest(PFDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
+{
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &OldIrql);
+
+ if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+ {
+ KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, OldIrql);
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ else
+ {
+ InsertTailList(&DeviceExtension->IrpQueue, &Irp->Tail.Overlay.ListEntry);
+ KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, OldIrql);
+ }
+}
+
+VOID
+CompletePendingRequest(PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+ PLIST_ENTRY NextIrp = NULL;
+ PIO_STACK_LOCATION Stack;
+ KIRQL oldIrql;
+ PIRP Irp = NULL;
+ URB *Urb;
+
+ KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
+
+ while(!IsListEmpty(&DeviceExtension->IrpQueue))
+ {
+ NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
+ Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
+
+ if (!Irp)
+ break;
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ ASSERT(Stack);
+
+ Urb = (PURB) Stack->Parameters.Others.Argument1;
+ ASSERT(Urb);
+
+ /* FIXME: Fill in information for Argument1/URB */
+
+ DPRINT("TransferBuffer %x\n", Urb->UrbControlDescriptorRequest.TransferBuffer);
+ DPRINT("TransferBufferLength %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
+ DPRINT("Index %x\n", Urb->UrbControlDescriptorRequest.Index);
+ DPRINT("DescriptorType %x\n", Urb->UrbControlDescriptorRequest.DescriptorType);
+ DPRINT("LanguageId %x\n", Urb->UrbControlDescriptorRequest.LanguageId);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+
+ KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
+ }
+
+ KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
+}
+
+NTSTATUS
+NTAPI
+ArrivalNotificationCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID PContext)
+{
+ IoFreeIrp(Irp);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+VOID
+DeviceArrivalWorkItem(PDEVICE_OBJECT DeviceObject, PVOID Context)
+{
+ PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+ PIO_STACK_LOCATION IrpStack = NULL;
+ PDEVICE_OBJECT PortDeviceObject = NULL;
+ PIRP Irp = NULL;
+
+ FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
+
+ PortDeviceObject = IoGetAttachedDeviceReference(FdoDeviceExtension->Pdo);
+
+ if (!PortDeviceObject)
+ {
+ DPRINT1("Unable to notify Pdos parent of device arrival.\n");
+ return;
+ }
+
+ Irp = IoAllocateIrp(PortDeviceObject->StackSize, FALSE);
+
+ if (!Irp)
+ {
+ DPRINT1("Unable to allocate IRP\n");
+ }
+
+ IoSetCompletionRoutine(Irp,
+ (PIO_COMPLETION_ROUTINE)ArrivalNotificationCompletion,
+ NULL,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ IrpStack = IoGetNextIrpStackLocation(Irp);
+ IrpStack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
+ IrpStack->MajorFunction = IRP_MJ_PNP;
+ IrpStack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
+
+ IoCallDriver(PortDeviceObject, Irp);
+}
+
diff --git a/reactos/drivers/usb/usbehci/misc.c b/reactos/drivers/usb/usbehci/misc.c
index b3aa20d0750..520c1c7aa8f 100644
--- a/reactos/drivers/usb/usbehci/misc.c
+++ b/reactos/drivers/usb/usbehci/misc.c
@@ -1,122 +1,14 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/misc.c
+ * PURPOSE: Misceallenous operations.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
#include "usbehci.h"
-VOID
-QueueRequest(PFDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
-{
- KIRQL oldIrql;
-
- KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
- InsertTailList(&DeviceExtension->IrpQueue, &Irp->Tail.Overlay.ListEntry);
- KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
-}
-
-VOID
-CompletePendingRequest(PFDO_DEVICE_EXTENSION DeviceExtension)
-{
- PLIST_ENTRY NextIrp = NULL;
- PIO_STACK_LOCATION Stack;
- KIRQL oldIrql;
- PIRP Irp = NULL;
- URB *Urb;
-
- KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
-
- /* No Irps in Queue? */
- if (IsListEmpty(&DeviceExtension->IrpQueue))
- {
- KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
- return;
- }
-
- NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
- while(TRUE)
- {
- Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
-
- if (!Irp)
- break;
-
- /* FIXME: Handle cancels */
- /*if (!IoSetCancelRoutine(Irp, NULL))
- {
-
- }*/
-
-
- Stack = IoGetCurrentIrpStackLocation(Irp);
-
- Urb = (PURB) Stack->Parameters.Others.Argument1;
-
- ASSERT(Urb);
-
- /* FIXME: Fill in information for Argument1/URB */
-
- DPRINT("TransferBuffer %x\n", Urb->UrbControlDescriptorRequest.TransferBuffer);
- DPRINT("TransferBufferLength %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
- DPRINT("Index %x\n", Urb->UrbControlDescriptorRequest.Index);
- DPRINT("DescriptorType %x\n", Urb->UrbControlDescriptorRequest.DescriptorType);
- DPRINT("LanguageId %x\n", Urb->UrbControlDescriptorRequest.LanguageId);
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
-
- KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
- }
-
- KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
-}
-
-NTSTATUS
-NTAPI
-ArrivalNotificationCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID PContext)
-{
- IoFreeIrp(Irp);
- return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-VOID
-DeviceArrivalWorkItem(PDEVICE_OBJECT DeviceObject, PVOID Context)
-{
- PFDO_DEVICE_EXTENSION FdoDeviceExtension;
- PIO_STACK_LOCATION IrpStack = NULL;
- PDEVICE_OBJECT PortDeviceObject = NULL;
- PIRP Irp = NULL;
-
- FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
-
- PortDeviceObject = IoGetAttachedDeviceReference(FdoDeviceExtension->Pdo);
-
- if (!PortDeviceObject)
- {
- DPRINT1("Unable to notify Pdos parent of device arrival.\n");
- return;
- }
-
- Irp = IoAllocateIrp(PortDeviceObject->StackSize, FALSE);
-
- if (!Irp)
- {
- DPRINT1("Unable to allocate IRP\n");
- }
-
- IoSetCompletionRoutine(Irp,
- (PIO_COMPLETION_ROUTINE)ArrivalNotificationCompletion,
- NULL,
- TRUE,
- TRUE,
- TRUE);
-
- IrpStack = IoGetNextIrpStackLocation(Irp);
- IrpStack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
- IrpStack->MajorFunction = IRP_MJ_PNP;
- IrpStack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
-
- IoCallDriver(PortDeviceObject, Irp);
-}
-
/*
Get SymblicName from Parameters in Registry Key
Caller is responsible for freeing pool of returned pointer
diff --git a/reactos/drivers/usb/usbehci/pdo.c b/reactos/drivers/usb/usbehci/pdo.c
index 9c966a16696..8334a2d1977 100644
--- a/reactos/drivers/usb/usbehci/pdo.c
+++ b/reactos/drivers/usb/usbehci/pdo.c
@@ -1,3 +1,11 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/pdo.c
+ * PURPOSE: USB EHCI device driver.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
/* INCLUDES *******************************************************************/
#define INITGUID
@@ -55,24 +63,14 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Urb = (PURB) Stack->Parameters.Others.Argument1;
Urb->UrbHeader.Status = 0;
- /* Check for ChildDevices */
- if (!FdoDeviceExtension->ChildDeviceCount)
- {
- /* No device has been plugged in yet. So just queue
- the irp and complete it when a device is connected */
- if (FdoDeviceExtension->DeviceState)
- QueueRequest(FdoDeviceExtension, Irp);
+ DPRINT1("Irp->CancelRoutine %x\n",Irp->CancelRoutine);
+ QueueRequest(FdoDeviceExtension, Irp);
+
+ Information = 0;
- Information = 0;
+ IoMarkIrpPending(Irp);
+ Status = STATUS_PENDING;
- IoMarkIrpPending(Irp);
- Status = STATUS_PENDING;
- }
- else
- {
- DPRINT1("Reporting of device connects not implemented yet.\n");
- Status = STATUS_SUCCESS;
- }
break;
}
/* FIXME: Handle all other Functions */
@@ -158,7 +156,7 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
default:
{
- DPRINT("Unhandled IoControlCode %x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
+ DPRINT1("Unhandled IoControlCode %x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
break;
}
}
diff --git a/reactos/drivers/usb/usbehci/urbreq.c b/reactos/drivers/usb/usbehci/urbreq.c
new file mode 100644
index 00000000000..8ff24016c0e
--- /dev/null
+++ b/reactos/drivers/usb/usbehci/urbreq.c
@@ -0,0 +1,299 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/urbreq.c
+ * PURPOSE: URB Related Functions.
+ * PROGRAMMERS:
+ * Michael Martin
+ */
+
+#include "usbehci.h"
+
+/* QueueHead must point to the base address in common buffer */
+PVOID
+IntializeHeadQueueForStandardRequest(PQUEUE_HEAD QueueHead,
+ PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD1,
+ PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD2,
+ PQUEUE_TRANSFER_DESCRIPTOR *CtrlTD3,
+ PEHCI_SETUP_FORMAT *CtrlSetup,
+ PVOID *CtrlData,
+ ULONG Size)
+{
+ QueueHead->HorizontalLinkPointer = (ULONG)QueueHead | QH_TYPE_QH;
+
+ /* Set NakCountReload to max value possible */
+ QueueHead->EndPointCapabilities1.NakCountReload = 0xF;
+
+ /* 1 for non high speed, 0 for high speed device */
+ QueueHead->EndPointCapabilities1.ControlEndPointFlag = 0;
+
+ QueueHead->EndPointCapabilities1.HeadOfReclamation = TRUE;
+ QueueHead->EndPointCapabilities1.MaximumPacketLength = 64;
+
+ /* Get the Initial Data Toggle from the QEDT */
+ QueueHead->EndPointCapabilities1.QEDTDataToggleControl = TRUE;
+
+ /* HIGH SPEED DEVICE */
+ QueueHead->EndPointCapabilities1.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+ QueueHead->EndPointCapabilities1.EndPointNumber = 0;
+
+ /* Only used for Periodic Schedule and Not High Speed devices.
+ Setting it to one result in undefined behavior for Async */
+ QueueHead->EndPointCapabilities1.InactiveOnNextTransaction = 0;
+
+ QueueHead->EndPointCapabilities1.DeviceAddress = 0;
+ QueueHead->EndPointCapabilities2.HubAddr = 0;
+ QueueHead->EndPointCapabilities2.NumberOfTransactionPerFrame = 0x01;
+
+ /* 0 For Async, 1 for periodoc schedule */
+ QueueHead->EndPointCapabilities2.InterruptScheduleMask = 0;
+
+ QueueHead->EndPointCapabilities2.PortNumber = 0;
+ QueueHead->EndPointCapabilities2.SplitCompletionMask = 0;
+ QueueHead->CurrentLinkPointer = 0;
+ QueueHead->QETDPointer = TERMINATE_POINTER;
+ QueueHead->AlternateNextPointer = TERMINATE_POINTER;
+ QueueHead->Token.Bits.InterruptOnComplete = TRUE;
+ QueueHead->BufferPointer[0] = 0;
+ QueueHead->BufferPointer[1] = 0;
+ QueueHead->BufferPointer[2] = 0;
+ QueueHead->BufferPointer[3] = 0;
+ QueueHead->BufferPointer[4] = 0;
+ /* Queue Head Initialized */
+
+ /* Queue Transfer Descriptors must be 32 byte aligned and reside in continous physical memory */
+ *CtrlTD1 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(QueueHead) + sizeof(QUEUE_HEAD) + 0x1F) & ~0x1F);
+ *CtrlTD2 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(*CtrlTD1) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0x1F) & ~0x1F);
+ *CtrlTD3 = (PQUEUE_TRANSFER_DESCRIPTOR) (((ULONG)(*CtrlTD2) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0x1F) & ~0x1F);
+
+ /* Must be Page aligned */
+ *CtrlSetup = (PEHCI_SETUP_FORMAT) (( (ULONG)(*CtrlTD3) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0xFFF) & ~0xFFF);
+ *CtrlData = (PSTANDARD_DEVICE_DESC) (( (ULONG)(*CtrlSetup) + sizeof(EHCI_SETUP_FORMAT) + 0xFFF) & ~0xFFF);
+
+ (*CtrlTD1)->NextPointer = TERMINATE_POINTER;
+ (*CtrlTD1)->AlternateNextPointer = TERMINATE_POINTER;
+ (*CtrlTD1)->BufferPointer[0] = (ULONG)MmGetPhysicalAddress((PVOID) (*CtrlSetup)).LowPart;
+ (*CtrlTD1)->Token.Bits.DataToggle = FALSE;
+ (*CtrlTD1)->Token.Bits.InterruptOnComplete = FALSE;
+ (*CtrlTD1)->Token.Bits.TotalBytesToTransfer = sizeof(EHCI_SETUP_FORMAT);
+ (*CtrlTD1)->Token.Bits.ErrorCounter = 0x03;
+ (*CtrlTD1)->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
+ (*CtrlTD1)->Token.Bits.Active = TRUE;
+
+ (*CtrlTD2)->NextPointer = TERMINATE_POINTER;
+ (*CtrlTD2)->AlternateNextPointer = TERMINATE_POINTER;
+ (*CtrlTD2)->BufferPointer[0] = (ULONG)MmGetPhysicalAddress((PVOID) (*CtrlData)).LowPart;
+ (*CtrlTD2)->Token.Bits.DataToggle = TRUE;
+ (*CtrlTD2)->Token.Bits.InterruptOnComplete = TRUE;
+ (*CtrlTD2)->Token.Bits.TotalBytesToTransfer = Size;
+ (*CtrlTD2)->Token.Bits.ErrorCounter = 0x03;
+ (*CtrlTD2)->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
+ (*CtrlTD2)->Token.Bits.Active = TRUE;
+
+ (*CtrlTD1)->NextPointer = (ULONG)MmGetPhysicalAddress((PVOID)(*CtrlTD2)).LowPart;
+
+ (*CtrlTD3)->NextPointer = TERMINATE_POINTER;
+ (*CtrlTD3)->AlternateNextPointer = TERMINATE_POINTER;
+ (*CtrlTD3)->BufferPointer[0] = 0;
+ (*CtrlTD3)->Token.Bits.Active = TRUE;
+ (*CtrlTD3)->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN;
+ (*CtrlTD3)->Token.Bits.InterruptOnComplete = TRUE;
+ (*CtrlTD3)->Token.Bits.DataToggle = TRUE;
+ (*CtrlTD3)->Token.Bits.ErrorCounter = 0x03;
+ (*CtrlTD2)->NextPointer = (ULONG) MmGetPhysicalAddress((PVOID)(*CtrlTD3)).LowPart;
+ return NULL;
+}
+
+BOOLEAN
+GetDeviceDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index)
+{
+ PEHCI_SETUP_FORMAT CtrlSetup = NULL;
+ PSTANDARD_DEVICE_DESC CtrlData = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1 = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2 = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3 = NULL;
+ PQUEUE_HEAD QueueHead;
+ PEHCI_USBCMD_CONTENT UsbCmd;
+ PEHCI_USBSTS_CONTEXT UsbSts;
+ LONG Base;
+ LONG tmp;
+
+ Base = (ULONG) DeviceExtension->ResourceMemory;
+
+ /* Set up the QUEUE HEAD in memory */
+ QueueHead = (PQUEUE_HEAD) ((ULONG)DeviceExtension->AsyncListQueueHeadPtr);
+
+ IntializeHeadQueueForStandardRequest(QueueHead,
+ &CtrlTD1,
+ &CtrlTD2,
+ &CtrlTD3,
+ &CtrlSetup,
+ (PVOID)&CtrlData,
+ sizeof(STANDARD_DEVICE_DESC));
+
+ /* FIXME: Use defines and handle other than Device Desciptors */
+ CtrlSetup->bmRequestType = 0x80;
+ CtrlSetup->bRequest = 0x06;
+ CtrlSetup->wValue = 0x0100;
+ CtrlSetup->wIndex = 0;
+ CtrlSetup->wLength = sizeof(STANDARD_DEVICE_DESC);
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+ UsbCmd->Run = FALSE;
+ WRITE_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD), tmp);
+
+ /* Wait for the controller to halt */
+ for (;;)
+ {
+ KeStallExecutionProcessor(10);
+ tmp = READ_REGISTER_ULONG((PULONG)(Base + EHCI_USBSTS));
+ UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
+ DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(Base + EHCI_USBSTS)));
+ if (UsbSts->HCHalted)
+ {
+ break;
+ }
+ }
+
+ /* Set to TRUE on interrupt for async completion */
+ DeviceExtension->AsyncComplete = FALSE;
+ QueueHead->QETDPointer = (ULONG) MmGetPhysicalAddress((PVOID)(CtrlTD1)).LowPart;
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+ UsbCmd->AsyncEnable = TRUE;
+
+ WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+
+ /* Interrupt on Async completion */
+ UsbCmd->DoorBell = TRUE;
+ UsbCmd->Run = TRUE;
+ WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
+
+ for (;;)
+ {
+ KeStallExecutionProcessor(10);
+ DPRINT("Waiting for completion!\n");
+ if (DeviceExtension->AsyncComplete == TRUE)
+ break;
+ }
+
+ DPRINT1("bLength %d\n", CtrlData->bLength);
+ DPRINT1("bDescriptorType %x\n", CtrlData->bDescriptorType);
+ DPRINT1("bcdUSB %x\n", CtrlData->bcdUSB);
+ DPRINT1("CtrlData->bDeviceClass %x\n", CtrlData->bDeviceClass);
+ DPRINT1("CtrlData->bDeviceSubClass %x\n", CtrlData->bDeviceSubClass);
+ DPRINT1("CtrlData->bDeviceProtocal %x\n", CtrlData->bDeviceProtocal);
+ DPRINT1("CtrlData->bMaxPacketSize %x\n", CtrlData->bMaxPacketSize);
+ DPRINT1("CtrlData->idVendor %x\n", CtrlData->idVendor);
+ DPRINT1("CtrlData->idProduct %x\n", CtrlData->idProduct);
+ DPRINT1("CtrlData->bcdDevice %x\n", CtrlData->bcdDevice);
+ DPRINT1("CtrlData->iManufacturer %x\n", CtrlData->iManufacturer);
+ DPRINT1("CtrlData->iProduct %x\n", CtrlData->iProduct);
+ DPRINT1("CtrlData->iSerialNumber %x\n", CtrlData->iSerialNumber);
+ DPRINT1("CtrlData->bNumConfigurations %x\n", CtrlData->bNumConfigurations);
+
+ /* Temporary: Remove */
+ if (CtrlData->bLength > 0)
+ {
+ /* We got valid data, try for strings */
+ UCHAR Manufacturer = CtrlData->iManufacturer;
+ UCHAR Product = CtrlData->iManufacturer;
+ UCHAR SerialNumber = CtrlData->iSerialNumber;
+
+ GetDeviceStringDescriptor(DeviceExtension, Manufacturer);
+ GetDeviceStringDescriptor(DeviceExtension, Product);
+ GetDeviceStringDescriptor(DeviceExtension, SerialNumber);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+GetDeviceStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index)
+{
+ PEHCI_SETUP_FORMAT CtrlSetup = NULL;
+ PSTRING_DESCRIPTOR CtrlData = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD1 = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD2 = NULL;
+ PQUEUE_TRANSFER_DESCRIPTOR CtrlTD3 = NULL;
+ PQUEUE_HEAD QueueHead;
+ PEHCI_USBCMD_CONTENT UsbCmd;
+ PEHCI_USBSTS_CONTEXT UsbSts;
+ LONG Base;
+ LONG tmp;
+
+ Base = (ULONG) DeviceExtension->ResourceMemory;
+DPRINT1("Index: %d\n", Index);
+ /* Set up the QUEUE HEAD in memory */
+ QueueHead = (PQUEUE_HEAD) ((ULONG)DeviceExtension->AsyncListQueueHeadPtr);
+
+ IntializeHeadQueueForStandardRequest(QueueHead,
+ &CtrlTD1,
+ &CtrlTD2,
+ &CtrlTD3,
+ &CtrlSetup,
+ (PVOID)&CtrlData,
+ sizeof(STRING_DESCRIPTOR) + 256);
+
+ /* FIXME: Use defines and handle other than Device Desciptors */
+ CtrlSetup->bmRequestType = 0x80;
+ CtrlSetup->bRequest = 0x06;
+ CtrlSetup->wValue = 0x0300 | Index;
+ CtrlSetup->wIndex = 0;
+ /* 256 pulled from thin air */
+ CtrlSetup->wLength = sizeof(STRING_DESCRIPTOR) + 256;
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+ UsbCmd->Run = FALSE;
+ WRITE_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD), tmp);
+
+ /* Wait for the controller to halt */
+ for (;;)
+ {
+ KeStallExecutionProcessor(10);
+ tmp = READ_REGISTER_ULONG((PULONG)(Base + EHCI_USBSTS));
+ UsbSts = (PEHCI_USBSTS_CONTEXT)&tmp;
+ DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(Base + EHCI_USBSTS)));
+ if (UsbSts->HCHalted)
+ {
+ break;
+ }
+ }
+
+ /* Set to TRUE on interrupt for async completion */
+ DeviceExtension->AsyncComplete = FALSE;
+ QueueHead->QETDPointer = (ULONG) MmGetPhysicalAddress((PVOID)(CtrlTD1)).LowPart;
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+ UsbCmd->AsyncEnable = TRUE;
+
+ WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
+
+ tmp = READ_REGISTER_ULONG((PULONG) (Base + EHCI_USBCMD));
+ UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+
+ /* Interrupt on Async completion */
+ UsbCmd->DoorBell = TRUE;
+ UsbCmd->Run = TRUE;
+ WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
+
+ for (;;)
+ {
+ KeStallExecutionProcessor(10);
+ DPRINT("Waiting for completion!\n");
+ if (DeviceExtension->AsyncComplete == TRUE)
+ break;
+ }
+
+ DPRINT1("String %S\n", &CtrlData->bString);
+
+ return TRUE;
+}
+
diff --git a/reactos/drivers/usb/usbehci/usbehci.c b/reactos/drivers/usb/usbehci/usbehci.c
index 4c2b60fee40..dd35b0d6dd1 100644
--- a/reactos/drivers/usb/usbehci/usbehci.c
+++ b/reactos/drivers/usb/usbehci/usbehci.c
@@ -1,21 +1,10 @@
/*
- * ReactOS USB ehci driver
- * Copyright (C) 2009 Michael Martin
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/usbehci.c
+ * PURPOSE: USB EHCI device driver.
+ * PROGRAMMERS:
+ * Michael Martin
*/
/* DEFINES *******************************************************************/
diff --git a/reactos/drivers/usb/usbehci/usbehci.h b/reactos/drivers/usb/usbehci/usbehci.h
index 75c2d9a4123..1e0eecfc452 100644
--- a/reactos/drivers/usb/usbehci/usbehci.h
+++ b/reactos/drivers/usb/usbehci/usbehci.h
@@ -53,6 +53,205 @@
#define EHCI_STS_ASS 0x8000
#define EHCI_ERROR_INT ( EHCI_STS_FATAL | EHCI_STS_ERR )
+
+/* Last bit in QUEUE ELEMENT TRANSFER DESCRIPTOR Next Pointer */
+/* Used for Queue Element Transfer Descriptor Pointers
+ and Queue Head Horizontal Link Pointers */
+#define TERMINATE_POINTER 0x01
+
+/* QUEUE ELEMENT TRANSFER DESCRIPTOR, Token defines and structs */
+
+/* PIDCodes for QETD_TOKEN
+OR with QUEUE_TRANSFER_DESCRIPTOR Token.PIDCode*/
+#define PID_CODE_OUT_TOKEN 0x00
+#define PID_CODE_IN_TOKEN 0x01
+#define PID_CODE_SETUP_TOKEN 0x02
+
+/* Split Transaction States
+OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */
+#define DO_START_SPLIT 0x00
+#define DO_COMPLETE_SPLIT 0x01
+
+/* Ping States, OR with QUEUE_TRANSFER_DESCRIPTOR Token. */
+#define PING_STATE_DO_OUT 0x00
+#define PING_STATE_DO_PING 0x01
+
+/* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */
+typedef struct _QETD_TOKEN_BITS
+{
+ ULONG PingState:1;
+ ULONG SplitTransactionState:1;
+ ULONG MissedMicroFrame:1;
+ ULONG TransactionError:1;
+ ULONG BabbelDetected:1;
+ ULONG DataBufferError:1;
+ ULONG Halted:1;
+ ULONG Active:1;
+ ULONG PIDCode:2;
+ ULONG ErrorCounter:2;
+ ULONG CurrentPage:3;
+ ULONG InterruptOnComplete:1;
+ ULONG TotalBytesToTransfer:15;
+ ULONG DataToggle:1;
+} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS;
+
+
+/* QUEUE ELEMENT TRANSFER DESCRIPTOR */
+typedef struct _QUEUE_TRANSFER_DESCRIPTOR
+{
+ ULONG NextPointer;
+ ULONG AlternateNextPointer;
+ union
+ {
+ QETD_TOKEN_BITS Bits;
+ ULONG DWord;
+ } Token;
+ ULONG BufferPointer[5];
+} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
+
+/* EndPointSpeeds of END_POINT_CAPABILITIES */
+#define QH_ENDPOINT_FULLSPEED 0x00
+#define QH_ENDPOINT_LOWSPEED 0x01
+#define QH_ENDPOINT_HIGHSPEED 0x02
+
+typedef struct _END_POINT_CAPABILITIES1
+{
+ ULONG DeviceAddress:7;
+ ULONG InactiveOnNextTransaction:1;
+ ULONG EndPointNumber:4;
+ ULONG EndPointSpeed:2;
+ ULONG QEDTDataToggleControl:1;
+ ULONG HeadOfReclamation:1;
+ ULONG MaximumPacketLength:11;
+ ULONG ControlEndPointFlag:1;
+ ULONG NakCountReload:4;
+} END_POINT_CAPABILITIES1, *PEND_POINT_CAPABILITIES1;
+
+typedef struct _END_POINT_CAPABILITIES2
+{
+ ULONG InterruptScheduleMask:8;
+ ULONG SplitCompletionMask:8;
+ ULONG HubAddr:6;
+ ULONG PortNumber:6;
+ /* Multi */
+ ULONG NumberOfTransactionPerFrame:2;
+} END_POINT_CAPABILITIES2, *PEND_POINT_CAPABILITIES2;
+
+
+/* QUEUE HEAD defines and structs */
+
+/* QUEUE HEAD Select Types, OR with QUEUE_HEAD HorizontalLinkPointer */
+#define QH_TYPE_IDT 0x00
+#define QH_TYPE_QH 0x02
+#define QH_TYPE_SITD 0x04
+#define QH_TYPE_FSTN 0x06
+
+/* QUEUE HEAD */
+typedef struct _QUEUE_HEAD
+{
+ ULONG HorizontalLinkPointer;
+ END_POINT_CAPABILITIES1 EndPointCapabilities1;
+ END_POINT_CAPABILITIES2 EndPointCapabilities2;
+ /* TERMINATE_POINTER not valid for this member */
+ ULONG CurrentLinkPointer;
+ /* TERMINATE_POINTER valid */
+ ULONG QETDPointer;
+ /* TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTER */
+ ULONG AlternateNextPointer;
+ /* Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid */
+ union
+ {
+ QETD_TOKEN_BITS Bits;
+ ULONG DWord;
+ } Token;
+ ULONG BufferPointer[5];
+} QUEUE_HEAD, *PQUEUE_HEAD;
+
+typedef struct _EHCI_SETUP_FORMAT
+{
+ UCHAR bmRequestType;
+ UCHAR bRequest;
+ USHORT wValue;
+ USHORT wIndex;
+ USHORT wLength;
+} EHCI_SETUP_FORMAT, *PEHCI_SETUP_FORMAT;
+
+typedef struct _STANDARD_DEVICE_DESC
+{
+ UCHAR bLength;
+ UCHAR bDescriptorType;
+ USHORT bcdUSB;
+ UCHAR bDeviceClass;
+ UCHAR bDeviceSubClass;
+ UCHAR bDeviceProtocal;
+ UCHAR bMaxPacketSize;
+ USHORT idVendor;
+ USHORT idProduct;
+ USHORT bcdDevice;
+ UCHAR iManufacturer;
+ UCHAR iProduct;
+ UCHAR iSerialNumber;
+ UCHAR bNumConfigurations;
+} STANDARD_DEVICE_DESC, *PSTANDARD_DEVICE_DESC;
+
+typedef struct _STRING_DESCRIPTOR
+{
+ UCHAR bLength; /* Size of this descriptor in bytes */
+ UCHAR bDescriptorType; /* STRING Descriptor Type */
+ UCHAR bString[0]; /* UNICODE encoded string */
+} STRING_DESCRIPTOR, *PSTRING_DESCRIPTOR;
+
+/* USBCMD register 32 bits */
+typedef struct _EHCI_USBCMD_CONTENT
+{
+ ULONG Run : 1;
+ ULONG HCReset : 1;
+ ULONG FrameListSize : 2;
+ ULONG PeriodicEnable : 1;
+ ULONG AsyncEnable : 1;
+ ULONG DoorBell : 1;
+ ULONG LightReset : 1;
+ ULONG AsyncParkCount : 2;
+ ULONG Reserved : 1;
+ ULONG AsyncParkEnable : 1;
+ ULONG Reserved1 : 4;
+ ULONG IntThreshold : 8;
+ ULONG Reserved2 : 8;
+
+} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_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_CONTEXT, *PEHCI_USBSTS_CONTEXT;
+
+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
{
ULONG PortCount : 4;
@@ -167,57 +366,6 @@ typedef struct _PDO_DEVICE_EXTENSION
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
-/* USBCMD register 32 bits */
-typedef struct _EHCI_USBCMD_CONTENT
-{
- ULONG Run : 1;
- ULONG HCReset : 1;
- ULONG FrameListSize : 2;
- ULONG PeriodicEnable : 1;
- ULONG AsyncEnable : 1;
- ULONG DoorBell : 1;
- ULONG LightReset : 1;
- ULONG AsyncParkCount : 2;
- ULONG Reserved : 1;
- ULONG AsyncParkEnable : 1;
- ULONG Reserved1 : 4;
- ULONG IntThreshold : 8;
- ULONG Reserved2 : 8;
-
-} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_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_CONTEXT, *PEHCI_USBSTS_CONTEXT;
-
-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;
-
NTSTATUS NTAPI
GetBusInterface(PDEVICE_OBJECT pcifido, PBUS_INTERFACE_STANDARD busInterface);
@@ -252,13 +400,10 @@ NTSTATUS NTAPI
PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
BOOLEAN
-GetDeviceDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, USHORT Port);
+GetDeviceDescriptor (PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index);
BOOLEAN
-GetDeviceDescriptor2(PFDO_DEVICE_EXTENSION DeviceExtension, USHORT Port);
-
-BOOLEAN
-GetStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, ULONG DecriptorStringNumber);
+GetDeviceStringDescriptor(PFDO_DEVICE_EXTENSION DeviceExtension, UCHAR Index);
VOID
CompletePendingRequest(PFDO_DEVICE_EXTENSION DeviceExtension);
@@ -275,4 +420,7 @@ CompletePendingRequest(PFDO_DEVICE_EXTENSION DeviceExtension);
VOID
DeviceArrivalWorkItem(PDEVICE_OBJECT DeviceObject, PVOID Context);
+VOID
+RequestCancel (PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
#endif
diff --git a/reactos/drivers/usb/usbehci/usbehci.rbuild b/reactos/drivers/usb/usbehci/usbehci.rbuild
index 69cc8960d58..c49c039e15a 100644
--- a/reactos/drivers/usb/usbehci/usbehci.rbuild
+++ b/reactos/drivers/usb/usbehci/usbehci.rbuild
@@ -8,4 +8,6 @@
pdo.c
common.c
misc.c
+ irp.c
+ urbreq.c