mirror of
https://github.com/reactos/reactos.git
synced 2024-07-28 15:19:09 +00:00
[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
This commit is contained in:
parent
bd3f5b9708
commit
df5cd2fcac
|
@ -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
|
||||
//
|
||||
|
|
|
@ -819,6 +819,7 @@ CUSBDevice::CreateConfigurationDescriptor(
|
|||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
ASSERT(InterfaceDescriptor->bLength);
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue