[usb/usbehci]:

- Remove all hardware related routines from fdo.c as they are now in hardware.c
- Replace ExecuteControlRequest with new SubmitControlTransfer.
- For internal control requests (originating from ehci driver) use an event to signal request completion.
- When submitting non internal control request save the Irp in the software part of the QueueHead.
For these requests check for errors and complete the Irp with the appropriate URB Status when the QueueHead is complete.
- Misc code cleanup and dead code removal.
- UsbEhci now works as before and should be ready for some forward progress.

svn path=/trunk/; revision=50249
This commit is contained in:
Michael Martin 2011-01-01 12:20:19 +00:00
parent 46fe11727a
commit 7996ddf5cc
7 changed files with 432 additions and 754 deletions

View file

@ -7,38 +7,11 @@
* Michael Martin (michael.martin@reactos.org)
*/
/* INCLUDES *******************************************************************/
#include "hwiface.h"
#include "usbehci.h"
#include "physmem.h"
#include <stdio.h>
VOID NTAPI
TimerDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
ULONG tmp;
ULONG Base;
LONG i;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeferredContext;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) FdoDeviceExtension->Pdo->DeviceExtension;
Base = (ULONG)FdoDeviceExtension->ResourceMemory;
for (i = 0; i < FdoDeviceExtension->ECHICaps.HCSParams.PortCount; i++)
{
tmp = READ_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)));
if ((tmp & 0x04) && (!(PdoDeviceExtension->Ports[i].PortChange & USB_PORT_STATUS_RESET)))
{
DPRINT("Port %x is enabled\n", i);
PdoDeviceExtension->Ports[i].PortChange |= USB_PORT_STATUS_RESET;
CompletePendingURBRequest(PdoDeviceExtension);
}
}
return;
}
VOID NTAPI
EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
@ -46,7 +19,8 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
ULONG CStatus;
ULONG tmp;
ULONG Base;
ULONG OpRegisters;
PEHCI_HOST_CONTROLLER hcd;
LONG i;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeferredContext;
@ -59,17 +33,122 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) FdoDeviceExtension->Pdo->DeviceExtension;
Base = (ULONG)FdoDeviceExtension->ResourceMemory;
OpRegisters = (ULONG)FdoDeviceExtension->hcd.OpRegisters;
hcd = &FdoDeviceExtension->hcd;
CStatus = (ULONG) SystemArgument2;
/* TD retired or Error */
if (CStatus & (EHCI_STS_INT | EHCI_ERROR_INT))
{
DPRINT("Asyn Complete!\n");
ULONG CurrentAddr, OffSet;
PQUEUE_HEAD CompletedQH, NextQH;
PQUEUE_TRANSFER_DESCRIPTOR CompletedTD;
/* AsyncListAddr Register will have the next QueueHead to execute */
CurrentAddr = GetAsyncListQueueRegister(hcd);
/* Calculate the VA for the next QueueHead */
OffSet = CurrentAddr - (ULONG)FdoDeviceExtension->hcd.CommonBufferPA.LowPart;
NextQH = (PQUEUE_HEAD)((ULONG)FdoDeviceExtension->hcd.CommonBufferVA + OffSet);
/* Get the previous QueueHead which is the QueueHead just completed */
CompletedQH = NextQH->PreviousQueueHead;
ASSERT(CompletedQH);
DPRINT("CompletedQH %x\n", CompletedQH);
//DumpQueueHead(CompletedQH);
/* Free memory for the Descriptors */
CompletedTD = CompletedQH->TransferDescriptor;
//DumpTransferDescriptor(CompletedTD);
FreeDescriptor(CompletedTD);
CompletedTD = CompletedTD->NextDescriptor;
//DumpTransferDescriptor(CompletedTD);
FreeDescriptor(CompletedTD);
CompletedTD = CompletedTD->NextDescriptor;
//DumpTransferDescriptor(CompletedTD);
FreeDescriptor(CompletedTD);
/* If the Event is set then release waiter */
if (CompletedQH->Event)
{
KeSetEvent(CompletedQH->Event, IO_NO_INCREMENT, FALSE);
}
/* Free the Mdl */
ASSERT(CompletedQH->MdlToFree);
IoFreeMdl(CompletedQH->MdlToFree);
/* Is there an IRP that needs to be completed */
if (CompletedQH->IrpToComplete)
{
PIRP Irp;
Irp = CompletedQH->IrpToComplete;
/* Check for error */
if (CStatus & EHCI_ERROR_INT)
{
PIO_STACK_LOCATION Stack;
PURB Urb;
Stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(Stack);
Urb = (PURB) Stack->Parameters.Others.Argument1;
ASSERT(FALSE);
/* Haled bit should be set */
if (CompletedQH->Token.Bits.Halted)
{
if (CompletedQH->Token.Bits.DataBufferError)
{
DPRINT1("Data buffer error\n");
Urb->UrbHeader.Status = USBD_STATUS_DATA_BUFFER_ERROR;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
}
else if (CompletedQH->Token.Bits.BabbleDetected)
{
DPRINT1("Babble Detected\n");
Urb->UrbHeader.Status = USBD_STATUS_BABBLE_DETECTED;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
}
else
{
DPRINT1("Stall PID\n");
Urb->UrbHeader.Status = USBD_STATUS_STALL_PID;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
}
}
}
else
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
DPRINT1("Completing Irp\n");
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
/* Unlink QueueHead */
UnlinkQueueHead(hcd, CompletedQH);
/* Wait for a complete AsnycList tranversal before deleting? */
DeleteQueueHead(CompletedQH);
}
/* Port Change */
if (CStatus & EHCI_STS_PCD)
{
/* Loop through the ports */
for (i = 0; i < FdoDeviceExtension->ECHICaps.HCSParams.PortCount; i++)
for (i = 0; i < FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortCount; i++)
{
tmp = READ_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)));
tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)));
/* Check for port change on this port */
if (tmp & 0x02)
@ -80,9 +159,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
DPRINT1("Device connected on port %d\n", i);
/* Check if a companion host controller exists */
if (FdoDeviceExtension->ECHICaps.HCSParams.CHCCount)
if (FdoDeviceExtension->hcd.ECHICaps.HCSParams.CHCCount)
{
tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
/* Port should be in disabled state, as per USB 2.0 specs */
if (tmp & 0x04)
@ -93,9 +172,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
/* Is this non high speed device */
if (tmp & 0x400)
{
DPRINT1("Releasing ownership to companion host controller!\n");
DPRINT1("Non HighSpeed device connected. Releasing ownership.\n");
/* Release ownership to companion host controller */
WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)), 0x4000);
WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), 0x2000);
continue;
}
}
@ -111,13 +190,14 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
//KeStallExecutionProcessor(20);
tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
PdoDeviceExtension->ChildDeviceCount++;
PdoDeviceExtension->Ports[i].PortStatus &= ~0x8000;
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_CONNECT;
PdoDeviceExtension->Ports[i].PortChange |= USB_PORT_STATUS_CONNECT;
DPRINT1("Completing URB\n");
CompletePendingURBRequest(PdoDeviceExtension);
}
else
@ -125,13 +205,19 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
DPRINT1("Device disconnected on port %d\n", i);
/* Clear status change */
tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
tmp |= 0x02;
WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)), tmp);
WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), tmp);
}
}
}
}
/* Asnyc Advance */
if (CStatus & EHCI_STS_IAA)
{
DPRINT1("Async Advance!\n");
}
}
BOOLEAN NTAPI
@ -139,17 +225,15 @@ InterruptService(PKINTERRUPT Interrupt, PVOID ServiceContext)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) ServiceContext;
ULONG CurrentFrame;
ULONG Base;
PEHCI_HOST_CONTROLLER hcd;
ULONG CStatus = 0;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
Base = (ULONG)FdoDeviceExtension->ResourceMemory;
hcd = &FdoDeviceExtension->hcd;
/* Read device status */
CStatus = READ_REGISTER_ULONG ((PULONG) (Base + EHCI_USBSTS));
CurrentFrame = READ_REGISTER_ULONG((PULONG) (Base + EHCI_FRINDEX));
CStatus = ReadControllerStatus(hcd);
CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR);
@ -158,9 +242,9 @@ InterruptService(PKINTERRUPT Interrupt, PVOID ServiceContext)
/* This interrupt isnt for us or not ready for it. */
return FALSE;
}
/* Clear status */
WRITE_REGISTER_ULONG((PULONG) (Base + EHCI_USBSTS), CStatus);
ClearControllerStatus(hcd, CStatus);
if (CStatus & EHCI_ERROR_INT)
{
@ -179,239 +263,10 @@ InterruptService(PKINTERRUPT Interrupt, PVOID ServiceContext)
/* FIXME: Reset the controller */
}
if (CStatus & EHCI_STS_INT)
{
FdoDeviceExtension->AsyncComplete = TRUE;
}
KeInsertQueueDpc(&FdoDeviceExtension->DpcObject, FdoDeviceExtension, (PVOID)CStatus);
return TRUE;
}
BOOLEAN
ResetPort(PFDO_DEVICE_EXTENSION FdoDeviceExtension, UCHAR Port)
{
ULONG Base;
ULONG tmp;
LARGE_INTEGER DueTime;
DPRINT("Reset Port %x\n", Port);
Base = (ULONG)FdoDeviceExtension->ResourceMemory;
tmp = READ_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * Port)));
tmp |= 0x100;
WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * Port)), tmp);
DueTime.QuadPart = -100;
KeSetTimerEx(&FdoDeviceExtension->UpdateTimer, DueTime, 0, &FdoDeviceExtension->TimerDpcObject);
return TRUE;
}
VOID
StopEhci(PDEVICE_OBJECT DeviceObject)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PEHCI_USBCMD_CONTENT UsbCmd;
ULONG base;
LONG tmp;
DPRINT("Stopping Ehci controller\n");
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
base = (ULONG)FdoDeviceExtension->ResourceMemory;
WRITE_REGISTER_ULONG((PULONG) (base + EHCI_USBINTR), 0);
tmp = READ_REGISTER_ULONG((PULONG) (base + EHCI_USBCMD));
UsbCmd = (PEHCI_USBCMD_CONTENT) & tmp;
UsbCmd->Run = 0;
WRITE_REGISTER_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
}
VOID
StartEhci(PDEVICE_OBJECT DeviceObject)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PEHCI_USBCMD_CONTENT UsbCmd;
PEHCI_USBSTS_CONTEXT usbsts;
NTSTATUS Status;
LONG tmp;
LONG tmp2;
ULONG base;
DPRINT("Starting Ehci controller\n");
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
base = (ULONG)FdoDeviceExtension->ResourceMemory;
tmp = READ_REGISTER_ULONG ((PULONG)(base + EHCI_USBCMD));
/* Stop the device */
UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
UsbCmd->Run = 0;
WRITE_REGISTER_ULONG ((PULONG)(base + EHCI_USBCMD), tmp);
/* Wait for the device to stop */
for (;;)
{
KeStallExecutionProcessor(10);
tmp = READ_REGISTER_ULONG((PULONG)(base + EHCI_USBSTS));
usbsts = (PEHCI_USBSTS_CONTEXT)&tmp;
if (usbsts->HCHalted)
{
break;
}
DPRINT("Waiting for Halt, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(base + EHCI_USBSTS)));
}
tmp = READ_REGISTER_ULONG ((PULONG)(base + EHCI_USBCMD));
/* Reset the device */
UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
UsbCmd->HCReset = TRUE;
WRITE_REGISTER_ULONG ((PULONG)(base + EHCI_USBCMD), tmp);
/* Wait for the device to reset */
for (;;)
{
KeStallExecutionProcessor(10);
tmp = READ_REGISTER_ULONG((PULONG)(base + EHCI_USBCMD));
UsbCmd = (PEHCI_USBCMD_CONTENT)&tmp;
if (!UsbCmd->HCReset)
{
break;
}
DPRINT("Waiting for reset, USBCMD: %x\n", READ_REGISTER_ULONG ((PULONG)(base + EHCI_USBCMD)));
}
UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
/* Disable Interrupts on the device */
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBINTR), 0);
/* Clear the Status */
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBSTS), 0x0000001f);
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_CTRLDSSEGMENT), 0);
/* Set the Periodic Frame List */
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_PERIODICLISTBASE), FdoDeviceExtension->PeriodicFramListPhysAddr.LowPart);
/* Set the Async List Queue */
WRITE_REGISTER_ULONG((PULONG) (base + EHCI_ASYNCLISTBASE), FdoDeviceExtension->AsyncListQueueHeadPtrPhysAddr.LowPart & ~(0x1f));
/* Set the ansync and periodic to disable */
UsbCmd->PeriodicEnable = 0;
UsbCmd->AsyncEnable = 0;
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBCMD), tmp);
/* Set the threshold */
UsbCmd->IntThreshold = 1;
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBCMD), tmp);
KeInitializeDpc(&FdoDeviceExtension->DpcObject,
EhciDefferedRoutine,
FdoDeviceExtension);
KeInitializeDpc(&FdoDeviceExtension->TimerDpcObject,
TimerDefferedRoutine,
FdoDeviceExtension);
Status = IoConnectInterrupt(&FdoDeviceExtension->EhciInterrupt,
InterruptService,
FdoDeviceExtension->DeviceObject,
NULL,
FdoDeviceExtension->Vector,
FdoDeviceExtension->Irql,
FdoDeviceExtension->Irql,
FdoDeviceExtension->Mode,
FdoDeviceExtension->IrqShared,
FdoDeviceExtension->Affinity,
FALSE);
/* Turn back on interrupts */
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBINTR),
EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
| EHCI_USBINTR_FLROVR | EHCI_USBINTR_PC);
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBINTR),
EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
| EHCI_USBINTR_FLROVR | EHCI_USBINTR_PC);
UsbCmd->Run = 1;
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_USBCMD), tmp);
/* Wait for the device to start */
for (;;)
{
KeStallExecutionProcessor(10);
tmp2 = READ_REGISTER_ULONG((PULONG)(base + EHCI_USBSTS));
usbsts = (PEHCI_USBSTS_CONTEXT)&tmp2;
if (!usbsts->HCHalted)
{
break;
}
DPRINT("Waiting for start, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(base + EHCI_USBSTS)));
}
/* Set all port routing to ECHI controller */
WRITE_REGISTER_ULONG((PULONG)(base + EHCI_CONFIGFLAG), 1);
}
VOID
GetCapabilities(PFDO_DEVICE_EXTENSION DeviceExtension, ULONG Base)
{
PEHCI_CAPS PCap;
PEHCI_HCS_CONTENT PHCS;
LONG i;
if (!DeviceExtension)
return;
PCap = &DeviceExtension->ECHICaps;
PCap->Length = READ_REGISTER_UCHAR((PUCHAR)Base);
PCap->Reserved = READ_REGISTER_UCHAR((PUCHAR)(Base + 1));
PCap->HCIVersion = READ_REGISTER_USHORT((PUSHORT)(Base + 2));
PCap->HCSParamsLong = READ_REGISTER_ULONG((PULONG)(Base + 4));
PCap->HCCParams = READ_REGISTER_ULONG((PULONG)(Base + 8));
DPRINT("Length %d\n", PCap->Length);
DPRINT("Reserved %d\n", PCap->Reserved);
DPRINT("HCIVersion %x\n", PCap->HCIVersion);
DPRINT("HCSParams %x\n", PCap->HCSParamsLong);
DPRINT("HCCParams %x\n", PCap->HCCParams);
if (PCap->HCCParams & 0x02)
DPRINT1("Frame list size is configurable\n");
if (PCap->HCCParams & 0x01)
DPRINT1("64bit address mode not supported!\n");
DPRINT1("Number of Ports: %d\n", PCap->HCSParams.PortCount);
if (PCap->HCSParams.PortPowerControl)
DPRINT1("Port Power Control is enabled\n");
if (!PCap->HCSParams.CHCCount)
{
DPRINT1("Number of Companion Host controllers %x\n", PCap->HCSParams.CHCCount);
DPRINT1("Number of Ports Per CHC: %d\n", PCap->HCSParams.PortPerCHC);
}
/* Copied from USBDRIVER in trunk */
PHCS = (PEHCI_HCS_CONTENT)&DeviceExtension->ECHICaps.HCSParams;
if (PHCS->PortRouteRules)
{
for (i = 0; i < PCap->HCSParams.PortCount; i++)
{
PCap->PortRoute[i] = READ_REGISTER_UCHAR((PUCHAR) (Base + 12 + i));
}
}
}
NTSTATUS
StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated)
{
@ -427,62 +282,6 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = TRUE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.DmaWidth = 2;
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
FdoDeviceExtension->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
&DeviceDescription,
&FdoDeviceExtension->MapRegisters);
if (FdoDeviceExtension->pDmaAdapter == NULL)
{
DPRINT1("IoGetDmaAdapter failed!\n");
ASSERT(FALSE);
}
/* Allocate Common Buffer for Periodic Frame List */
FdoDeviceExtension->PeriodicFramList =
FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
sizeof(ULONG) * 1024, &FdoDeviceExtension->PeriodicFramListPhysAddr, FALSE);
if (FdoDeviceExtension->PeriodicFramList == NULL)
{
DPRINT1("FdoDeviceExtension->PeriodicFramList is null\n");
return STATUS_UNSUCCESSFUL;
}
/* Zeroize it */
RtlZeroMemory(FdoDeviceExtension->PeriodicFramList, sizeof(ULONG) * 1024);
ExInitializeFastMutex(&FdoDeviceExtension->FrameListMutex);
/* Allocate Common Buffer for Async List Head Queue */
FdoDeviceExtension->AsyncListQueueHeadPtr =
FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
/* FIXME: Memory Size should be calculated using
structures sizes needed for queue head + 20480 (max data transfer */
20800,
&FdoDeviceExtension->AsyncListQueueHeadPtrPhysAddr, FALSE);
if (FdoDeviceExtension->AsyncListQueueHeadPtr == NULL)
{
DPRINT1("Failed to allocate common buffer for AsyncListQueueHeadPtr!\n");
return STATUS_UNSUCCESSFUL;
}
/* Zeroize it */
RtlZeroMemory(FdoDeviceExtension->AsyncListQueueHeadPtr,
/* FIXME: Same as FIXME above */
20800);
ExInitializeFastMutex(&FdoDeviceExtension->AsyncListMutex);
Status = IoGetDeviceProperty(FdoDeviceExtension->LowerDevice,
DevicePropertyAddress,
sizeof(ULONG),
@ -531,26 +330,21 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
}
case CmResourceTypeMemory:
{
ULONG ResourceBase = 0;
ULONG MemLength;
PVOID ResourceBase = 0;
DPRINT("Mem Start: %x\n", resource->u.Memory.Start);
DPRINT("Mem Length: %d\n", resource->u.Memory.Length);
ResourceBase = (ULONG) MmMapIoSpace(resource->u.Memory.Start, resource->u.Memory.Length, FALSE);
ResourceBase = MmMapIoSpace(resource->u.Memory.Start, resource->u.Memory.Length, FALSE);
DPRINT("ResourceBase %x\n", ResourceBase);
FdoDeviceExtension->ResourceBase = (PULONG) ResourceBase;
GetCapabilities(FdoDeviceExtension, (ULONG)ResourceBase);
FdoDeviceExtension->ResourceMemory = (PULONG)((ULONG)ResourceBase + FdoDeviceExtension->ECHICaps.Length);
DPRINT("ResourceMemory %x\n", FdoDeviceExtension->ResourceMemory);
if (FdoDeviceExtension->ResourceBase == NULL)
if (ResourceBase == NULL)
{
DPRINT1("MmMapIoSpace failed!!!!!!!!!\n");
}
MemLength = resource->u.Memory.Length;
FdoDeviceExtension->Size = MemLength;
GetCapabilities(&FdoDeviceExtension->hcd.ECHICaps, (ULONG)ResourceBase);
DPRINT1("hcd.ECHICaps.Length %x\n", FdoDeviceExtension->hcd.ECHICaps.Length);
FdoDeviceExtension->hcd.OpRegisters = (ULONG)((ULONG)ResourceBase + FdoDeviceExtension->hcd.ECHICaps.Length);
break;
}
case CmResourceTypeDma:
@ -573,7 +367,90 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
}
}
StartEhci(DeviceObject);
KeInitializeDpc(&FdoDeviceExtension->DpcObject,
EhciDefferedRoutine,
FdoDeviceExtension);
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = TRUE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.DmaWidth = 2;
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
FdoDeviceExtension->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
&DeviceDescription,
&FdoDeviceExtension->MapRegisters);
if (FdoDeviceExtension->pDmaAdapter == NULL)
{
DPRINT1("Ehci: IoGetDmaAdapter failed!\n");
ASSERT(FALSE);
}
/* Allocate Common Buffer for Periodic Frame List */
FdoDeviceExtension->PeriodicFrameList.VirtualAddr =
FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
sizeof(ULONG) * 1024, &FdoDeviceExtension->PeriodicFrameList.PhysicalAddr, FALSE);
if (FdoDeviceExtension->PeriodicFrameList.VirtualAddr == NULL)
{
DPRINT1("Ehci: FdoDeviceExtension->PeriodicFramList is null\n");
return STATUS_UNSUCCESSFUL;
}
/* Zeroize it */
RtlZeroMemory(FdoDeviceExtension->PeriodicFrameList.VirtualAddr, sizeof(ULONG) * 1024);
ExInitializeFastMutex(&FdoDeviceExtension->FrameListMutex);
/* Allocate pages for queueheads and descriptors */
FdoDeviceExtension->hcd.CommonBufferVA =
FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
PAGE_SIZE * 16,
&FdoDeviceExtension->hcd.CommonBufferPA,
FALSE);
if (FdoDeviceExtension->hcd.CommonBufferVA == 0)
{
DPRINT1("Ehci: Failed to allocate common buffer!\n");
return STATUS_UNSUCCESSFUL;
}
FdoDeviceExtension->hcd.CommonBufferSize = PAGE_SIZE * 16;
/* Zeroize it */
RtlZeroMemory(FdoDeviceExtension->hcd.CommonBufferVA,
PAGE_SIZE * 16);
/* Init SpinLock for host controller device lock */
KeInitializeSpinLock(&FdoDeviceExtension->hcd.Lock);
/* Reserved a Queue Head that will always be in the AsyncList Address Register */
FdoDeviceExtension->hcd.AsyncListQueue = CreateQueueHead(&FdoDeviceExtension->hcd);
FdoDeviceExtension->hcd.AsyncListQueue->HorizontalLinkPointer = FdoDeviceExtension->hcd.AsyncListQueue->PhysicalAddr | QH_TYPE_QH;
FdoDeviceExtension->hcd.AsyncListQueue->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
FdoDeviceExtension->hcd.AsyncListQueue->Token.Bits.InterruptOnComplete = FALSE;
/* Ensure the controller is stopped */
StopEhci(&FdoDeviceExtension->hcd);
Status = IoConnectInterrupt(&FdoDeviceExtension->EhciInterrupt,
InterruptService,
FdoDeviceExtension->DeviceObject,
NULL,
FdoDeviceExtension->Vector,
FdoDeviceExtension->Irql,
FdoDeviceExtension->Irql,
FdoDeviceExtension->Mode,
FdoDeviceExtension->IrqShared,
FdoDeviceExtension->Affinity,
FALSE);
StartEhci(&FdoDeviceExtension->hcd);
DPRINT1("AsycnAddr %x\n", GetAsyncListQueueRegister(&FdoDeviceExtension->hcd));
FdoDeviceExtension->DeviceState = DEVICESTARTED;
return STATUS_SUCCESS;
@ -628,7 +505,7 @@ FdoQueryBusRelations(
/* Bail on any other error */
if (!NT_SUCCESS(Status))
{
DPRINT1("UsbEhci: Failed to create PDO %wZ, Status %x\n", &DeviceName, Status);
DPRINT1("Ehci: Failed to create PDO %wZ, Status %x\n", &DeviceName, Status);
return Status;
}
}
@ -639,7 +516,7 @@ FdoQueryBusRelations(
PdoDeviceExtension->ControllerFdo = DeviceObject;
PdoDeviceExtension->DeviceObject = Pdo;
PdoDeviceExtension->NumberOfPorts = DeviceExtension->ECHICaps.HCSParams.PortCount;
PdoDeviceExtension->NumberOfPorts = DeviceExtension->hcd.ECHICaps.HCSParams.PortCount;
InitializeListHead(&PdoDeviceExtension->IrpQueue);
KeInitializeSpinLock(&PdoDeviceExtension->IrpQueueLock);
@ -683,6 +560,7 @@ FdoDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
case IRP_MN_START_DEVICE:
{
DPRINT1("Ehci: START_DEVICE\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Status = ForwardAndWait(DeviceObject, Irp);
@ -905,7 +783,7 @@ FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
PUSB_DEVICE UsbDevice = NULL;
URB *Urb;
/*FIXME: This should never be called by a miniport as the miniport should only be dealing with the pdo */
/*FIXME: This should never be called by upper drivers as they should only be dealing with the pdo */
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) FdoDeviceExtension->Pdo->DeviceExtension;
@ -924,7 +802,7 @@ FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
if (!UsbDevice)
{
DPRINT1("Invalid DeviceHandle or device not connected\n");
DPRINT1("Ehci: Invalid DeviceHandle or device not connected\n");
return STATUS_DEVICE_NOT_CONNECTED;
}
switch (Urb->UrbHeader.Function)
@ -946,7 +824,6 @@ FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
case USB_DEVICE_DESCRIPTOR_TYPE:
{
/* FIXME: This probably not used for FDO and should be removed? */
DPRINT1("USB DEVICE DESC\n");
break;
}
@ -954,55 +831,13 @@ FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
DPRINT1("USB CONFIG DESC\n");
//break;
case USB_STRING_DESCRIPTOR_TYPE:
DPRINT1("Usb String Descriptor\n");
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
PUSB_STRING_DESCRIPTOR UsbString;
BOOLEAN ResultOk;
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Reserved = 0;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
{
CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
RtlZeroMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength-1);
}
else
CtrlSetup.wIndex.W = 0;
CtrlSetup.wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, UsbDevice->Address, UsbDevice->Port,
Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength);
if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
{
UsbString = Urb->UrbControlDescriptorRequest.TransferBuffer;
DPRINT1("Index %x\n", Urb->UrbControlDescriptorRequest.Index);
DPRINT1("BufferLength %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
DPRINT1("Length %x\n", UsbString->bLength);
if (Urb->UrbControlDescriptorRequest.Index == 0)
{
DPRINT1("%x\n", (ULONG)Urb->UrbControlDescriptorRequest.TransferBuffer);
}
else
DPRINT1("String %S\n", &UsbString->bString);
}
UsbString = Urb->UrbControlDescriptorRequest.TransferBuffer;
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
Status = STATUS_SUCCESS;
Information = UsbString->bLength;
DPRINT1("Usb String Descriptor\n");
break;
}
default:
{
DPRINT1("Descriptor Type %x not supported!\n", Urb->UrbControlDescriptorRequest.DescriptorType);
DPRINT1("Ehci: Descriptor Type %x not supported!\n", Urb->UrbControlDescriptorRequest.DescriptorType);
}
}
break;

