Index: trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 27339)
@@ -6576,4 +6576,13 @@
 #endif /* VBOX_WITH_HGSMI */
 
+#ifdef VBOXVDMA
+    if(rc == VINF_SUCCESS)
+    {
+        /* @todo: perhaps this should be done from some guest->host callback,
+        * that would as well specify the cmd pool size */
+        rc = vboxVDMAConstruct(pThis, &pThis->pVdma, 1024);
+        AssertRC(rc);
+    }
+#endif
     /*
      * Statistics.
Index: trunk/src/VBox/Devices/Graphics/DevVGA.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 27339)
@@ -492,8 +492,9 @@
 
 # ifdef VBOXVDMA
-int vboxVDMAConstruct(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma);
-int vboxVDMADestruct(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma);
-void vboxVDMAControl(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd);
-void vboxVDMACommand(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd);
+typedef struct VBOXVDMAHOST *PVBOXVDMAHOST;
+int vboxVDMAConstruct(PVGASTATE pVGAState, struct VBOXVDMAHOST **ppVdma, uint32_t cPipeElements);
+int vboxVDMADestruct(PVBOXVDMAHOST pVdma);
+void vboxVDMAControl(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd);
+void vboxVDMACommand(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd);
 # endif /* VBOXVDMA */
 
