mirror of
https://github.com/reactos/reactos.git
synced 2025-05-14 23:03:53 +00:00
[USBEHCI_NEW]
- Create member for storing the request object - Add interface function which is invoked when the queue head should be freed - Add support functions which deal with completed queue heads svn path=/branches/usb-bringup/; revision=51440
This commit is contained in:
parent
4dff45da57
commit
982eb59ba0
4 changed files with 227 additions and 0 deletions
|
@ -194,6 +194,7 @@ typedef struct _QUEUE_HEAD
|
||||||
PIRP IrpToComplete;
|
PIRP IrpToComplete;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
|
PVOID Request;
|
||||||
} QUEUE_HEAD, *PQUEUE_HEAD;
|
} QUEUE_HEAD, *PQUEUE_HEAD;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -474,6 +474,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
// If the request was initialized with an setup packet, it will return false
|
// If the request was initialized with an setup packet, it will return false
|
||||||
|
|
||||||
virtual BOOLEAN ShouldReleaseRequestAfterCompletion() = 0;
|
virtual BOOLEAN ShouldReleaseRequestAfterCompletion() = 0;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// FreeQueueHead
|
||||||
|
//
|
||||||
|
// Description: frees the queue head with the associated transfer descriptors
|
||||||
|
|
||||||
|
virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IUSBRequest *PUSBREQUEST;
|
typedef IUSBRequest *PUSBREQUEST;
|
||||||
|
|
|
@ -51,10 +51,17 @@ protected:
|
||||||
PQUEUE_HEAD AsyncListQueueHead;
|
PQUEUE_HEAD AsyncListQueueHead;
|
||||||
PQUEUE_HEAD PendingListQueueHead;
|
PQUEUE_HEAD PendingListQueueHead;
|
||||||
|
|
||||||
|
// queue head manipulation functions
|
||||||
VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
||||||
VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead);
|
VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead);
|
||||||
VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
||||||
PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
|
PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
|
||||||
|
|
||||||
|
// called for each completed queue head
|
||||||
|
NTSTATUS QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
|
||||||
|
|
||||||
|
// called when the completion queue is cleaned up
|
||||||
|
VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead);
|
||||||
};
|
};
|
||||||
|
|
||||||
//=================================================================================================
|
//=================================================================================================
|
||||||
|
@ -142,6 +149,11 @@ CUSBQueue::AddUSBRequest(
|
||||||
//
|
//
|
||||||
LinkQueueHead(PendingListQueueHead, QueueHead);
|
LinkQueueHead(PendingListQueueHead, QueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add extra reference which is released when the request is completed
|
||||||
|
//
|
||||||
|
Request->AddRef();
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,6 +326,154 @@ CUSBQueue::UnlinkQueueHeadChain(
|
||||||
return FirstQueueHead;
|
return FirstQueueHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBQueue::QueueHeadCompletion(
|
||||||
|
PQUEUE_HEAD CurrentQH,
|
||||||
|
NTSTATUS Status)
|
||||||
|
{
|
||||||
|
IUSBRequest *Request;
|
||||||
|
USBD_STATUS UrbStatus;
|
||||||
|
PQUEUE_HEAD NewQueueHead;
|
||||||
|
|
||||||
|
//
|
||||||
|
// this function is called when a queue head has been completed
|
||||||
|
//
|
||||||
|
PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get contained usb request
|
||||||
|
//
|
||||||
|
Request = (IUSBRequest*)CurrentQH->Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(Request);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the queue head was completed with errors
|
||||||
|
//
|
||||||
|
if (CurrentQH->Token.Bits.Halted)
|
||||||
|
{
|
||||||
|
if (CurrentQH->Token.Bits.DataBufferError)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// data buffer error
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_DATA_BUFFER_ERROR;
|
||||||
|
}
|
||||||
|
else if (CurrentQH->Token.Bits.BabbleDetected)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// babble detected
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_BABBLE_DETECTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// stall pid
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_STALL_PID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// well done ;)
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// notify request that a queue head has been completed
|
||||||
|
//
|
||||||
|
Request->CompletionCallback(Status, UrbStatus, CurrentQH);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now unlink the queue head
|
||||||
|
// FIXME: implement chained queue heads
|
||||||
|
//
|
||||||
|
UnlinkQueueHead(CurrentQH);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the request is complete
|
||||||
|
//
|
||||||
|
if (Request->IsRequestComplete() == FALSE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request is still in complete
|
||||||
|
// get new queue head
|
||||||
|
//
|
||||||
|
Status = Request->GetQueueHead(&NewQueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to pending list
|
||||||
|
//
|
||||||
|
LinkQueueHead(PendingListQueueHead, NewQueueHead);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: put queue head into completed queue head list
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBQueue::QueueHeadCleanup(
|
||||||
|
PQUEUE_HEAD CurrentQH)
|
||||||
|
{
|
||||||
|
IUSBRequest * Request;
|
||||||
|
BOOLEAN ShouldReleaseWhenDone;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
|
||||||
|
PC_ASSERT(CurrentQH->Request);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get request
|
||||||
|
//
|
||||||
|
Request = (IUSBRequest*)CurrentQH->Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// let IUSBRequest free the queue head
|
||||||
|
//
|
||||||
|
Request->FreeQueueHead(CurrentQH);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if we should release request when done
|
||||||
|
//
|
||||||
|
ShouldReleaseWhenDone = Request->ShouldReleaseRequestAfterCompletion();
|
||||||
|
|
||||||
|
//
|
||||||
|
// release reference when the request was added
|
||||||
|
//
|
||||||
|
Request->Release();
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the operation was asynchronous
|
||||||
|
//
|
||||||
|
if (ShouldReleaseWhenDone)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// release outstanding reference count
|
||||||
|
//
|
||||||
|
Request->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// request is now released
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CreateUSBQueue(
|
CreateUSBQueue(
|
||||||
PUSBQUEUE *OutUsbQueue)
|
PUSBQUEUE *OutUsbQueue)
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
|
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
|
||||||
virtual BOOLEAN IsRequestInitialized();
|
virtual BOOLEAN IsRequestInitialized();
|
||||||
virtual BOOLEAN ShouldReleaseRequestAfterCompletion();
|
virtual BOOLEAN ShouldReleaseRequestAfterCompletion();
|
||||||
|
virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead);
|
||||||
|
|
||||||
// local functions
|
// local functions
|
||||||
ULONG InternalGetTransferType();
|
ULONG InternalGetTransferType();
|
||||||
|
@ -416,6 +417,11 @@ CUSBRequest::GetQueueHead(
|
||||||
// store queue head
|
// store queue head
|
||||||
//
|
//
|
||||||
m_QueueHead = *OutHead;
|
m_QueueHead = *OutHead;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store request object
|
||||||
|
//
|
||||||
|
(*OutHead)->Request = PVOID(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -936,6 +942,58 @@ CUSBRequest::ShouldReleaseRequestAfterCompletion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
VOID
|
||||||
|
CUSBRequest::FreeQueueHead(
|
||||||
|
IN struct _QUEUE_HEAD * QueueHead)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: support chained queue heads
|
||||||
|
//
|
||||||
|
PC_ASSERT(QueueHead == m_QueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// release queue head
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
|
||||||
|
|
||||||
|
//
|
||||||
|
// nullify pointer
|
||||||
|
//
|
||||||
|
m_QueueHead = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// release transfer descriptors
|
||||||
|
//
|
||||||
|
|
||||||
|
if (m_TransferDescriptors[0])
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// release transfer descriptors
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(m_TransferDescriptors[0], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
|
||||||
|
m_TransferDescriptors[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_TransferDescriptors[1])
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// release transfer descriptors
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(m_TransferDescriptors[1], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
|
||||||
|
m_TransferDescriptors[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_TransferDescriptors[2])
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// release transfer descriptors
|
||||||
|
//
|
||||||
|
m_DmaManager->Release(m_TransferDescriptors[2], sizeof(QUEUE_TRANSFER_DESCRIPTOR));
|
||||||
|
m_TransferDescriptors[2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
InternalCreateUSBRequest(
|
InternalCreateUSBRequest(
|
||||||
PUSBREQUEST *OutRequest)
|
PUSBREQUEST *OutRequest)
|
||||||
|
|
Loading…
Reference in a new issue