mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-28 12:23:28 +00:00
[USBPORT]
- Begin implementing split transfers. Patch by Vadim Galyant. svn path=/trunk/; revision=75783
This commit is contained in:
@@ -12,6 +12,7 @@ list(APPEND SOURCE
|
||||
power.c
|
||||
queue.c
|
||||
roothub.c
|
||||
trfsplit.c
|
||||
urb.c
|
||||
usb2.c
|
||||
usbport.c
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user