Index: trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp	(revision 27339)
@@ -1299,5 +1299,5 @@
         {
             PVBOXVDMACBUF_DR pCmd = (PVBOXVDMACBUF_DR)VBoxSHGSMIBufferData ((PVBOXSHGSMIHEADER)pvBuffer);
-            vboxVDMACommand(pVGAState, pVGAState->pVdma, pCmd);
+            vboxVDMACommand(pVGAState->pVdma, pCmd);
             rc = VINF_SUCCESS;
             break;
@@ -1306,5 +1306,5 @@
         {
             PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMIBufferData ((PVBOXSHGSMIHEADER)pvBuffer);
-            vboxVDMAControl(pVGAState, pVGAState->pVdma, pCmd);
+            vboxVDMAControl(pVGAState->pVdma, pCmd);
             rc = VINF_SUCCESS;
             break;
Index: trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp	(revision 27339)
@@ -21,4 +21,7 @@
 #include <VBox/pdmdev.h>
 #include <VBox/VBoxVideo.h>
+#include <iprt/semaphore.h>
+#include <iprt/thread.h>
+#include <iprt/mem.h>
 
 #include "DevVGA.h"
@@ -26,34 +29,465 @@
 #include "HGSMI/HGSMIHostHlp.h"
 
+typedef enum
+{
+    VBOXVDMAPIPE_STATE_CLOSED    = 0,
+    VBOXVDMAPIPE_STATE_CREATED   = 1,
+    VBOXVDMAPIPE_STATE_OPENNED   = 2,
+    VBOXVDMAPIPE_STATE_CLOSING   = 3
+} VBOXVDMAPIPE_STATE;
+
 typedef struct VBOXVDMAPIPE
 {
-    HGSMILIST List;
-
     RTSEMEVENT hEvent;
     /* critical section for accessing pipe properties */
     RTCRITSECT hCritSect;
+    VBOXVDMAPIPE_STATE enmState;
     /* true iff the other end needs Event notification */
     bool bNeedNotify;
 } VBOXVDMAPIPE, *PVBOXVDMAPIPE;
 
+typedef enum
+{
+    VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0,
+    VBOXVDMAPIPE_CMD_TYPE_DMACMD    = 1,
+    VBOXVDMAPIPE_CMD_TYPE_DMACTL    = 2
+} VBOXVDMAPIPE_CMD_TYPE;
+
+typedef struct VBOXVDMAPIPE_CMD_BODY
+{
+    VBOXVDMAPIPE_CMD_TYPE enmType;
+    union
+    {
+        PVBOXVDMACBUF_DR pDr;
+        PVBOXVDMA_CTL    pCtl;
+        void            *pvCmd;
+    } u;
+}VBOXVDMAPIPE_CMD_BODY, *PVBOXVDMAPIPE_CMD_BODY;
+
+typedef struct VBOXVDMAPIPE_CMD
+{
+    HGSMILISTENTRY Entry;
+    VBOXVDMAPIPE_CMD_BODY Cmd;
+} VBOXVDMAPIPE_CMD, *PVBOXVDMAPIPE_CMD;
+
+#define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE)  ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) )
+
+typedef struct VBOXVDMAPIPE_CMD_POOL
+{
+    HGSMILIST List;
+    uint32_t cCmds;
+    VBOXVDMAPIPE_CMD aCmds[1];
+} VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL;
+
 typedef struct VBOXVDMAHOST
 {
     VBOXVDMAPIPE Pipe;
+    HGSMILIST PendingList;
     RTTHREAD hWorkerThread;
+    PHGSMIINSTANCE pHgsmi;
+    VBOXVDMAPIPE_CMD_POOL CmdPool;
 } VBOXVDMAHOST, *PVBOXVDMAHOST;
 
-int vboxVDMAConstruct(PVGASTATE pVGAState, struct VBOXVDMAHOST **ppVdma)
-{
+int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe)
+{
+    int rc = RTSemEventCreate(&pPipe->hEvent);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCritSectInit(&pPipe->hCritSect);
+        AssertRC(rc);
+        if (RT_SUCCESS(rc))
+        {
+            pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED;
+            pPipe->bNeedNotify = true;
+            return VINF_SUCCESS;
+//            RTCritSectDelete(pPipe->hCritSect);
+        }
+        RTSemEventDestroy(pPipe->hEvent);
+    }
+    return rc;
+}
+
+int vboxVDMAPipeOpenServer(PVBOXVDMAPIPE pPipe)
+{
+    int rc = RTCritSectEnter(&pPipe->hCritSect);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
+        switch (pPipe->enmState)
+        {
+            case VBOXVDMAPIPE_STATE_CREATED:
+                pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED;
+                pPipe->bNeedNotify = false;
+                rc = VINF_SUCCESS;
+                break;
+            case VBOXVDMAPIPE_STATE_OPENNED:
+                pPipe->bNeedNotify = false;
+                rc = VINF_ALREADY_INITIALIZED;
+                break;
+            default:
+                AssertBreakpoint();
+                rc = VERR_INVALID_STATE;
+                break;
+        }
+
+        RTCritSectLeave(&pPipe->hCritSect);
+    }
+    return rc;
+}
+
+int vboxVDMAPipeCloseServer(PVBOXVDMAPIPE pPipe)
+{
+    int rc = RTCritSectEnter(&pPipe->hCritSect);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
+                || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
+        switch (pPipe->enmState)
+        {
+            case VBOXVDMAPIPE_STATE_CLOSING:
+                pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
+                rc = VINF_SUCCESS;
+                break;
+            case VBOXVDMAPIPE_STATE_CLOSED:
+                rc = VINF_ALREADY_INITIALIZED;
+                break;
+            default:
+                AssertBreakpoint();
+                rc = VERR_INVALID_STATE;
+                break;
+        }
+
+        RTCritSectLeave(&pPipe->hCritSect);
+    }
+    return rc;
+}
+
+int vboxVDMAPipeCloseClient(PVBOXVDMAPIPE pPipe)
+{
+    int rc = RTCritSectEnter(&pPipe->hCritSect);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        bool bNeedNotify = false;
+        Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
+                || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED
+                ||  pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
+        switch (pPipe->enmState)
+        {
+            case VBOXVDMAPIPE_STATE_OPENNED:
+                pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING;
+                bNeedNotify = pPipe->bNeedNotify;
+                pPipe->bNeedNotify = false;
+                break;
+            case VBOXVDMAPIPE_STATE_CREATED:
+                pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
+                pPipe->bNeedNotify = false;
+                break;
+            case VBOXVDMAPIPE_STATE_CLOSED:
+                rc = VINF_ALREADY_INITIALIZED;
+                break;
+            default:
+                AssertBreakpoint();
+                rc = VERR_INVALID_STATE;
+                break;
+        }
+
+        RTCritSectLeave(&pPipe->hCritSect);
+
+        if (bNeedNotify)
+        {
+            rc = RTSemEventSignal(pPipe->hEvent);
+            AssertRC(rc);
+        }
+    }
+    return rc;
+}
+
+
+typedef DECLCALLBACK(bool) FNHVBOXVDMARWCB(PVBOXVDMAPIPE pPipe, void *pvCallback);
+typedef FNHVBOXVDMARWCB *PFNHVBOXVDMARWCB;
+
+int vboxVDMAPipeModifyServer(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
+{
+    int rc = RTCritSectEnter(&pPipe->hCritSect);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        do
+        {
+            Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
+                    || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
+
+            if (pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED)
+            {
+                bool bProcessing = pfnCallback(pPipe, pvCallback);
+                pPipe->bNeedNotify = !bProcessing;
+                if (bProcessing)
+                {
+                    RTCritSectLeave(&pPipe->hCritSect);
+                    rc = VINF_SUCCESS;
+                    break;
+                }
+                else if (pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING)
+                {
+                    pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
+                    RTCritSectLeave(&pPipe->hCritSect);
+                    rc = VINF_EOF;
+                    break;
+                }
+            }
+            else
+            {
+                AssertBreakpoint();
+                rc = VERR_INVALID_STATE;
+                RTCritSectLeave(&pPipe->hCritSect);
+                break;
+            }
+
+            RTCritSectLeave(&pPipe->hCritSect);
+
+            rc = RTSemEventWait(pPipe->hEvent, RT_INDEFINITE_WAIT);
+            AssertRC(rc);
+            if (!RT_SUCCESS(rc))
+                break;
+
+            rc = RTCritSectEnter(&pPipe->hCritSect);
+            AssertRC(rc);
+            if (!RT_SUCCESS(rc))
+                break;
+        } while (1);
+    }
+
+    return rc;
+}
+
+int vboxVDMAPipeModifyClient(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
+{
+    int rc = RTCritSectEnter(&pPipe->hCritSect);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        bool bNeedNotify = false;
+        Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
+        if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED)
+        {
+            bool bModified = pfnCallback(pPipe, pvCallback);
+            if (bModified)
+            {
+                bNeedNotify = pPipe->bNeedNotify;
+                pPipe->bNeedNotify = false;
+            }
+        }
+        else
+            rc = VERR_INVALID_STATE;
+
+        RTCritSectLeave(&pPipe->hCritSect);
+
+        if (bNeedNotify)
+        {
+            rc = RTSemEventSignal(pPipe->hEvent);
+            AssertRC(rc);
+        }
+    }
+    return rc;
+}
+
+int vboxVDMAPipeDestruct(PVBOXVDMAPIPE pPipe)
+{
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
+            || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
+    /* ensure the pipe is closed */
+    vboxVDMAPipeCloseClient(pPipe);
+
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
+
+    if (pPipe->enmState != VBOXVDMAPIPE_STATE_CLOSED)
+        return VERR_INVALID_STATE;
+
+    int rc = RTCritSectDelete(&pPipe->hCritSect);
+    AssertRC(rc);
+
+    rc = RTSemEventDestroy(pPipe->hEvent);
+    AssertRC(rc);
+
     return VINF_SUCCESS;
 }
 
