From ce0ab52c935b0e11bd5b14bbec368df6d8885e1d Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Sat, 9 Jan 2010 19:28:29 +0000 Subject: [PATCH] [usb/usbehci] - Added numerous structures required for Asynchronous Lists used to communicate with controller. Needs much more work. - Implement initial retrieving Device and String Descriptors from USB devices. - Fixed improper handling of Queued IRPs that was causing crashes. - For now, always queue the Irp if the request is a Urb of type Get Descriptor. - Reorganized code to trim down source files. svn path=/trunk/; revision=45017 --- reactos/drivers/usb/usbehci/common.c | 8 + reactos/drivers/usb/usbehci/fdo.c | 12 +- reactos/drivers/usb/usbehci/irp.c | 144 ++++++++++ reactos/drivers/usb/usbehci/misc.c | 124 +-------- reactos/drivers/usb/usbehci/pdo.c | 32 ++- reactos/drivers/usb/usbehci/urbreq.c | 299 +++++++++++++++++++++ reactos/drivers/usb/usbehci/usbehci.c | 23 +- reactos/drivers/usb/usbehci/usbehci.h | 260 ++++++++++++++---- reactos/drivers/usb/usbehci/usbehci.rbuild | 2 + 9 files changed, 696 insertions(+), 208 deletions(-) create mode 100644 reactos/drivers/usb/usbehci/irp.c create mode 100644 reactos/drivers/usb/usbehci/urbreq.c 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