Index: trunk/src/VBox/Devices/Graphics/DevVGA.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 29707)
+++ trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 29742)
@@ -408,4 +408,10 @@
     /** Base port in the assigned PCI I/O space. */
     RTIOPORT                    IOPortBase;
+#ifdef VBOXVDMA
+    /* specifies guest driver caps, i.e. whether it can handle IRQs from the adapter,
+     * the way it can handle assync HGSMI command completion, etc. */
+    uint32_t                    fGuestCaps;
+#endif
+
     uint8_t                     Padding7[6];
 #endif /* VBOX_WITH_HGSMI */
Index: trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp	(revision 29707)
+++ trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp	(revision 29742)
@@ -1244,62 +1244,72 @@
         PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
         PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
-        VBVAHOSTCMD *pHostCmd;
-    //    Assert(0);
-
-        int32_t iDisplay = pCmd->iDisplay;
+
         Assert(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH);
-        if(pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT)
-        {
-            rc = HGSMIHostCommandAlloc (pIns,
-                                          (void**)&pHostCmd,
-                                          VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT)),
-                                          HGSMI_CH_VBVA,
-                                          VBVAHG_EVENT);
+#ifdef VBOXVDMA
+        if (pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD)
+        {
+            rc = HGSMICompleteGuestCommand(pIns, pCmd, !!(pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ));
             AssertRC(rc);
-            if(RT_SUCCESS(rc))
-            {
-                memset(pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT)));
-                pHostCmd->iDstID = pCmd->iDisplay;
-                pHostCmd->customOpCode = 0;
-                VBVAHOSTCMDEVENT *pBody = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDEVENT);
-                pBody->pEvent = pCmd->GuestVBVAReserved1;
-            }
         }
         else
-        {
-            HGSMIOFFSET offCmd = HGSMIPointerToOffsetHost (pIns, pCmd);
-            Assert(offCmd != HGSMIOFFSET_VOID);
-            if(offCmd != HGSMIOFFSET_VOID)
+#endif
+        {
+            VBVAHOSTCMD *pHostCmd;
+            int32_t iDisplay = pCmd->iDisplay;
+
+            if(pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT)
             {
                 rc = HGSMIHostCommandAlloc (pIns,
-                                          (void**)&pHostCmd,
-                                          VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE)),
-                                          HGSMI_CH_VBVA,
-                                          VBVAHG_DISPLAY_CUSTOM);
+                                              (void**)&pHostCmd,
+                                              VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT)),
+                                              HGSMI_CH_VBVA,
+                                              VBVAHG_EVENT);
                 AssertRC(rc);
                 if(RT_SUCCESS(rc))
                 {
-                    memset(pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE)));
+                    memset(pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDEVENT)));
                     pHostCmd->iDstID = pCmd->iDisplay;
-                    pHostCmd->customOpCode = VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE;
-                    VBVAHOSTCMDVHWACMDCOMPLETE *pBody = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDVHWACMDCOMPLETE);
-                    pBody->offCmd = offCmd;
+                    pHostCmd->customOpCode = 0;
+                    VBVAHOSTCMDEVENT *pBody = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDEVENT);
+                    pBody->pEvent = pCmd->GuestVBVAReserved1;
                 }
             }
             else
             {
-                rc = VERR_INVALID_PARAMETER;
-            }
-        }
-
-        if(RT_SUCCESS(rc))
-        {
-            rc = HGSMIHostCommandProcessAndFreeAsynch(pIns, pHostCmd, (pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ) != 0);
-            AssertRC(rc);
+                HGSMIOFFSET offCmd = HGSMIPointerToOffsetHost (pIns, pCmd);
+                Assert(offCmd != HGSMIOFFSET_VOID);
+                if(offCmd != HGSMIOFFSET_VOID)
+                {
+                    rc = HGSMIHostCommandAlloc (pIns,
+                                              (void**)&pHostCmd,
+                                              VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE)),
+                                              HGSMI_CH_VBVA,
+                                              VBVAHG_DISPLAY_CUSTOM);
+                    AssertRC(rc);
+                    if(RT_SUCCESS(rc))
+                    {
+                        memset(pHostCmd, 0 , VBVAHOSTCMD_SIZE(sizeof(VBVAHOSTCMDVHWACMDCOMPLETE)));
+                        pHostCmd->iDstID = pCmd->iDisplay;
+                        pHostCmd->customOpCode = VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE;
+                        VBVAHOSTCMDVHWACMDCOMPLETE *pBody = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDVHWACMDCOMPLETE);
+                        pBody->offCmd = offCmd;
+                    }
+                }
+                else
+                {
+                    rc = VERR_INVALID_PARAMETER;
+                }
+            }
+
             if(RT_SUCCESS(rc))
             {
-                return rc;
-            }
-            HGSMIHostCommandFree (pIns, pHostCmd);
+                rc = HGSMIHostCommandProcessAndFreeAsynch(pIns, pHostCmd, (pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ) != 0);
+                AssertRC(rc);
+                if(RT_SUCCESS(rc))
+                {
+                    return rc;
+                }
+                HGSMIHostCommandFree (pIns, pHostCmd);
+            }
         }
     }
@@ -1621,4 +1631,18 @@
 #endif
 
+#ifdef VBOXVDMA
+        case VBVA_INFO_CAPS:
+        {
+            if (cbBuffer < sizeof (VBVACAPS))
+            {
+                rc = VERR_INVALID_PARAMETER;
+                break;
+            }
+
+            VBVACAPS *pCaps = (VBVACAPS*)pvBuffer;
+            pVGAState->fGuestCaps = pCaps->fCaps;
+            pCaps->rc = VINF_SUCCESS;
+        } break;
+#endif
         default:
             Log(("Unsupported VBVA guest command %d!!!\n",