-int vboxVDMADestruct(PVGASTATE pVGAState, struct VBOXVDMAHOST **pVdma)
-{
+void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd)
+{
+    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
+    pCmd->rc = VINF_SUCCESS;
+    int rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
+    AssertRC(rc);
+}
+
+void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd)
+{
+    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
+    pCmd->i32Result = VINF_SUCCESS;
+    int rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
+    AssertRC(rc);
+}
+
+typedef struct
+{
+    struct VBOXVDMAHOST *pVdma;
+    VBOXVDMAPIPE_CMD_BODY Cmd;
+    bool bHasCmd;
+} VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT;
+
+DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
+{
+    PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback;
+    struct VBOXVDMAHOST *pVdma = pContext->pVdma;
+    HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->PendingList);
+    if (pEntry)
+    {
+        PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
+        Assert(pPipeCmd);
+        pContext->Cmd = pPipeCmd->Cmd;
+        hgsmiListPrepend(&pVdma->CmdPool.List, pEntry);
+        pContext->bHasCmd = true;
+        return true;
+    }
+
+    pContext->bHasCmd = false;
+    return false;
+}
+
+DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
+{
+    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
+    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
+    VBOXVDMACMD_PROCESS_CONTEXT Context;
+    Context.pVdma = pVdma;
+
+    int rc = vboxVDMAPipeOpenServer(&pVdma->Pipe);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        do
+        {
+            rc = vboxVDMAPipeModifyServer(&pVdma->Pipe, vboxVDMACommandProcessCb, &Context);
+            AssertRC(rc);
+            if (RT_SUCCESS(rc))
+            {
+                switch (Context.Cmd.enmType)
+                {
+                    case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
+                    {
+                        PVBOXVDMACBUF_DR pDr = Context.Cmd.u.pDr;
+                        vboxVDMACommandProcess(pVdma, pDr);
+                        break;
+                    }
+                    case VBOXVDMAPIPE_CMD_TYPE_DMACTL:
+                    {
+                        PVBOXVDMA_CTL pCtl = Context.Cmd.u.pCtl;
+                        vboxVDMAControlProcess(pVdma, pCtl);
+                        break;
+                    }
+                    default:
+                        AssertBreakpoint();
+                        break;
+                }
+
+                if (rc == VINF_EOF)
+                {
+                    rc = VINF_SUCCESS;
+                    break;
+                }
+            }
+            else
+                break;
+        } while (1);
+    }
+
+    /* always try to close the pipe to make sure the client side is notified */
+    int tmpRc = vboxVDMAPipeCloseServer(&pVdma->Pipe);
+    AssertRC(tmpRc);
+    return rc;
+}
+
+int vboxVDMAConstruct(PVGASTATE pVGAState, struct VBOXVDMAHOST **ppVdma, uint32_t cPipeElements)
+{
+    int rc;
+    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ (RT_OFFSETOF(VBOXVDMAHOST, CmdPool.aCmds[cPipeElements]));
+    Assert(pVdma);
+    if (pVdma)
+    {
+        hgsmiListInit(&pVdma->PendingList);
+        pVdma->pHgsmi = pVGAState->pHGSMI;
+
+        rc = vboxVDMAPipeConstruct(&pVdma->Pipe);
+        AssertRC(rc);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
+            AssertRC(rc);
+            if (RT_SUCCESS(rc))
+            {
+                hgsmiListInit(&pVdma->CmdPool.List);
+                pVdma->CmdPool.cCmds = cPipeElements;
+                for (uint32_t i = 0; i < cPipeElements; ++i)
+                {
+                    hgsmiListAppend(&pVdma->CmdPool.List, &pVdma->CmdPool.aCmds[i].Entry);
+                }
+                *ppVdma = pVdma;
+                return VINF_SUCCESS;
+            }
+
+            int tmpRc = vboxVDMAPipeDestruct(&pVdma->Pipe);
+            AssertRC(tmpRc);
+        }
+
+        RTMemFree(pVdma);
+    }
+    else
+        rc = VERR_OUT_OF_RESOURCES;
+
+    return rc;
+}
+
+int vboxVDMADestruct(struct VBOXVDMAHOST **pVdma)
+{
+    AssertBreakpoint();
     return VINF_SUCCESS;
 }
 
