VirtualBox

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

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

wddm: bugfixes + stubs for DMA support in VGA device

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/*
2 * Copyright (C) 2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
13 * Clara, CA 95054 USA or visit http://www.sun.com if you need
14 * additional information or have any questions.
15 */
16
17#include "../VBoxVideo.h"
18#include "../Helper.h"
19
20#include <VBox/VBoxGuestLib.h>
21#include <VBox/VBoxVideo.h>
22#include "VBoxVideoVdma.h"
23#include "../VBoxVideo.h"
24
25/*
26 * This is currently used by VDMA. It is invisible for Vdma API clients since
27 * Vdma transport may change if we choose to use another (e.g. more light-weight)
28 * transport for DMA commands submission
29 */
30
31
32static int vboxVdmaInformHost (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
33{
34 int rc = VINF_SUCCESS;
35
36 PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc (&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
37 if (pCmd)
38 {
39 pCmd->enmCtl = enmCtl;
40 pCmd->u32Offset = pInfo->CmdHeap.area.offBase;
41 pCmd->i32Result = VERR_NOT_SUPPORTED;
42
43 VBoxSHGSMICommandSubmitSynch (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
44
45 rc = pCmd->i32Result;
46 AssertRC(rc);
47
48 VBoxSHGSMICommandFree (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
49 }
50 else
51 {
52 drprintf((__FUNCTION__": HGSMIHeapAlloc failed\n"));
53 rc = VERR_OUT_OF_RESOURCES;
54 }
55
56 return rc;
57}
58
59/* create a DMACommand buffer */
60int vboxVdmaCreate (PDEVICE_EXTENSION pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer)
61{
62 Assert((offBuffer & 0xfff) == 0);
63 Assert((cbBuffer & 0xfff) == 0);
64 Assert(offBuffer);
65 Assert(cbBuffer);
66
67 if((offBuffer & 0xfff)
68 || (cbBuffer & 0xfff)
69 || !offBuffer
70 || !cbBuffer)
71 {
72 drprintf((__FUNCTION__": invalid parameters: offBuffer(0x%x), cbBuffer(0x%x)", offBuffer, cbBuffer));
73 return VERR_INVALID_PARAMETER;
74 }
75
76 pInfo->fEnabled = FALSE;
77 PVOID pvBuffer;
78
79 int rc = VBoxMapAdapterMemory (pDevExt,
80 &pvBuffer,
81 offBuffer,
82 cbBuffer);
83 Assert(RT_SUCCESS(rc));
84 if (RT_SUCCESS(rc))
85 {
86 /* Setup a HGSMI heap within the adapter information area. */
87 rc = HGSMIHeapSetup (&pInfo->CmdHeap,
88 pvBuffer,
89 cbBuffer,
90 offBuffer,
91 false /*fOffsetBased*/);
92 Assert(RT_SUCCESS(rc));
93 if(RT_SUCCESS(rc))
94 return rc;
95 else
96 drprintf((__FUNCTION__": HGSMIHeapSetup failed rc = 0x%x\n", rc));
97
98 VBoxUnmapAdapterMemory(pDevExt, &pvBuffer, cbBuffer);
99 }
100 else
101 drprintf((__FUNCTION__": VBoxMapAdapterMemory failed rc = 0x%x\n", rc));
102
103 return rc;
104}
105
106int vboxVdmaDisable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
107{
108 dfprintf((__FUNCTION__"\n"));
109
110 Assert(pInfo->fEnabled);
111 if (!pInfo->fEnabled)
112 return VINF_ALREADY_INITIALIZED;
113
114 /* ensure nothing else is submitted */
115 pInfo->fEnabled = FALSE;
116
117 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_DISABLE);
118 AssertRC(rc);
119 return rc;
120}
121
122int vboxVdmaEnable (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
123{
124 dfprintf((__FUNCTION__"\n"));
125
126 Assert(!pInfo->fEnabled);
127 if (pInfo->fEnabled)
128 return VINF_ALREADY_INITIALIZED;
129
130 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_ENABLE);
131 Assert(RT_SUCCESS(rc));
132 if (RT_SUCCESS(rc))
133 pInfo->fEnabled = TRUE;
134
135 return rc;
136}
137
138int vboxVdmaFlush (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
139{
140 dfprintf((__FUNCTION__"\n"));
141
142 Assert(pInfo->fEnabled);
143 if (!pInfo->fEnabled)
144 return VINF_ALREADY_INITIALIZED;
145
146 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_FLUSH);
147 Assert(RT_SUCCESS(rc));
148
149 return rc;
150}
151
152int vboxVdmaDestroy (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo)
153{
154 int rc = VINF_SUCCESS;
155 Assert(!pInfo->fEnabled);
156 if (pInfo->fEnabled)
157 rc = vboxVdmaDisable (pDevExt, pInfo);
158 VBoxUnmapAdapterMemory (pDevExt, (void**)&pInfo->CmdHeap.area.pu8Base, pInfo->CmdHeap.area.cbArea);
159 return rc;
160}
161
162void vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
163{
164 VBoxSHGSMICommandFree (&pInfo->CmdHeap, pDr);
165}
166
167PVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, PVBOXVDMACMDBUF_INFO pBufInfo)
168{
169 PVBOXVDMACBUF_DR pCmdDr;
170
171 if (pBufInfo->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
172 {
173 /* data info is a pointer to the buffer to be coppied and included in the command */
174 pCmdDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, sizeof (VBOXVDMACBUF_DR) + pBufInfo->cbBuf, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
175 Assert(pCmdDr);
176 if (!pCmdDr)
177 return NULL;
178
179 void * pvData = VBOXVDMACBUF_DR_TAIL(pCmdDr, void*);
180 memcpy(pvData, (void*)pBufInfo->Location.pvBuf, pBufInfo->cbBuf);
181 }
182 else
183 {
184 pCmdDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, sizeof (VBOXVDMACBUF_DR), HGSMI_CH_VBVA, VBVA_VDMA_CMD);
185 Assert(pCmdDr);
186 if (!pCmdDr)
187 return NULL;
188
189 if (!(pBufInfo->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET))
190 pCmdDr->Location.phBuf = pBufInfo->Location.phBuf;
191 else
192 pCmdDr->Location.offVramBuf = pBufInfo->Location.offVramBuf;
193 }
194
195 pCmdDr->fFlags = pBufInfo->fFlags;
196 pCmdDr->cbBuf = pBufInfo->cbBuf;
197 pCmdDr->u32FenceId = pBufInfo->u32FenceId;
198
199 return pCmdDr;
200}
201
202static DECLCALLBACK(void) vboxVdmaCBufDrCompletion(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
203{
204 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
205 PVBOXVDMAINFO pInfo = &pDevExt->u.primary.Vdma;
206
207 vboxVdmaCBufDrFree (pInfo, (PVBOXVDMACBUF_DR)pvCmd);
208}
209
210static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext,
211 PFNVBOXSHGSMICMDCOMPLETION *ppfnCompletion, void **ppvCompletion)
212{
213 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pvContext;
214 PVBOXVDMAINFO pVdma = &pDevExt->u.primary.Vdma;
215 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
216 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvCmd;
217
218 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
219
220 if (RT_SUCCESS(pDr->rc))
221 {
222 notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
223 notify.DmaCompleted.SubmissionFenceId = pDr->u32FenceId;
224 notify.DmaCompleted.NodeOrdinal = 0; /* @todo: ? */
225 notify.DmaCompleted.EngineOrdinal = 0; /* @todo: ? */
226 pVdma->uLastCompletedCmdFenceId = pDr->u32FenceId;
227 pDevExt->bSetNotifyDxDpc = TRUE;
228 }
229 else if (pDr->rc == VERR_INTERRUPTED)
230 {
231 notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
232 notify.DmaPreempted.PreemptionFenceId = pDr->u32FenceId;
233 notify.DmaPreempted.LastCompletedFenceId = pVdma->uLastCompletedCmdFenceId;
234 notify.DmaPreempted.NodeOrdinal = 0; /* @todo: ? */
235 notify.DmaPreempted.EngineOrdinal = 0; /* @todo: ? */
236 pDevExt->bSetNotifyDxDpc = TRUE;
237 }
238 else
239 {
240 AssertBreakpoint();
241 notify.InterruptType = DXGK_INTERRUPT_DMA_FAULTED;
242 notify.DmaFaulted.FaultedFenceId = pDr->u32FenceId;
243 notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
244 notify.DmaFaulted.NodeOrdinal = 0; /* @todo: ? */
245 notify.DmaFaulted.EngineOrdinal = 0; /* @todo: ? */
246 pDevExt->bSetNotifyDxDpc = TRUE;
247 }
248
249 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
250
251 /* inform SHGSMI we want to be called at DPC later */
252 *ppfnCompletion = vboxVdmaCBufDrCompletion;
253 *ppvCompletion = pvContext;
254}
255
256void vboxVdmaCBufDrSubmit (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
257{
258 VBoxSHGSMICommandSubmitAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, 0);
259}
260
261int vboxVdmaCBufSubmit (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACMDBUF_INFO pBufInfo)
262{
263 dfprintf((__FUNCTION__"\n"));
264
265 PVBOXVDMACBUF_DR pdr = vboxVdmaCBufDrCreate (pInfo, pBufInfo);
266 if (!pdr)
267 return VERR_OUT_OF_RESOURCES;
268
269 vboxVdmaCBufDrSubmit (pDevExt, pInfo, pdr);
270
271 return VINF_SUCCESS;
272}
273
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