VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp@ 69496

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.2 KB
Line 
1/* $Id: VBoxMPCr.cpp 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2012-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#ifdef VBOX_WITH_CROGL
18
19#include "VBoxMPWddm.h"
20#include "VBoxMPCr.h"
21
22#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
23
24#include <cr_protocol.h>
25
26CR_CAPS_INFO g_VBoxMpCrHostCapsInfo;
27static uint32_t g_VBoxMpCr3DSupported = 0;
28
29uint32_t VBoxMpCrGetHostCaps(void)
30{
31 return g_VBoxMpCrHostCapsInfo.u32Caps;
32}
33
34bool VBoxMpCrCtlConIs3DSupported(void)
35{
36 return !!g_VBoxMpCr3DSupported;
37}
38
39static void* vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
40{
41 return VBoxSHGSMIHeapBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, cbData);
42}
43
44static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
45{
46 return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area,
47 (const HGSMIBUFFERHEADER *)pvBuffer);
48}
49
50static void* vboxMpCrShgsmiBufferFromOffset(PVBOXMP_DEVEXT pDevExt, VBOXVIDEOOFFSET offBuffer)
51{
52 return HGSMIOffsetToPointer(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (HGSMIOFFSET)offBuffer);
53}
54
55static void vboxMpCrShgsmiBufferFree(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
56{
57 VBoxSHGSMIHeapBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pvBuffer);
58}
59
60static VBOXVIDEOOFFSET vboxMpCrShgsmiTransportBufOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, void* pvBuffer)
61{
62 return vboxMpCrShgsmiBufferOffset(pCon->pDevExt, pvBuffer);
63}
64
65static void* vboxMpCrShgsmiTransportBufFromOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVIDEOOFFSET offBuffer)
66{
67 return vboxMpCrShgsmiBufferFromOffset(pCon->pDevExt, offBuffer);
68}
69
70void* VBoxMpCrShgsmiTransportBufAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t cbBuffer)
71{
72 return vboxMpCrShgsmiBufferAlloc(pCon->pDevExt, cbBuffer);
73}
74
75void VBoxMpCrShgsmiTransportBufFree(PVBOXMP_CRSHGSMITRANSPORT pCon, void* pvBuffer)
76{
77 vboxMpCrShgsmiBufferFree(pCon->pDevExt, pvBuffer);
78}
79
80static int vboxMpCrShgsmiBufCacheBufReinit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache,
81 PVBOXMP_CRSHGSMICON_BUFDR pDr, uint32_t cbRequested)
82{
83 RT_NOREF(pCache);
84 if (pDr->cbBuf >= cbRequested)
85 return VINF_SUCCESS;
86
87 if (pDr->pvBuf)
88 VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
89
90 pDr->pvBuf = VBoxMpCrShgsmiTransportBufAlloc(pCon, cbRequested);
91 if (!pDr->pvBuf)
92 {
93 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed"));
94 pDr->cbBuf = 0;
95 return VERR_NO_MEMORY;
96 }
97
98 pDr->cbBuf = cbRequested;
99 return VINF_SUCCESS;
100}
101
102static void vboxMpCrShgsmiBufCacheFree(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache,
103 PVBOXMP_CRSHGSMICON_BUFDR pDr)
104{
105 if (ASMAtomicCmpXchgPtr(&pCache->pBufDr, pDr, NULL))
106 return;
107
108 /* the value is already cached, free the current one */
109 VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
110 vboxWddmMemFree(pDr);
111}
112
113static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheGetAllocDr(PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
114{
115 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = (PVBOXMP_CRSHGSMICON_BUFDR)ASMAtomicXchgPtr((void * volatile *)&pCache->pBufDr, NULL);
116 if (!pBufDr)
117 {
118 pBufDr = (PVBOXMP_CRSHGSMICON_BUFDR)vboxWddmMemAllocZero(sizeof (*pBufDr));
119 if (!pBufDr)
120 {
121 WARN(("vboxWddmMemAllocZero failed!"));
122 return NULL;
123 }
124 }
125 return pBufDr;
126}
127
128static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon,
129 PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
130{
131 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
132 int rc = vboxMpCrShgsmiBufCacheBufReinit(pCon, pCache, pBufDr, cbBuffer);
133 if (RT_SUCCESS(rc))
134 return pBufDr;
135
136 WARN(("vboxMpCrShgsmiBufCacheBufReinit failed, rc %d", rc));
137
138 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pBufDr);
139 return NULL;
140}
141
142static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAllocAny(PVBOXMP_CRSHGSMITRANSPORT pCon,
143 PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
144{
145 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
146
147 if (pBufDr->cbBuf)
148 return pBufDr;
149
150 int rc = vboxMpCrShgsmiBufCacheBufReinit(pCon, pCache, pBufDr, cbBuffer);
151 if (RT_SUCCESS(rc))
152 return pBufDr;
153
154 WARN(("vboxMpCrShgsmiBufCacheBufReinit failed, rc %d", rc));
155
156 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pBufDr);
157 return NULL;
158}
159
160
161static int vboxMpCrShgsmiBufCacheInit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
162{
163 RT_NOREF(pCon);
164 memset(pCache, 0, sizeof (*pCache));
165 return VINF_SUCCESS;
166}
167
168static void vboxMpCrShgsmiBufCacheTerm(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
169{
170 if (pCache->pBufDr)
171 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pCache->pBufDr);
172}
173
174int VBoxMpCrShgsmiTransportCreate(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_DEVEXT pDevExt)
175{
176 memset(pCon, 0, sizeof (*pCon));
177 pCon->pDevExt = pDevExt;
178 return VINF_SUCCESS;
179#if 0 /** @todo should this be unreachable? */
180 int rc;
181// int rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->CmdDrCache);
182// if (RT_SUCCESS(rc))
183 {
184 rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->WbDrCache);
185 if (RT_SUCCESS(rc))
186 {
187 }
188 else
189 {
190 WARN(("vboxMpCrShgsmiBufCacheInit2 failed rc %d", rc));
191 }
192// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
193 }
194// else
195// {
196// WARN(("vboxMpCrShgsmiBufCacheInit1 failed rc %d", rc));
197// }
198
199 return rc;
200#endif
201}
202
203void VBoxMpCrShgsmiTransportTerm(PVBOXMP_CRSHGSMITRANSPORT pCon)
204{
205 vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->WbDrCache);
206// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
207}
208
209typedef struct VBOXMP_CRHGSMICMD_BASE
210{
211// VBOXMP_CRHGSMICMD_HDR Hdr;
212 CRVBOXHGSMIHDR CmdHdr;
213} VBOXMP_CRHGSMICMD_BASE, *PVBOXMP_CRHGSMICMD_BASE;
214
215typedef struct VBOXMP_CRHGSMICMD_WRITEREAD
216{
217// VBOXMP_CRHGSMICMD_HDR Hdr;
218 CRVBOXHGSMIWRITEREAD Cmd;
219} VBOXMP_CRHGSMICMD_WRITEREAD, *PVBOXMP_CRHGSMICMD_WRITEREAD;
220
221typedef struct VBOXMP_CRHGSMICMD_READ
222{
223// VBOXMP_CRHGSMICMD_HDR Hdr;
224 CRVBOXHGSMIREAD Cmd;
225} VBOXMP_CRHGSMICMD_READ, *PVBOXMP_CRHGSMICMD_READ;
226
227typedef struct VBOXMP_CRHGSMICMD_WRITE
228{
229// VBOXMP_CRHGSMICMD_HDR Hdr;
230 CRVBOXHGSMIWRITE Cmd;
231} VBOXMP_CRHGSMICMD_WRITE, *PVBOXMP_CRHGSMICMD_WRITE;
232
233
234#define VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers) \
235 VBOXWDDM_ROUNDBOUND(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]), 8)
236#define VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) \
237 ( VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers) + VBOXWDDM_ROUNDBOUND(_cbCmdBuf, 8))
238#define VBOXMP_CRSHGSMICON_CMD_GET_CMDBUF(_pCmd, _cBuffers, _type) \
239 ((_type*)(((uint8_t*)(_pCmd)) + VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers)))
240#define VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(_pCmd, _cBuffers, _cbCmdBuf, _type) \
241 ((_type*)(((uint8_t*)(_pCmd)) + VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
242#define VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(_pCtx, _cBuffers, _cbCmdBuf, _type) \
243 ((_type*)(((uint8_t*)(_pCtx)) - VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
244#define VBOXMP_CRSHGSMICON_CMD_SIZE(_cBuffers, _cbCmdBuf, _cbCtx) \
245 (VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) + (_cbCtx))
246
247
248#define VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) \
249 VBOXWDDM_ROUNDBOUND((VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]))), 8)
250#define VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) \
251 ( VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) + VBOXWDDM_ROUNDBOUND(_cbCmdBuf, 8))
252#define VBOXMP_CRSHGSMICON_DR_GET_CRCMD(_pDr) \
253 (VBOXVDMACMD_BODY((_pDr), VBOXVDMACMD_CHROMIUM_CMD))
254#define VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(_pDr, _cBuffers, _type) \
255 ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers)))
256#define VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(_pDr, _cBuffers, _cbCmdBuf, _type) \
257 ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
258#define VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(_pCtx, _cBuffers, _cbCmdBuf) \
259 ((VBOXVDMACMD*)(((uint8_t*)(_pCtx)) - VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
260#define VBOXMP_CRSHGSMICON_DR_SIZE(_cBuffers, _cbCmdBuf, _cbCtx) \
261 (VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) + (_cbCtx))
262
263
264static int vboxMpCrShgsmiTransportCmdSubmitDr(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACBUF_DR pDr,
265 PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
266{
267
268 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
269 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
270 vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, pfnComplete, pCon);
271 /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
272 vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
273 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
274 if (RT_SUCCESS(rc))
275 {
276 return VINF_SUCCESS;
277 }
278
279 WARN(("vboxVdmaCBufDrSubmit failed rc %d", rc));
280 return rc;
281}
282
283static int vboxMpCrShgsmiTransportCmdSubmitDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACMD pHdr,
284 PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
285{
286 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
287 return vboxMpCrShgsmiTransportCmdSubmitDr(pCon, pDr, pfnComplete);
288}
289
290static void vboxMpCrShgsmiTransportCmdTermDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACMD pHdr)
291{
292 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
293 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
294 vboxVdmaCBufDrFree (&pDevExt->u.primary.Vdma, pDr);
295}
296
297
298typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc,
299 void *pvRx, uint32_t cbRx, void *pvCtx);
300typedef FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION *PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION;
301
302static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
303 PVOID pvContext)
304{
305 RT_NOREF(pDevExt);
306 /* we should be called from our DPC routine */
307 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
308
309 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
310 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
311 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
312 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
313 const UINT cBuffers = 2;
314 Assert(pBody->cBuffers == cBuffers);
315 PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
316 CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
317 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
318 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIREAD));
319 CRVBOXHGSMIREAD * pWr = (CRVBOXHGSMIREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
320 PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION)pBufCmd->u64GuestData;
321 VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[1];
322 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
323 void *pvRx = NULL;
324 uint32_t cbRx = 0;
325
326 int rc = pDr->rc;
327 if (RT_SUCCESS(rc))
328 {
329 rc = pWr->hdr.result;
330 if (RT_SUCCESS(rc))
331 {
332 cbRx = pCmd->cbBuffer;
333 if (cbRx)
334 pvRx = pWbDr->pvBuf;
335 }
336 else
337 {
338 WARN(("CRVBOXHGSMIREAD failed, rc %d", rc));
339 }
340 }
341 else
342 {
343 WARN(("dma command buffer failed rc %d!", rc));
344 }
345
346 if (pfnCompletion)
347 {
348 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
349 pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
350 }
351
352 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
353}
354
355static void* vboxMpCrShgsmiTransportCmdCreateReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, PVBOXVDMACBUF_DR pDr,
356 uint32_t cbDrData, PVBOXMP_CRSHGSMICON_BUFDR pWbDr,
357 PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion,
358 uint32_t cbContextData)
359{
360 RT_NOREF(cbDrData);
361 const uint32_t cBuffers = 2;
362 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), cbContextData);
363 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
364 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
365 PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
366 CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
367
368 if (cbCmd > cbContextData)
369 {
370 ERR(("the passed descriptor is less than needed!"));
371 return NULL;
372 }
373
374 memset(pDr, 0, VBOXVDMACBUF_DR_SIZE(cbCmd));
375
376 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET;
377 pDr->cbBuf = cbCmd;
378 pDr->rc = VERR_NOT_IMPLEMENTED;
379 pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
380
381 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
382 pHdr->u32CmdSpecific = 0;
383
384 pBody->cBuffers = cBuffers;
385
386 pCmd->hdr.result = VERR_WRONG_ORDER;
387 pCmd->hdr.u32ClientID = u32ClientID;
388 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
389 // pCmd->hdr.u32Reserved = 0;
390 pCmd->iBuffer = 1;
391
392 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
393 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
394 pBufCmd->cbBuffer = sizeof (*pCmd);
395 pBufCmd->u32GuestData = 0;
396 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
397
398 pBufCmd = &pBody->aBuffers[1];
399 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
400 pBufCmd->cbBuffer = pWbDr->cbBuf;
401 pBufCmd->u32GuestData = 0;
402 pBufCmd->u64GuestData = (uintptr_t)pWbDr;
403
404 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
405}
406
407static int vboxMpCrShgsmiTransportCmdSubmitReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
408{
409 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_READ));
410 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendReadAsyncCompletion);
411}
412
413typedef struct VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX
414{
415 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion;
416 void *pvContext;
417
418} VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX, *PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX;
419
420static DECLCALLBACK(void) vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc,
421 void *pvRx, uint32_t cbRx, void *pvCtx)
422{
423 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pData = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)pvCtx;
424 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = pData->pfnCompletion;
425 if (pfnCompletion)
426 pfnCompletion(pCon, rc, pvRx, cbRx, pData->pvContext);
427}
428
429static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
430 PVOID pvContext)
431{
432 RT_NOREF(pDevExt);
433 /* we should be called from our DPC routine */
434 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
435
436 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
437 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
438 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
439 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
440 const UINT cBuffers = 3;
441 Assert(pBody->cBuffers == cBuffers);
442 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
443 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
444 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
445 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITEREAD));
446 CRVBOXHGSMIWRITEREAD * pWr = (CRVBOXHGSMIWRITEREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
447 VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[2];
448 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
449 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION)pBufCmd->u64GuestData;
450 void *pvRx = NULL;
451 uint32_t cbRx = 0;
452
453 int rc = pDr->rc;
454 if (RT_SUCCESS(rc))
455 {
456 rc = pWr->hdr.result;
457 if (RT_SUCCESS(rc))
458 {
459 cbRx = pCmd->cbWriteback;
460 if (cbRx)
461 pvRx = pWbDr->pvBuf;
462 }
463 else if (rc == VERR_BUFFER_OVERFLOW)
464 {
465 /* issue read */
466 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
467 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
468 pWbDr = vboxMpCrShgsmiBufCacheAlloc(pCon, &pCon->WbDrCache, pCmd->cbWriteback);
469 if (pWbDr)
470 {
471 /* the Read Command is shorter than WriteRead, so just reuse the Write-Read descriptor here */
472 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pReadCtx;
473 pReadCtx = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)vboxMpCrShgsmiTransportCmdCreateReadAsync(pCon,
474 pCmd->hdr.u32ClientID,
475 pDr,
476 VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof(VBOXMP_CRHGSMICMD_WRITEREAD), 0),
477 pWbDr,
478 vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion,
479 sizeof(*pReadCtx));
480 pReadCtx->pfnCompletion = pfnCompletion;
481 pReadCtx->pvContext = pvCtx;
482 vboxMpCrShgsmiTransportCmdSubmitReadAsync(pCon, pReadCtx);
483 /* don't do completion here, the completion will be called from the read completion we issue here */
484 pfnCompletion = NULL;
485 /* the current pWbDr was already freed, and we'll free the Read dr in the Read Completion */
486 pWbDr = NULL;
487 }
488 else
489 {
490 WARN(("vboxMpCrShgsmiBufCacheAlloc failed for %d", pCmd->cbWriteback));
491 rc = VERR_NO_MEMORY;
492 }
493 }
494 else
495 {
496 WARN(("CRVBOXHGSMIWRITEREAD failed, rc %d", rc));
497 }
498 }
499 else
500 {
501 WARN(("dma command buffer failed rc %d!", rc));
502 }
503
504 if (pfnCompletion)
505 {
506 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
507 pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
508 }
509
510 if (pWbDr)
511 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
512}
513
514static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
515 PVOID pvContext)
516{
517 RT_NOREF(pDevExt);
518 /* we should be called from our DPC routine */
519 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
520
521 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
522 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
523 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
524 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
525 const UINT cBuffers = 2;
526 Assert(pBody->cBuffers == cBuffers);
527 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
528 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
529 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
530 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITE));
531 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)pBufCmd->u64GuestData;
532
533 int rc = pDr->rc;
534 if (RT_SUCCESS(rc))
535 {
536 rc = pCmd->hdr.result;
537 if (!RT_SUCCESS(rc))
538 {
539 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
540 }
541 }
542 else
543 {
544 WARN(("dma command buffer failed rc %d!", rc));
545 }
546
547 if (pfnCompletion)
548 {
549 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
550 pfnCompletion(pCon, rc, pvCtx);
551 }
552}
553
554static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext)
555{
556 RT_NOREF(pHeap);
557 /* we should be called from our DPC routine */
558 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
559
560 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
561 VBOXCMDVBVA_CRCMD_CMD *pCmd;
562 int rc = VBoxCmdVbvaConCmdCompletionData(pvCmd, &pCmd);
563 const UINT cBuffers = 2;
564 Assert(pCmd->cBuffers == cBuffers);
565 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
566 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)(*pu64Completion);
567
568 if (!RT_SUCCESS(rc))
569 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
570
571 if (pfnCompletion)
572 pfnCompletion(pCon, rc, (void*)(pu64Completion+1));
573}
574
575void* VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
576 uint32_t cbBuffer,
577 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion,
578 uint32_t cbContextData)
579{
580 const uint32_t cBuffers = 3;
581 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), cbContextData);
582 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
583 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
584 if (!pDr)
585 {
586 WARN(("vboxVdmaCBufDrCreate failed"));
587 return NULL;
588 }
589
590 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = vboxMpCrShgsmiBufCacheAllocAny(pCon, &pCon->WbDrCache, 1000);
591 if (!pWbDr)
592 {
593 WARN(("vboxMpCrShgsmiBufCacheAlloc for wb dr failed"));
594 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
595 return NULL;
596 }
597
598 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
599 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
600 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
601 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
602
603 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
604 pDr->cbBuf = cbCmd;
605 pDr->rc = VERR_NOT_IMPLEMENTED;
606// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
607
608
609 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
610 pHdr->u32CmdSpecific = 0;
611
612 pBody->cBuffers = cBuffers;
613
614 pCmd->hdr.result = VERR_WRONG_ORDER;
615 pCmd->hdr.u32ClientID = u32ClientID;
616 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
617 // pCmd->hdr.u32Reserved = 0;
618 pCmd->iBuffer = 1;
619 pCmd->iWriteback = 2;
620 pCmd->cbWriteback = 0;
621
622 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
623 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
624 pBufCmd->cbBuffer = sizeof (*pCmd);
625 pBufCmd->u32GuestData = 0;
626 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
627
628 pBufCmd = &pBody->aBuffers[1];
629 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pvBuffer);
630 pBufCmd->cbBuffer = cbBuffer;
631 pBufCmd->u32GuestData = 0;
632 pBufCmd->u64GuestData = 0;
633
634 pBufCmd = &pBody->aBuffers[2];
635 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
636 pBufCmd->cbBuffer = pWbDr->cbBuf;
637 pBufCmd->u32GuestData = 0;
638 pBufCmd->u64GuestData = (uintptr_t)pWbDr;
639
640 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
641}
642
643static void * vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
644 uint32_t cbBuffer,
645 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
646 uint32_t cbContextData)
647{
648 const uint32_t cBuffers = 2;
649 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_CMD_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8, cbContextData);
650 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBoxCmdVbvaConCmdAlloc(pDevExt, cbCmd);
651 if (!pCmd)
652 {
653 WARN(("VBoxCmdVbvaConCmdAlloc failed"));
654 return NULL;
655 }
656
657 pCmd->cBuffers = cBuffers;
658
659 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_CMD_GET_CMDBUF(pCmd, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
660 CRVBOXHGSMIWRITE *pCmdWrite = &pWrData->Cmd;
661
662 pCmdWrite->hdr.result = VERR_WRONG_ORDER;
663 pCmdWrite->hdr.u32ClientID = u32ClientID;
664 pCmdWrite->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
665 // pCmdWrite->hdr.u32Reserved = 0;
666 pCmdWrite->iBuffer = 1;
667
668 VBOXCMDVBVA_CRCMD_BUFFER *pBufCmd = &pCmd->aBuffers[0];
669 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pCmdWrite);
670 pBufCmd->cbBuffer = sizeof (*pCmdWrite);
671
672 pBufCmd = &pCmd->aBuffers[1];
673 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
674 pBufCmd->cbBuffer = cbBuffer;
675
676 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
677 *pu64Completion = (uintptr_t)pfnCompletion;
678 return pu64Completion + 1;
679}
680
681void* vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
682 uint32_t cbBuffer,
683 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
684 uint32_t cbContextData)
685{
686 const uint32_t cBuffers = 2;
687 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), cbContextData);
688 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
689 if (!pDr)
690 {
691 WARN(("vboxVdmaCBufDrCreate failed"));
692 return NULL;
693 }
694
695 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
696 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
697 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
698 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
699
700 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
701 pDr->cbBuf = cbCmd;
702 pDr->rc = VERR_NOT_IMPLEMENTED;
703// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
704
705 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
706 pHdr->u32CmdSpecific = 0;
707
708 pBody->cBuffers = cBuffers;
709
710 pCmd->hdr.result = VERR_WRONG_ORDER;
711 pCmd->hdr.u32ClientID = u32ClientID;
712 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
713 // pCmd->hdr.u32Reserved = 0;
714 pCmd->iBuffer = 1;
715
716 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
717 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
718 pBufCmd->cbBuffer = sizeof (*pCmd);
719 pBufCmd->u32GuestData = 0;
720 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
721
722 pBufCmd = &pBody->aBuffers[1];
723 pBufCmd->offBuffer = vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
724 pBufCmd->cbBuffer = cbBuffer;
725 pBufCmd->u32GuestData = 0;
726 pBufCmd->u64GuestData = 0;
727
728 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
729}
730
731void* VBoxMpCrShgsmiTransportCmdCreateWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
732 uint32_t cbBuffer,
733 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
734 uint32_t cbContextData)
735{
736 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
737 if (pDevExt->fCmdVbvaEnabled)
738 return vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion,
739 cbContextData);
740 return vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion, cbContextData);
741}
742
743int VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
744{
745 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
746 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion);
747}
748
749static int vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
750{
751 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
752 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion);
753}
754
755static int vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
756{
757 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
758 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
759 VBOXCMDVBVA_CRCMD_CMD);
760 return VBoxCmdVbvaConCmdSubmitAsync(pDevExt, pCmd, vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion, pCon);
761}
762
763int VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
764{
765 if (pCon->pDevExt->fCmdVbvaEnabled)
766 return vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(pCon, pvContext);
767 return vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(pCon, pvContext);
768}
769
770void VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
771{
772 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
773 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
774}
775
776static void vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
777{
778 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
779 VBOXCMDVBVA_CRCMD_CMD);
780 VBoxCmdVbvaConCmdFree(pCon->pDevExt, pCmd);
781}
782
783static void vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
784{
785 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
786 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
787}
788
789void VBoxMpCrShgsmiTransportCmdTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
790{
791 if (pCon->pDevExt->fCmdVbvaEnabled)
792 vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(pCon, pvContext);
793 else
794 vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(pCon, pvContext);
795}
796
797static int vboxMpCrCtlAddRef(PVBOXMP_CRCTLCON pCrCtlCon)
798{
799 if (pCrCtlCon->cCrCtlRefs++)
800 return VINF_ALREADY_INITIALIZED;
801
802 int rc = VbglR0CrCtlCreate(&pCrCtlCon->hCrCtl);
803 if (RT_SUCCESS(rc))
804 {
805 Assert(pCrCtlCon->hCrCtl);
806 return VINF_SUCCESS;
807 }
808
809 WARN(("vboxCrCtlCreate failed, rc (%d)", rc));
810
811 --pCrCtlCon->cCrCtlRefs;
812 return rc;
813}
814
815static int vboxMpCrCtlRelease(PVBOXMP_CRCTLCON pCrCtlCon)
816{
817 Assert(pCrCtlCon->cCrCtlRefs);
818 if (--pCrCtlCon->cCrCtlRefs)
819 {
820 return VINF_SUCCESS;
821 }
822
823 int rc = VbglR0CrCtlDestroy(pCrCtlCon->hCrCtl);
824 if (RT_SUCCESS(rc))
825 {
826 pCrCtlCon->hCrCtl = NULL;
827 return VINF_SUCCESS;
828 }
829
830 WARN(("vboxCrCtlDestroy failed, rc (%d)", rc));
831
832 ++pCrCtlCon->cCrCtlRefs;
833 return rc;
834}
835
836static int vboxMpCrCtlConSetVersion(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
837{
838 CRVBOXHGCMSETVERSION parms;
839 int rc;
840
841 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_VERSION, SHCRGL_CPARMS_SET_VERSION);
842
843 parms.vMajor.type = VMMDevHGCMParmType_32bit;
844 parms.vMajor.u.value32 = vMajor;
845 parms.vMinor.type = VMMDevHGCMParmType_32bit;
846 parms.vMinor.u.value32 = vMinor;
847
848 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
849 if (RT_FAILURE(rc))
850 WARN(("vboxCrCtlConCall/SET_VERSION failed, rc = %Rrc", rc));
851 return rc;
852}
853
854static int vboxMpCrCtlConGetCapsLegacy(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t *pu32Caps)
855{
856 CRVBOXHGCMGETCAPS parms;
857 int rc;
858
859 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_LEGACY, SHCRGL_CPARMS_GET_CAPS_LEGACY);
860
861 parms.Caps.type = VMMDevHGCMParmType_32bit;
862 parms.Caps.u.value32 = 0;
863
864 *pu32Caps = 0;
865
866 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
867 if (RT_FAILURE(rc))
868 {
869 WARN(("vboxCrCtlConCall/GET_CAPS_LEAGCY failed, rc=%Rrc", rc));
870 return rc;
871 }
872
873 /* if host reports it supports CR_VBOX_CAP_CMDVBVA, clean it up,
874 * we only support CR_VBOX_CAP_CMDVBVA of the proper version reported by SHCRGL_GUEST_FN_GET_CAPS_NEW */
875 parms.Caps.u.value32 &= ~CR_VBOX_CAP_CMDVBVA;
876
877 *pu32Caps = parms.Caps.u.value32;
878
879 return VINF_SUCCESS;
880}
881
882static int vboxMpCrCtlConGetCapsNew(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, CR_CAPS_INFO *pCapsInfo)
883{
884 pCapsInfo->u32Caps = CR_VBOX_CAPS_ALL;
885 pCapsInfo->u32CmdVbvaVersion = CR_CMDVBVA_VERSION;
886
887 CRVBOXHGCMGETCAPS parms;
888 int rc;
889
890 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_NEW, SHCRGL_CPARMS_GET_CAPS_NEW);
891
892 parms.Caps.type = VMMDevHGCMParmType_LinAddr;
893 parms.Caps.u.Pointer.u.linearAddr = (uintptr_t)pCapsInfo;
894 parms.Caps.u.Pointer.size = sizeof (*pCapsInfo);
895
896 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
897 if (RT_FAILURE(rc))
898 {
899 WARN(("vboxCrCtlConCall/GET_CAPS_NEW failed, rc=%Rrc", rc));
900 return rc;
901 }
902
903 if (pCapsInfo->u32CmdVbvaVersion != CR_CMDVBVA_VERSION)
904 {
905 WARN(("CmdVbva version mismatch (%d), expected(%d)", pCapsInfo->u32CmdVbvaVersion, CR_CMDVBVA_VERSION));
906 pCapsInfo->u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
907 }
908
909 pCapsInfo->u32Caps &= CR_VBOX_CAPS_ALL;
910
911 return VINF_SUCCESS;
912}
913
914static int vboxMpCrCtlConSetPID(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
915{
916 CRVBOXHGCMSETPID parms;
917 int rc;
918
919 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_PID, SHCRGL_CPARMS_SET_PID);
920
921 parms.u64PID.type = VMMDevHGCMParmType_64bit;
922 parms.u64PID.u.value64 = (uintptr_t)PsGetCurrentProcessId();
923
924 Assert(parms.u64PID.u.value64);
925
926 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
927 if (RT_FAILURE(rc))
928 WARN(("vboxCrCtlConCall/SET_PIDfailed, rc=%Rrc", rc));
929 return rc;
930}
931
932int VBoxMpCrCtlConConnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon,
933 uint32_t crVersionMajor, uint32_t crVersionMinor,
934 uint32_t *pu32ClientID)
935{
936 uint32_t u32ClientID;
937 int rc = vboxMpCrCtlAddRef(pCrCtlCon);
938 if (RT_SUCCESS(rc))
939 {
940 rc = VbglR0CrCtlConConnect(pCrCtlCon->hCrCtl, &u32ClientID);
941 if (RT_SUCCESS(rc))
942 {
943 rc = vboxMpCrCtlConSetVersion(pCrCtlCon, u32ClientID, crVersionMajor, crVersionMinor);
944 if (RT_SUCCESS(rc))
945 {
946 rc = vboxMpCrCtlConSetPID(pCrCtlCon, u32ClientID);
947 if (RT_SUCCESS(rc))
948 {
949 *pu32ClientID = u32ClientID;
950 return VINF_SUCCESS;
951 }
952 else
953 {
954 WARN(("vboxMpCrCtlConSetPID failed, rc (%d)", rc));
955 }
956 }
957 else
958 {
959 WARN(("vboxMpCrCtlConSetVersion failed, rc (%d)", rc));
960 }
961 VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
962 }
963 else
964 {
965 WARN(("vboxCrCtlConConnect failed, rc (%d)", rc));
966 }
967 vboxMpCrCtlRelease(pCrCtlCon);
968 }
969 else
970 {
971 WARN(("vboxMpCrCtlAddRef failed, rc (%d)", rc));
972 }
973
974 *pu32ClientID = 0;
975 Assert(RT_FAILURE(rc));
976 return rc;
977}
978
979int VBoxMpCrCtlConConnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
980 uint32_t crVersionMajor, uint32_t crVersionMinor,
981 uint32_t *pu32ClientID)
982{
983 if (pCrCtlCon->hCrCtl)
984 {
985 WARN(("pCrCtlCon is HGCM connection"));
986 return VERR_INVALID_STATE;
987 }
988
989 Assert(!pCrCtlCon->cCrCtlRefs);
990 return VBoxCmdVbvaConConnect(pDevExt, &pDevExt->CmdVbva,
991 crVersionMajor, crVersionMinor,
992 pu32ClientID);
993}
994
995int VBoxMpCrCtlConConnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
996 uint32_t crVersionMajor, uint32_t crVersionMinor,
997 uint32_t *pu32ClientID)
998{
999 if (pDevExt->fCmdVbvaEnabled)
1000 {
1001 return VBoxMpCrCtlConConnectVbva(pDevExt, pCrCtlCon,
1002 crVersionMajor, crVersionMinor,
1003 pu32ClientID);
1004 }
1005 return VBoxMpCrCtlConConnectHgcm(pCrCtlCon,
1006 crVersionMajor, crVersionMinor,
1007 pu32ClientID);
1008}
1009
1010int VBoxMpCrCtlConDisconnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1011{
1012 int rc = VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
1013 if (RT_SUCCESS(rc))
1014 {
1015 vboxMpCrCtlRelease(pCrCtlCon);
1016 return VINF_SUCCESS;
1017 }
1018 WARN(("vboxCrCtlConDisconnect failed, rc (%d)", rc));
1019 return rc;
1020}
1021
1022int VBoxMpCrCtlConDisconnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1023{
1024 RT_NOREF(pDevExt, pCrCtlCon);
1025 Assert(!pCrCtlCon->hCrCtl);
1026 Assert(!pCrCtlCon->cCrCtlRefs);
1027 return VBoxCmdVbvaConDisconnect(pDevExt, &pDevExt->CmdVbva, u32ClientID);
1028}
1029
1030int VBoxMpCrCtlConDisconnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1031{
1032 if (!pCrCtlCon->hCrCtl)
1033 return VBoxMpCrCtlConDisconnectVbva(pDevExt, pCrCtlCon, u32ClientID);
1034 return VBoxMpCrCtlConDisconnectHgcm(pCrCtlCon, u32ClientID);
1035}
1036
1037int VBoxMpCrCtlConCall(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1038{
1039 int rc = VbglR0CrCtlConCallRaw(pCrCtlCon->hCrCtl, pData, cbData);
1040 if (RT_SUCCESS(rc))
1041 return VINF_SUCCESS;
1042
1043 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1044 return rc;
1045}
1046
1047int VBoxMpCrCtlConCallUserData(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1048{
1049 int rc = VbglR0CrCtlConCallUserDataRaw(pCrCtlCon->hCrCtl, pData, cbData);
1050 if (RT_SUCCESS(rc))
1051 return VINF_SUCCESS;
1052
1053 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1054 return rc;
1055}
1056
1057void VBoxMpCrCtlConInit(void)
1058{
1059 g_VBoxMpCr3DSupported = 0;
1060 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1061
1062 VBOXMP_CRCTLCON CrCtlCon = {0};
1063 uint32_t u32ClientID = 0;
1064 int rc = VBoxMpCrCtlConConnectHgcm(&CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &u32ClientID);
1065 if (RT_FAILURE(rc))
1066 {
1067 LOGREL(("VBoxMpCrCtlConConnectHgcm failed with rc(%d), 3D not supported!", rc));
1068 return;
1069 }
1070
1071 rc = vboxMpCrCtlConGetCapsNew(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo);
1072 if (RT_FAILURE(rc))
1073 {
1074 WARN(("vboxMpCrCtlConGetCapsNew failed rc (%d), ignoring..", rc));
1075 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1076 rc = vboxMpCrCtlConGetCapsLegacy(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo.u32Caps);
1077 if (RT_FAILURE(rc))
1078 {
1079 WARN(("vboxMpCrCtlConGetCapsLegacy failed rc (%d), ignoring..", rc));
1080 g_VBoxMpCrHostCapsInfo.u32Caps = 0;
1081 }
1082 }
1083
1084 if (g_VBoxMpCrHostCapsInfo.u32Caps & CR_VBOX_CAP_HOST_CAPS_NOT_SUFFICIENT)
1085 {
1086 LOGREL(("Insufficient host 3D capabilities"));
1087 g_VBoxMpCr3DSupported = 0;
1088 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1089 }
1090 else
1091 {
1092 g_VBoxMpCr3DSupported = 1;
1093 }
1094
1095#if 0 //ndef DEBUG_misha
1096 g_VBoxMpCrHostCapsInfo.u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
1097 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1098#endif
1099
1100 rc = VBoxMpCrCtlConDisconnectHgcm(&CrCtlCon, u32ClientID);
1101 if (RT_FAILURE(rc))
1102 WARN(("VBoxMpCrCtlConDisconnectHgcm failed rc (%d), ignoring..", rc));
1103}
1104
1105int VBoxMpCrCmdRxReadbackHandler(CRMessageReadback *pRx, uint32_t cbRx)
1106{
1107 if (cbRx < sizeof (*pRx))
1108 {
1109 WARN(("invalid rx size %d", cbRx));
1110 return VERR_INVALID_PARAMETER;
1111 }
1112 void* pvData = VBoxMpCrCmdRxReadbackData(pRx);
1113 uint32_t cbData = VBoxMpCrCmdRxReadbackDataSize(pRx, cbRx);
1114 void *pvDataPtr = *((void**)&pRx->readback_ptr);
1115 memcpy(pvDataPtr, pvData, cbData);
1116 return VINF_SUCCESS;
1117}
1118
1119int VBoxMpCrCmdRxHandler(CRMessageHeader *pRx, uint32_t cbRx)
1120{
1121 if (cbRx < sizeof (*pRx))
1122 {
1123 WARN(("invalid rx size %d", cbRx));
1124 return VERR_INVALID_PARAMETER;
1125 }
1126 CRMessageHeader *pHdr = (CRMessageHeader*)pRx;
1127 switch (pHdr->type)
1128 {
1129 case CR_MESSAGE_READBACK:
1130 return VBoxMpCrCmdRxReadbackHandler((CRMessageReadback*)pRx, cbRx);
1131 default:
1132 WARN(("unsupported rx message type: %d", pHdr->type));
1133 return VERR_INVALID_PARAMETER;
1134 }
1135}
1136
1137#endif /* VBOX_WITH_CROGL */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette