[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
This commit is contained in:
Michael Martin 2010-01-09 19:28:29 +00:00
parent f1e6ecbc60
commit ce0ab52c93
9 changed files with 696 additions and 208 deletions

View file

@ -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"

View file

@ -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 */
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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 *******************************************************************/

View file

@ -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

View file

@ -8,4 +8,6 @@
<file>pdo.c</file>
<file>common.c</file>
<file>misc.c</file>
<file>irp.c</file>
<file>urbreq.c</file>
</module>