-void vboxVDMAControl(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd)
-{
-    PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
+typedef struct
+{
+    struct VBOXVDMAHOST *pVdma;
+    VBOXVDMAPIPE_CMD_BODY Cmd;
+    bool bQueued;
+} VBOXVDMACMD_SUBMIT_CONTEXT, *PVBOXVDMACMD_SUBMIT_CONTEXT;
+
+DECLCALLBACK(bool) vboxVDMACommandSubmitCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
+{
+    PVBOXVDMACMD_SUBMIT_CONTEXT pContext = (PVBOXVDMACMD_SUBMIT_CONTEXT)pvCallback;
+    struct VBOXVDMAHOST *pVdma = pContext->pVdma;
+    HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->CmdPool.List);
+    Assert(pEntry);
+    if (pEntry)
+    {
+        PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
+        pPipeCmd->Cmd = pContext->Cmd;
+        VBoxSHGSMICommandMarkAsynchCompletion(pContext->Cmd.u.pvCmd);
+        pContext->bQueued = true;
+        hgsmiListAppend(&pVdma->PendingList, pEntry);
+        return true;
+    }
+
+    /* @todo: should we try to flush some commands here? */
+    pContext->bQueued = false;
+    return false;
+}
+
+void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd)
+{
+#if 0
+    PHGSMIINSTANCE pIns = pVdma->pHgsmi;
 
     switch (pCmd->enmCtl)
@@ -73,17 +507,62 @@
     }
 
