VirtualBox

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

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

Introducing macros for initializing the VBoxGuestHGCMCallInfo structure.

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

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