From df5cd2fcacb63fa7bdf1f2dce3d9785d2f70174b Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Thu, 16 Feb 2012 14:49:59 +0000 Subject: [PATCH] [USBEHCI] - Abort pipe when performing sync reset request - add assert to check for bogus interface descriptors - use endpoint max packet size when available - flip data toggle after each transfer - remove dead code - use maximum of 4 pages or rest current buffer size when performing a bulk requests - use nak reload count 3 - perform 1 transaction per frame svn path=/trunk/; revision=55634 --- .../drivers/usb/usbehci/hub_controller.cpp | 15 +++- reactos/drivers/usb/usbehci/usb_device.cpp | 1 + reactos/drivers/usb/usbehci/usb_queue.cpp | 90 ++++++++++++++++--- reactos/drivers/usb/usbehci/usb_request.cpp | 82 ++++++++++++----- 4 files changed, 153 insertions(+), 35 deletions(-) diff --git a/reactos/drivers/usb/usbehci/hub_controller.cpp b/reactos/drivers/usb/usbehci/hub_controller.cpp index acde656342b..7fe6b0185ec 100644 --- a/reactos/drivers/usb/usbehci/hub_controller.cpp +++ b/reactos/drivers/usb/usbehci/hub_controller.cpp @@ -1740,7 +1740,7 @@ CHubController::HandleSyncResetAndClearStall( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("HandleSyncResetAndClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1748,6 +1748,19 @@ CHubController::HandleSyncResetAndClearStall( return STATUS_DEVICE_NOT_CONNECTED; } + // + // abort pipe + // + Status = HandleAbortPipe(Irp, Urb); + if (!NT_SUCCESS(Status)) + { + // + // failed + // + DPRINT1("[USBEHCI] failed to reset pipe %x\n", Status) + } + + // // get endpoint descriptor // diff --git a/reactos/drivers/usb/usbehci/usb_device.cpp b/reactos/drivers/usb/usbehci/usb_device.cpp index b75f9703dc3..8e1077a74f5 100644 --- a/reactos/drivers/usb/usbehci/usb_device.cpp +++ b/reactos/drivers/usb/usbehci/usb_device.cpp @@ -819,6 +819,7 @@ CUSBDevice::CreateConfigurationDescriptor( // // move to next descriptor // + ASSERT(InterfaceDescriptor->bLength); InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); } diff --git a/reactos/drivers/usb/usbehci/usb_queue.cpp b/reactos/drivers/usb/usbehci/usb_queue.cpp index 3c7d4db58fe..3f1348b8844 100644 --- a/reactos/drivers/usb/usbehci/usb_queue.cpp +++ b/reactos/drivers/usb/usbehci/usb_queue.cpp @@ -427,7 +427,7 @@ CUSBQueue::LinkQueueHead( // // Link the LIST_ENTRYs // - ASSERT(IsListEmpty(&HeadQueueHead->LinkedQueueHeads)); + //ASSERT(IsListEmpty(&HeadQueueHead->LinkedQueueHeads)); InsertTailList(&HeadQueueHead->LinkedQueueHeads, &NewQueueHead->LinkedQueueHeads); // @@ -435,7 +435,7 @@ CUSBQueue::LinkQueueHead( // Entry = NewQueueHead->LinkedQueueHeads.Blink; LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - ASSERT(LastQueueHead == HeadQueueHead); + //ASSERT(LastQueueHead == HeadQueueHead); LastQueueHead->HorizontalLinkPointer = (NewQueueHead->PhysicalAddr | QH_TYPE_QH); // @@ -443,7 +443,7 @@ CUSBQueue::LinkQueueHead( // Entry = NewQueueHead->LinkedQueueHeads.Flink; NextQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - ASSERT(NextQueueHead == HeadQueueHead); + //ASSERT(NextQueueHead == HeadQueueHead); NewQueueHead->HorizontalLinkPointer = (NextQueueHead->PhysicalAddr | QH_TYPE_QH); // @@ -858,7 +858,6 @@ CUSBQueue::CompleteAsyncRequests() KIRQL OldLevel; PLIST_ENTRY Entry; PQUEUE_HEAD CurrentQH; - IUSBRequest *Request; DPRINT("CUSBQueue::CompleteAsyncRequests\n"); @@ -884,11 +883,6 @@ CUSBQueue::CompleteAsyncRequests() // CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - // - // Get the Request for this QueueHead - // - Request = (IUSBRequest*) CurrentQH->Request; - // // release lock // @@ -937,8 +931,82 @@ CUSBQueue::AbortDevicePipe( IN UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + KIRQL OldLevel; + PLIST_ENTRY Entry; + PQUEUE_HEAD QueueHead; + LIST_ENTRY ListHead; + + // + // lock completed async list + // + KeAcquireSpinLock(m_Lock, &OldLevel); + + DPRINT1("AbortDevicePipe DeviceAddress %x EndpointDescriptor %p Addr %x\n", DeviceAddress, EndpointDescriptor, EndpointDescriptor->bEndpointAddress); + + // + // init list head + // + InitializeListHead(&ListHead); + + + // + // walk async list + // + ASSERT(AsyncListQueueHead); + Entry = AsyncListQueueHead->LinkedQueueHeads.Flink; + + while(Entry != &AsyncListQueueHead->LinkedQueueHeads) + { + // + // get queue head structure + // + QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); + ASSERT(QueueHead); + + // + // move to next entry + // + Entry = Entry->Flink; + + if (QueueHead->EndPointCharacteristics.DeviceAddress == DeviceAddress && + QueueHead->EndPointCharacteristics.EndPointNumber == (EndpointDescriptor->bEndpointAddress & 0xF) && QueueHead->Token.Bits.Halted) + { + // + // unlink queue head + // + UnlinkQueueHead(QueueHead); + + // + // add to temp list + // + InsertTailList(&ListHead, &QueueHead->LinkedQueueHeads); + } + } + + // + // release lock + // + KeReleaseSpinLock(m_Lock, OldLevel); + + while(!IsListEmpty(&ListHead)) + { + // + // remove entry + // + Entry = RemoveHeadList(&ListHead); + + // + // get queue head structure + // + QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); + ASSERT(QueueHead); + + // + // cleanup queue head + // + QueueHeadCleanup(QueueHead); + } + return STATUS_SUCCESS; } diff --git a/reactos/drivers/usb/usbehci/usb_request.cpp b/reactos/drivers/usb/usbehci/usb_request.cpp index 46ed3a4c4dd..27be3736ca1 100644 --- a/reactos/drivers/usb/usbehci/usb_request.cpp +++ b/reactos/drivers/usb/usbehci/usb_request.cpp @@ -62,11 +62,10 @@ public: NTSTATUS BuildSetupPacket(); NTSTATUS BuildSetupPacketFromURB(); ULONG InternalCalculateTransferLength(); - NTSTATUS BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset); + NTSTATUS BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, IN PQUEUE_TRANSFER_DESCRIPTOR AlternativeDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset); VOID InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength); VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead); - // constructor / destructor CUSBRequest(IUnknown *OuterUnknown){} virtual ~CUSBRequest(){} @@ -734,6 +733,7 @@ CUSBRequest::BuildTransferDescriptorChain( IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, + IN PQUEUE_TRANSFER_DESCRIPTOR AlternativeDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, @@ -742,6 +742,19 @@ CUSBRequest::BuildTransferDescriptorChain( PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL; NTSTATUS Status; ULONG DescriptorLength, TransferBufferOffset = 0; + ULONG MaxPacketSize = 0, TransferSize; + + // + // is there an endpoint descriptor + // + if (m_EndpointDescriptor) + { + // + // use endpoint packet size + // + MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; + } + do { @@ -754,8 +767,22 @@ CUSBRequest::BuildTransferDescriptorChain( // // failed to allocate transfer descriptor // - ASSERT(FALSE); - return Status; + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (MaxPacketSize) + { + // + // transfer size is minimum available buffer or endpoint size + // + TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize); + } + else + { + // + // use available buffer + // + TransferSize = TransferBufferLength - TransferBufferOffset; } // @@ -763,7 +790,7 @@ CUSBRequest::BuildTransferDescriptorChain( // InitDescriptor(CurrentDescriptor, (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), - TransferBufferLength - TransferBufferOffset, + TransferSize, PidCode, InitialDataToggle, &DescriptorLength); @@ -783,9 +810,17 @@ CUSBRequest::BuildTransferDescriptorChain( // // link to current descriptor // - LastDescriptor->AlternateNextPointer = CurrentDescriptor->PhysicalAddr; LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr; LastDescriptor = CurrentDescriptor; + + if (AlternativeDescriptor) + { + // + // link to alternative next pointer + // + LastDescriptor->AlternateNextPointer = AlternativeDescriptor->PhysicalAddr; + } + } else { @@ -795,6 +830,11 @@ CUSBRequest::BuildTransferDescriptorChain( LastDescriptor = FirstDescriptor = CurrentDescriptor; } + // + // flip data toggle + // + InitialDataToggle = !InitialDataToggle; + if(TransferBufferLength == TransferBufferOffset) { // @@ -802,6 +842,7 @@ CUSBRequest::BuildTransferDescriptorChain( // break; } + }while(TRUE); if (OutFirstDescriptor) @@ -822,11 +863,6 @@ CUSBRequest::BuildTransferDescriptorChain( if (OutDataToggle) { - // - // flip data toggle - // - InitialDataToggle = !InitialDataToggle; - // // store result data toggle // @@ -918,14 +954,7 @@ CUSBRequest::BuildControlTransferQueueHead( // QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress(); - if (m_EndpointDescriptor) - { - // - // set endpoint address and max packet length - // - QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F; - QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; - } + ASSERT(m_EndpointDescriptor == FALSE); // // init setup descriptor @@ -954,6 +983,7 @@ CUSBRequest::BuildControlTransferQueueHead( m_TransferBufferLength, InternalGetPidDirection(), TRUE, + NULL, &FirstDescriptor, &LastDescriptor, NULL, @@ -1136,14 +1166,20 @@ CUSBRequest::BuildBulkTransferQueueHead( // ASSERT(m_EndpointDescriptor); + // + // use 4 * PAGE_SIZE at max for each new request + // + ULONG MaxTransferLength = min(4 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted); + // // build bulk transfer descriptor chain // Status = BuildTransferDescriptorChain(QueueHead, Base, - m_TransferBufferLength - m_TransferBufferLengthCompleted, + MaxTransferLength, InternalGetPidDirection(), m_EndpointDescriptor->DataToggle, + NULL, &FirstDescriptor, &LastDescriptor, &m_EndpointDescriptor->DataToggle, @@ -1152,7 +1188,7 @@ CUSBRequest::BuildBulkTransferQueueHead( // // FIXME: handle errors // - ASSERT(ChainDescriptorLength == m_TransferBufferLength); + //ASSERT(ChainDescriptorLength == m_TransferBufferLength); // // move to next offset @@ -1279,7 +1315,7 @@ CUSBRequest::CreateQueueHead( // // Set NakCountReload to max value possible // - QueueHead->EndPointCharacteristics.NakCountReload = 0xF; + QueueHead->EndPointCharacteristics.NakCountReload = 0x3; // // Get the Initial Data Toggle from the QEDT @@ -1290,7 +1326,7 @@ CUSBRequest::CreateQueueHead( // FIXME: check if High Speed Device // QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; - QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03; + QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01; QueueHead->Token.DWord = 0; QueueHead->Token.Bits.InterruptOnComplete = FALSE;