VirtualBox

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

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

DevVGA,HGSMI,++: Code cleanup in progress. bugref:9094

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.0 KB
Line 
1/* $Id: VBoxMPCr.cpp 71590 2018-03-31 18:34:28Z 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
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 RT_UNTRUSTED_VOLATILE_HOST *vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
41{
42 return VBoxSHGSMIHeapBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, cbData);
43}
44
45static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
46{
47 return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, pvBuffer);
48}
49
50static void RT_UNTRUSTED_VOLATILE_HOST *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 RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
56{
57 VBoxSHGSMIHeapBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pvBuffer);
58}
59
60static VBOXVIDEOOFFSET vboxMpCrShgsmiTransportBufOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
61{
62 return vboxMpCrShgsmiBufferOffset(pCon->pDevExt, pvBuffer);
63}
64
65static void RT_UNTRUSTED_VOLATILE_HOST *vboxMpCrShgsmiTransportBufFromOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVIDEOOFFSET offBuffer)
66{
67 return vboxMpCrShgsmiBufferFromOffset(pCon->pDevExt, offBuffer);
68}
69
70void RT_UNTRUSTED_VOLATILE_HOST *VBoxMpCrShgsmiTransportBufAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t cbBuffer)
71{
72 return vboxMpCrShgsmiBufferAlloc(pCon->pDevExt, cbBuffer);
73}
74
75void VBoxMpCrShgsmiTransportBufFree(PVBOXMP_CRSHGSMITRANSPORT pCon, void RT_UNTRUSTED_VOLATILE_HOST *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 RT_UNTRUSTED_VOLATILE_HOST *pvRx,
300 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 RT_UNTRUSTED_VOLATILE_HOST *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
421/** @callback_method_impl{FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION} */
422static DECLCALLBACK(void) vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc,
423 void RT_UNTRUSTED_VOLATILE_HOST *pvRx,
424 uint32_t cbRx, void *pvCtx)
425{
426 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pData = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)pvCtx;
427 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = pData->pfnCompletion;
428 if (pfnCompletion)
429 pfnCompletion(pCon, rc, pvRx, cbRx, pData->pvContext);
430}
431
432static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
433 PVOID pvContext)
434{
435 RT_NOREF(pDevExt);
436 /* we should be called from our DPC routine */
437 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
438
439 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
440 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
441 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
442 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
443 const UINT cBuffers = 3;
444 Assert(pBody->cBuffers == cBuffers);
445 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
446 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
447 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
448 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITEREAD));
449 CRVBOXHGSMIWRITEREAD * pWr = (CRVBOXHGSMIWRITEREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
450 VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[2];
451 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
452 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION)pBufCmd->u64GuestData;
453 void RT_UNTRUSTED_VOLATILE_HOST *pvRx = NULL;
454 uint32_t cbRx = 0;
455
456 int rc = pDr->rc;
457 if (RT_SUCCESS(rc))
458 {
459 rc = pWr->hdr.result;
460 if (RT_SUCCESS(rc))
461 {
462 cbRx = pCmd->cbWriteback;
463 if (cbRx)
464 pvRx = pWbDr->pvBuf;
465 }
466 else if (rc == VERR_BUFFER_OVERFLOW)
467 {
468 /* issue read */
469 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
470 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
471 pWbDr = vboxMpCrShgsmiBufCacheAlloc(pCon, &pCon->WbDrCache, pCmd->cbWriteback);
472 if (pWbDr)
473 {
474 /* the Read Command is shorter than WriteRead, so just reuse the Write-Read descriptor here */
475 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pReadCtx;
476 pReadCtx = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)vboxMpCrShgsmiTransportCmdCreateReadAsync(pCon,
477 pCmd->hdr.u32ClientID,
478 pDr,
479 VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof(VBOXMP_CRHGSMICMD_WRITEREAD), 0),
480 pWbDr,
481 vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion,
482 sizeof(*pReadCtx));
483 pReadCtx->pfnCompletion = pfnCompletion;
484 pReadCtx->pvContext = pvCtx;
485 vboxMpCrShgsmiTransportCmdSubmitReadAsync(pCon, pReadCtx);
486 /* don't do completion here, the completion will be called from the read completion we issue here */
487 pfnCompletion = NULL;
488 /* the current pWbDr was already freed, and we'll free the Read dr in the Read Completion */
489 pWbDr = NULL;
490 }
491 else
492 {
493 WARN(("vboxMpCrShgsmiBufCacheAlloc failed for %d", pCmd->cbWriteback));
494 rc = VERR_NO_MEMORY;
495 }
496 }
497 else
498 {
499 WARN(("CRVBOXHGSMIWRITEREAD failed, rc %d", rc));
500 }
501 }
502 else
503 {
504 WARN(("dma command buffer failed rc %d!", rc));
505 }
506
507 if (pfnCompletion)
508 {
509 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
510 pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
511 }
512
513 if (pWbDr)
514 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
515}
516
517static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
518 PVOID pvContext)
519{
520 RT_NOREF(pDevExt);
521 /* we should be called from our DPC routine */
522 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
523
524 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
525 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
526 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
527 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
528 const UINT cBuffers = 2;
529 Assert(pBody->cBuffers == cBuffers);
530 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
531 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
532 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
533 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITE));
534 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)pBufCmd->u64GuestData;
535
536 int rc = pDr->rc;
537 if (RT_SUCCESS(rc))
538 {
539 rc = pCmd->hdr.result;
540 if (!RT_SUCCESS(rc))
541 {
542 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
543 }
544 }
545 else
546 {
547 WARN(("dma command buffer failed rc %d!", rc));
548 }
549
550 if (pfnCompletion)
551 {
552 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
553 pfnCompletion(pCon, rc, pvCtx);
554 }
555}
556
557/** @callback_method_impl{FNVBOXSHGSMICMDCOMPLETION} */
558static DECLCALLBACK(VOID)
559vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvCmd, void *pvContext)
560{
561 RT_NOREF(pHeap);
562 /* we should be called from our DPC routine */
563 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
564
565 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
566 VBOXCMDVBVA_CRCMD_CMD RT_UNTRUSTED_VOLATILE_HOST *pCmd = NULL;
567 int rc = VBoxCmdVbvaConCmdCompletionData(pvCmd, &pCmd);
568 const UINT cBuffers = 2;
569 Assert(pCmd->cBuffers == cBuffers);
570 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
571 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)(*pu64Completion);
572
573 if (!RT_SUCCESS(rc))
574 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
575
576 if (pfnCompletion)
577 pfnCompletion(pCon, rc, (void*)(pu64Completion+1));
578}
579
580void* VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
581 uint32_t cbBuffer,
582 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion,
583 uint32_t cbContextData)
584{
585 const uint32_t cBuffers = 3;
586 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), cbContextData);
587 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
588 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
589 if (!pDr)
590 {
591 WARN(("vboxVdmaCBufDrCreate failed"));
592 return NULL;
593 }
594
595 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = vboxMpCrShgsmiBufCacheAllocAny(pCon, &pCon->WbDrCache, 1000);
596 if (!pWbDr)
597 {
598 WARN(("vboxMpCrShgsmiBufCacheAlloc for wb dr failed"));
599 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
600 return NULL;
601 }
602
603 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
604 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
605 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
606 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
607
608 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
609 pDr->cbBuf = cbCmd;
610 pDr->rc = VERR_NOT_IMPLEMENTED;
611// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
612
613
614 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
615 pHdr->u32CmdSpecific = 0;
616
617 pBody->cBuffers = cBuffers;
618
619 pCmd->hdr.result = VERR_WRONG_ORDER;
620 pCmd->hdr.u32ClientID = u32ClientID;
621 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
622 // pCmd->hdr.u32Reserved = 0;
623 pCmd->iBuffer = 1;
624 pCmd->iWriteback = 2;
625 pCmd->cbWriteback = 0;
626
627 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
628 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
629 pBufCmd->cbBuffer = sizeof (*pCmd);
630 pBufCmd->u32GuestData = 0;
631 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
632
633 pBufCmd = &pBody->aBuffers[1];
634 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pvBuffer);
635 pBufCmd->cbBuffer = cbBuffer;
636 pBufCmd->u32GuestData = 0;
637 pBufCmd->u64GuestData = 0;
638
639 pBufCmd = &pBody->aBuffers[2];
640 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
641 pBufCmd->cbBuffer = pWbDr->cbBuf;
642 pBufCmd->u32GuestData = 0;
643 pBufCmd->u64GuestData = (uintptr_t)pWbDr;
644
645 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
646}
647
648static void * vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
649 uint32_t cbBuffer,
650 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
651 uint32_t cbContextData)
652{
653 const uint32_t cBuffers = 2;
654 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_CMD_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8, cbContextData);
655 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBoxCmdVbvaConCmdAlloc(pDevExt, cbCmd);
656 if (!pCmd)
657 {
658 WARN(("VBoxCmdVbvaConCmdAlloc failed"));
659 return NULL;
660 }
661
662 pCmd->cBuffers = cBuffers;
663
664 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_CMD_GET_CMDBUF(pCmd, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
665 CRVBOXHGSMIWRITE *pCmdWrite = &pWrData->Cmd;
666
667 pCmdWrite->hdr.result = VERR_WRONG_ORDER;
668 pCmdWrite->hdr.u32ClientID = u32ClientID;
669 pCmdWrite->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
670 // pCmdWrite->hdr.u32Reserved = 0;
671 pCmdWrite->iBuffer = 1;
672
673 VBOXCMDVBVA_CRCMD_BUFFER *pBufCmd = &pCmd->aBuffers[0];
674 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pCmdWrite);
675 pBufCmd->cbBuffer = sizeof (*pCmdWrite);
676
677 pBufCmd = &pCmd->aBuffers[1];
678 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
679 pBufCmd->cbBuffer = cbBuffer;
680
681 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
682 *pu64Completion = (uintptr_t)pfnCompletion;
683 return pu64Completion + 1;
684}
685
686void* vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
687 uint32_t cbBuffer,
688 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
689 uint32_t cbContextData)
690{
691 const uint32_t cBuffers = 2;
692 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), cbContextData);
693 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
694 if (!pDr)
695 {
696 WARN(("vboxVdmaCBufDrCreate failed"));
697 return NULL;
698 }
699
700 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
701 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
702 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
703 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
704
705 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
706 pDr->cbBuf = cbCmd;
707 pDr->rc = VERR_NOT_IMPLEMENTED;
708// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
709
710 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
711 pHdr->u32CmdSpecific = 0;
712
713 pBody->cBuffers = cBuffers;
714
715 pCmd->hdr.result = VERR_WRONG_ORDER;
716 pCmd->hdr.u32ClientID = u32ClientID;
717 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
718 // pCmd->hdr.u32Reserved = 0;
719 pCmd->iBuffer = 1;
720
721 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
722 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
723 pBufCmd->cbBuffer = sizeof (*pCmd);
724 pBufCmd->u32GuestData = 0;
725 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
726
727 pBufCmd = &pBody->aBuffers[1];
728 pBufCmd->offBuffer = vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
729 pBufCmd->cbBuffer = cbBuffer;
730 pBufCmd->u32GuestData = 0;
731 pBufCmd->u64GuestData = 0;
732
733 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
734}
735
736void* VBoxMpCrShgsmiTransportCmdCreateWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
737 uint32_t cbBuffer,
738 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
739 uint32_t cbContextData)
740{
741 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
742 if (pDevExt->fCmdVbvaEnabled)
743 return vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion,
744 cbContextData);
745 return vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion, cbContextData);
746}
747
748int VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
749{
750 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
751 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion);
752}
753
754static int vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
755{
756 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
757 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion);
758}
759
760static int vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
761{
762 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
763 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
764 VBOXCMDVBVA_CRCMD_CMD);
765 return VBoxCmdVbvaConCmdSubmitAsync(pDevExt, pCmd, vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion, pCon);
766}
767
768int VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
769{
770 if (pCon->pDevExt->fCmdVbvaEnabled)
771 return vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(pCon, pvContext);
772 return vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(pCon, pvContext);
773}
774
775void VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
776{
777 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
778 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
779}
780
781static void vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
782{
783 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
784 VBOXCMDVBVA_CRCMD_CMD);
785 VBoxCmdVbvaConCmdFree(pCon->pDevExt, pCmd);
786}
787
788static void vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
789{
790 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
791 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
792}
793
794void VBoxMpCrShgsmiTransportCmdTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
795{
796 if (pCon->pDevExt->fCmdVbvaEnabled)
797 vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(pCon, pvContext);
798 else
799 vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(pCon, pvContext);
800}
801
802static int vboxMpCrCtlAddRef(PVBOXMP_CRCTLCON pCrCtlCon)
803{
804 if (pCrCtlCon->cCrCtlRefs++)
805 return VINF_ALREADY_INITIALIZED;
806
807 int rc = VbglR0CrCtlCreate(&pCrCtlCon->hCrCtl);
808 if (RT_SUCCESS(rc))
809 {
810 Assert(pCrCtlCon->hCrCtl);
811 return VINF_SUCCESS;
812 }
813
814 WARN(("vboxCrCtlCreate failed, rc (%d)", rc));
815
816 --pCrCtlCon->cCrCtlRefs;
817 return rc;
818}
819
820static int vboxMpCrCtlRelease(PVBOXMP_CRCTLCON pCrCtlCon)
821{
822 Assert(pCrCtlCon->cCrCtlRefs);
823 if (--pCrCtlCon->cCrCtlRefs)
824 {
825 return VINF_SUCCESS;
826 }
827
828 int rc = VbglR0CrCtlDestroy(pCrCtlCon->hCrCtl);
829 if (RT_SUCCESS(rc))
830 {
831 pCrCtlCon->hCrCtl = NULL;
832 return VINF_SUCCESS;
833 }
834
835 WARN(("vboxCrCtlDestroy failed, rc (%d)", rc));
836
837 ++pCrCtlCon->cCrCtlRefs;
838 return rc;
839}
840
841static int vboxMpCrCtlConSetVersion(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
842{
843 CRVBOXHGCMSETVERSION parms;
844 int rc;
845
846 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_VERSION, SHCRGL_CPARMS_SET_VERSION);
847
848 parms.vMajor.type = VMMDevHGCMParmType_32bit;
849 parms.vMajor.u.value32 = vMajor;
850 parms.vMinor.type = VMMDevHGCMParmType_32bit;
851 parms.vMinor.u.value32 = vMinor;
852
853 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
854 if (RT_FAILURE(rc))
855 WARN(("vboxCrCtlConCall/SET_VERSION failed, rc = %Rrc", rc));
856 return rc;
857}
858
859static int vboxMpCrCtlConGetCapsLegacy(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t *pu32Caps)
860{
861 CRVBOXHGCMGETCAPS parms;
862 int rc;
863
864 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_LEGACY, SHCRGL_CPARMS_GET_CAPS_LEGACY);
865
866 parms.Caps.type = VMMDevHGCMParmType_32bit;
867 parms.Caps.u.value32 = 0;
868
869 *pu32Caps = 0;
870
871 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
872 if (RT_FAILURE(rc))
873 {
874 WARN(("vboxCrCtlConCall/GET_CAPS_LEAGCY failed, rc=%Rrc", rc));
875 return rc;
876 }
877
878 /* if host reports it supports CR_VBOX_CAP_CMDVBVA, clean it up,
879 * we only support CR_VBOX_CAP_CMDVBVA of the proper version reported by SHCRGL_GUEST_FN_GET_CAPS_NEW */
880 parms.Caps.u.value32 &= ~CR_VBOX_CAP_CMDVBVA;
881
882 *pu32Caps = parms.Caps.u.value32;
883
884 return VINF_SUCCESS;
885}
886
887static int vboxMpCrCtlConGetCapsNew(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, CR_CAPS_INFO *pCapsInfo)
888{
889 pCapsInfo->u32Caps = CR_VBOX_CAPS_ALL;
890 pCapsInfo->u32CmdVbvaVersion = CR_CMDVBVA_VERSION;
891
892 CRVBOXHGCMGETCAPS parms;
893 int rc;
894
895 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_NEW, SHCRGL_CPARMS_GET_CAPS_NEW);
896
897 parms.Caps.type = VMMDevHGCMParmType_LinAddr;
898 parms.Caps.u.Pointer.u.linearAddr = (uintptr_t)pCapsInfo;
899 parms.Caps.u.Pointer.size = sizeof (*pCapsInfo);
900
901 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
902 if (RT_FAILURE(rc))
903 {
904 WARN(("vboxCrCtlConCall/GET_CAPS_NEW failed, rc=%Rrc", rc));
905 return rc;
906 }
907
908 if (pCapsInfo->u32CmdVbvaVersion != CR_CMDVBVA_VERSION)
909 {
910 WARN(("CmdVbva version mismatch (%d), expected(%d)", pCapsInfo->u32CmdVbvaVersion, CR_CMDVBVA_VERSION));
911 pCapsInfo->u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
912 }
913
914 pCapsInfo->u32Caps &= CR_VBOX_CAPS_ALL;
915
916 return VINF_SUCCESS;
917}
918
919static int vboxMpCrCtlConSetPID(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
920{
921 CRVBOXHGCMSETPID parms;
922 int rc;
923
924 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_PID, SHCRGL_CPARMS_SET_PID);
925
926 parms.u64PID.type = VMMDevHGCMParmType_64bit;
927 parms.u64PID.u.value64 = (uintptr_t)PsGetCurrentProcessId();
928
929 Assert(parms.u64PID.u.value64);
930
931 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
932 if (RT_FAILURE(rc))
933 WARN(("vboxCrCtlConCall/SET_PIDfailed, rc=%Rrc", rc));
934 return rc;
935}
936
937int VBoxMpCrCtlConConnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon,
938 uint32_t crVersionMajor, uint32_t crVersionMinor,
939 uint32_t *pu32ClientID)
940{
941 uint32_t u32ClientID;
942 int rc = vboxMpCrCtlAddRef(pCrCtlCon);
943 if (RT_SUCCESS(rc))
944 {
945 rc = VbglR0CrCtlConConnect(pCrCtlCon->hCrCtl, &u32ClientID);
946 if (RT_SUCCESS(rc))
947 {
948 rc = vboxMpCrCtlConSetVersion(pCrCtlCon, u32ClientID, crVersionMajor, crVersionMinor);
949 if (RT_SUCCESS(rc))
950 {
951 rc = vboxMpCrCtlConSetPID(pCrCtlCon, u32ClientID);
952 if (RT_SUCCESS(rc))
953 {
954 *pu32ClientID = u32ClientID;
955 return VINF_SUCCESS;
956 }
957 else
958 {
959 WARN(("vboxMpCrCtlConSetPID failed, rc (%d)", rc));
960 }
961 }
962 else
963 {
964 WARN(("vboxMpCrCtlConSetVersion failed, rc (%d)", rc));
965 }
966 VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
967 }
968 else
969 {
970 WARN(("vboxCrCtlConConnect failed, rc (%d)", rc));
971 }
972 vboxMpCrCtlRelease(pCrCtlCon);
973 }
974 else
975 {
976 WARN(("vboxMpCrCtlAddRef failed, rc (%d)", rc));
977 }
978
979 *pu32ClientID = 0;
980 Assert(RT_FAILURE(rc));
981 return rc;
982}
983
984int VBoxMpCrCtlConConnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
985 uint32_t crVersionMajor, uint32_t crVersionMinor,
986 uint32_t *pu32ClientID)
987{
988 if (pCrCtlCon->hCrCtl)
989 {
990 WARN(("pCrCtlCon is HGCM connection"));
991 return VERR_INVALID_STATE;
992 }
993
994 Assert(!pCrCtlCon->cCrCtlRefs);
995 return VBoxCmdVbvaConConnect(pDevExt, &pDevExt->CmdVbva,
996 crVersionMajor, crVersionMinor,
997 pu32ClientID);
998}
999
1000int VBoxMpCrCtlConConnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
1001 uint32_t crVersionMajor, uint32_t crVersionMinor,
1002 uint32_t *pu32ClientID)
1003{
1004 if (pDevExt->fCmdVbvaEnabled)
1005 {
1006 return VBoxMpCrCtlConConnectVbva(pDevExt, pCrCtlCon,
1007 crVersionMajor, crVersionMinor,
1008 pu32ClientID);
1009 }
1010 return VBoxMpCrCtlConConnectHgcm(pCrCtlCon,
1011 crVersionMajor, crVersionMinor,
1012 pu32ClientID);
1013}
1014
1015int VBoxMpCrCtlConDisconnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1016{
1017 int rc = VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
1018 if (RT_SUCCESS(rc))
1019 {
1020 vboxMpCrCtlRelease(pCrCtlCon);
1021 return VINF_SUCCESS;
1022 }
1023 WARN(("vboxCrCtlConDisconnect failed, rc (%d)", rc));
1024 return rc;
1025}
1026
1027int VBoxMpCrCtlConDisconnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1028{
1029 RT_NOREF(pDevExt, pCrCtlCon);
1030 Assert(!pCrCtlCon->hCrCtl);
1031 Assert(!pCrCtlCon->cCrCtlRefs);
1032 return VBoxCmdVbvaConDisconnect(pDevExt, &pDevExt->CmdVbva, u32ClientID);
1033}
1034
1035int VBoxMpCrCtlConDisconnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1036{
1037 if (!pCrCtlCon->hCrCtl)
1038 return VBoxMpCrCtlConDisconnectVbva(pDevExt, pCrCtlCon, u32ClientID);
1039 return VBoxMpCrCtlConDisconnectHgcm(pCrCtlCon, u32ClientID);
1040}
1041
1042int VBoxMpCrCtlConCall(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1043{
1044 int rc = VbglR0CrCtlConCallRaw(pCrCtlCon->hCrCtl, pData, cbData);
1045 if (RT_SUCCESS(rc))
1046 return VINF_SUCCESS;
1047
1048 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1049 return rc;
1050}
1051
1052int VBoxMpCrCtlConCallUserData(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1053{
1054 int rc = VbglR0CrCtlConCallUserDataRaw(pCrCtlCon->hCrCtl, pData, cbData);
1055 if (RT_SUCCESS(rc))
1056 return VINF_SUCCESS;
1057
1058 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1059 return rc;
1060}
1061
1062void VBoxMpCrCtlConInit(void)
1063{
1064 g_VBoxMpCr3DSupported = 0;
1065 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1066
1067 VBOXMP_CRCTLCON CrCtlCon = {0};
1068 uint32_t u32ClientID = 0;
1069 int rc = VBoxMpCrCtlConConnectHgcm(&CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &u32ClientID);
1070 if (RT_FAILURE(rc))
1071 {
1072 LOGREL(("VBoxMpCrCtlConConnectHgcm failed with rc(%d), 3D not supported!", rc));
1073 return;
1074 }
1075
1076 rc = vboxMpCrCtlConGetCapsNew(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo);
1077 if (RT_FAILURE(rc))
1078 {
1079 WARN(("vboxMpCrCtlConGetCapsNew failed rc (%d), ignoring..", rc));
1080 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1081 rc = vboxMpCrCtlConGetCapsLegacy(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo.u32Caps);
1082 if (RT_FAILURE(rc))
1083 {
1084 WARN(("vboxMpCrCtlConGetCapsLegacy failed rc (%d), ignoring..", rc));
1085 g_VBoxMpCrHostCapsInfo.u32Caps = 0;
1086 }
1087 }
1088
1089 if (g_VBoxMpCrHostCapsInfo.u32Caps & CR_VBOX_CAP_HOST_CAPS_NOT_SUFFICIENT)
1090 {
1091 LOGREL(("Insufficient host 3D capabilities"));
1092 g_VBoxMpCr3DSupported = 0;
1093 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1094 }
1095 else
1096 {
1097 g_VBoxMpCr3DSupported = 1;
1098 }
1099
1100#if 0 //ndef DEBUG_misha
1101 g_VBoxMpCrHostCapsInfo.u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
1102 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1103#endif
1104
1105 rc = VBoxMpCrCtlConDisconnectHgcm(&CrCtlCon, u32ClientID);
1106 if (RT_FAILURE(rc))
1107 WARN(("VBoxMpCrCtlConDisconnectHgcm failed rc (%d), ignoring..", rc));
1108}
1109
1110int VBoxMpCrCmdRxReadbackHandler(CRMessageReadback RT_UNTRUSTED_VOLATILE_HOST *pRx, uint32_t cbRx)
1111{
1112 if (cbRx < sizeof(*pRx))
1113 {
1114 WARN(("invalid rx size %d", cbRx));
1115 return VERR_INVALID_PARAMETER;
1116 }
1117 void *pvSrc = VBoxMpCrCmdRxReadbackData(pRx);
1118 uint32_t cbData = VBoxMpCrCmdRxReadbackDataSize(pRx, cbRx);
1119 void *pvDst = *((void**)&pRx->readback_ptr);
1120 memcpy(pvDst, pvSrc, cbData);
1121 return VINF_SUCCESS;
1122}
1123
1124int VBoxMpCrCmdRxHandler(CRMessageHeader RT_UNTRUSTED_VOLATILE_HOST *pRx, uint32_t cbRx)
1125{
1126 if (cbRx < sizeof(*pRx))
1127 {
1128 WARN(("invalid rx size %d", cbRx));
1129 return VERR_INVALID_PARAMETER;
1130 }
1131 CRMessageType enmType = pRx->type;
1132 switch (enmType)
1133 {
1134 case CR_MESSAGE_READBACK:
1135 return VBoxMpCrCmdRxReadbackHandler((CRMessageReadback RT_UNTRUSTED_VOLATILE_HOST *)pRx, cbRx);
1136 default:
1137 WARN(("unsupported rx message type: %d", enmType));
1138 return VERR_INVALID_PARAMETER;
1139 }
1140}
1141
1142#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