[USBPORT]

- Begin implementing split transfers. Patch by Vadim Galyant.

svn path=/trunk/; revision=75783
This commit is contained in:
Thomas Faber
2017-09-08 07:17:34 +00:00
parent cb8ab26d8b
commit ba2be71aa9
7 changed files with 549 additions and 67 deletions
@@ -12,6 +12,7 @@ list(APPEND SOURCE
power.c
queue.c
roothub.c
trfsplit.c
urb.c
usb2.c
usbport.c
+1 -2
View File
@@ -1279,8 +1279,7 @@ USBPORT_DmaEndpointPaused(IN PDEVICE_OBJECT FdoDevice,
if (Transfer->Flags & TRANSFER_FLAG_SPLITED)
{
DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_CancelSplitTransfer\n");
ASSERT(FALSE); //USBPORT_CancelSplitTransfer();
USBPORT_CancelSplitTransfer(Transfer);
}
else
{
+42 -18
View File
@@ -529,6 +529,8 @@ USBPORT_CancelActiveTransferIrp(IN PDEVICE_OBJECT DeviceObject,
PUSBPORT_TRANSFER Transfer;
PUSBPORT_ENDPOINT Endpoint;
PIRP irp;
PUSBPORT_TRANSFER SplitTransfer;
PLIST_ENTRY Entry;
KIRQL OldIrql;
DPRINT_CORE("USBPORT_CancelActiveTransferIrp: Irp - %p\n", Irp);
@@ -543,30 +545,52 @@ USBPORT_CancelActiveTransferIrp(IN PDEVICE_OBJECT DeviceObject,
irp = USBPORT_FindActiveTransferIrp(FdoDevice, Irp);
if (irp)
if (!irp)
{
Urb = URB_FROM_IRP(irp);
Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
Endpoint = Transfer->Endpoint;
DPRINT_CORE("USBPORT_CancelActiveTransferIrp: irp - %p, Urb - %p, Transfer - %p\n",
irp,
Urb,
Transfer);
KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
Transfer->Flags |= TRANSFER_FLAG_CANCELED;
KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
USBPORT_InvalidateEndpointHandler(FdoDevice,
Endpoint,
INVALIDATE_ENDPOINT_WORKER_THREAD);
return;
}
Urb = URB_FROM_IRP(irp);
Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
Endpoint = Transfer->Endpoint;
DPRINT_CORE("USBPORT_CancelActiveTransferIrp: irp - %p, Urb - %p, Transfer - %p\n",
irp,
Urb,
Transfer);
KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
Transfer->Flags |= TRANSFER_FLAG_CANCELED;
if (Transfer->Flags & TRANSFER_FLAG_PARENT)
{
KeAcquireSpinLockAtDpcLevel(&Transfer->TransferSpinLock);
Entry = Transfer->SplitTransfersList.Flink;
while (Entry && Entry != &Transfer->SplitTransfersList)
{
SplitTransfer = CONTAINING_RECORD(Entry,
USBPORT_TRANSFER,
SplitLink);
SplitTransfer->Flags |= TRANSFER_FLAG_CANCELED;
Entry = Entry->Flink;
}
KeReleaseSpinLockFromDpcLevel(&Transfer->TransferSpinLock);
}
KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
USBPORT_InvalidateEndpointHandler(FdoDevice,
Endpoint,
INVALIDATE_ENDPOINT_WORKER_THREAD);
return;
}
VOID
+329
View File
@@ -0,0 +1,329 @@
#include "usbport.h"
#define NDEBUG
#include <debug.h>
ULONG
NTAPI
USBPORT_MakeSplitTransfer(IN PDEVICE_OBJECT FdoDevice,
IN PUSBPORT_TRANSFER Transfer,
IN PUSBPORT_TRANSFER SplitTransfer,
IN ULONG MaxTransferSize,
IN PULONG SgIdx,
IN PULONG SgOffset,
IN ULONG TransferRemainLen,
IN ULONG TransferOffset)
{
PUSBPORT_SCATTER_GATHER_LIST SplitSgList;
PUSBPORT_SCATTER_GATHER_ELEMENT Element0;
PUSBPORT_SCATTER_GATHER_ELEMENT Element1;
SIZE_T SgLength;
SIZE_T SgRemainLen;
DPRINT("USBPORT_MakeSplitTransfer: ... \n");
SplitSgList = &SplitTransfer->SgList;
Element0 = &SplitSgList->SgElement[0];
SgLength = Transfer->SgList.SgElement[*SgIdx].SgTransferLength - *SgOffset;
if (SgLength > MaxTransferSize)
{
/* SgLength > MaxTransferSize */
SplitTransfer->SgList.SgElementCount = 1;
Element0->SgOffset = 0;
Element0->SgTransferLength = MaxTransferSize;
Element0->SgPhysicalAddress.LowPart = Transfer->SgList.SgElement[*SgIdx].SgPhysicalAddress.LowPart + *SgOffset;
SplitTransfer->TransferParameters.IsTransferSplited = TRUE;
SplitTransfer->TransferParameters.TransferBufferLength = MaxTransferSize;
SplitTransfer->SgList.CurrentVa = Transfer->SgList.CurrentVa + TransferOffset;
SplitTransfer->SgList.MappedSystemVa = (PVOID)((ULONG_PTR)Transfer->SgList.MappedSystemVa + TransferOffset);
SplitTransfer->Flags |= TRANSFER_FLAG_SPLITED;
*SgOffset += MaxTransferSize;
TransferRemainLen -= MaxTransferSize;
return TransferRemainLen;
}
/* SgLength <= MaxTransferSize */
SplitTransfer->SgList.SgElementCount = 1;
TransferRemainLen -= SgLength;
Element0->SgOffset = 0;
Element0->SgTransferLength = SgLength;
Element0->SgPhysicalAddress.LowPart = Transfer->SgList.SgElement[*SgIdx].SgPhysicalAddress.LowPart + *SgOffset;
SplitTransfer->TransferParameters.TransferBufferLength = SgLength;
SplitTransfer->TransferParameters.IsTransferSplited = TRUE;
SplitTransfer->SgList.CurrentVa = Transfer->SgList.CurrentVa + TransferOffset;
SplitTransfer->SgList.MappedSystemVa = (PVOID)((ULONG_PTR)Transfer->SgList.MappedSystemVa + TransferOffset);
SplitTransfer->Flags |= TRANSFER_FLAG_SPLITED;
*SgOffset += SgLength;
SgRemainLen = MaxTransferSize - SgLength;
if (SgRemainLen > TransferRemainLen)
{
SgRemainLen = TransferRemainLen;
}
if (!SgRemainLen)
{
/* SgLength == MaxTransferSize */
++*SgIdx;
*SgOffset = 0;
return TransferRemainLen;
}
/* SgLength < MaxTransferSize */
DPRINT1("MakeSplitTransfer: SgRemainLen - %x\n", SgRemainLen);
DPRINT1("MakeSplitTransfer: SgIdx - %x\n", *SgIdx);
++*SgIdx;
*SgOffset = 0;
SplitTransfer->SgList.SgElementCount++;
Element1 = &SplitSgList->SgElement[1];
Element1->SgOffset = SgRemainLen;
Element1->SgTransferLength = Element0->SgTransferLength;
Element1->SgPhysicalAddress.LowPart = Transfer->SgList.SgElement[*SgIdx].SgPhysicalAddress.LowPart + *SgOffset;
SplitTransfer->TransferParameters.TransferBufferLength += SgRemainLen;
*SgOffset += SgRemainLen;
TransferRemainLen -= SgRemainLen;
return TransferRemainLen;
}
VOID
NTAPI
USBPORT_SplitBulkInterruptTransfer(IN PDEVICE_OBJECT FdoDevice,
IN PUSBPORT_ENDPOINT Endpoint,
IN PUSBPORT_TRANSFER Transfer,
IN PLIST_ENTRY List)
{
PUSBPORT_TRANSFER SplitTransfer;
LIST_ENTRY tmplist;
ULONG NeedSplits;
SIZE_T TransferBufferLength;
SIZE_T MaxTransferSize;
SIZE_T TransferOffset = 0;
SIZE_T RemainLength;
ULONG ix;
ULONG SgIdx = 0;
ULONG SgOffset = 0;
DPRINT("USBPORT_SplitBulkInterruptTransfer: ... \n");
MaxTransferSize = Endpoint->EndpointProperties.TotalMaxPacketSize *
(Endpoint->EndpointProperties.MaxTransferSize /
Endpoint->EndpointProperties.TotalMaxPacketSize);
if (Endpoint->EndpointProperties.MaxTransferSize > PAGE_SIZE)
{
KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
}
TransferBufferLength = Transfer->TransferParameters.TransferBufferLength;
Transfer->Flags |= TRANSFER_FLAG_PARENT;
NeedSplits = TransferBufferLength / MaxTransferSize + 1;
InitializeListHead(&tmplist);
DPRINT1("USBPORT_SplitBulkInterruptTransfer: TransferBufferLength - %x, NeedSplits - %x\n",
TransferBufferLength, NeedSplits);
if (!NeedSplits)
{
DPRINT1("USBPORT_SplitBulkInterruptTransfer: DbgBreakPoint \n");
DbgBreakPoint();
goto Exit;
}
for (ix = 0; ix < NeedSplits; ++ix)
{
SplitTransfer = ExAllocatePoolWithTag(NonPagedPool,
Transfer->FullTransferLength,
USB_PORT_TAG);
if (!SplitTransfer)
{
DPRINT1("USBPORT_SplitBulkInterruptTransfer: DbgBreakPoint \n");
DbgBreakPoint();
goto Exit;
}
RtlCopyMemory(SplitTransfer, Transfer, Transfer->FullTransferLength);
SplitTransfer->MiniportTransfer = (PVOID)((ULONG_PTR)SplitTransfer +
SplitTransfer->PortTransferLength);
InsertTailList(&tmplist, &SplitTransfer->TransferLink);
}
if (Transfer->TransferParameters.TransferBufferLength == 0)
{
goto Exit;
}
RemainLength = Transfer->TransferParameters.TransferBufferLength;
do
{
SplitTransfer = CONTAINING_RECORD(tmplist.Flink,
USBPORT_TRANSFER,
TransferLink);
RemoveHeadList(&tmplist);
RemainLength = USBPORT_MakeSplitTransfer(FdoDevice,
Transfer,
SplitTransfer,
MaxTransferSize,
&SgIdx,
&SgOffset,
RemainLength,
TransferOffset);
TransferOffset += SplitTransfer->TransferParameters.TransferBufferLength;
InsertTailList(List, &SplitTransfer->TransferLink);
InsertTailList(&Transfer->SplitTransfersList,&SplitTransfer->SplitLink);
}
while (RemainLength != 0);
Exit:
while (!IsListEmpty(&tmplist))
{
DPRINT1("USBPORT_SplitBulkInterruptTransfer: ... \n");
SplitTransfer = CONTAINING_RECORD(tmplist.Flink,
USBPORT_TRANSFER,
TransferLink);
RemoveHeadList(&tmplist);
ExFreePoolWithTag(SplitTransfer, USB_PORT_TAG);
}
return;
}
VOID
NTAPI
USBPORT_SplitTransfer(IN PDEVICE_OBJECT FdoDevice,
IN PUSBPORT_ENDPOINT Endpoint,
IN PUSBPORT_TRANSFER Transfer,
IN PLIST_ENTRY List)
{
ULONG TransferType;
DPRINT("USBPORT_SplitTransfer ... \n");
InitializeListHead(List);
InitializeListHead(&Transfer->SplitTransfersList);
Transfer->USBDStatus = USBD_STATUS_SUCCESS;
if (Transfer->TransferParameters.TransferBufferLength >
Endpoint->EndpointProperties.MaxTransferSize)
{
TransferType = Endpoint->EndpointProperties.TransferType;
if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
{
USBPORT_SplitBulkInterruptTransfer(FdoDevice,
Endpoint,
Transfer,
List);
}
else if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS ||
TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
{
KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
}
else
{
DPRINT1("USBPORT_SplitTransfer: Unknown TransferType - %x\n",
TransferType);
}
}
else
{
InsertTailList(List, &Transfer->TransferLink);
}
}
VOID
NTAPI
USBPORT_DoneSplitTransfer(IN PUSBPORT_TRANSFER SplitTransfer)
{
PUSBPORT_TRANSFER ParentTransfer;
KIRQL OldIrql;
DPRINT("USBPORT_DoneSplitTransfer: ... \n");
ParentTransfer = SplitTransfer->ParentTransfer;
ParentTransfer->CompletedTransferLen += SplitTransfer->CompletedTransferLen;
if (SplitTransfer->USBDStatus != USBD_STATUS_SUCCESS)
{
DPRINT1("USBPORT_DoneSplitTransfer: SplitTransfer->USBDStatus - %X\n",
SplitTransfer->USBDStatus);
ParentTransfer->USBDStatus = SplitTransfer->USBDStatus;
}
KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
RemoveEntryList(&SplitTransfer->SplitLink);
ExFreePoolWithTag(SplitTransfer, USB_PORT_TAG);
if (IsListEmpty(&ParentTransfer->SplitTransfersList))
{
KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
USBPORT_DoneTransfer(ParentTransfer);
}
else
{
KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
}
}
VOID
NTAPI
USBPORT_CancelSplitTransfer(IN PUSBPORT_TRANSFER SplitTransfer)
{
PUSBPORT_TRANSFER ParentTransfer;
PUSBPORT_ENDPOINT Endpoint;
KIRQL OldIrql;
DPRINT("USBPORT_CancelSplitTransfer \n");
Endpoint = SplitTransfer->Endpoint;
ParentTransfer = SplitTransfer->ParentTransfer;
ParentTransfer->CompletedTransferLen += SplitTransfer->CompletedTransferLen;
KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
RemoveEntryList(&SplitTransfer->SplitLink);
KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
ExFreePool(SplitTransfer);
if (IsListEmpty(&ParentTransfer->SplitTransfersList))
{
InsertTailList(&Endpoint->CancelList, &ParentTransfer->TransferLink);
}
}
+136 -43
View File
@@ -789,7 +789,7 @@ USBPORT_FlushDoneTransfers(IN PDEVICE_OBJECT FdoDevice)
if ((Transfer->Flags & TRANSFER_FLAG_SPLITED))
{
ASSERT(FALSE);// USBPORT_DoneSplitTransfer(Transfer);
USBPORT_DoneSplitTransfer(Transfer);
}
else
{
@@ -1946,8 +1946,11 @@ USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
IN ULONG TransferLength)
{
PUSBPORT_TRANSFER Transfer;
PDEVICE_OBJECT FdoDevice;
PUSBPORT_DEVICE_EXTENSION FdoExtension;
PUSBPORT_TRANSFER ParentTransfer;
PUSBPORT_TRANSFER SplitTransfer;
PLIST_ENTRY SplitHead;
PLIST_ENTRY Entry;
KIRQL OldIrql;
DPRINT_CORE("USBPORT_MiniportCompleteTransfer: USBDStatus - %x, TransferLength - %x\n",
USBDStatus,
@@ -1957,20 +1960,47 @@ USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
USBPORT_TRANSFER,
TransferParameters);
FdoDevice = Transfer->Endpoint->FdoDevice;
FdoExtension = FdoDevice->DeviceExtension;
Transfer->Flags |= TRANSFER_FLAG_COMPLETED;
Transfer->CompletedTransferLen = TransferLength;
RemoveEntryList(&Transfer->TransferLink);
if (((Transfer->Flags & TRANSFER_FLAG_SPLITED) == 0) ||
TransferLength >= Transfer->TransferParameters.TransferBufferLength)
{
goto Exit;
}
Transfer->USBDStatus = USBDStatus;
ParentTransfer = Transfer->ParentTransfer;
ExInterlockedInsertTailList(&FdoExtension->DoneTransferList,
&Transfer->TransferLink,
&FdoExtension->DoneTransferSpinLock);
KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
KeInsertQueueDpc(&FdoExtension->TransferFlushDpc, NULL, NULL);
if (IsListEmpty(&ParentTransfer->SplitTransfersList))
{
goto Exit;
}
SplitHead = &ParentTransfer->SplitTransfersList;
Entry = SplitHead->Flink;
while (Entry && !IsListEmpty(SplitHead))
{
SplitTransfer = CONTAINING_RECORD(Entry,
USBPORT_TRANSFER,
SplitLink);
if (!(SplitTransfer->Flags & TRANSFER_FLAG_SUBMITED))
{
DPRINT1("USBPORT_MiniportCompleteTransfer: SplitTransfer->Flags - %X\n",
SplitTransfer->Flags);
//Add TRANSFER_FLAG_xxx
}
Entry = Entry->Flink;
}
KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
Exit:
USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
}
VOID
@@ -2250,6 +2280,9 @@ USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
SIZE_T ElementLength;
PUSBPORT_DEVICE_HANDLE DeviceHandle;
PDMA_OPERATIONS DmaOperations;
USBD_STATUS USBDStatus;
LIST_ENTRY List;
PUSBPORT_TRANSFER transfer;
DPRINT_CORE("USBPORT_MapTransfer: ... \n");
@@ -2266,12 +2299,12 @@ USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
Transfer->SgList.CurrentVa = CurrentVa;
Transfer->SgList.MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
sgList = &Transfer->SgList;
sgList->Flags = 0;
sgList->Flags = 0;
sgList->CurrentVa = CurrentVa;
sgList->MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl,
NormalPagePriority);
Transfer->MapRegisterBase = MapRegisterBase;
ix = 0;
@@ -2337,15 +2370,52 @@ USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
}
while (CurrentLength != Transfer->TransferParameters.TransferBufferLength);
Transfer->SgList.SgElementCount = ix;
sgList->SgElementCount = ix;
if (Endpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed)
{
Transfer->Flags |= TRANSFER_FLAG_HIGH_SPEED;
}
Transfer->Flags |= TRANSFER_FLAG_DMA_MAPPED;
ASSERT(Transfer->TransferParameters.TransferBufferLength <=
Endpoint->EndpointProperties.MaxTransferSize);
if ((Transfer->Flags & TRANSFER_FLAG_ISO) == 0)
{
KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
&Endpoint->EndpointOldIrql);
KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
InsertTailList(&Endpoint->TransferList, &Transfer->TransferLink);
KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
USBPORT_SplitTransfer(FdoDevice, Endpoint, Transfer, &List);
while (!IsListEmpty(&List))
{
transfer = CONTAINING_RECORD(List.Flink,
USBPORT_TRANSFER,
TransferLink);
RemoveHeadList(&List);
InsertTailList(&Endpoint->TransferList, &transfer->TransferLink);
}
KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
Endpoint->EndpointOldIrql);
}
else
{
USBDStatus = USBPORT_InitializeIsoTransfer(FdoDevice,
&Urb->UrbIsochronousTransfer,
Transfer);
if (USBDStatus != USBD_STATUS_SUCCESS)
{
KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
&Endpoint->EndpointOldIrql);
USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
Endpoint->EndpointOldIrql);
}
}
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
@@ -2438,6 +2508,7 @@ USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
PUSBPORT_TRANSFER Transfer;
PUSBPORT_PIPE_HANDLE PipeHandle;
USBD_STATUS USBDStatus;
SIZE_T IsoBlockLen = 0;
DPRINT_CORE("USBPORT_AllocateTransfer: FdoDevice - %p, Urb - %p, DeviceHandle - %p, Irp - %p, Event - %p\n",
FdoDevice,
@@ -2458,15 +2529,24 @@ USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
PagesNeed = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
TransferLength);
if (PagesNeed > 0)
{
PagesNeed--;
}
}
if (Urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
{
DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME.\n");
DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME\n");
//IsoBlockLen = sizeof(USBPORT_ISO_BLOCK) +
// Urb->UrbIsochronousTransfer.NumberOfPackets *
// sizeof(USBPORT_ISO_BLOCK_PACKET);
}
PortTransferLength = sizeof(USBPORT_TRANSFER) +
PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT);
PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT) +
IsoBlockLen;
FullTransferLength = PortTransferLength +
FdoExtension->MiniPortInterface->Packet.MiniPortTransferSize;
@@ -2475,30 +2555,43 @@ USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
FullTransferLength,
USB_PORT_TAG);
if (Transfer)
if (!Transfer)
{
RtlZeroMemory(Transfer, FullTransferLength);
Transfer->Irp = Irp;
Transfer->Urb = Urb;
Transfer->Endpoint = PipeHandle->Endpoint;
Transfer->Event = Event;
Transfer->PortTransferLength = PortTransferLength;
Transfer->FullTransferLength = FullTransferLength;
Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
PortTransferLength);
Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
USBDStatus = USBD_STATUS_SUCCESS;
DPRINT1("USBPORT_AllocateTransfer: Transfer not allocated!\n");
return USBD_STATUS_INSUFFICIENT_RESOURCES;
}
else
RtlZeroMemory(Transfer, FullTransferLength);
Transfer->Irp = Irp;
Transfer->Urb = Urb;
Transfer->Endpoint = PipeHandle->Endpoint;
Transfer->Event = Event;
Transfer->PortTransferLength = PortTransferLength;
Transfer->FullTransferLength = FullTransferLength;
Transfer->IsoBlockPtr = NULL;
Transfer->Period = 0;
Transfer->ParentTransfer = Transfer;
if (IsoBlockLen)
{
USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
Transfer->IsoBlockPtr = (PVOID)((ULONG_PTR)Transfer +
PortTransferLength - IsoBlockLen);
Transfer->Period = PipeHandle->Endpoint->EndpointProperties.Period;
Transfer->Flags |= TRANSFER_FLAG_ISO;
}
Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
PortTransferLength);
KeInitializeSpinLock(&Transfer->TransferSpinLock);
Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
USBDStatus = USBD_STATUS_SUCCESS;
DPRINT_CORE("USBPORT_AllocateTransfer: return USBDStatus - %x\n",
USBDStatus);
+37 -1
View File
@@ -121,11 +121,14 @@
/* Transfer Flags (USBPORT_TRANSFER) */
#define TRANSFER_FLAG_CANCELED 0x00000001
#define TRANSFER_FLAG_DMA_MAPPED 0x00000002
#define TRANSFER_FLAG_HIGH_SPEED 0x00000004
#define TRANSFER_FLAG_SUBMITED 0x00000008
#define TRANSFER_FLAG_ABORTED 0x00000010
#define TRANSFER_FLAG_ISO 0x00000020
#define TRANSFER_FLAG_DEVICE_GONE 0x00000080
#define TRANSFER_FLAG_SPLITED 0x00000100
#define TRANSFER_FLAG_COMPLETED 0x00000200
#define TRANSFER_FLAG_PARENT 0x00000400
extern KSPIN_LOCK USBPORT_SpinLock;
extern LIST_ENTRY USBPORT_MiniPortDrivers;
@@ -218,6 +221,8 @@ typedef struct _USBPORT_ENDPOINT {
LIST_ENTRY FlushAbortLink;
} USBPORT_ENDPOINT, *PUSBPORT_ENDPOINT;
typedef struct _USBPORT_ISO_BLOCK *PUSBPORT_ISO_BLOCK;
typedef struct _USBPORT_TRANSFER {
ULONG Flags;
PIRP Irp;
@@ -237,8 +242,15 @@ typedef struct _USBPORT_TRANSFER {
PVOID MapRegisterBase;
ULONG TimeOut;
LARGE_INTEGER Time;
struct _USBPORT_TRANSFER * ParentTransfer;
KSPIN_LOCK TransferSpinLock;
LIST_ENTRY SplitTransfersList; // for parent transfers
LIST_ENTRY SplitLink; // for splitted transfers
ULONG Period;
PUSBPORT_ISO_BLOCK IsoBlockPtr; // pointer on IsoBlock
// SgList should be LAST field
USBPORT_SCATTER_GATHER_LIST SgList; // Non IsoTransfer
USBPORT_SCATTER_GATHER_LIST SgList; // variable length
//USBPORT_ISO_BLOCK IsoBlock; // variable length
} USBPORT_TRANSFER, *PUSBPORT_TRANSFER;
typedef struct _USBPORT_IRP_TABLE {
@@ -573,6 +585,11 @@ USBPORT_InvalidateControllerHandler(
IN PDEVICE_OBJECT FdoDevice,
IN ULONG Type);
VOID
NTAPI
USBPORT_DoneTransfer(
IN PUSBPORT_TRANSFER Transfer);
/* debug.c */
ULONG
NTAPI
@@ -1120,6 +1137,25 @@ NTAPI
USBPORT_RootHubPowerAndChirpAllCcPorts(
IN PDEVICE_OBJECT FdoDevice);
/* trfsplit.c */
VOID
NTAPI
USBPORT_SplitTransfer(
IN PDEVICE_OBJECT FdoDevice,
IN PUSBPORT_ENDPOINT Endpoint,
IN PUSBPORT_TRANSFER Transfer,
IN PLIST_ENTRY List);
VOID
NTAPI
USBPORT_DoneSplitTransfer(
IN PUSBPORT_TRANSFER SplitTransfer);
VOID
NTAPI
USBPORT_CancelSplitTransfer(
IN PUSBPORT_TRANSFER SplitTransfer);
/* urb.c */
NTSTATUS
NTAPI
@@ -626,16 +626,16 @@ typedef struct _USBPORT_SCATTER_GATHER_LIST {
ULONG_PTR CurrentVa;
PVOID MappedSystemVa;
ULONG SgElementCount;
USBPORT_SCATTER_GATHER_ELEMENT SgElement[1];
USBPORT_SCATTER_GATHER_ELEMENT SgElement[2];
} USBPORT_SCATTER_GATHER_LIST, *PUSBPORT_SCATTER_GATHER_LIST;
C_ASSERT(sizeof(USBPORT_SCATTER_GATHER_LIST) == 24 + 4 * sizeof(PVOID));
C_ASSERT(sizeof(USBPORT_SCATTER_GATHER_LIST) == 48 + 4 * sizeof(PVOID));
typedef struct _USBPORT_TRANSFER_PARAMETERS {
ULONG TransferFlags;
ULONG TransferBufferLength;
ULONG TransferCounter;
ULONG Reserved1;
BOOL IsTransferSplited;
ULONG Reserved2;
USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
} USBPORT_TRANSFER_PARAMETERS, *PUSBPORT_TRANSFER_PARAMETERS;