VirtualBox

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

Last change on this file since 57801 was 51330, checked in by vboxsync, 11 years ago

crOpenGL: more extended flexible caps info, backwards compatibility fixes

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