VBoxVideoVdma.cpp revision 04f964d82c1af6d3b6cb05e6abccc20a1e051966
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync * Copyright (C) 2010 Oracle Corporation
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * available from http://www.virtualbox.org. This file is free software;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * General Public License (GPL) as published by the Free Software
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync#include "../Helper.h"
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync KeInitializeEvent(&pPipe->Event, SynchronizationEvent, FALSE);
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
e33247bff4fddfdba92538374bcc9e2753044a38vboxsync bool bNeedNotify = false;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
d46ee884c41b808b239563b1978468aae12e33a2vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync /* ensure the pipe is closed */
d46ee884c41b808b239563b1978468aae12e33a2vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncNTSTATUS vboxVdmaPipeSvrCmdGetList(PVBOXVDMAPIPE pPipe, PLIST_ENTRY pDetachHead)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBOXVDMAPIPE_STATE enmState = VBOXVDMAPIPE_STATE_CLOSED;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync Assert(pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync vboxVideoLeDetach(&pPipe->CmdListHead, pDetachHead);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync } while (1);
fd0cf98cb3eafc5c96b7e95d934b01c5df4785fbvboxsyncNTSTATUS vboxVdmaPipeCltCmdPut(PVBOXVDMAPIPE pPipe, PVBOXVDMAPIPE_CMD_HDR pCmd)
d46ee884c41b808b239563b1978468aae12e33a2vboxsync bool bNeedNotify = false;
358a99c385080f7f31166943f3ac3a2aea6b5263vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync InsertHeadList(&pPipe->CmdListHead, &pCmd->ListEntry);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncPVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXVDMAGG pVdma, uint32_t cbCmd)
358a99c385080f7f31166943f3ac3a2aea6b5263vboxsync return (PVBOXVDMAPIPE_CMD_DR)vboxWddmMemAllocZero(cbCmd);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync * helper function used for system thread creation
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncstatic NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync InitializeObjectAttributes(&fObjectAttributes, NULL, OBJ_KERNEL_HANDLE,
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync fStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS,
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL,
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncDECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const PVBOXWDDM_RECTS_INFO pRects, PVBOXWDDM_RECTS_INFO pResult)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync if (vboxWddmRectIntersection(pArea, &pRects->aRects[i], &pResult->aRects[pResult->cRects]))
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync * @param pDevExt
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncNTSTATUS vboxVdmaGgDirtyRectsProcess(VBOXVDMAPIPE_CMD_RECTSINFO *pRectsInfo)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PVBOXWDDM_RECTS_INFO pRects = &pRectsInfo->UpdateRects;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync uint32_t cbCmd = VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pRects->cRects);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync for (PLIST_ENTRY pCur = pDevExt->ContextList3D.Flink; pCur != &pDevExt->ContextList3D; pCur = pCur->Flink)
fd0cf98cb3eafc5c96b7e95d934b01c5df4785fbvboxsync PVBOXWDDM_CONTEXT pCurContext = VBOXWDDMENTRY_2_CONTEXT(pCur);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync pCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pCurContext->CmContext, cbCmd);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync pCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdReinitForContext(pCmd, &pCurContext->CmContext);
a12929133f77ffa755a13a7d5d2ff3d87c41c9c5vboxsync vboxVdmaDirtyRectsCalcIntersection(&pContext->ViewRect, pRects, &pCmd->RectsInfo);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync vboxVideoCmCmdSubmit(pCmd, VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pCmd->RectsInfo.cRects));
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync bool bRectShanged = (pContext->ViewRect.left != pContextRect->left
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync || pContext->ViewRect.bottom != pContextRect->bottom);
5ff3fa0492332325f57e80636321619e2224027evboxsync uint32_t cbDrCmd = VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pRects->cRects + 1);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pContext->CmContext, cbDrCmd);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdReinitForContext(pCmd, &pContext->CmContext);
5ff3fa0492332325f57e80636321619e2224027evboxsync pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmd);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync memcpy (pDirtyRect, pRects->aRects, sizeof (RECT) * pRects->cRects);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync vboxVideoCmCmdSubmit(pDrCmd, VBOXVIDEOCM_SUBMITSIZE_DEFAULT);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync NTSTATUS Status = vboxVdmaPipeSvrOpen(&pVdma->CmdPipe);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync Status = vboxVdmaPipeSvrCmdGetList(&pVdma->CmdPipe, &CmdList);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync Assert(Status == STATUS_SUCCESS || Status == STATUS_PIPE_CLOSING);
d3bef44ac7674167abeada174f0d6cf0572249c5vboxsync for (PLIST_ENTRY pCur = CmdList.Blink; pCur != &CmdList; pCur = CmdList.Blink)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PVBOXVDMAPIPE_CMD_DR pDr = VBOXVDMAPIPE_CMD_DR_FROM_ENTRY(pCur);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PVBOXVDMAPIPE_CMD_RECTSINFO pRects = (PVBOXVDMAPIPE_CMD_RECTSINFO)pDr;
04ee5d908f45a7883257fa7e40fb42bbdbaf24b9vboxsync } while (1);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync /* always try to close the pipe to make sure the client side is notified */
fd0cf98cb3eafc5c96b7e95d934b01c5df4785fbvboxsync NTSTATUS Status = vboxVdmaPipeConstruct(&pVdma->CmdPipe);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync Status = vboxVdmaGgThreadCreate(&pVdma->pThread, vboxVdmaGgWorkerThread, pVdma);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync NTSTATUS tmpStatus = vboxVdmaPipeDestruct(&pVdma->CmdPipe);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync /* we're here ONLY in case of an error */
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync /* this informs the server thread that it should complete all current commands and exit */
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync NTSTATUS Status = vboxVdmaPipeCltClose(&pVdma->CmdPipe);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
358a99c385080f7f31166943f3ac3a2aea6b5263vboxsyncNTSTATUS vboxVdmaGgCmdPost(PVBOXVDMAGG pVdma, PVBOXVDMAPIPE_CMD_DR pCmd)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync return vboxVdmaPipeCltCmdPut(&pVdma->CmdPipe, &pCmd->PipeHdr);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync * This is currently used by VDMA. It is invisible for Vdma API clients since
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync * Vdma transport may change if we choose to use another (e.g. more light-weight)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync * transport for DMA commands submission
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncstatic int vboxWddmVdmaSubmitVbva(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync if (vboxVbvaBufferBeginUpdate (pDevExt, &pDevExt->u.primary.Vbva))
358a99c385080f7f31166943f3ac3a2aea6b5263vboxsync rc = vboxVbvaReportCmdOffset(pDevExt, &pDevExt->u.primary.Vbva, offDr);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync vboxVbvaBufferEndUpdate (pDevExt, &pDevExt->u.primary.Vbva);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncstatic int vboxWddmVdmaSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncstatic int vboxVdmaInformHost (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
34aaaf212fe61ccafbae15eb832d6062ba548799vboxsync PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
34aaaf212fe61ccafbae15eb832d6062ba548799vboxsync const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
34aaaf212fe61ccafbae15eb832d6062ba548799vboxsync rc = VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync /* fail to submit, cancel it */
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync } while (0);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync VBoxSHGSMICommandFree (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync drprintf((__FUNCTION__": HGSMIHeapAlloc failed\n"));
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync/* create a DMACommand buffer */
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncint vboxVdmaCreate (PDEVICE_EXTENSION pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync drprintf((__FUNCTION__": invalid parameters: offBuffer(0x%x), cbBuffer(0x%x)", offBuffer, cbBuffer));
34aaaf212fe61ccafbae15eb832d6062ba548799vboxsync /* Setup a HGSMI heap within the adapter information area. */
d46ee884c41b808b239563b1978468aae12e33a2vboxsync false /*fOffsetBased*/);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync NTSTATUS Status = vboxVdmaGgConstruct(&pInfo->DmaGg);
d46ee884c41b808b239563b1978468aae12e33a2vboxsync drprintf((__FUNCTION__": HGSMIHeapSetup failed rc = 0x%x\n", rc));
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBoxUnmapAdapterMemory(pDevExt, &pvBuffer, cbBuffer);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync drprintf((__FUNCTION__": VBoxMapAdapterMemory failed rc = 0x%x\n", rc));
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncint vboxVdmaDisable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync /* ensure nothing else is submitted */
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_DISABLE);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncint vboxVdmaEnable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_ENABLE);
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsyncint vboxVdmaFlush (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_FLUSH);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncint vboxVdmaDestroy (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync NTSTATUS Status = vboxVdmaGgDestruct(&pInfo->DmaGg);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBoxUnmapAdapterMemory (pDevExt, (void**)&pInfo->CmdHeap.area.pu8Base, pInfo->CmdHeap.area.cbArea);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncvoid vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncPVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync uint32_t cbDr = VBOXVDMACBUF_DR_SIZE(cbTrailingData);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync drprintf((__FUNCTION__": VBoxSHGSMICommandAlloc returned NULL\n"));
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncstatic DECLCALLBACK(void) vboxVdmaCBufDrCompletion(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync vboxVdmaCBufDrFree (pInfo, (PVBOXVDMACBUF_DR)pvCmd);
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsyncstatic DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext,
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync PFNVBOXSHGSMICMDCOMPLETION *ppfnCompletion, void **ppvCompletion)
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync memset(¬ify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
d46ee884c41b808b239563b1978468aae12e33a2vboxsync PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pDr->u64GuestContext;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync notify.DmaCompleted.SubmissionFenceId = pDr->u32FenceId;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync notify.DmaCompleted.NodeOrdinal = pContext->NodeOrdinal;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync pContext->uLastCompletedCmdFenceId = pDr->u32FenceId;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync pVdma->uLastCompletedPagingBufferCmdFenceId = pDr->u32FenceId;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
d46ee884c41b808b239563b1978468aae12e33a2vboxsync notify.DmaPreempted.PreemptionFenceId = pDr->u32FenceId;
d46ee884c41b808b239563b1978468aae12e33a2vboxsync notify.DmaPreempted.LastCompletedFenceId = pContext->uLastCompletedCmdFenceId;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync notify.DmaPreempted.NodeOrdinal = pContext->NodeOrdinal;
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync notify.DmaPreempted.LastCompletedFenceId = pVdma->uLastCompletedPagingBufferCmdFenceId;
d46ee884c41b808b239563b1978468aae12e33a2vboxsync notify.DmaFaulted.FaultedFenceId = pDr->u32FenceId;
d46ee884c41b808b239563b1978468aae12e33a2vboxsync notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
8cd393943ea52545c4d063f5a94436639f0f80b6vboxsync notify.DmaFaulted.NodeOrdinal = pContext->NodeOrdinal;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
f83c571186f95b28f63a1acb516edaf6ee372419vboxsync /* inform SHGSMI we want to be called at DPC later */
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncint vboxVdmaCBufDrSubmit(PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pInfo->CmdHeap, pHdr);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBoxSHGSMICommandDoneAsynch(&pInfo->CmdHeap, pHdr);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync /* fail to submit, cancel it */
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBoxSHGSMICommandCancelAsynch(&pInfo->CmdHeap, pHdr);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync } while (0);