VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp@ 28800

Last change on this file since 28800 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/*
2 * Copyright (C) 2010 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 */
12
13#include "../VBoxVideo.h"
14#include "../Helper.h"
15
16#include <VBox/VBoxGuestLib.h>
17#include <VBox/VBoxVideo.h>
18#include "VBoxVideoVdma.h"
19#include "../VBoxVideo.h"
20
21/*
22 * This is currently used by VDMA. It is invisible for Vdma API clients since
23 * Vdma transport may change if we choose to use another (e.g. more light-weight)
24 * transport for DMA commands submission
25 */
26
27#ifdef VBOXVDMA_WITH_VBVA
28static int vboxWddmVdmaSubmitVbva(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
29{
30 int rc;
31 if (vboxVbvaBufferBeginUpdate (pDevExt, &pDevExt->u.primary.Vbva))
32 {
33 rc = vboxVbvaReportCmdOffset(pDevExt, &pDevExt->u.primary.Vbva, offDr);
34 vboxVbvaBufferEndUpdate (pDevExt, &pDevExt->u.primary.Vbva);
35 }
36 else
37 {
38 AssertBreakpoint();
39 rc = VERR_INVALID_STATE;
40 }
41 return rc;
42}
43#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitVbva
44#else
45static int vboxWddmVdmaSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
46{
47 VBoxHGSMIGuestWrite(pDevExt, offDr);
48 return VINF_SUCCESS;
49}
50#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitHgsmi
51#endif
52
53static int vboxVdmaInformHost (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
54{
55 int rc = VINF_SUCCESS;
56
57 PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
58 if (pCmd)
59 {
60 pCmd->enmCtl = enmCtl;
61 pCmd->u32Offset = pInfo->CmdHeap.area.offBase;
62 pCmd->i32Result = VERR_NOT_SUPPORTED;
63
64 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
65 Assert(pHdr);
66 if (pHdr)
67 {
68 do
69 {
70 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
71 Assert(offCmd != HGSMIOFFSET_VOID);
72 if (offCmd != HGSMIOFFSET_VOID)
73 {
74 rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
75 AssertRC(rc);
76 if (RT_SUCCESS(rc))
77 {
78 rc = VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
79 AssertRC(rc);
80 if (RT_SUCCESS(rc))
81 {
82 rc = pCmd->i32Result;
83 AssertRC(rc);
84 }
85 break;
86 }
87 }
88 else
89 rc = VERR_INVALID_PARAMETER;
90 /* fail to submit, cancel it */
91 VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
92 } while (0);
93 }
94
95 VBoxSHGSMICommandFree (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
96 }
97 else
98 {
99 drprintf((__FUNCTION__": HGSMIHeapAlloc failed\n"));
100 rc = VERR_OUT_OF_RESOURCES;
101 }
102
103 return rc;
104}
105
106/* create a DMACommand buffer */
107int vboxVdmaCreate (PDEVICE_EXTENSION pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer)
108{
109 Assert((offBuffer & 0xfff) == 0);
110 Assert((cbBuffer & 0xfff) == 0);
111 Assert(offBuffer);
112 Assert(cbBuffer);
113
114 if((offBuffer & 0xfff)
115 || (cbBuffer & 0xfff)
116 || !offBuffer
117 || !cbBuffer)
118 {
119 drprintf((__FUNCTION__": invalid parameters: offBuffer(0x%x), cbBuffer(0x%x)", offBuffer, cbBuffer));
120 return VERR_INVALID_PARAMETER;
121 }
122
123 pInfo->fEnabled = FALSE;
124 PVOID pvBuffer;
125
126 int rc = VBoxMapAdapterMemory (pDevExt,
127 &pvBuffer,
128 offBuffer,
129 cbBuffer);
130 Assert(RT_SUCCESS(rc));
131 if (RT_SUCCESS(rc))
132 {
133 /* Setup a HGSMI heap within the adapter information area. */
134 rc = HGSMIHeapSetup (&pInfo->CmdHeap,
135 pvBuffer,
136 cbBuffer,
137 offBuffer,
138 false /*fOffsetBased*/);
139 Assert(RT_SUCCESS(rc));
140 if(RT_SUCCESS(rc))
141 return rc;
142 else
143 drprintf((__FUNCTION__": HGSMIHeapSetup failed rc = 0x%x\n", rc));
144
145 VBoxUnmapAdapterMemory(pDevExt, &pvBuffer, cbBuffer);
146 }
147 else
148 drprintf((__FUNCTION__": VBoxMapAdapterMemory failed rc = 0x%x\n", rc));
149
150 return rc;
151}
152
153int vboxVdmaDisable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
154{
155 dfprintf((__FUNCTION__"\n"));
156
157 Assert(pInfo->fEnabled);
158 if (!pInfo->fEnabled)
159 return VINF_ALREADY_INITIALIZED;
160
161 /* ensure nothing else is submitted */
162 pInfo->fEnabled = FALSE;
163
164 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_DISABLE);
165 AssertRC(rc);
166 return rc;
167}
168
169int vboxVdmaEnable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
170{
171 dfprintf((__FUNCTION__"\n"));
172
173 Assert(!pInfo->fEnabled);
174 if (pInfo->fEnabled)
175 return VINF_ALREADY_INITIALIZED;
176
177 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_ENABLE);
178 Assert(RT_SUCCESS(rc));
179 if (RT_SUCCESS(rc))
180 pInfo->fEnabled = TRUE;
181
182 return rc;
183}
184
185int vboxVdmaFlush (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
186{
187 dfprintf((__FUNCTION__"\n"));
188
189 Assert(pInfo->fEnabled);
190 if (!pInfo->fEnabled)
191 return VINF_ALREADY_INITIALIZED;
192
193 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_FLUSH);
194 Assert(RT_SUCCESS(rc));
195
196 return rc;
197}
198
199int vboxVdmaDestroy (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
200{
201 int rc = VINF_SUCCESS;
202 Assert(!pInfo->fEnabled);
203 if (pInfo->fEnabled)
204 rc = vboxVdmaDisable (pDevExt, pInfo);
205 VBoxUnmapAdapterMemory (pDevExt, (void**)&pInfo->CmdHeap.area.pu8Base, pInfo->CmdHeap.area.cbArea);
206 return rc;
207}
208
209void vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
210{
211 VBoxSHGSMICommandFree (&pInfo->CmdHeap, pDr);
212}
213
214PVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData)
215{
216 uint32_t cbDr = sizeof (VBOXVDMACBUF_DR) + cbTrailingData;
217 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
218 Assert(pDr);
219 if (pDr)
220 memset (pDr, 0, cbDr);
221 else
222 drprintf((__FUNCTION__": VBoxSHGSMICommandAlloc returned NULL\n"));
223
224 return pDr;
225}
226
227static DECLCALLBACK(void) vboxVdmaCBufDrCompletion(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
228{
229 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
230 PVBOXVDMAINFO pInfo = &pDevExt->u.primary.Vdma;
231
232 vboxVdmaCBufDrFree (pInfo, (PVBOXVDMACBUF_DR)pvCmd);
233}
234
235static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext,
236 PFNVBOXSHGSMICMDCOMPLETION *ppfnCompletion, void **ppvCompletion)
237{
238 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
239 PVBOXVDMAINFO pVdma = &pDevExt->u.primary.Vdma;
240 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
241 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvCmd;
242
243 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
244
245 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pDr->u64GuestContext;
246
247 if (RT_SUCCESS(pDr->rc))
248 {
249 notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
250 notify.DmaCompleted.SubmissionFenceId = pDr->u32FenceId;
251 if (pContext)
252 {
253 notify.DmaCompleted.NodeOrdinal = pContext->NodeOrdinal;
254 notify.DmaCompleted.EngineOrdinal = 0;
255 pContext->uLastCompletedCmdFenceId = pDr->u32FenceId;
256 }
257 else
258 pVdma->uLastCompletedPagingBufferCmdFenceId = pDr->u32FenceId;
259 pDevExt->bSetNotifyDxDpc = TRUE;
260 }
261 else if (pDr->rc == VERR_INTERRUPTED)
262 {
263 notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
264 notify.DmaPreempted.PreemptionFenceId = pDr->u32FenceId;
265 if (pContext)
266 {
267 notify.DmaPreempted.LastCompletedFenceId = pContext->uLastCompletedCmdFenceId;
268 notify.DmaPreempted.NodeOrdinal = pContext->NodeOrdinal;
269 notify.DmaPreempted.EngineOrdinal = 0;
270 }
271 else
272 notify.DmaPreempted.LastCompletedFenceId = pVdma->uLastCompletedPagingBufferCmdFenceId;
273
274 pDevExt->bSetNotifyDxDpc = TRUE;
275 }
276 else
277 {
278 AssertBreakpoint();
279 notify.InterruptType = DXGK_INTERRUPT_DMA_FAULTED;
280 notify.DmaFaulted.FaultedFenceId = pDr->u32FenceId;
281 notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
282 if (pContext)
283 {
284 notify.DmaFaulted.NodeOrdinal = pContext->NodeOrdinal;
285 notify.DmaFaulted.EngineOrdinal = 0;
286 }
287 pDevExt->bSetNotifyDxDpc = TRUE;
288 }
289
290 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
291
292 /* inform SHGSMI we want to be called at DPC later */
293 *ppfnCompletion = vboxVdmaCBufDrCompletion;
294 *ppvCompletion = pvContext;
295}
296
297int vboxVdmaCBufDrSubmit(PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
298{
299 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
300 Assert(pHdr);
301 int rc = VERR_GENERAL_FAILURE;
302 if (pHdr)
303 {
304 do
305 {
306 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pInfo->CmdHeap, pHdr);
307 Assert(offCmd != HGSMIOFFSET_VOID);
308 if (offCmd != HGSMIOFFSET_VOID)
309 {
310 rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
311 AssertRC(rc);
312 if (RT_SUCCESS(rc))
313 {
314 VBoxSHGSMICommandDoneAsynch(&pInfo->CmdHeap, pHdr);
315 AssertRC(rc);
316 break;
317 }
318 }
319 else
320 rc = VERR_INVALID_PARAMETER;
321 /* fail to submit, cancel it */
322 VBoxSHGSMICommandCancelAsynch(&pInfo->CmdHeap, pHdr);
323 } while (0);
324 }
325 else
326 rc = VERR_INVALID_PARAMETER;
327 return rc;
328}
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