From ba2be71aa93ce2de9bfc25a889bc0ee8e9f27785 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Fri, 8 Sep 2017 07:17:34 +0000 Subject: [PATCH] [USBPORT] - Begin implementing split transfers. Patch by Vadim Galyant. svn path=/trunk/; revision=75783 --- reactos/drivers/usb/usbport/CMakeLists.txt | 1 + reactos/drivers/usb/usbport/endpoint.c | 3 +- reactos/drivers/usb/usbport/queue.c | 60 +++- reactos/drivers/usb/usbport/trfsplit.c | 329 ++++++++++++++++++ reactos/drivers/usb/usbport/usbport.c | 179 +++++++--- reactos/drivers/usb/usbport/usbport.h | 38 +- .../reactos/drivers/usbport/usbmport.h | 6 +- 7 files changed, 549 insertions(+), 67 deletions(-) create mode 100644 reactos/drivers/usb/usbport/trfsplit.c diff --git a/reactos/drivers/usb/usbport/CMakeLists.txt b/reactos/drivers/usb/usbport/CMakeLists.txt index 52db9347e46..6f0d1884fdd 100644 --- a/reactos/drivers/usb/usbport/CMakeLists.txt +++ b/reactos/drivers/usb/usbport/CMakeLists.txt @@ -12,6 +12,7 @@ list(APPEND SOURCE power.c queue.c roothub.c + trfsplit.c urb.c usb2.c usbport.c diff --git a/reactos/drivers/usb/usbport/endpoint.c b/reactos/drivers/usb/usbport/endpoint.c index b0ec684f6c9..2931794ec61 100644 --- a/reactos/drivers/usb/usbport/endpoint.c +++ b/reactos/drivers/usb/usbport/endpoint.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 { diff --git a/reactos/drivers/usb/usbport/queue.c b/reactos/drivers/usb/usbport/queue.c index 9cdebbcb6fd..ab16801522c 100644 --- a/reactos/drivers/usb/usbport/queue.c +++ b/reactos/drivers/usb/usbport/queue.c @@ -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 diff --git a/reactos/drivers/usb/usbport/trfsplit.c b/reactos/drivers/usb/usbport/trfsplit.c new file mode 100644 index 00000000000..5f129b8220b --- /dev/null +++ b/reactos/drivers/usb/usbport/trfsplit.c @@ -0,0 +1,329 @@ +#include "usbport.h" + +#define NDEBUG +#include + +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); + } +} diff --git a/reactos/drivers/usb/usbport/usbport.c b/reactos/drivers/usb/usbport/usbport.c index cae479b05e5..29ab313a46f 100644 --- a/reactos/drivers/usb/usbport/usbport.c +++ b/reactos/drivers/usb/usbport/usbport.c @@ -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); diff --git a/reactos/drivers/usb/usbport/usbport.h b/reactos/drivers/usb/usbport/usbport.h index b9ea84e0c11..efe44121096 100644 --- a/reactos/drivers/usb/usbport/usbport.h +++ b/reactos/drivers/usb/usbport/usbport.h @@ -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 diff --git a/reactos/sdk/include/reactos/drivers/usbport/usbmport.h b/reactos/sdk/include/reactos/drivers/usbport/usbmport.h index 8cb2c96adcf..2b14bac56af 100644 --- a/reactos/sdk/include/reactos/drivers/usbport/usbmport.h +++ b/reactos/sdk/include/reactos/drivers/usbport/usbmport.h @@ -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;