reactos/drivers/usb/usbehci/transfer.c
Johannes Anderwald 2e8b524c99 [USBEHCI]
- Re-implement DMA buffer routines. It is now faster and consumes less memory overhead per allocated memory block.
- IoGetDeviceProperty needs a PDO
- Add few comments
- No need to clear buffer twice in CreateQueueHead / CreateDescriptor




svn path=/branches/cmake-bringup/; revision=51324
2011-04-13 01:37:14 +00:00

250 lines
8.6 KiB
C

/*
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbehci/transfer.c
* PURPOSE: Transfers to EHCI.
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
*/
#include "transfer.h"
#include <debug.h>
VOID
BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
{
switch (Urb->UrbHeader.Function)
{
/* CLEAR FEATURE */
case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
DPRINT1("Not implemented!\n");
break;
/* GET CONFIG */
case URB_FUNCTION_GET_CONFIGURATION:
CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
CtrlSetup->bmRequestType.B = 0x80;
CtrlSetup->wLength = 1;
break;
/* GET DESCRIPTOR */
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
CtrlSetup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
CtrlSetup->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
CtrlSetup->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
CtrlSetup->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
CtrlSetup->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
CtrlSetup->bmRequestType.B = 0x80;
break;
/* GET INTERFACE */
case URB_FUNCTION_GET_INTERFACE:
CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x80;
CtrlSetup->wLength = 1;
break;
/* GET STATUS */
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x80;
CtrlSetup->wLength = 2;
break;
case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x81;
CtrlSetup->wLength = 2;
break;
case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x82;
CtrlSetup->wLength = 2;
break;
/* SET ADDRESS */
/* SET CONFIG */
case URB_FUNCTION_SELECT_CONFIGURATION:
CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
CtrlSetup->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
CtrlSetup->wIndex.W = 0;
CtrlSetup->wLength = 0;
CtrlSetup->bmRequestType.B = 0x00;
break;
/* SET DESCRIPTOR */
case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
DPRINT1("Not implemented\n");
break;
/* SET FEATURE */
case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x80;
break;
case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x81;
break;
case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup->bmRequestType.B = 0x82;
break;
/* SET INTERFACE*/
case URB_FUNCTION_SELECT_INTERFACE:
CtrlSetup->bRequest = USB_REQUEST_SET_INTERFACE;
CtrlSetup->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting;
CtrlSetup->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber;
CtrlSetup->wLength = 0;
CtrlSetup->bmRequestType.B = 0x01;
break;
/* SYNC FRAME */
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
DPRINT1("Not implemented\n");
break;
default:
DPRINT1("Unknown USB Request!\n");
break;
}
}
BOOLEAN
SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
PVOID TransferBuffer,
ULONG TransferBufferLength,
PIRP IrpToComplete)
{
PQUEUE_HEAD QueueHead;
PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
ULONG MdlPhysicalAddr;
PKEVENT Event = NULL;
PMDL pMdl = NULL;
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA;
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
/* allocate memory */
Status = DmaMemAllocator_Allocate(hcd->DmaMemAllocator, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&CtrlSetupVA, &PhysicalAddress);
ASSERT(Status == STATUS_SUCCESS);
RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
/* If no Irp then wait on completion */
if (IrpToComplete == NULL)
{
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
KeInitializeEvent(Event, NotificationEvent, FALSE);
}
if (TransferBuffer)
{
/* Allocate Mdl for Buffer */
pMdl = IoAllocateMdl(TransferBuffer,
TransferBufferLength,
FALSE,
FALSE,
NULL);
/* Lock Physical Pages */
MmBuildMdlForNonPagedPool(pMdl);
//MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
MdlPhysicalAddr = MmGetPhysicalAddress((PVOID)TransferBuffer).LowPart;
}
QueueHead = CreateQueueHead(hcd);
Descriptor[0] = CreateDescriptor(hcd,
PID_CODE_SETUP_TOKEN,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
Descriptor[0]->Token.Bits.InterruptOnComplete = FALSE;
Descriptor[0]->Token.Bits.DataToggle = FALSE;
/* Save the first descriptor */
QueueHead->TransferDescriptor = Descriptor[0];
if (TransferBuffer)
{
Descriptor[1] = CreateDescriptor(hcd,
PID_CODE_IN_TOKEN,
TransferBufferLength);
}
Descriptor[2] = CreateDescriptor(hcd,
PID_CODE_OUT_TOKEN,
0);
Descriptor[1]->Token.Bits.InterruptOnComplete = FALSE;
/* Link the descriptors */
if (TransferBuffer)
{
Descriptor[0]->NextDescriptor = Descriptor[1];
Descriptor[1]->NextDescriptor = Descriptor[2];
Descriptor[1]->PreviousDescriptor = Descriptor[0];
Descriptor[2]->PreviousDescriptor = Descriptor[1];
}
else
{
Descriptor[0]->NextDescriptor = Descriptor[2];
Descriptor[2]->PreviousDescriptor = Descriptor[0];
}
/* Assign the descritors buffers */
Descriptor[0]->BufferPointer[0] = PhysicalAddress.LowPart;
if (TransferBuffer)
{
Descriptor[1]->BufferPointer[0] = MdlPhysicalAddr;
Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
}
else
{
Descriptor[0]->NextPointer = Descriptor[2]->PhysicalAddr;
}
QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
QueueHead->IrpToComplete = IrpToComplete;
QueueHead->MdlToFree = pMdl;
QueueHead->Event = Event;
/* Link in the QueueHead */
LinkQueueHead(hcd, QueueHead);
if (IrpToComplete == NULL)
{
DPRINT1("Waiting For Completion %x!\n", Event);
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
ExFreePool(Event);
}
return TRUE;
}