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_new/hardware.h?rev=51440&r1=51439&r2=51440&view=diff
==============================================================================
--- 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_new/interfaces.h?rev=51440&r1=51439&r2=51440&view=diff
==============================================================================
--- 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_new/usb_queue.cpp?rev=51440&r1=51439&r2=51440&view=diff
==============================================================================
--- 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_new/usb_request.cpp?rev=51440&r1=51439&r2=51440&view=diff
==============================================================================
--- 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)


Reply via email to