View file

@ -8,6 +8,19 @@
*/
#include "usbehci.h"
#include "hwiface.h"
#include "physmem.h"
#include "transfer.h"
VOID NTAPI
WorkerThread(IN PVOID Context)
{
PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context;
CompletePendingURBRequest((PPDO_DEVICE_EXTENSION)WorkItemData->Context);
ExFreePool(WorkItemData);
}
VOID
RemoveUrbRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
@ -23,7 +36,8 @@ RequestURBCancel (PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
KIRQL OldIrql = Irp->CancelIrql;
IoReleaseCancelSpinLock(DISPATCH_LEVEL);
DPRINT1("IRP CANCELLED\n");
ASSERT(FALSE);
KeAcquireSpinLockAtDpcLevel(&PdoDeviceExtension->IrpQueueLock);
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
@ -40,7 +54,7 @@ QueueURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &OldIrql);
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
if ((Irp->Cancel) && (IoSetCancelRoutine(Irp, RequestURBCancel)))
{
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
@ -67,7 +81,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
ASSERT(Stack);
Urb = (PURB) Stack->Parameters.Others.Argument1;
ASSERT(Urb);
Information = 0;
@ -92,9 +105,12 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER UsbDevice %x\n", UsbDevice);
if (&UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor != Urb->UrbBulkOrInterruptTransfer.PipeHandle)
{
DPRINT1("Invalid Parameter, Expected EndPointDescriptor of %x, but got %x\n", &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor, Urb->UrbBulkOrInterruptTransfer.PipeHandle);
Status = STATUS_INVALID_PARAMETER;
ASSERT(FALSE);
break;
}
@ -128,6 +144,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
{
DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
if (Urb->UrbControlGetStatusRequest.Index == 0)
{
ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer != NULL);
@ -143,25 +160,55 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
switch(Urb->UrbControlDescriptorRequest.DescriptorType)
{
case USB_DEVICE_DESCRIPTOR_TYPE:
{
PUCHAR BufPtr;
DPRINT1("Device Descr Type\n");
if (Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR))
{
Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
}
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
{
DPRINT1("ROOTHUB!\n");
BufPtr = (PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer;
DPRINT1("Length %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
/* Copy the Device Descriptor */
RtlCopyMemory(BufPtr, &UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
DumpDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
break;
}
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer != NULL);
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
&UsbDevice->DeviceDescriptor,
Urb->UrbControlDescriptorRequest.TransferBufferLength);
DPRINT("Calling BuildSetUpPacketFromUrb\n");
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
DPRINT("SubmitControlTransfer\n");
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
break;
}
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
{
PUCHAR BufPtr;
LONG i, j;
DPRINT1("Config Descr Type\n");
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
{
DPRINT1("ROOTHUB!\n");
}
if (Urb->UrbControlDescriptorRequest.TransferBufferLength >= UsbDevice->ActiveConfig->ConfigurationDescriptor.wTotalLength)
{
Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->ActiveConfig->ConfigurationDescriptor.wTotalLength;
@ -171,7 +218,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT1("TransferBufferLenth %x is too small!!!\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
DPRINT("Configuration Descriptor cannot fit into given buffer!\n");
DPRINT1("Configuration Descriptor cannot fit into given buffer!\n");
break;
}
}
@ -179,6 +226,8 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
BufPtr = (PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer;
DPRINT1("Length %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
/* Copy the Configuration Descriptor */
RtlCopyMemory(BufPtr, &UsbDevice->ActiveConfig->ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
@ -193,31 +242,30 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
for (i = 0; i < UsbDevice->ActiveConfig->ConfigurationDescriptor.bNumInterfaces; i++)
{
/* Copy the Interface Descriptor */
RtlCopyMemory(BufPtr, &UsbDevice->ActiveConfig->Interfaces[i]->InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
RtlCopyMemory(BufPtr,
&UsbDevice->ActiveConfig->Interfaces[i]->InterfaceDescriptor,
sizeof(USB_INTERFACE_DESCRIPTOR));
BufPtr += sizeof(USB_INTERFACE_DESCRIPTOR);
for (j = 0; j < UsbDevice->ActiveConfig->Interfaces[i]->InterfaceDescriptor.bNumEndpoints; j++)
{
/* Copy the EndPoint Descriptor */
RtlCopyMemory(BufPtr, &UsbDevice->ActiveConfig->Interfaces[i]->EndPoints[j]->EndPointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
RtlCopyMemory(BufPtr,
&UsbDevice->ActiveConfig->Interfaces[i]->EndPoints[j]->EndPointDescriptor,
sizeof(USB_ENDPOINT_DESCRIPTOR));
BufPtr += sizeof(USB_ENDPOINT_DESCRIPTOR);
}
}
DumpFullConfigurationDescriptor((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
break;
}
case USB_STRING_DESCRIPTOR_TYPE:
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
PUSB_STRING_DESCRIPTOR StringDesc;
BOOLEAN ResultOk;
StringDesc = (PUSB_STRING_DESCRIPTOR) Urb->UrbControlDescriptorRequest.TransferBuffer;
DPRINT1("StringDescriptorType\n");
DPRINT1("Urb->UrbControlDescriptorRequest.Index %x\n", Urb->UrbControlDescriptorRequest.Index);
DPRINT1("Urb->UrbControlDescriptorRequest.LanguageId %x\n", Urb->UrbControlDescriptorRequest.LanguageId);
if (Urb->UrbControlDescriptorRequest.Index == 0)
DPRINT("Requesting LANGID's\n");
RtlZeroMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength-1);
DPRINT1("Requesting LANGID's\n");
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
@ -229,8 +277,14 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
CtrlSetup.wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, UsbDevice->Address, UsbDevice->Port,
Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength);
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
break;
}
default:
@ -245,8 +299,8 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
LONG iCount, pCount;
DPRINT("Selecting Configuration\n");
DPRINT("Urb->UrbSelectConfiguration.ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
DPRINT1("Selecting Configuration\n");
DPRINT1("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
if (Urb->UrbSelectConfiguration.ConfigurationDescriptor)
{
@ -254,6 +308,9 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
DPRINT1("Length %x\n", InterfaceInfo->Length);
DPRINT1("NumberOfPipes %x\n", InterfaceInfo->NumberOfPipes);
for (iCount = 0; iCount < Urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; iCount++)
{
InterfaceInfo->InterfaceHandle = (PVOID)&UsbDevice->ActiveInterface->InterfaceDescriptor;
@ -274,6 +331,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
/* InterfaceInfo->Pipes[j].PipeFlags = 0; */
}
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
if (InterfaceInfo->Length == 0) break;
}
}
else
@ -284,6 +342,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case URB_FUNCTION_CLASS_DEVICE:
{
DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
switch (Urb->UrbControlVendorClassRequest.Request)
{
case USB_REQUEST_GET_DESCRIPTOR:
@ -353,7 +412,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT1("USB_DEVICE_CLASS_HUB request\n");
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
UsbHubDescr->bDescriptorType = 0x29;
UsbHubDescr->bNumberOfPorts = 0x08;
UsbHubDescr->bNumberOfPorts = PdoDeviceExtension->NumberOfPorts;
UsbHubDescr->wHubCharacteristics = 0x0012;
UsbHubDescr->bPowerOnToPowerGood = 0x01;
UsbHubDescr->bHubControlCurrent = 0x00;
@ -383,6 +442,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
DPRINT1("Unhandled URB request for class device\n");
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
ASSERT(FALSE);
}
}
break;
@ -390,13 +450,13 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
case URB_FUNCTION_CLASS_OTHER:
{
DPRINT("URB_FUNCTION_CLASS_OTHER\n");
/* FIXME: Each one of these needs to make sure that the index value is a valid for the number of ports and return STATUS_UNSUCCESSFUL is not */
/* FIXME: Each one of these needs to make sure that the index value is a valid for the number of ports and return STATUS_UNSUCCESSFUL if not */
switch (Urb->UrbControlVendorClassRequest.Request)
{
case USB_REQUEST_GET_STATUS:
{
DPRINT("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
DPRINT1("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer != 0);
DPRINT("PortStatus %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
@ -407,20 +467,23 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case USB_REQUEST_CLEAR_FEATURE:
{
DPRINT("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
Urb->UrbControlVendorClassRequest.Value);
switch (Urb->UrbControlVendorClassRequest.Value)
{
case C_PORT_CONNECTION:
DPRINT1("C_PORT_CONNECTION\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
break;
case C_PORT_RESET:
DPRINT1("C_PORT_RESET\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
break;
default:
DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
break;
}
CompletePendingURBRequest(PdoDeviceExtension);
break;
}
case USB_REQUEST_SET_FEATURE:
@ -432,32 +495,43 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case PORT_RESET:
{
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
ResetPort(FdoDeviceExtension, Urb->UrbControlVendorClassRequest.Index-1);
//PWORKITEMDATA WorkItemData;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
ResetPort(&FdoDeviceExtension->hcd, Urb->UrbControlVendorClassRequest.Index-1);
//WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEMDATA));
//WorkItemData->Context = PdoDeviceExtension;
//ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)WorkerThread, (PVOID) WorkItemData)
//ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
//IoMarkIrpPending(Irp);
//Status = STATUS_PENDING;
break;
}
case PORT_ENABLE:
{
DPRINT1("PORT_ENABLE not implemented\n");
DPRINT("PORT_ENABLE not implemented\n");
break;
}
case PORT_POWER:
{
DPRINT1("PORT_POWER not implemented\n");
DPRINT("PORT_POWER not implemented\n");
break;
}
default:
{
DPRINT1("Unknown Set Feature!\n");
DPRINT("Unknown Set Feature!\n");
break;
}
}
CompletePendingURBRequest(PdoDeviceExtension);
break;
}
case USB_REQUEST_SET_ADDRESS:
{
DPRINT1("USB_REQUEST_SET_ADDRESS\n");
ASSERT(FALSE);
break;
}
case USB_REQUEST_GET_DESCRIPTOR:
@ -508,7 +582,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
}
}
Irp->IoStatus.Status = Status;
@ -539,8 +612,11 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
if (!Irp)
{
DPRINT1("No IRP\n");
break;
}
IoSetCancelRoutine(Irp, NULL);
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
HandleUrbRequest(DeviceExtension, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);

View file

@ -55,7 +55,7 @@ const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
0x00 /* MaxPower; */
};
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
{
/* one interface */
0x09, /* bLength: Interface; */
@ -80,31 +80,6 @@ const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
};
/* FIXME: Do something better */
VOID NTAPI
UrbWorkerThread(PVOID Context)
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Context;
NTSTATUS Status;
LARGE_INTEGER DueTime;
PVOID PollEvents[] = { (PVOID) &PdoDeviceExtension->QueueDrainedEvent, (PVOID) &PdoDeviceExtension->Timer };
DueTime.QuadPart = 0;
KeInitializeTimerEx(&PdoDeviceExtension->Timer, SynchronizationTimer);
KeSetTimerEx(&PdoDeviceExtension->Timer, DueTime, 100, NULL);
while (TRUE)
{
Status = KeWaitForMultipleObjects(2, PollEvents, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
if (!PdoDeviceExtension->HaltQueue)
KeResetEvent(&PdoDeviceExtension->QueueDrainedEvent);
CompletePendingURBRequest(PdoDeviceExtension);
}
DPRINT1("Thread terminated\n");
}
NTSTATUS NTAPI
PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
@ -139,7 +114,8 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
(UsbDevice == PdoDeviceExtension->UsbDevices[0]))
{
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle == &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle != &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
{
DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
}
@ -172,6 +148,10 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Status = STATUS_PENDING;
break;
}
else
{
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB send to device %x\n", UsbDevice);
}
Status = HandleUrbRequest(PdoDeviceExtension, Irp);
@ -419,10 +399,10 @@ PdoDispatchPnp(
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
{
PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_HIGH_SPEED | 0x8000;
PdoDeviceExtension->Ports[i].PortStatus = 0x8000;
PdoDeviceExtension->Ports[i].PortChange = 0;
if (!FdoDeviceExtension->ECHICaps.HCSParams.PortPowerControl)
if (!FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortPowerControl)
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_POWER;
}
@ -470,19 +450,6 @@ PdoDispatchPnp(
PdoDeviceExtension->UsbDevices[0] = RootHubDevice;
/* Create a thread to handle the URB's */
/*
Status = PsCreateSystemThread(&PdoDeviceExtension->ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
UrbWorkerThread,
(PVOID)PdoDeviceExtension);
if (!NT_SUCCESS(Status))
DPRINT1("Failed Thread Creation with Status: %x\n", Status);
*/
Status = IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_HUB, NULL, &InterfaceSymLinkName);
if (!NT_SUCCESS(Status))
{

View file

@ -1,216 +0,0 @@
/*
* 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 (michael.martin@reactos.org)
*/
#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,
PUSB_DEFAULT_PIPE_SETUP_PACKET *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 = (PUSB_DEFAULT_PIPE_SETUP_PACKET) (( (ULONG)(*CtrlTD3) + sizeof(QUEUE_TRANSFER_DESCRIPTOR) + 0xFFF) & ~0xFFF);
*CtrlData = (PVOID) (( (ULONG)(*CtrlSetup) + sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) + 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(USB_DEFAULT_PIPE_SETUP_PACKET);
(*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;
if (Size == 0)
(*CtrlTD2)->BufferPointer[0] = 0;
else
(*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.TotalBytesToTransfer = 0;
(*CtrlTD3)->Token.Bits.DataToggle = TRUE;
(*CtrlTD3)->Token.Bits.ErrorCounter = 0x03;
(*CtrlTD2)->NextPointer = (ULONG) MmGetPhysicalAddress((PVOID)(*CtrlTD3)).LowPart;
return NULL;
}
BOOLEAN
ExecuteControlRequest(PFDO_DEVICE_EXTENSION DeviceExtension, PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, UCHAR Address, ULONG Port, PVOID Buffer, ULONG BufferLength)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup = NULL;
PVOID 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;
DPRINT1("ExecuteControlRequest: Buffer %x, Length %x\n", Buffer, BufferLength);
ExAcquireFastMutex(&DeviceExtension->AsyncListMutex);
Base = (ULONG) DeviceExtension->ResourceMemory;
/* Set up the QUEUE HEAD in memory */
QueueHead = (PQUEUE_HEAD) ((ULONG)DeviceExtension->AsyncListQueueHeadPtr);
/* Initialize the memory pointers */
IntializeHeadQueueForStandardRequest(QueueHead,
&CtrlTD1,
&CtrlTD2,
&CtrlTD3,
&CtrlSetup,
(PVOID)&CtrlData,
BufferLength);
QueueHead->EndPointCapabilities2.PortNumber = Port;
QueueHead->EndPointCapabilities1.DeviceAddress = Address;
CtrlSetup->bmRequestType._BM.Recipient = SetupPacket->bmRequestType._BM.Recipient;
CtrlSetup->bmRequestType._BM.Type = SetupPacket->bmRequestType._BM.Type;
CtrlSetup->bmRequestType._BM.Dir = SetupPacket->bmRequestType._BM.Dir;
CtrlSetup->bRequest = SetupPacket->bRequest;
CtrlSetup->wValue.LowByte = SetupPacket->wValue.LowByte;
CtrlSetup->wValue.HiByte = SetupPacket->wValue.HiByte;
CtrlSetup->wIndex.W = SetupPacket->wIndex.W;
CtrlSetup->wLength = SetupPacket->wLength;
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(100);
DPRINT("Waiting for completion!\n");
if (DeviceExtension->AsyncComplete == TRUE)
break;
}
UsbCmd->Run = FALSE;
WRITE_REGISTER_ULONG((PULONG)(Base + EHCI_USBCMD), tmp);
if (SetupPacket->bmRequestType._BM.Dir == BMREQUEST_DEVICE_TO_HOST)
{
if ((Buffer) && (BufferLength))
{
RtlCopyMemory(Buffer, CtrlData, BufferLength);
}
else
DPRINT1("Unable to copy data to buffer\n");
}
ExReleaseFastMutex(&DeviceExtension->AsyncListMutex);
return TRUE;
}

View file

@ -88,7 +88,6 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
DPRINT1("Driver Entry %wZ!\n", RegistryPath);
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbEhciCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbEhciClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = UsbEhciCleanup;

View file

@ -4,12 +4,15 @@
<library>ntoskrnl</library>
<library>hal</library>
<file>usbehci.c</file>
<file>hardware.c</file>
<file>physmem.c</file>
<file>hwiface.c</file>
<file>transfer.c</file>
<file>fdo.c</file>
<file>pdo.c</file>
<file>common.c</file>
<file>misc.c</file>
<file>irp.c</file>
<file>usbiffn.c</file>
<file>urbreq.c</file>
<file>usbehci.rc</file>
</module>

View file

@ -10,6 +10,7 @@
#include "usbehci.h"
#include <hubbusif.h>
#include <usbbusif.h>
#include "transfer.h"
PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub)
{
@ -30,8 +31,8 @@ PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent
DPRINT1("This is the root hub\n");
}
UsbDevicePointer->Address = 0;// DeviceNumber;
UsbDevicePointer->Port = Port;
UsbDevicePointer->Address = 0;//DeviceNumber;
UsbDevicePointer->Port = Port - 1;
UsbDevicePointer->ParentDevice = Parent;
UsbDevicePointer->IsHub = Hub;
@ -55,6 +56,7 @@ InterfaceDereference(PVOID BusContext)
/* Bus Interface Hub V5 Functions */
NTSTATUS
USB_BUSIFFN
CreateUsbDevice(PVOID BusContext,
@ -65,6 +67,7 @@ CreateUsbDevice(PVOID BusContext,
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PUSB_DEVICE UsbDevice;
LONG i = 0;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber);
@ -97,8 +100,6 @@ CreateUsbDevice(PVOID BusContext,
return STATUS_SUCCESS;
}
/* Called when SCE reports a change */
/* FIXME: Do something better for memory */
NTSTATUS
USB_BUSIFFN
InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
@ -110,12 +111,10 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
PUSB_ENDPOINT_DESCRIPTOR EndpointDesc;
PUSB_DEVICE UsbDevice;
BOOLEAN ResultOk;
PVOID Buffer;
PUCHAR Ptr;
LONG i, j, k;
DPRINT1("Ehci: InitializeUsbDevice called, device %x\n", DeviceHandle);
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
@ -127,59 +126,32 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
return STATUS_DEVICE_NOT_CONNECTED;
}
Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, USB_POOL_TAG);
if (!Buffer)
{
DPRINT1("Out of memory\n");
return STATUS_NO_MEMORY;
}
Ptr = Buffer;
/* Set the device address */
/*
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Reserved = 0;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_HOST_TO_DEVICE;
CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
CtrlSetup.wValue.W = UsbDevice->Address;
CtrlSetup.wIndex.W = 0;
CtrlSetup.wLength = 0;
DPRINT1("Setting Address to %x\n", UsbDevice->Address);
ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, 0, UsbDevice->Port, NULL, 0);
*/
/* Get the Device Descriptor */
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
CtrlSetup.wValue.LowByte = 0;
CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
CtrlSetup.wIndex.W = 0;
CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
DPRINT1("Requesting Descriptor\n");
ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, UsbDevice->Address, UsbDevice->Port,
&UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
DPRINT1("bLength %x\n", UsbDevice->DeviceDescriptor.bLength);
DPRINT1("bDescriptorType %x\n", UsbDevice->DeviceDescriptor.bDescriptorType);
DPRINT1("idVendor %x\n", UsbDevice->DeviceDescriptor.idVendor);
DPRINT1("idProduct %x\n", UsbDevice->DeviceDescriptor.idProduct);
DPRINT1("bNumDescriptors %x\n", UsbDevice->DeviceDescriptor.bNumConfigurations);
if (UsbDevice->DeviceDescriptor.bNumConfigurations == 0)
CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
CtrlSetup.bmRequestType.B = 0x80;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
&UsbDevice->DeviceDescriptor,
sizeof(USB_DEVICE_DESCRIPTOR),
NULL);
//DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor);
if (UsbDevice->DeviceDescriptor.bLength != 0x12)
{
DPRINT1("No Configurations. That cant be good!\n");
DPRINT1("Failed to get Device Descriptor from device connected on port %d\n", UsbDevice->Port);
return STATUS_DEVICE_DATA_ERROR;
}
if (UsbDevice->DeviceDescriptor.bNumConfigurations == 0)
{
DPRINT1("Device on port %d has no configurations!\n", UsbDevice->Port);
return STATUS_DEVICE_DATA_ERROR;
}
UsbDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PVOID) * UsbDevice->DeviceDescriptor.bNumConfigurations,
USB_POOL_TAG);
@ -190,22 +162,38 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
return STATUS_NO_MEMORY;
}
Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, USB_POOL_TAG);
if (!Buffer)
{
DPRINT1("Out of memory\n");
return STATUS_NO_MEMORY;
}
Ptr = Buffer;
for (i = 0; i < UsbDevice->DeviceDescriptor.bNumConfigurations; i++)
{
/* Get the Device Configuration Descriptor */
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Reserved = 0;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
CtrlSetup.wValue.LowByte = 0;
CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
CtrlSetup.wIndex.W = 0;
CtrlSetup.wLength = PAGE_SIZE;
ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, UsbDevice->Address, UsbDevice->Port, Buffer, PAGE_SIZE);
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Buffer,
PAGE_SIZE,
NULL);
ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)Ptr;
//DumpFullConfigurationDescriptor(ConfigDesc);
ASSERT(ConfigDesc->wTotalLength <= PAGE_SIZE);
UsbDevice->Configs[i] = ExAllocatePoolWithTag(NonPagedPool,
@ -244,6 +232,26 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
UsbDevice->ActiveInterface = UsbDevice->Configs[0]->Interfaces[0];
return STATUS_SUCCESS;
/* Set the device address */
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Reserved = 0;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_HOST_TO_DEVICE;
CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
CtrlSetup.wValue.W = UsbDevice->Address;
CtrlSetup.wIndex.W = 0;
CtrlSetup.wLength = 0;
DPRINT1("Setting Address to %x\n", UsbDevice->Address);
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
NULL,
0,
NULL);
return STATUS_SUCCESS;
}
NTSTATUS
@ -256,7 +264,8 @@ GetUsbDescriptors(PVOID BusContext,
PULONG ConfigDescriptorBufferLength)
{
PUSB_DEVICE UsbDevice;
DPRINT1("Ehci: GetUsbDescriptor %x, %x, %x, %x\n", DeviceDescriptorBuffer, *DeviceDescriptorBufferLength, ConfigDescriptorBuffer, *ConfigDescriptorBufferLength);
DPRINT1("Ehci: GetUsbDescriptor %x, %x, %x, %x\n", DeviceDescriptorBuffer, *DeviceDescriptorBufferLength,
ConfigDescriptorBuffer, *ConfigDescriptorBufferLength);
UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
@ -345,7 +354,7 @@ NTSTATUS
USB_BUSIFFN
RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVICE_HANDLE NewDeviceHandle)
{
DPRINT1("Ehci: RestoreUsbDevice called\n");
DPRINT1("Ehci: RestoreUsbDevice not implemented! %x, %x, %x\n", BusContext, OldDeviceHandle, NewDeviceHandle);
return STATUS_NOT_SUPPORTED;
}
@ -353,7 +362,7 @@ NTSTATUS
USB_BUSIFFN
GetPortHackFlags(PVOID BusContext, PULONG Flags)
{
DPRINT1("Ehci: GetPortHackFlags called\n");
DPRINT1("Ehci: GetPortHackFlags not implemented. %x, %x\n", BusContext, Flags);
return STATUS_NOT_SUPPORTED;
}
@ -370,7 +379,8 @@ QueryDeviceInformation(PVOID BusContext,
ULONG SizeNeeded;
LONG i;
DPRINT1("Ehci: QueryDeviceInformation (%x, %x, %x, %d, %x\n", BusContext, DeviceHandle, DeviceInformationBuffer, DeviceInformationBufferLength, LengthReturned);
DPRINT1("Ehci: QueryDeviceInformation (%x, %x, %x, %d, %x\n", BusContext, DeviceHandle, DeviceInformationBuffer,
DeviceInformationBufferLength, LengthReturned);
UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
@ -409,7 +419,9 @@ QueryDeviceInformation(PVOID BusContext,
for (i = 0; i < UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints; i++)
{
RtlCopyMemory(&DeviceInfo->PipeList[i].EndpointDescriptor, &UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
RtlCopyMemory(&DeviceInfo->PipeList[i].EndpointDescriptor,
&UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor,
sizeof(USB_ENDPOINT_DESCRIPTOR));
}
return STATUS_SUCCESS;
}
@ -452,7 +464,7 @@ NTSTATUS
USB_BUSIFFN
ControllerSelectiveSuspend(PVOID BusContext, BOOLEAN Enable)
{
DPRINT1("Ehci: ControllerSelectiveSuspend called\n");
DPRINT1("Ehci: ControllerSelectiveSuspend not implemented\n");
return STATUS_NOT_SUPPORTED;
}
@ -469,11 +481,13 @@ GetExtendedHubInformation(PVOID BusContext,
PPDO_DEVICE_EXTENSION PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExntension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
LONG i;
DPRINT1("Ehci: GetExtendedHubInformation BusContext %x, PDO %x\n", BusContext, HubPhysicalDeviceObject);
DPRINT1("Ehci: GetExtendedHubInformation BusContext %x, PDO %x, InformationBuffer %x\n",
BusContext, HubPhysicalDeviceObject, HubInformationBuffer);
/* Set the default return value */
*LengthReturned = 0;
DPRINT1("InformationLevel %x\n", UsbExtHubInfo->InformationLevel);
DPRINT("InformationLevel %x\n", UsbExtHubInfo->InformationLevel);
/* Caller is suppose to have set InformationLevel to 0. However usbehci from MS seems to ignore this */
if (UsbExtHubInfo->InformationLevel != 0)
@ -486,7 +500,7 @@ GetExtendedHubInformation(PVOID BusContext,
for (i=0; i < UsbExtHubInfo->NumberOfPorts; i++)
{
UsbExtHubInfo->Port[i].PhysicalPortNumber = i + 1;
UsbExtHubInfo->Port[i].PortLabelNumber = FdoDeviceExntension->ECHICaps.HCSParams.PortCount;
UsbExtHubInfo->Port[i].PortLabelNumber = FdoDeviceExntension->hcd.ECHICaps.HCSParams.PortCount;
UsbExtHubInfo->Port[i].VidOverride = 0;
UsbExtHubInfo->Port[i].PidOverride = 0;
UsbExtHubInfo->Port[i].PortAttributes = USB_PORTATTR_SHARED_USB2;
@ -536,7 +550,7 @@ NTSTATUS
USB_BUSIFFN
Initialize20Hub(PVOID BusContext, PUSB_DEVICE_HANDLE HubDeviceHandle, ULONG TtCount)
{
DPRINT1("Ehci: Initialize20Hub called, HubDeviceHandle: %x\n", HubDeviceHandle);
DPRINT1("Ehci: Initialize20Hub called, HubDeviceHandle: %x, TtCount %x\n", HubDeviceHandle, TtCount);
/* FIXME: */
/* Create the Irp Queue for SCE */
/* Should queue be created for each device or each enpoint??? */
@ -586,7 +600,7 @@ VOID
USB_BUSIFFN
SetDeviceHandleData(PVOID BusContext, PVOID DeviceHandle, PDEVICE_OBJECT UsbDevicePdo)
{
DPRINT1("Ehci: SetDeviceHandleData called\n");
DPRINT1("Ehci: SetDeviceHandleData not implemented %x, %x, %x\n", BusContext, DeviceHandle, UsbDevicePdo);
}