-    int rc = VBoxSHGSMICommandCompleteSynch (pIns, pCmd);
-    AssertRC(rc);
-}
-
-void vboxVDMACommand(PVGASTATE pVGAState, struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd)
-{
-    PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
-    pCmd->rc = VINF_SUCCESS;
-
-    /* @todo: submit command for processing thread */
-
-    int rc = VBoxSHGSMICommandCompleteSynch (pIns, pCmd);
-    AssertRC(rc);
-}
-
+    int rc = VBoxSHGSMICommandComplete (pIns, pCmd);
+    AssertRC(rc);
+#else
+    /* test asinch completion */
+    VBOXVDMACMD_SUBMIT_CONTEXT Context;
+    Context.pVdma = pVdma;
+    Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACTL;
+    Context.Cmd.u.pCtl = pCmd;
+
+    int rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        Assert(Context.bQueued);
+        if (Context.bQueued)
+        {
+            /* success */
+            return;
+        }
+        rc = VERR_OUT_OF_RESOURCES;
+    }
+
+    /* failure */
+    Assert(RT_FAILURE(rc));
+    PHGSMIINSTANCE pIns = pVdma->pHgsmi;
+    pCmd->i32Result = rc;
+    int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
+    AssertRC(tmpRc);
+
+#endif
+}
+
+void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd)
+{
+    VBOXVDMACMD_SUBMIT_CONTEXT Context;
+    Context.pVdma = pVdma;
+    Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACMD;
+    Context.Cmd.u.pDr = pCmd;
+
+    int rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        Assert(Context.bQueued);
+        if (Context.bQueued)
+        {
+            /* success */
+            return;
+        }
+        rc = VERR_OUT_OF_RESOURCES;
+    }
+
+    /* failure */
+    Assert(RT_FAILURE(rc));
+    PHGSMIINSTANCE pIns = pVdma->pHgsmi;
+    pCmd->rc = rc;
+    int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
+    AssertRC(tmpRc);
+}
+
Index: trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHostHlp.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHostHlp.h	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/HGSMI/HGSMIHostHlp.h	(revision 27339)
@@ -40,4 +40,13 @@
 
 void hgsmiListAppend (HGSMILIST *pList, HGSMILISTENTRY *pEntry);
+DECLINLINE(void) hgsmiListPrepend (HGSMILIST *pList, HGSMILISTENTRY *pEntry)
+{
+    HGSMILISTENTRY * pHead = pList->pHead;
+    pList->pHead = pEntry;
+    pEntry->pNext = pHead;
+    if (!pHead)
+        pList->pTail = pEntry;
+}
+
 void hgsmiListRemove (HGSMILIST *pList, HGSMILISTENTRY *pEntry, HGSMILISTENTRY *pPrev);
 
