Author: janderwald Date: Sat Apr 23 19:36:23 2011 New Revision: 51440
URL: http://svn.reactos.org/svn/reactos?rev=51440&view=rev Log: [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
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.h branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] Sat Apr 23 19:36:23 2011 @@ -194,6 +194,7 @@ PIRP IrpToComplete; PMDL Mdl; PKEVENT Event; + PVOID Request; } QUEUE_HEAD, *PQUEUE_HEAD;
//
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Sat Apr 23 19:36:23 2011 @@ -474,6 +474,14 @@ // If the request was initialized with an setup packet, it will return false
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;
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] Sat Apr 23 19:36:23 2011 @@ -51,10 +51,17 @@ PQUEUE_HEAD AsyncListQueueHead; PQUEUE_HEAD PendingListQueueHead;
+ // queue head manipulation functions VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead); VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); 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); };
//================================================================================================= @@ -141,6 +148,11 @@ // Add it to the pending list // LinkQueueHead(PendingListQueueHead, QueueHead); + + // + // add extra reference which is released when the request is completed + // + Request->AddRef();
return STATUS_SUCCESS; } @@ -315,6 +327,154 @@ }
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 CreateUSBQueue( PUSBQUEUE *OutUsbQueue) {
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] Sat Apr 23 19:36:23 2011 @@ -46,6 +46,7 @@ virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode); virtual BOOLEAN IsRequestInitialized(); virtual BOOLEAN ShouldReleaseRequestAfterCompletion(); + virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead);
// local functions ULONG InternalGetTransferType(); @@ -416,6 +417,11 @@ // store queue head // m_QueueHead = *OutHead; + + // + // store request object + // + (*OutHead)->Request = PVOID(this); }
// @@ -936,6 +942,58 @@ } }
+//----------------------------------------------------------------------------------------- +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 InternalCreateUSBRequest( PUSBREQUEST *OutRequest)