@@ -63,4 +72,45 @@
 HGSMILISTENTRY * hgsmiListRemoveAll (HGSMILIST *pList, HGSMILISTENTRY ** ppTail /* optional */);
 
+DECLINLINE(void) hgsmiListAppendAll (HGSMILIST *pList, HGSMILISTENTRY *pHead, HGSMILISTENTRY *pTail)
+{
+    if(hgsmiListIsEmpty (pList))
+    {
+        pList->pHead = pHead;
+        pList->pTail = pTail;
+    }
+    else
+    {
+        pList->pTail->pNext = pHead;
+        pList->pTail = pTail;
+    }
+}
+
+DECLINLINE(void) hgsmiListPrependAll (HGSMILIST *pList, HGSMILISTENTRY *pHead, HGSMILISTENTRY *pTail)
+{
+    HGSMILISTENTRY *pOldHead = pList->pHead;
+    if(!pOldHead)
+    {
+        pList->pHead = pHead;
+        pList->pTail = pTail;
+    }
+    else
+    {
+        pList->pHead = pHead;
+        pTail->pNext = pOldHead;
+    }
+}
+
+DECLINLINE(void) hgsmiListCat (HGSMILIST *pList, HGSMILIST *pList2)
+{
+    hgsmiListAppendAll (pList, pList2->pHead, pList2->pTail);
+    hgsmiListInit (pList2);
+}
+
+DECLINLINE(void) hgsmiListPrepCat (HGSMILIST *pList, HGSMILIST *pList2)
+{
+    hgsmiListPrependAll (pList, pList2->pHead, pList2->pTail);
+    hgsmiListInit (pList2);
+}
+
 
 #endif /* !__HGSMIHostHlp_h__*/
Index: trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.cpp	(revision 27339)
@@ -40,16 +40,9 @@
 }
 
-int VBoxSHGSMICommandCompleteAsynch (PHGSMIINSTANCE pIns, void *pvData)
+int VBoxSHGSMICommandComplete (PHGSMIINSTANCE pIns, void *pvData)
 {
     PVBOXSHGSMIHEADER pHdr = VBoxSHGSMIBufferHeader (pvData);
-    Assert(!!(pHdr->fFlags & VBOXSHGSMI_FLAG_HG_ASYNCH));
-    return vboxSHGSMICommandCompleteAsynch (pIns, pHdr);
-}
-
-int VBoxSHGSMICommandCompleteSynch (PHGSMIINSTANCE pIns, void *pvData)
-{
-    PVBOXSHGSMIHEADER pHdr = VBoxSHGSMIBufferHeader (pvData);
-    Assert(!(pHdr->fFlags & VBOXSHGSMI_FLAG_HG_ASYNCH));
-    if (vboxSHGSMICommandCanCompleteSynch(pHdr))
+    if (!(pHdr->fFlags & VBOXSHGSMI_FLAG_HG_ASYNCH) /* <- check if synchronous completion */
+            && vboxSHGSMICommandCanCompleteSynch(pHdr)) /* <- check if can complete synchronously */
         return VINF_SUCCESS;
     pHdr->fFlags |= VBOXSHGSMI_FLAG_HG_ASYNCH;
Index: trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h	(revision 27338)
+++ trunk/src/VBox/Devices/Graphics/HGSMI/SHGSMIHost.h	(revision 27339)
@@ -19,9 +19,7 @@
 #include "HGSMIHost.h"
 
-int VBoxSHGSMICommandCompleteAsynch (PHGSMIINSTANCE pIns, void *pvData);
+int VBoxSHGSMICommandComplete (PHGSMIINSTANCE pIns, void *pvData);
 
 void VBoxSHGSMICommandMarkAsynchCompletion (void *pvData);
 
-int VBoxSHGSMICommandCompleteSynch (PHGSMIINSTANCE pIns, void *pvData);
-
 #endif /* #ifndef ___SHGSMIHost_h___ */
