VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.cpp@ 22136

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

video hw accel: fix cmd loss

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 100.4 KB
Line 
1/*
2 * VirtualBox Video miniport driver for NT/2k/XP
3 *
4 * Based on DDK sample code.
5 *
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
17 * Clara, CA 95054 USA or visit http://www.sun.com if you need
18 * additional information or have any questions.
19 */
20
21#include "VBoxVideo.h"
22#include "Helper.h"
23
24#include <iprt/log.h>
25#include <VBox/VMMDev.h>
26#include <VBox/VBoxGuest.h>
27#include <VBox/VBoxVideo.h>
28
29#include <VBox/VBoxGuestLib.h>
30#include <VBoxDisplay.h>
31
32#ifdef VBOX_WITH_HGSMI
33#include <iprt/initterm.h>
34#endif
35
36#if _MSC_VER >= 1400 /* bird: MS fixed swprintf to be standard-conforming... */
37#define _INC_SWPRINTF_INL_
38extern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
39#endif
40#include <wchar.h>
41
42#include "vboxioctl.h"
43
44
45static WCHAR VBoxChipType[] = L"VBOX";
46static WCHAR VBoxDACType[] = L"Integrated RAMDAC";
47static WCHAR VBoxAdapterString[] = L"VirtualBox Video Adapter";
48static WCHAR VBoxBiosString[] = L"Version 0xB0C2 or later";
49
50/*
51 * Globals for the last custom resolution set. This is important
52 * for system startup so that we report the last currently set
53 * custom resolution and Windows can use it again.
54 */
55ULONG gCustomXRes = 0;
56ULONG gCustomYRes = 0;
57ULONG gCustomBPP = 0;
58
59int vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult);
60
61ULONG DriverEntry(IN PVOID Context1, IN PVOID Context2)
62{
63 VIDEO_HW_INITIALIZATION_DATA InitData;
64 ULONG rc;
65
66#ifdef VBOX_WITH_HGSMI
67 RTR0Init(0);
68#endif
69
70 dprintf(("VBoxVideo::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
71
72 VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
73 InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
74 InitData.HwFindAdapter = VBoxVideoFindAdapter;
75 InitData.HwInitialize = VBoxVideoInitialize;
76#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
77 InitData.HwInterrupt = VBoxVideoInterrupt;
78#else
79 InitData.HwInterrupt = NULL;
80#endif
81 InitData.HwStartIO = VBoxVideoStartIO;
82 InitData.HwResetHw = VBoxVideoResetHW;
83 InitData.HwDeviceExtensionSize = 0;
84 // nowhere documented but without the following line, NT4 SP0 will choke
85 InitData.AdapterInterfaceType = PCIBus;
86 InitData.HwGetPowerState = VBoxVideoGetPowerState;
87 InitData.HwSetPowerState = VBoxVideoSetPowerState;
88 InitData.HwGetVideoChildDescriptor = VBoxVideoGetChildDescriptor;
89 InitData.HwDeviceExtensionSize = sizeof(DEVICE_EXTENSION);
90
91 // our DDK is at the Win2k3 level so we have to take special measures
92 // for backwards compatibility
93 switch (vboxQueryWinVersion())
94 {
95 case WINNT4:
96 InitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
97 break;
98 case WIN2K:
99 InitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
100 break;
101 }
102 rc = VideoPortInitialize(Context1, Context2, &InitData, NULL);
103
104 dprintf(("VBoxVideo::DriverEntry: returning with rc = 0x%x\n", rc));
105 return rc;
106}
107
108/*+++
109
110Routine Description:
111
112 This routine is used to read back various registry values.
113
114Arguments:
115
116 HwDeviceExtension
117 Supplies a pointer to the miniport's device extension.
118
119 Context
120 Context value passed to the get registry parameters routine.
121 If this is not null assume it's a ULONG* and save the data value in it.
122
123 ValueName
124 Name of the value requested.
125
126 ValueData
127 Pointer to the requested data.
128
129 ValueLength
130 Length of the requested data.
131
132Return Value:
133
134 If the variable doesn't exist return an error,
135 else if a context is supplied assume it's a PULONG and fill in the value
136 and return no error, else if the value is non-zero return an error.
137
138---*/
139VP_STATUS VBoxRegistryCallback(PVOID HwDeviceExtension, PVOID Context,
140 PWSTR ValueName, PVOID ValueData, ULONG ValueLength)
141{
142 //dprintf(("VBoxVideo::VBoxRegistryCallback: Context: %p, ValueName: %S, ValueData: %p, ValueLength: %d\n",
143 // Context, ValueName, ValueData, ValueLength));
144 if (ValueLength)
145 {
146 if (Context)
147 *(ULONG *)Context = *(PULONG)ValueData;
148 else if (*((PULONG)ValueData) != 0)
149 return ERROR_INVALID_PARAMETER;
150 return NO_ERROR;
151 }
152 else
153 return ERROR_INVALID_PARAMETER;
154}
155
156/*
157 * Global list of supported standard video modes. It will be
158 * filled dynamically.
159 */
160#define MAX_VIDEO_MODES 128
161static VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 2] = { 0 };
162/* number of available video modes, set by VBoxBuildModesTable */
163static uint32_t gNumVideoModes = 0;
164
165static uint32_t g_xresNoVRAM = 0, g_yresNoVRAM = 0, g_bppNoVRAM = 0;
166
167/**
168 * Helper function to dynamically build our table of standard video
169 * modes. We take the amount of VRAM and create modes with standard
170 * geometries until we've either reached the maximum number of modes
171 * or the available VRAM does not allow for additional modes.
172 */
173VOID VBoxBuildModesTable(PDEVICE_EXTENSION DeviceExtension)
174{
175 /* we need this static counter to always have a new mode index for our */
176 /* custom video mode, otherwise Windows thinks there is no mode switch */
177 static int gInvocationCounter = 0;
178
179 /* the resolution matrix */
180 struct
181 {
182 uint16_t xRes;
183 uint16_t yRes;
184 } resolutionMatrix[] =
185 {
186 /* standard modes */
187 { 640, 480 },
188 { 800, 600 },
189 { 1024, 768 },
190 { 1152, 864 },
191 { 1280, 960 },
192 { 1280, 1024 },
193 { 1400, 1050 },
194 { 1600, 1200 },
195 { 1920, 1440 },
196 /* multi screen modes with 1280x1024 */
197 { 2560, 1024 },
198 { 3840, 1024 },
199 { 5120, 1024 },
200 /* multi screen modes with 1600x1200 */
201 { 3200, 1200 },
202 { 4800, 1200 },
203 { 6400, 1200 },
204 };
205 size_t matrixSize = sizeof(resolutionMatrix) / sizeof(resolutionMatrix[0]);
206
207 /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
208 size_t maxModesPerColorDepth = MAX_VIDEO_MODES / 2 / 4;
209
210 /* size of the VRAM in bytes */
211 ULONG vramSize = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
212
213 gNumVideoModes = 0;
214
215 size_t numModesCurrentColorDepth;
216 size_t matrixIndex;
217 VP_STATUS status = 0;
218
219 /*
220 * Query the y-offset from the host
221 */
222 ULONG yOffset = vboxGetHeightReduction();
223
224#ifdef VBOX_WITH_8BPP_MODES
225 /*
226 * 8 bit video modes
227 */
228 numModesCurrentColorDepth = 0;
229 matrixIndex = 0;
230 while (numModesCurrentColorDepth < maxModesPerColorDepth)
231 {
232 /* are there any modes left in the matrix? */
233 if (matrixIndex >= matrixSize)
234 break;
235
236 /* does the mode fit into the VRAM? */
237 if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 1 > (LONG)vramSize)
238 {
239 ++matrixIndex;
240 continue;
241 }
242
243 /* does the host like that mode? */
244 if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
245 {
246 ++matrixIndex;
247 continue;
248 }
249
250 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
251 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
252 VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
253 VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
254 VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 1;
255 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
256 VideoModes[gNumVideoModes].BitsPerPlane = 8;
257 VideoModes[gNumVideoModes].Frequency = 60;
258 VideoModes[gNumVideoModes].XMillimeter = 320;
259 VideoModes[gNumVideoModes].YMillimeter = 240;
260 VideoModes[gNumVideoModes].NumberRedBits = 6;
261 VideoModes[gNumVideoModes].NumberGreenBits = 6;
262 VideoModes[gNumVideoModes].NumberBlueBits = 6;
263 VideoModes[gNumVideoModes].RedMask = 0;
264 VideoModes[gNumVideoModes].GreenMask = 0;
265 VideoModes[gNumVideoModes].BlueMask = 0;
266 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
267 VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
268 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
269 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
270 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
271
272 /* a new mode has been filled in */
273 ++gNumVideoModes;
274 ++numModesCurrentColorDepth;
275 /* advance to the next mode matrix entry */
276 ++matrixIndex;
277 }
278#endif /* VBOX_WITH_8BPP_MODES */
279
280 /*
281 * 16 bit video modes
282 */
283 numModesCurrentColorDepth = 0;
284 matrixIndex = 0;
285 while (numModesCurrentColorDepth < maxModesPerColorDepth)
286 {
287 /* are there any modes left in the matrix? */
288 if (matrixIndex >= matrixSize)
289 break;
290
291 /* does the mode fit into the VRAM? */
292 if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 2 > (LONG)vramSize)
293 {
294 ++matrixIndex;
295 continue;
296 }
297
298 /* does the host like that mode? */
299 if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
300 {
301 ++matrixIndex;
302 continue;
303 }
304
305 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
306 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
307 VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
308 VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
309 VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 2;
310 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
311 VideoModes[gNumVideoModes].BitsPerPlane = 16;
312 VideoModes[gNumVideoModes].Frequency = 60;
313 VideoModes[gNumVideoModes].XMillimeter = 320;
314 VideoModes[gNumVideoModes].YMillimeter = 240;
315 VideoModes[gNumVideoModes].NumberRedBits = 5;
316 VideoModes[gNumVideoModes].NumberGreenBits = 6;
317 VideoModes[gNumVideoModes].NumberBlueBits = 5;
318 VideoModes[gNumVideoModes].RedMask = 0xF800;
319 VideoModes[gNumVideoModes].GreenMask = 0x7E0;
320 VideoModes[gNumVideoModes].BlueMask = 0x1F;
321 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
322 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
323 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
324 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
325
326 /* a new mode has been filled in */
327 ++gNumVideoModes;
328 ++numModesCurrentColorDepth;
329 /* advance to the next mode matrix entry */
330 ++matrixIndex;
331 }
332
333 /*
334 * 24 bit video modes
335 */
336 numModesCurrentColorDepth = 0;
337 matrixIndex = 0;
338 while (numModesCurrentColorDepth < maxModesPerColorDepth)
339 {
340 /* are there any modes left in the matrix? */
341 if (matrixIndex >= matrixSize)
342 break;
343
344 /* does the mode fit into the VRAM? */
345 if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 3 > (LONG)vramSize)
346 {
347 ++matrixIndex;
348 continue;
349 }
350
351 /* does the host like that mode? */
352 if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
353 {
354 ++matrixIndex;
355 continue;
356 }
357
358 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
359 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
360 VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
361 VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
362 VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 3;
363 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
364 VideoModes[gNumVideoModes].BitsPerPlane = 24;
365 VideoModes[gNumVideoModes].Frequency = 60;
366 VideoModes[gNumVideoModes].XMillimeter = 320;
367 VideoModes[gNumVideoModes].YMillimeter = 240;
368 VideoModes[gNumVideoModes].NumberRedBits = 8;
369 VideoModes[gNumVideoModes].NumberGreenBits = 8;
370 VideoModes[gNumVideoModes].NumberBlueBits = 8;
371 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
372 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
373 VideoModes[gNumVideoModes].BlueMask = 0xFF;
374 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
375 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
376 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
377 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
378
379 /* a new mode has been filled in */
380 ++gNumVideoModes;
381 ++numModesCurrentColorDepth;
382 /* advance to the next mode matrix entry */
383 ++matrixIndex;
384 }
385
386 /*
387 * 32 bit video modes
388 */
389 numModesCurrentColorDepth = 0;
390 matrixIndex = 0;
391 while (numModesCurrentColorDepth < maxModesPerColorDepth)
392 {
393 /* are there any modes left in the matrix? */
394 if (matrixIndex >= matrixSize)
395 break;
396
397 /* does the mode fit into the VRAM? */
398 if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 4 > (LONG)vramSize)
399 {
400 ++matrixIndex;
401 continue;
402 }
403
404 /* does the host like that mode? */
405 if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
406 {
407 ++matrixIndex;
408 continue;
409 }
410
411 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
412 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
413 VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
414 VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
415 VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 4;
416 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
417 VideoModes[gNumVideoModes].BitsPerPlane = 32;
418 VideoModes[gNumVideoModes].Frequency = 60;
419 VideoModes[gNumVideoModes].XMillimeter = 320;
420 VideoModes[gNumVideoModes].YMillimeter = 240;
421 VideoModes[gNumVideoModes].NumberRedBits = 8;
422 VideoModes[gNumVideoModes].NumberGreenBits = 8;
423 VideoModes[gNumVideoModes].NumberBlueBits = 8;
424 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
425 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
426 VideoModes[gNumVideoModes].BlueMask = 0xFF;
427 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
428 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
429 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
430 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
431
432 /* a new mode has been filled in */
433 ++gNumVideoModes;
434 ++numModesCurrentColorDepth;
435 /* advance to the next mode matrix entry */
436 ++matrixIndex;
437 }
438
439 /*
440 * Next, check the registry for additional modes
441 */
442 int curKeyNo = 0;
443 do
444 {
445 /* check if there is space in the mode list */
446 if (gNumVideoModes >= MAX_VIDEO_MODES)
447 break;
448
449 wchar_t keyname[24];
450 uint32_t xres, yres, bpp = 0;
451 swprintf(keyname, L"CustomMode%dWidth", curKeyNo);
452 status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
453 keyname,
454 FALSE,
455 VBoxRegistryCallback,
456 &xres);
457 /* upon the first error, we give up */
458 if (status != NO_ERROR)
459 break;
460 swprintf(keyname, L"CustomMode%dHeight", curKeyNo);
461 status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
462 keyname,
463 FALSE,
464 VBoxRegistryCallback,
465 &yres);
466 /* upon the first error, we give up */
467 if (status != NO_ERROR)
468 break;
469 swprintf(keyname, L"CustomMode%dBPP", curKeyNo);
470 status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
471 keyname,
472 FALSE,
473 VBoxRegistryCallback,
474 &bpp);
475 /* upon the first error, we give up */
476 if (status != NO_ERROR)
477 break;
478
479 dprintf(("VBoxVideo: custom mode %u returned: xres = %u, yres = %u, bpp = %u\n",
480 curKeyNo, xres, yres, bpp));
481
482 /* first test: do the values make sense? */
483 if ( (xres > (1 << 16))
484 || (yres > (1 << 16))
485 || ( (bpp != 16)
486 && (bpp != 24)
487 && (bpp != 32)))
488 break;
489
490 /* round down width to be a multiple of 8 */
491 xres &= 0xFFF8;
492
493 /* second test: does it fit within our VRAM? */
494 if (xres * yres * (bpp / 8) > vramSize)
495 break;
496
497 /* third test: does the host like the video mode? */
498 if (!vboxLikesVideoMode(xres, yres, bpp))
499 break;
500
501 dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
502 /*
503 * Build mode entry.
504 * Note that we have to apply the y offset for the custom mode.
505 */
506 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
507 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
508 VideoModes[gNumVideoModes].VisScreenWidth = xres;
509 VideoModes[gNumVideoModes].VisScreenHeight = yres - yOffset;
510 VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
511 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
512 VideoModes[gNumVideoModes].BitsPerPlane = bpp;
513 VideoModes[gNumVideoModes].Frequency = 60;
514 VideoModes[gNumVideoModes].XMillimeter = 320;
515 VideoModes[gNumVideoModes].YMillimeter = 240;
516 switch (bpp)
517 {
518 case 16:
519 VideoModes[gNumVideoModes].NumberRedBits = 5;
520 VideoModes[gNumVideoModes].NumberGreenBits = 6;
521 VideoModes[gNumVideoModes].NumberBlueBits = 5;
522 VideoModes[gNumVideoModes].RedMask = 0xF800;
523 VideoModes[gNumVideoModes].GreenMask = 0x7E0;
524 VideoModes[gNumVideoModes].BlueMask = 0x1F;
525 break;
526 case 24:
527 VideoModes[gNumVideoModes].NumberRedBits = 8;
528 VideoModes[gNumVideoModes].NumberGreenBits = 8;
529 VideoModes[gNumVideoModes].NumberBlueBits = 8;
530 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
531 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
532 VideoModes[gNumVideoModes].BlueMask = 0xFF;
533 break;
534 case 32:
535 VideoModes[gNumVideoModes].NumberRedBits = 8;
536 VideoModes[gNumVideoModes].NumberGreenBits = 8;
537 VideoModes[gNumVideoModes].NumberBlueBits = 8;
538 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
539 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
540 VideoModes[gNumVideoModes].BlueMask = 0xFF;
541 break;
542 }
543 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
544 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
545 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres - yOffset;
546 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
547 ++gNumVideoModes;
548
549 /* next run */
550 curKeyNo++;
551 /* only support 128 modes for now */
552 if (curKeyNo >= 128)
553 break;
554
555 } while(1);
556
557
558 /*
559 * Now we ask the host for a display change request. If there's one,
560 * this will be appended as a special mode so that it can be used by
561 * the Additions service process. The mode table is guaranteed to have
562 * two spare entries for this mode (alternating index thus 2).
563 */
564 uint32_t xres, yres, bpp = 0;
565 if ( ( vboxQueryDisplayRequest(&xres, &yres, &bpp)
566 && (xres || yres || bpp))
567 || (gCustomXRes || gCustomYRes || gCustomBPP))
568 {
569 dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
570 /* handle the startup case */
571 if (DeviceExtension->CurrentMode == 0)
572 {
573 xres = gCustomXRes;
574 yres = gCustomYRes;
575 bpp = gCustomBPP;
576 dprintf(("VBoxVideo: using stored custom resolution %dx%dx%d\n", xres, yres, bpp));
577 }
578 /* round down to multiple of 8 */
579 if ((xres & 0xfff8) != xres)
580 dprintf(("VBoxVideo: rounding down xres from %d to %d\n", xres, xres & 0xfff8));
581 xres &= 0xfff8;
582 /* take the current values for the fields that are not set */
583 if (DeviceExtension->CurrentMode != 0)
584 {
585 if (!xres)
586 xres = DeviceExtension->CurrentModeWidth;
587 if (!yres)
588 yres = DeviceExtension->CurrentModeHeight;
589 if (!bpp)
590 {
591 bpp = DeviceExtension->CurrentModeBPP;
592 }
593 }
594
595 /* does the host like that mode? */
596 if (vboxLikesVideoMode(xres, yres, bpp))
597 {
598 /* we must have a valid video mode by now and it must fit within the VRAM */
599 if ( ( xres
600 && yres
601 && ( (bpp == 16)
602#ifdef VBOX_WITH_8BPP_MODES
603 || (bpp == 8)
604#endif
605 || (bpp == 24)
606 || (bpp == 32)))
607 && (xres * yres * (bpp / 8) < vramSize))
608
609 {
610 /* we need an alternating index */
611 if (DeviceExtension->CurrentMode != 0)
612 {
613 if (gInvocationCounter % 2)
614 gNumVideoModes++;
615 gInvocationCounter++;
616 }
617
618 dprintf(("VBoxVideo: setting special mode to xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
619 /*
620 * Build mode entry.
621 * Note that we do not apply the y offset for the custom mode. It is
622 * only used for the predefined modes that the user can configure in
623 * the display properties dialog.
624 */
625 VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
626 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
627 VideoModes[gNumVideoModes].VisScreenWidth = xres;
628 VideoModes[gNumVideoModes].VisScreenHeight = yres;
629 VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
630 VideoModes[gNumVideoModes].NumberOfPlanes = 1;
631 VideoModes[gNumVideoModes].BitsPerPlane = bpp;
632 VideoModes[gNumVideoModes].Frequency = 60;
633 VideoModes[gNumVideoModes].XMillimeter = 320;
634 VideoModes[gNumVideoModes].YMillimeter = 240;
635 switch (bpp)
636 {
637#ifdef VBOX_WITH_8BPP_MODES
638 case 8:
639 VideoModes[gNumVideoModes].NumberRedBits = 6;
640 VideoModes[gNumVideoModes].NumberGreenBits = 6;
641 VideoModes[gNumVideoModes].NumberBlueBits = 6;
642 VideoModes[gNumVideoModes].RedMask = 0;
643 VideoModes[gNumVideoModes].GreenMask = 0;
644 VideoModes[gNumVideoModes].BlueMask = 0;
645 break;
646#endif
647 case 16:
648 VideoModes[gNumVideoModes].NumberRedBits = 5;
649 VideoModes[gNumVideoModes].NumberGreenBits = 6;
650 VideoModes[gNumVideoModes].NumberBlueBits = 5;
651 VideoModes[gNumVideoModes].RedMask = 0xF800;
652 VideoModes[gNumVideoModes].GreenMask = 0x7E0;
653 VideoModes[gNumVideoModes].BlueMask = 0x1F;
654 break;
655 case 24:
656 VideoModes[gNumVideoModes].NumberRedBits = 8;
657 VideoModes[gNumVideoModes].NumberGreenBits = 8;
658 VideoModes[gNumVideoModes].NumberBlueBits = 8;
659 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
660 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
661 VideoModes[gNumVideoModes].BlueMask = 0xFF;
662 break;
663 case 32:
664 VideoModes[gNumVideoModes].NumberRedBits = 8;
665 VideoModes[gNumVideoModes].NumberGreenBits = 8;
666 VideoModes[gNumVideoModes].NumberBlueBits = 8;
667 VideoModes[gNumVideoModes].RedMask = 0xFF0000;
668 VideoModes[gNumVideoModes].GreenMask = 0xFF00;
669 VideoModes[gNumVideoModes].BlueMask = 0xFF;
670 break;
671 }
672 VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
673#ifdef VBOX_WITH_8BPP_MODES
674 if (bpp == 8)
675 VideoModes[gNumVideoModes].AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
676#endif
677 VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
678 VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres;
679 VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
680 ++gNumVideoModes;
681
682 /* for the startup case, we need this mode twice due to the alternating mode number */
683 if (DeviceExtension->CurrentMode == 0)
684 {
685 dprintf(("VBoxVideo: making a copy of the custom mode as #%d\n", gNumVideoModes + 1));
686 memcpy(&VideoModes[gNumVideoModes], &VideoModes[gNumVideoModes - 1], sizeof(VIDEO_MODE_INFORMATION));
687 VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
688 gNumVideoModes++;
689 }
690
691 /* store this video mode as the last custom video mode */
692 status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomXRes",
693 &xres, sizeof(ULONG));
694 if (status != NO_ERROR)
695 dprintf(("VBoxVideo: error %d writing CustomXRes\n", status));
696 status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomYRes",
697 &yres, sizeof(ULONG));
698 if (status != NO_ERROR)
699 dprintf(("VBoxVideo: error %d writing CustomYRes\n", status));
700 status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomBPP",
701 &bpp, sizeof(ULONG));
702 if (status != NO_ERROR)
703 dprintf(("VBoxVideo: error %d writing CustomBPP\n", status));
704 }
705 else
706 {
707 dprintf(("VBoxVideo: invalid parameters for special mode: (xres = %d, yres = %d, bpp = %d, vramSize = %d)\n",
708 xres, yres, bpp, vramSize));
709 if (xres * yres * (bpp / 8) >= vramSize
710 && (xres != g_xresNoVRAM || yres != g_yresNoVRAM || bpp != g_bppNoVRAM))
711 {
712 LogRel(("VBoxVideo: not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.\n",
713 xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));
714 g_xresNoVRAM = xres;
715 g_yresNoVRAM = yres;
716 g_bppNoVRAM = bpp;
717 }
718 }
719 }
720 else
721 dprintf(("VBoxVideo: host does not like special mode: (xres = %d, yres = %d, bpp = %d)\n",
722 xres, yres, bpp));
723 }
724#ifdef DEBUG
725 {
726 int i;
727 dprintf(("VBoxVideo: VideoModes (CurrentMode = %d)\n", DeviceExtension->CurrentMode));
728 for (i=0; i<MAX_VIDEO_MODES + 2; i++)
729 {
730 if ( VideoModes[i].VisScreenWidth
731 || VideoModes[i].VisScreenHeight
732 || VideoModes[i].BitsPerPlane)
733 {
734 dprintf((" %2d: %4d x %4d @ %2d\n",
735 i, VideoModes[i].VisScreenWidth,
736 VideoModes[i].VisScreenHeight, VideoModes[i].BitsPerPlane));
737 }
738 }
739 }
740#endif
741}
742
743/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
744void VBoxComputeFrameBufferSizes (PDEVICE_EXTENSION PrimaryExtension)
745{
746#ifndef VBOX_WITH_HGSMI
747 ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
748 - PrimaryExtension->u.primary.cbMiniportHeap
749 - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
750#else
751 ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
752 - PrimaryExtension->u.primary.cbMiniportHeap
753 - VBVA_ADAPTER_INFORMATION_SIZE;
754#endif /* VBOX_WITH_HGSMI */
755
756 /* Size of a framebuffer. */
757
758 ULONG ulSize = ulAvailable / PrimaryExtension->u.primary.cDisplays;
759
760 /* Align down to 4096 bytes. */
761 ulSize &= ~0xFFF;
762
763 dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: cbVRAM = 0x%08X, cDisplays = %d, ulSize = 0x%08X, ulSize * cDisplays = 0x%08X, slack = 0x%08X\n",
764 PrimaryExtension->u.primary.cbVRAM, PrimaryExtension->u.primary.cDisplays,
765 ulSize, ulSize * PrimaryExtension->u.primary.cDisplays,
766 ulAvailable - ulSize * PrimaryExtension->u.primary.cDisplays));
767
768#ifndef VBOX_WITH_HGSMI
769 if (ulSize > VBOX_VIDEO_DISPLAY_INFORMATION_SIZE)
770 {
771 /* Compute the size of the framebuffer. */
772 ulSize -= VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
773 }
774 else
775 {
776 /* Should not really get here. But still do it safely. */
777 ulSize = 0;
778 }
779#endif /* !VBOX_WITH_HGSMI */
780
781 /* Update the primary info. */
782 PrimaryExtension->u.primary.ulMaxFrameBufferSize = ulSize;
783#ifndef VBOX_WITH_HGSMI
784 PrimaryExtension->u.primary.ulDisplayInformationSize = VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
785#endif /* !VBOX_WITH_HGSMI */
786
787 /* Update the per extension info. */
788 PDEVICE_EXTENSION Extension = PrimaryExtension;
789 ULONG ulFrameBufferOffset = 0;
790 while (Extension)
791 {
792 Extension->ulFrameBufferOffset = ulFrameBufferOffset;
793 /* That is assigned when a video mode is set. */
794 Extension->ulFrameBufferSize = 0;
795
796 dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: [%d] ulFrameBufferOffset 0x%08X\n",
797 Extension->iDevice, ulFrameBufferOffset));
798
799#ifndef VBOX_WITH_HGSMI
800 ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize
801 + PrimaryExtension->u.primary.ulDisplayInformationSize;
802#else
803 ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize;
804#endif /* VBOX_WITH_HGSMI */
805
806 Extension = Extension->pNext;
807 }
808}
809
810int VBoxMapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv, ULONG ulOffset, ULONG ulSize)
811{
812 dprintf(("VBoxVideo::VBoxMapAdapterMemory 0x%08X[0x%X]\n", ulOffset, ulSize));
813
814 if (!ulSize)
815 {
816 dprintf(("Illegal length 0!\n"));
817 return ERROR_INVALID_PARAMETER;
818 }
819
820 PHYSICAL_ADDRESS FrameBuffer;
821 FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + ulOffset;
822
823 PVOID VideoRamBase = NULL;
824 ULONG inIoSpace = 0;
825 ULONG VideoRamLength = ulSize;
826
827 VP_STATUS Status = VideoPortMapMemory (PrimaryExtension, FrameBuffer,
828 &VideoRamLength, &inIoSpace,
829 &VideoRamBase);
830
831 if (Status == NO_ERROR)
832 {
833 *ppv = VideoRamBase;
834 }
835
836 dprintf(("VBoxVideo::VBoxMapAdapterMemory rc = %d\n", Status));
837
838 return Status;
839}
840
841void VBoxUnmapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv)
842{
843 dprintf(("VBoxVideo::VBoxMapAdapterMemory\n"));
844
845 if (*ppv)
846 {
847 VideoPortUnmapMemory(PrimaryExtension, *ppv, NULL);
848 }
849
850 *ppv = NULL;
851}
852
853#ifndef VBOX_WITH_HGSMI
854static void vboxQueryConf (PDEVICE_EXTENSION PrimaryExtension, uint32_t u32Index, ULONG *pulValue)
855{
856 dprintf(("VBoxVideo::vboxQueryConf: u32Index = %d\n", u32Index));
857
858 typedef struct _VBOXVIDEOQCONF32
859 {
860 VBOXVIDEOINFOHDR hdrQuery;
861 VBOXVIDEOINFOQUERYCONF32 query;
862 VBOXVIDEOINFOHDR hdrEnd;
863 } VBOXVIDEOQCONF32;
864
865 VBOXVIDEOQCONF32 *p = (VBOXVIDEOQCONF32 *)PrimaryExtension->u.primary.pvAdapterInformation;
866
867 p->hdrQuery.u8Type = VBOX_VIDEO_INFO_TYPE_QUERY_CONF32;
868 p->hdrQuery.u8Reserved = 0;
869 p->hdrQuery.u16Length = sizeof (VBOXVIDEOINFOQUERYCONF32);
870
871 p->query.u32Index = u32Index;
872 p->query.u32Value = 0;
873
874 p->hdrEnd.u8Type = VBOX_VIDEO_INFO_TYPE_END;
875 p->hdrEnd.u8Reserved = 0;
876 p->hdrEnd.u16Length = 0;
877
878 /* Let the host to process the commands. */
879 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
880 VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY);
881
882 *pulValue = (ULONG)p->query.u32Value;
883
884 dprintf(("VBoxVideo::vboxQueryConf: u32Value = %d\n", p->query.u32Value));
885}
886
887static void vboxSetupAdapterInfo (PDEVICE_EXTENSION PrimaryExtension)
888{
889 dprintf(("VBoxVideo::vboxSetupAdapterInfo\n"));
890
891 VBOXVIDEOINFOHDR *pHdr;
892
893 uint8_t *pu8 = (uint8_t *)PrimaryExtension->u.primary.pvAdapterInformation;
894
895 PDEVICE_EXTENSION Extension = PrimaryExtension;
896 while (Extension)
897 {
898 pHdr = (VBOXVIDEOINFOHDR *)pu8;
899 pu8 += sizeof (VBOXVIDEOINFOHDR);
900
901 pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_DISPLAY;
902 pHdr->u8Reserved = 0;
903 pHdr->u16Length = sizeof (VBOXVIDEOINFODISPLAY);
904
905 VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
906 pu8 += sizeof (VBOXVIDEOINFODISPLAY);
907
908 pDisplay->u32Index = Extension->iDevice;
909 pDisplay->u32Offset = Extension->ulFrameBufferOffset;
910 pDisplay->u32FramebufferSize = PrimaryExtension->u.primary.ulMaxFrameBufferSize;
911 pDisplay->u32InformationSize = PrimaryExtension->u.primary.ulDisplayInformationSize;
912
913 Extension = Extension->pNext;
914 }
915
916
917 /* The heap description. */
918 pHdr = (VBOXVIDEOINFOHDR *)pu8;
919 pu8 += sizeof (VBOXVIDEOINFOHDR);
920
921 pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_NV_HEAP;
922 pHdr->u8Reserved = 0;
923 pHdr->u16Length = sizeof (VBOXVIDEOINFONVHEAP);
924
925 VBOXVIDEOINFONVHEAP *pHeap = (VBOXVIDEOINFONVHEAP *)pu8;
926 pu8 += sizeof (VBOXVIDEOINFONVHEAP);
927
928 pHeap->u32HeapOffset = PrimaryExtension->u.primary.cbVRAM
929 - PrimaryExtension->u.primary.cbMiniportHeap
930 - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
931 pHeap->u32HeapSize = PrimaryExtension->u.primary.cbMiniportHeap;
932
933
934 /* The END marker. */
935 pHdr = (VBOXVIDEOINFOHDR *)pu8;
936 pu8 += sizeof (VBOXVIDEOINFOHDR);
937
938 pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_END;
939 pHdr->u8Reserved = 0;
940 pHdr->u16Length = 0;
941
942 /* Inform the host about the display configuration. */
943 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
944 VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY);
945
946 dprintf(("VBoxVideo::vboxSetupAdapterInfo finished\n"));
947}
948
949/**
950 * Helper function to register secondary displays (DualView). Note that this will not
951 * be available on pre-XP versions, and some editions on XP will fail because they are
952 * intentionally crippled.
953 */
954VOID VBoxSetupDisplays(PDEVICE_EXTENSION PrimaryExtension, PVIDEO_PORT_CONFIG_INFO pConfigInfo, ULONG AdapterMemorySize)
955{
956 VP_STATUS rc = NO_ERROR;
957
958 dprintf(("VBoxVideo::VBoxSetupDisplays: PrimaryExtension = %p\n",
959 PrimaryExtension));
960
961 /* Preinitialize the primary extension. */
962 PrimaryExtension->pNext = NULL;
963 PrimaryExtension->pPrimary = PrimaryExtension;
964 PrimaryExtension->iDevice = 0;
965 PrimaryExtension->ulFrameBufferOffset = 0;
966 PrimaryExtension->ulFrameBufferSize = 0;
967 PrimaryExtension->u.primary.ulVbvaEnabled = 0;
968 PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
969 PrimaryExtension->u.primary.cDisplays = 1;
970 PrimaryExtension->u.primary.cbVRAM = AdapterMemorySize;
971 PrimaryExtension->u.primary.cbMiniportHeap = 0;
972 PrimaryExtension->u.primary.pvMiniportHeap = NULL;
973 PrimaryExtension->u.primary.pvAdapterInformation = NULL;
974 PrimaryExtension->u.primary.ulMaxFrameBufferSize = 0;
975 PrimaryExtension->u.primary.ulDisplayInformationSize = 0;
976
977 /* Verify whether the HW supports VirtualBox extensions. */
978 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
979 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_VBOX_VIDEO);
980
981 if (VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA) == VBE_DISPI_ID_VBOX_VIDEO)
982 {
983 PrimaryExtension->u.primary.bVBoxVideoSupported = TRUE;
984 }
985
986 dprintf(("VBoxVideo::VBoxSetupDisplays: bVBoxVideoSupported = %d\n",
987 PrimaryExtension->u.primary.bVBoxVideoSupported));
988
989 if (PrimaryExtension->u.primary.bVBoxVideoSupported)
990 {
991 /* Map the adapter information. It will be needed to query some configuration values. */
992 rc = VBoxMapAdapterMemory (PrimaryExtension,
993 &PrimaryExtension->u.primary.pvAdapterInformation,
994 PrimaryExtension->u.primary.cbVRAM - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE,
995 VBOX_VIDEO_ADAPTER_INFORMATION_SIZE
996 );
997 if (rc != NO_ERROR)
998 {
999 dprintf(("VBoxVideo::VBoxSetupDisplays: VBoxMapAdapterMemory pvAdapterInfoirrmation failed rc = %d\n",
1000 rc));
1001
1002 PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
1003 }
1004 }
1005
1006 /* Setup the non-volatile heap and the adapter memory. */
1007 if (PrimaryExtension->u.primary.bVBoxVideoSupported)
1008 {
1009 /* Query the size of the non-volatile heap. */
1010 ULONG cbMiniportHeap = 0;
1011 vboxQueryConf (PrimaryExtension, VBOX_VIDEO_QCI32_OFFSCREEN_HEAP_SIZE, &cbMiniportHeap);
1012
1013 /* Do not allow too big heap. 50% of VRAM should be enough. */
1014 ULONG cbMiniportHeapMaxSize = AdapterMemorySize / 2 - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
1015
1016 if (cbMiniportHeap > cbMiniportHeapMaxSize)
1017 {
1018 cbMiniportHeap = cbMiniportHeapMaxSize;
1019 }
1020
1021 /* Round up to 4096. */
1022 PrimaryExtension->u.primary.cbMiniportHeap = (cbMiniportHeap + 0xFFF) & ~0xFFF;
1023
1024 dprintf(("VBoxVideo::VBoxSetupDisplays: cbMiniportHeap = 0x%08X, PrimaryExtension->u.primary.cbMiniportHeap = 0x%08X, cbMiniportHeapMaxSize = 0x%08X\n",
1025 cbMiniportHeap, PrimaryExtension->u.primary.cbMiniportHeap, cbMiniportHeapMaxSize));
1026
1027 /* Map the heap region and the adapter information area.
1028 *
1029 * Note: the heap will be used by display drivers, possibly by a few instances
1030 * in multimonitor configuration, but the memory is mapped here ones.
1031 * It is assumed that all display drivers and the miniport has the SAME
1032 * virtual address space.
1033 *
1034 */
1035 rc = VBoxMapAdapterMemory (PrimaryExtension,
1036 &PrimaryExtension->u.primary.pvMiniportHeap,
1037 PrimaryExtension->u.primary.cbVRAM
1038 - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE
1039 - PrimaryExtension->u.primary.cbMiniportHeap,
1040 PrimaryExtension->u.primary.cbMiniportHeap
1041 );
1042
1043 if (rc != NO_ERROR)
1044 {
1045 PrimaryExtension->u.primary.cbMiniportHeap = 0;
1046 PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
1047 }
1048 }
1049
1050 /* Check whether the guest supports multimonitors. */
1051 if (PrimaryExtension->u.primary.bVBoxVideoSupported)
1052 {
1053 typedef VP_STATUS (*PFNCREATESECONDARYDISPLAY)(PVOID, PVOID *, ULONG);
1054 PFNCREATESECONDARYDISPLAY pfnCreateSecondaryDisplay = NULL;
1055
1056 /* Dynamically query the VideoPort import to be binary compatible across Windows versions */
1057 if (vboxQueryWinVersion() > WINNT4)
1058 {
1059 /* This bluescreens on NT4, hence the above version check */
1060 pfnCreateSecondaryDisplay = (PFNCREATESECONDARYDISPLAY)(pConfigInfo->VideoPortGetProcAddress)
1061 (PrimaryExtension,
1062 (PUCHAR)"VideoPortCreateSecondaryDisplay");
1063 }
1064
1065 if (pfnCreateSecondaryDisplay != NULL)
1066 {
1067 /* Query the configured number of displays. */
1068 ULONG cDisplays = 0;
1069 vboxQueryConf (PrimaryExtension, VBOX_VIDEO_QCI32_MONITOR_COUNT, &cDisplays);
1070
1071 dprintf(("VBoxVideo::VBoxSetupDisplays: cDisplays = %d\n",
1072 cDisplays));
1073
1074 if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS)
1075 {
1076 /* Host reported some bad value. Continue in the 1 screen mode. */
1077 cDisplays = 1;
1078 }
1079
1080 PDEVICE_EXTENSION pPrev = PrimaryExtension;
1081
1082 ULONG iDisplay;
1083 for (iDisplay = 1; iDisplay < cDisplays; iDisplay++)
1084 {
1085 PDEVICE_EXTENSION SecondaryExtension = NULL;
1086 rc = pfnCreateSecondaryDisplay (PrimaryExtension, (PVOID*)&SecondaryExtension, VIDEO_DUALVIEW_REMOVABLE);
1087
1088 dprintf(("VBoxVideo::VBoxSetupDisplays: VideoPortCreateSecondaryDisplay returned %#x, SecondaryExtension = %p\n",
1089 rc, SecondaryExtension));
1090
1091 if (rc != NO_ERROR)
1092 {
1093 break;
1094 }
1095
1096 SecondaryExtension->pNext = NULL;
1097 SecondaryExtension->pPrimary = PrimaryExtension;
1098 SecondaryExtension->iDevice = iDisplay;
1099 SecondaryExtension->ulFrameBufferOffset = 0;
1100 SecondaryExtension->ulFrameBufferSize = 0;
1101 SecondaryExtension->u.secondary.bEnabled = FALSE;
1102
1103 /* Update the list pointers. */
1104 pPrev->pNext = SecondaryExtension;
1105 pPrev = SecondaryExtension;
1106
1107 /* Take the successfully created display into account. */
1108 PrimaryExtension->u.primary.cDisplays++;
1109 }
1110
1111 /* Failure to create secondary displays is not fatal */
1112 rc = NO_ERROR;
1113 }
1114 }
1115
1116 /* Now when the number of monitors is known and extensions are created,
1117 * calculate the layout of framebuffers.
1118 */
1119 VBoxComputeFrameBufferSizes (PrimaryExtension);
1120
1121 if (PrimaryExtension->u.primary.bVBoxVideoSupported)
1122 {
1123 /* Setup the information for the host. */
1124 vboxSetupAdapterInfo (PrimaryExtension);
1125 }
1126 else
1127 {
1128 /* Unmap the memory if VBoxVideo is not supported. */
1129 VBoxUnmapAdapterMemory (PrimaryExtension, &PrimaryExtension->u.primary.pvMiniportHeap);
1130 VBoxUnmapAdapterMemory (PrimaryExtension, &PrimaryExtension->u.primary.pvAdapterInformation);
1131 }
1132
1133 dprintf(("VBoxVideo::VBoxSetupDisplays: finished\n"));
1134}
1135#endif /* VBOX_WITH_HGSMI */
1136
1137VP_STATUS VBoxVideoFindAdapter(IN PVOID HwDeviceExtension,
1138 IN PVOID HwContext, IN PWSTR ArgumentString,
1139 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
1140 OUT PUCHAR Again)
1141{
1142 VP_STATUS rc;
1143 USHORT DispiId;
1144 ULONG AdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
1145 VIDEO_ACCESS_RANGE AccessRanges[] =
1146 {
1147 {
1148 {0, VBE_DISPI_LFB_PHYSICAL_ADDRESS},
1149 VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES,
1150 0,
1151 FALSE,
1152 FALSE,
1153 0
1154 }
1155 };
1156
1157 dprintf(("VBoxVideo::VBoxVideoFindAdapter\n"));
1158
1159 VideoPortCreateSpinLock(HwDeviceExtension, &((PDEVICE_EXTENSION)HwDeviceExtension)->u.primary.pGHRWLock);
1160
1161 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
1162 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
1163 DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
1164 if (DispiId == VBE_DISPI_ID2)
1165 {
1166 dprintf(("VBoxVideo::VBoxVideoFoundAdapter: found the VBE card\n"));
1167 /*
1168 * Write some hardware information to registry, so that
1169 * it's visible in Windows property dialog.
1170 */
1171
1172 rc = VideoPortSetRegistryParameters(
1173 HwDeviceExtension,
1174 L"HardwareInformation.ChipType",
1175 VBoxChipType,
1176 sizeof(VBoxChipType));
1177
1178 rc = VideoPortSetRegistryParameters(
1179 HwDeviceExtension,
1180 L"HardwareInformation.DacType",
1181 VBoxDACType,
1182 sizeof(VBoxDACType));
1183
1184 /*
1185 * Query the adapter's memory size. It's a bit of a hack, we just read
1186 * an ULONG from the data port without setting an index before.
1187 */
1188 AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
1189 rc = VideoPortSetRegistryParameters(
1190 HwDeviceExtension,
1191 L"HardwareInformation.MemorySize",
1192 &AdapterMemorySize,
1193 sizeof(ULONG));
1194
1195 rc = VideoPortSetRegistryParameters(
1196 HwDeviceExtension,
1197 L"HardwareInformation.AdapterString",
1198 VBoxAdapterString,
1199 sizeof(VBoxAdapterString));
1200
1201 rc = VideoPortSetRegistryParameters(
1202 HwDeviceExtension,
1203 L"HardwareInformation.BiosString",
1204 VBoxBiosString,
1205 sizeof(VBoxBiosString));
1206#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
1207 VIDEO_ACCESS_RANGE tmpRanges[1];
1208 ULONG slot;
1209
1210 /* need to call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */
1211 VP_STATUS status = VideoPortGetAccessRanges(HwDeviceExtension,
1212 0,
1213 NULL,
1214 1,
1215 tmpRanges,
1216 NULL,
1217 NULL,
1218 (PULONG) &slot);
1219 Assert(status == NO_ERROR );
1220// Assert(AccessRanges[0].RangeStart.QuadPart == tmpRanges[0].RangeStart.QuadPart);
1221// Assert(AccessRanges[0].RangeLength == tmpRanges[0].RangeLength);
1222// Assert(AccessRanges[0].RangeInIoSpace == tmpRanges[0].RangeInIoSpace);
1223// Assert(AccessRanges[0].RangeVisible == tmpRanges[0].RangeVisible);
1224// Assert(AccessRanges[0].RangeShareable == tmpRanges[0].RangeShareable);
1225// Assert(AccessRanges[0].RangePassive == tmpRanges[0].RangePassive);
1226
1227 /* no matter what we get with VideoPortGetAccessRanges, we assert the default ranges */
1228#endif
1229 rc = VideoPortVerifyAccessRanges(HwDeviceExtension, 1, AccessRanges);
1230 dprintf(("VBoxVideo::VBoxVideoFindAdapter: VideoPortVerifyAccessRanges returned 0x%x\n", rc));
1231 // @todo for some reason, I get an ERROR_INVALID_PARAMETER from NT4 SP0
1232 // It does not seem to like getting me these port addresses. So I just
1233 // pretend success to make the driver work.
1234 rc = NO_ERROR;
1235
1236#ifndef VBOX_WITH_HGSMI
1237 /* Initialize VBoxGuest library */
1238 rc = VbglInit ();
1239
1240 dprintf(("VBoxVideo::VBoxVideoFindAdapter: VbglInit returned 0x%x\n", rc));
1241
1242 /* Setup the Device Extension and if possible secondary displays. */
1243 VBoxSetupDisplays((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo, AdapterMemorySize);
1244#else
1245 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
1246 rc = VbglInit ();
1247
1248 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old
1249 * code will be ifdef'ed and later removed.
1250 * The host will however support both old and new interface to keep compatibility
1251 * with old guest additions.
1252 */
1253 if (VBoxHGSMIIsSupported ((PDEVICE_EXTENSION)HwDeviceExtension))
1254 {
1255 LogRel(("VBoxVideo: using HGSMI\n"));
1256
1257 VBoxSetupDisplaysHGSMI((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo, AdapterMemorySize);
1258 }
1259#endif /* VBOX_WITH_HGSMI */
1260
1261 // pretend success to make the driver work.
1262 rc = NO_ERROR;
1263 } else
1264 {
1265 dprintf(("VBoxVideo::VBoxVideoFindAdapter: VBE card not found, returning ERROR_DEV_NOT_EXIST\n"));
1266 rc = ERROR_DEV_NOT_EXIST;
1267 }
1268 dprintf(("VBoxVideo::VBoxVideoFindAdapter: returning with rc = 0x%x\n", rc));
1269 return rc;
1270}
1271
1272/**
1273 * VBoxVideoInitialize
1274 *
1275 * Performs the first initialization of the adapter, after the HAL has given
1276 * up control of the video hardware to the video port driver.
1277 */
1278BOOLEAN VBoxVideoInitialize(PVOID HwDeviceExtension)
1279{
1280 VP_STATUS status;
1281
1282 dprintf(("VBoxVideo::VBoxVideoInitialize\n"));
1283
1284 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
1285
1286 /* Initialize the request pointer. */
1287 pDevExt->u.primary.pvReqFlush = NULL;
1288
1289 /*
1290 * Get the last custom resolution
1291 */
1292 status = VideoPortGetRegistryParameters(HwDeviceExtension,
1293 L"CustomXRes",
1294 FALSE,
1295 VBoxRegistryCallback,
1296 &gCustomXRes);
1297 if (status != NO_ERROR)
1298 gCustomXRes = 0;
1299 status = VideoPortGetRegistryParameters(HwDeviceExtension,
1300 L"CustomYRes",
1301 FALSE,
1302 VBoxRegistryCallback,
1303 &gCustomYRes);
1304 if (status != NO_ERROR)
1305 gCustomYRes = 0;
1306 status = VideoPortGetRegistryParameters(HwDeviceExtension,
1307 L"CustomBPP",
1308 FALSE,
1309 VBoxRegistryCallback,
1310 &gCustomBPP);
1311 if (status != NO_ERROR)
1312 gCustomBPP = 0;
1313
1314 dprintf(("VBoxVideo: got stored custom resolution %dx%dx%d\n", gCustomXRes, gCustomYRes, gCustomBPP));
1315
1316 return TRUE;
1317}
1318
1319#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
1320
1321BOOLEAN VBoxVideoInterrupt(PVOID HwDeviceExtension)
1322{
1323 PDEVICE_EXTENSION devExt = (PDEVICE_EXTENSION)HwDeviceExtension;
1324 PDEVICE_EXTENSION PrimaryExtension = devExt->pPrimary;
1325 uint32_t flags = PrimaryExtension->u.primary.pHostFlags->u32HostFlags;
1326 if((flags & HGSMIHOSTFLAGS_IRQ) != 0)
1327 {
1328 if((flags & HGSMIHOSTFLAGS_COMMANDS_PENDING) != 0)
1329 {
1330 /* schedule a DPC*/
1331 BOOLEAN bResult = VideoPortQueueDpc(PrimaryExtension, VBoxVideoHGSMIDpc, (PVOID)1);
1332 Assert(bResult);
1333 }
1334 /* clear the IRQ */
1335 HGSMIClearIrq (PrimaryExtension);
1336 return TRUE;
1337 }
1338 return FALSE;
1339}
1340#endif
1341
1342/**
1343 * VBoxVideoStartIO
1344 *
1345 * Processes the specified Video Request Packet.
1346 */
1347BOOLEAN VBoxVideoStartIO(PVOID HwDeviceExtension,
1348 PVIDEO_REQUEST_PACKET RequestPacket)
1349{
1350 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
1351
1352 BOOLEAN Result;
1353
1354// dprintf(("VBoxVideo::VBoxVideoStartIO: Code %08X\n", RequestPacket->IoControlCode));
1355
1356 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1357
1358 switch (RequestPacket->IoControlCode)
1359 {
1360 case IOCTL_VIDEO_SET_CURRENT_MODE:
1361 {
1362 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
1363 {
1364 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1365 return TRUE;
1366 }
1367 Result = VBoxVideoSetCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
1368 (PVIDEO_MODE)RequestPacket->InputBuffer,
1369 RequestPacket->StatusBlock);
1370 break;
1371 }
1372
1373 case IOCTL_VIDEO_RESET_DEVICE:
1374 {
1375 Result = VBoxVideoResetDevice((PDEVICE_EXTENSION)HwDeviceExtension,
1376 RequestPacket->StatusBlock);
1377 break;
1378 }
1379
1380 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
1381 {
1382 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
1383 RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
1384 {
1385 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1386 return TRUE;
1387 }
1388 Result = VBoxVideoMapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
1389 (PVIDEO_MEMORY)RequestPacket->InputBuffer,
1390 (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer,
1391 RequestPacket->StatusBlock);
1392 break;
1393 }
1394
1395 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
1396 {
1397 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
1398 {
1399 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1400 return TRUE;
1401 }
1402 Result = VBoxVideoUnmapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
1403 (PVIDEO_MEMORY)RequestPacket->InputBuffer,
1404 RequestPacket->StatusBlock);
1405 break;
1406 }
1407
1408 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
1409 {
1410 PVIDEO_SHARE_MEMORY pShareMemory;
1411 PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
1412 PHYSICAL_ADDRESS shareAddress;
1413 PVOID virtualAddress = NULL;
1414 ULONG sharedViewSize;
1415 ULONG inIoSpace = 0;
1416 VP_STATUS status;
1417
1418 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY\n"));
1419
1420 if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION))
1421 || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
1422
1423 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
1424 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1425 Result = FALSE;
1426 break;
1427 }
1428
1429 pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
1430
1431 if ( (pShareMemory->ViewOffset > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize)
1432 || ((pShareMemory->ViewOffset + pShareMemory->ViewSize) > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize) ) {
1433
1434 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INVALID_PARAMETER %x:%x size %x\n", pShareMemory->ViewOffset, pShareMemory->ViewSize, pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize));
1435 RequestPacket->StatusBlock->Status = ERROR_INVALID_PARAMETER;
1436 Result = FALSE;
1437 break;
1438 }
1439
1440 RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
1441
1442 virtualAddress = pShareMemory->ProcessHandle;
1443 sharedViewSize = pShareMemory->ViewSize;
1444
1445 shareAddress.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + pDevExt->ulFrameBufferOffset;
1446
1447 status = VideoPortMapMemory(HwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress);
1448 if (status != NO_ERROR)
1449 dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortMapMemory failed with %x\n", status));
1450 Result = (status == NO_ERROR);
1451
1452 pShareMemoryInformation = (PVIDEO_SHARE_MEMORY_INFORMATION)RequestPacket->OutputBuffer;
1453 pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
1454 pShareMemoryInformation->VirtualAddress = virtualAddress;
1455 pShareMemoryInformation->SharedViewSize = sharedViewSize;
1456 break;
1457 }
1458
1459 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
1460 {
1461 PVIDEO_SHARE_MEMORY pShareMemory;
1462 VP_STATUS status;
1463
1464 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY\n"));
1465
1466 if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
1467 {
1468 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
1469 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1470 Result = FALSE;
1471 break;
1472 }
1473
1474 pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
1475
1476 status = VideoPortUnmapMemory(HwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle);
1477 if (status != NO_ERROR)
1478 dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortUnmapMemory failed with %x\n", status));
1479 Result = (status == NO_ERROR);
1480 break;
1481 }
1482
1483 /*
1484 * The display driver asks us how many video modes we support
1485 * so that it can supply an appropriate buffer for the next call.
1486 */
1487 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
1488 {
1489 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
1490 {
1491 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1492 return TRUE;
1493 }
1494 Result = VBoxVideoQueryNumAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
1495 (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer,
1496 RequestPacket->StatusBlock);
1497 break;
1498 }
1499
1500 /*
1501 * The display driver asks us to provide a list of supported video modes
1502 * into a buffer it has allocated.
1503 */
1504 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
1505 {
1506 if (RequestPacket->OutputBufferLength <
1507 gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION))
1508 {
1509 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1510 return TRUE;
1511 }
1512 Result = VBoxVideoQueryAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
1513 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
1514 RequestPacket->StatusBlock);
1515 break;
1516 }
1517
1518 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
1519 {
1520 if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) ||
1521 RequestPacket->InputBufferLength <
1522 (((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) +
1523 sizeof(VIDEO_CLUT))
1524 {
1525 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1526 return TRUE;
1527 }
1528 Result = VBoxVideoSetColorRegisters((PDEVICE_EXTENSION)HwDeviceExtension,
1529 (PVIDEO_CLUT)RequestPacket->InputBuffer,
1530 RequestPacket->StatusBlock);
1531 break;
1532 }
1533
1534 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
1535 {
1536 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
1537 {
1538 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1539 return TRUE;
1540 }
1541 Result = VBoxVideoQueryCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
1542 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
1543 RequestPacket->StatusBlock);
1544 break;
1545 }
1546
1547 // show the pointer
1548 case IOCTL_VIDEO_ENABLE_POINTER:
1549 {
1550 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_ENABLE_POINTER\n"));
1551 // find out whether the host wants absolute positioning
1552 if (vboxQueryHostWantsAbsolute())
1553 {
1554 // tell the host to use the guest's pointer
1555 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
1556
1557 /* Visible and No Shape means Show the pointer.
1558 * It is enough to init only this field.
1559 */
1560 PointerAttributes.Enable = VBOX_MOUSE_POINTER_VISIBLE;
1561
1562#ifndef VBOX_WITH_HGSMI
1563 Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
1564#else
1565 Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, &PointerAttributes, sizeof (PointerAttributes));
1566#endif/* VBOX_WITH_HGSMI */
1567
1568 if (!Result)
1569 dprintf(("VBoxVideo::VBoxVideoStartIO: Could not hide hardware pointer -> fallback\n"));
1570 } else
1571 {
1572 // fallback to software pointer
1573 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1574 Result = FALSE;
1575 }
1576 break;
1577 }
1578
1579 // hide the pointer
1580 case IOCTL_VIDEO_DISABLE_POINTER:
1581 {
1582 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_DISABLE_POINTER\n"));
1583 // find out whether the host wants absolute positioning
1584 if (vboxQueryHostWantsAbsolute())
1585 {
1586 // tell the host to hide pointer
1587 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
1588
1589 /* Enable == 0 means no shape, not visible.
1590 * It is enough to init only this field.
1591 */
1592 PointerAttributes.Enable = 0;
1593
1594#ifndef VBOX_WITH_HGSMI
1595 Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
1596#else
1597 Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, &PointerAttributes, sizeof (PointerAttributes));
1598#endif/* VBOX_WITH_HGSMI */
1599
1600 if (!Result)
1601 dprintf(("VBoxVideo::VBoxVideoStartIO: Could not hide hardware pointer -> fallback\n"));
1602 } else
1603 {
1604 // fallback to software pointer
1605 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1606 Result = FALSE;
1607 }
1608 break;
1609 }
1610
1611 /*
1612 * Change the pointer shape
1613 */
1614 case IOCTL_VIDEO_SET_POINTER_ATTR:
1615 {
1616 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_ATTR\n"));
1617 if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_ATTRIBUTES))
1618 {
1619 dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small (%d bytes)\n", RequestPacket->InputBufferLength));
1620 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1621 return TRUE;
1622 }
1623 // find out whether the host wants absolute positioning
1624 if (vboxQueryHostWantsAbsolute())
1625 {
1626 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)RequestPacket->InputBuffer;
1627#if 0
1628 dprintf(("Pointer shape information:\n"
1629 "\tFlags: %d\n"
1630 "\tWidth: %d\n"
1631 "\tHeight: %d\n"
1632 "\tWidthInBytes: %d\n"
1633 "\tEnable: %d\n"
1634 "\tColumn: %d\n"
1635 "\tRow: %d\n",
1636 pPointerAttributes->Flags, pPointerAttributes->Width, pPointerAttributes->Height,
1637 pPointerAttributes->WidthInBytes, pPointerAttributes->Enable, pPointerAttributes->Column,
1638 pPointerAttributes->Row));
1639 dprintf(("\tBytes attached: %d\n", RequestPacket->InputBufferLength - sizeof(VIDEO_POINTER_ATTRIBUTES)));
1640#endif
1641#ifndef VBOX_WITH_HGSMI
1642 Result = vboxUpdatePointerShape(pPointerAttributes, RequestPacket->InputBufferLength);
1643#else
1644 Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, pPointerAttributes, RequestPacket->InputBufferLength);
1645#endif/* VBOX_WITH_HGSMI */
1646 if (!Result)
1647 dprintf(("VBoxVideo::VBoxVideoStartIO: Could not set hardware pointer -> fallback\n"));
1648 } else
1649 {
1650 dprintf(("VBoxVideo::VBoxVideoStartIO: Fallback to software pointer\n"));
1651 // fallback to software pointer
1652 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1653 Result = FALSE;
1654 }
1655 break;
1656 }
1657
1658 // query pointer information
1659 case IOCTL_VIDEO_QUERY_POINTER_ATTR:
1660 {
1661 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_ATTR\n"));
1662 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1663 Result = FALSE;
1664 break;
1665 }
1666
1667 // set the pointer position
1668 case IOCTL_VIDEO_SET_POINTER_POSITION:
1669 {
1670 /// @todo There is an issue when we disable pointer integration.
1671 // The guest pointer will be invisible. We have to somehow cause
1672 // the pointer attributes to be set again. But how? The same holds
1673 // true for the opposite case where we get two pointers.
1674
1675 //dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_POSITION\n"));
1676 // find out whether the host wants absolute positioning
1677 if (vboxQueryHostWantsAbsolute())
1678 {
1679 // @todo we are supposed to show currently invisible pointer?
1680 Result = TRUE;
1681 } else
1682 {
1683 // fallback to software pointer
1684 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1685 Result = FALSE;
1686 }
1687 break;
1688 }
1689
1690 // query the pointer position
1691 case IOCTL_VIDEO_QUERY_POINTER_POSITION:
1692 {
1693 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_POSITION\n"));
1694 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION))
1695 {
1696 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
1697 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1698 return TRUE;
1699 }
1700 Result = FALSE;
1701 uint16_t mousePosX;
1702 uint16_t mousePosY;
1703 if (vboxQueryPointerPos(&mousePosX, &mousePosY))
1704 {
1705 PVIDEO_POINTER_POSITION pointerPos = (PVIDEO_POINTER_POSITION)RequestPacket->OutputBuffer;
1706 PVIDEO_MODE_INFORMATION ModeInfo;
1707 ModeInfo = &VideoModes[((PDEVICE_EXTENSION)HwDeviceExtension)->CurrentMode - 1];
1708 // map from 0xFFFF to the current resolution
1709 pointerPos->Column = (SHORT)(mousePosX / (0xFFFF / ModeInfo->VisScreenWidth));
1710 pointerPos->Row = (SHORT)(mousePosY / (0xFFFF / ModeInfo->VisScreenHeight));
1711 RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_POSITION);
1712 Result = TRUE;
1713 }
1714 if (!Result)
1715 {
1716 // fallback to software pointer
1717 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1718 }
1719 break;
1720 }
1721
1722 // Determine hardware cursor capabilities. We will always report that we are
1723 // very capable even though the host might not want to do pointer integration.
1724 // This is done because we can still return errors on the actual calls later to
1725 // make the display driver go to the fallback routines.
1726 case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
1727 {
1728 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES\n"));
1729 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES))
1730 {
1731 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
1732 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1733 return TRUE;
1734 }
1735 PVIDEO_POINTER_CAPABILITIES pCaps = (PVIDEO_POINTER_CAPABILITIES)RequestPacket->OutputBuffer;
1736 pCaps->Flags = VIDEO_MODE_ASYNC_POINTER |
1737 VIDEO_MODE_COLOR_POINTER |
1738 VIDEO_MODE_MONO_POINTER;
1739 // for now we go with 64x64 cursors
1740 pCaps->MaxWidth = 64;
1741 pCaps->MaxHeight = 64;
1742 // that doesn't seem to be relevant, VBoxDisp doesn't use it
1743 pCaps->HWPtrBitmapStart = -1;
1744 pCaps->HWPtrBitmapEnd = -1;
1745 RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES);
1746 Result = TRUE;
1747 break;
1748 }
1749
1750 /* Attach/detach DualView devices */
1751 case IOCTL_VIDEO_SWITCH_DUALVIEW:
1752 {
1753 ULONG ulAttach;
1754
1755 ulAttach = *((PULONG)RequestPacket->InputBuffer);
1756 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SWITCH_DUALVIEW[%d] (%ld)\n", pDevExt->iDevice, ulAttach));
1757
1758 if (pDevExt->iDevice > 0)
1759 {
1760 pDevExt->u.secondary.bEnabled = (BOOLEAN)ulAttach;
1761 }
1762 Result = TRUE;
1763 break;
1764 }
1765
1766 case IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY:
1767 {
1768 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY\n"));
1769
1770 if (pDevExt->pPrimary->u.primary.bVBoxVideoSupported)
1771 {
1772 /* The display driver must have prepared the monitor information. */
1773#ifndef VBOX_WITH_HGSMI
1774 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
1775 VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
1776#else
1777 VBoxVideoHostWriteUlong(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, VBE_DISPI_INDEX_VBOX_VIDEO, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
1778#endif
1779 }
1780 else
1781 {
1782 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1783 }
1784 Result = pDevExt->pPrimary->u.primary.bVBoxVideoSupported;
1785 break;
1786 }
1787
1788#ifndef VBOX_WITH_HGSMI
1789 case IOCTL_VIDEO_QUERY_DISPLAY_INFO:
1790 {
1791 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
1792
1793 if (RequestPacket->OutputBufferLength < sizeof(QUERYDISPLAYINFORESULT))
1794 {
1795 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1796 RequestPacket->OutputBufferLength, sizeof(QUERYDISPLAYINFORESULT)));
1797 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1798 return FALSE;
1799 }
1800
1801 QUERYDISPLAYINFORESULT *pDispInfo = (QUERYDISPLAYINFORESULT *)RequestPacket->OutputBuffer;
1802
1803 pDispInfo->iDevice = pDevExt->iDevice;
1804 pDispInfo->u32DisplayInfoSize = pDevExt->pPrimary->u.primary.ulDisplayInformationSize;
1805
1806 RequestPacket->StatusBlock->Information = sizeof(QUERYDISPLAYINFORESULT);
1807 Result = TRUE;
1808
1809 break;
1810 }
1811#endif /* !VBOX_WITH_HGSMI */
1812
1813 case IOCTL_VIDEO_VBVA_ENABLE:
1814 {
1815 int rc;
1816 ULONG ulEnable;
1817
1818 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE\n"));
1819
1820 if (RequestPacket->InputBufferLength < sizeof(ULONG))
1821 {
1822 dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small: %d needed: %d!!!\n",
1823 RequestPacket->InputBufferLength, sizeof(ULONG)));
1824 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1825 return FALSE;
1826 }
1827
1828 if (RequestPacket->OutputBufferLength < sizeof(VBVAENABLERESULT))
1829 {
1830 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1831 RequestPacket->OutputBufferLength, sizeof(VBVAENABLERESULT)));
1832 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1833 return FALSE;
1834 }
1835
1836 ulEnable = *(ULONG *)RequestPacket->InputBuffer;
1837 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE ulEnable = %08X\n", ulEnable));
1838
1839 rc = vboxVbvaEnable (pDevExt, ulEnable, (VBVAENABLERESULT *)RequestPacket->OutputBuffer);
1840 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE completed rc = %Rrc\n", rc));
1841
1842 if (RT_FAILURE (rc))
1843 {
1844 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE: failed to enable VBVA\n"));
1845 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1846 return FALSE;
1847 }
1848
1849 RequestPacket->StatusBlock->Information = sizeof(VBVAENABLERESULT);
1850 Result = TRUE;
1851
1852 break;
1853 }
1854
1855 /* Private ioctls */
1856 case IOCTL_VIDEO_VBOX_SETVISIBLEREGION:
1857 {
1858 uint32_t cRect = RequestPacket->InputBufferLength/sizeof(RTRECT);
1859 int rc;
1860
1861 dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRect=%d\n", cRect));
1862 if ( RequestPacket->InputBufferLength < sizeof(RTRECT)
1863 || RequestPacket->InputBufferLength != cRect*sizeof(RTRECT))
1864 {
1865 dprintf(("VBoxVideo::IOCTL_VIDEO_VBOX_SETVISIBLEREGION: Output buffer too small: %d needed: %d!!!\n",
1866 RequestPacket->OutputBufferLength, sizeof(RTRECT)));
1867 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1868 return FALSE;
1869 }
1870 /*
1871 * Inform the host about the visible region
1872 */
1873 VMMDevVideoSetVisibleRegion *req = NULL;
1874
1875 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
1876 sizeof (VMMDevVideoSetVisibleRegion) + (cRect-1)*sizeof(RTRECT),
1877 VMMDevReq_VideoSetVisibleRegion);
1878
1879 if (RT_SUCCESS(rc))
1880 {
1881 req->cRect = cRect;
1882 memcpy(&req->Rect, RequestPacket->InputBuffer, cRect*sizeof(RTRECT));
1883
1884 rc = VbglGRPerform (&req->header);
1885
1886 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
1887 {
1888 Result = TRUE;
1889 break;
1890 }
1891 }
1892 dprintf(("VBoxVideo::VBoxVideoStartIO: Failed with rc=%x (hdr.rc=%x)\n", rc, (req) ? req->header.rc : -1));
1893 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1894 return FALSE;
1895 }
1896
1897#ifdef VBOX_WITH_HGSMI
1898 case IOCTL_VIDEO_QUERY_HGSMI_INFO:
1899 {
1900 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_HGSMI_INFO\n"));
1901
1902 if (RequestPacket->OutputBufferLength < sizeof(QUERYHGSMIRESULT))
1903 {
1904 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1905 RequestPacket->OutputBufferLength, sizeof(QUERYHGSMIRESULT)));
1906 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1907 return FALSE;
1908 }
1909
1910 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1911 {
1912 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1913 return FALSE;
1914 }
1915
1916 QUERYHGSMIRESULT *pInfo = (QUERYHGSMIRESULT *)RequestPacket->OutputBuffer;
1917
1918 pInfo->iDevice = pDevExt->iDevice;
1919 pInfo->ulFlags = 0;
1920
1921 /* Describes VRAM chunk for this display device. */
1922 pInfo->areaDisplay = pDevExt->areaDisplay;
1923
1924 pInfo->u32DisplayInfoSize = VBVA_DISPLAY_INFORMATION_SIZE;
1925 pInfo->u32MinVBVABufferSize = VBVA_MIN_BUFFER_SIZE;
1926
1927 RequestPacket->StatusBlock->Information = sizeof(QUERYHGSMIRESULT);
1928 Result = TRUE;
1929
1930 break;
1931 }
1932 case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS:
1933 {
1934 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS\n"));
1935
1936 if (RequestPacket->OutputBufferLength < sizeof(HGSMIQUERYCALLBACKS))
1937 {
1938 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1939 RequestPacket->OutputBufferLength, sizeof(HGSMIQUERYCALLBACKS)));
1940 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1941 return FALSE;
1942 }
1943
1944 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1945 {
1946 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1947 return FALSE;
1948 }
1949
1950 HGSMIQUERYCALLBACKS *pInfo = (HGSMIQUERYCALLBACKS *)RequestPacket->OutputBuffer;
1951
1952 pInfo->hContext = pDevExt;
1953 pInfo->pfnHGSMIGHCommandPost = hgsmiGHCommandPost;
1954 pInfo->pfnCompletionHandler = hgsmiHostCmdComplete;
1955 pInfo->pfnRequestCommandsHandler = hgsmiHostCmdRequest;
1956
1957 RequestPacket->StatusBlock->Information = sizeof(HGSMIQUERYCALLBACKS);
1958 Result = TRUE;
1959 break;
1960 }
1961 case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE:
1962 {
1963 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_HANDLER_ENABLE\n"));
1964
1965 if (RequestPacket->InputBufferLength< sizeof(HGSMIHANDLERENABLE))
1966 {
1967 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1968 RequestPacket->InputBufferLength, sizeof(HGSMIHANDLERENABLE)));
1969 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1970 return FALSE;
1971 }
1972
1973 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1974 {
1975 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1976 return FALSE;
1977 }
1978
1979 HGSMIHANDLERENABLE *pInfo = (HGSMIHANDLERENABLE *)RequestPacket->InputBuffer;
1980
1981 int rc = vboxVBVAChannelDisplayEnable(pDevExt->pPrimary,
1982 pDevExt->iDevice,
1983 pInfo->u8Channel);
1984 if(RT_FAILURE(rc))
1985 {
1986 RequestPacket->StatusBlock->Status = ERROR_INVALID_NAME;
1987 }
1988 Result = TRUE;
1989 break;
1990 }
1991 case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE:
1992 {
1993 /* TODO: implement */
1994 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1995 {
1996 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1997 return FALSE;
1998 }
1999 break;
2000 }
2001#endif /* VBOX_WITH_HGSMI */
2002
2003 default:
2004 dprintf(("VBoxVideo::VBoxVideoStartIO: Unsupported %p, fn %d(0x%x)\n",
2005 RequestPacket->IoControlCode,
2006 (RequestPacket->IoControlCode >> 2) & 0xFFF,
2007 (RequestPacket->IoControlCode >> 2) & 0xFFF));
2008 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
2009 return FALSE;
2010 }
2011
2012 if (Result)
2013 RequestPacket->StatusBlock->Status = NO_ERROR;
2014 else
2015 RequestPacket->StatusBlock->Information = 0;
2016
2017// dprintf(("VBoxVideo::VBoxVideoStartIO: Completed\n"));
2018
2019 return TRUE;
2020}
2021
2022/**
2023 * VBoxVideoReset HW
2024 *
2025 * Resets the video hardware.
2026 */
2027BOOLEAN VBoxVideoResetHW(PVOID HwDeviceExtension, ULONG Columns, ULONG Rows)
2028{
2029 dprintf(("VBoxVideo::VBoxVideoResetHW\n"));
2030
2031 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
2032
2033 if (pDevExt->iDevice > 0)
2034 {
2035 dprintf(("VBoxVideo::VBoxVideoResetHW: Skipping for non-primary display %d\n",
2036 pDevExt->iDevice));
2037 return TRUE;
2038 }
2039
2040#ifndef VBOX_WITH_HGSMI
2041 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2042 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
2043#else
2044 VBoxVideoHostWriteUshort(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
2045#endif
2046
2047 if (pDevExt->u.primary.pvReqFlush != NULL)
2048 {
2049 VbglGRFree ((VMMDevRequestHeader *)pDevExt->u.primary.pvReqFlush);
2050 pDevExt->u.primary.pvReqFlush = NULL;
2051 }
2052
2053 VbglTerminate ();
2054
2055 VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvMiniportHeap);
2056 VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvAdapterInformation);
2057
2058 return TRUE;
2059}
2060
2061/**
2062 * VBoxVideoGetPowerState
2063 *
2064 * Queries whether the device can support the requested power state.
2065 */
2066VP_STATUS VBoxVideoGetPowerState(PVOID HwDeviceExtension, ULONG HwId,
2067 PVIDEO_POWER_MANAGEMENT VideoPowerControl)
2068{
2069 dprintf(("VBoxVideo::VBoxVideoGetPowerState\n"));
2070 return NO_ERROR;
2071}
2072
2073/**
2074 * VBoxVideoSetPowerState
2075 *
2076 * Sets the power state of the specified device
2077 */
2078VP_STATUS VBoxVideoSetPowerState(PVOID HwDeviceExtension, ULONG HwId,
2079 PVIDEO_POWER_MANAGEMENT VideoPowerControl)
2080{
2081 dprintf(("VBoxVideo::VBoxVideoSetPowerState\n"));
2082 return NO_ERROR;
2083}
2084
2085/**
2086 * VBoxVideoSetGraphicsCap
2087 *
2088 * Tells the host whether or not we currently support graphics in the
2089 * additions
2090 */
2091BOOLEAN FASTCALL VBoxVideoSetGraphicsCap(BOOLEAN isEnabled)
2092{
2093 VMMDevReqGuestCapabilities2 *req = NULL;
2094 int rc;
2095
2096 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2097 sizeof (VMMDevReqGuestCapabilities2),
2098 VMMDevReq_SetGuestCapabilities);
2099
2100 if (!RT_SUCCESS(rc))
2101 dprintf(("VBoxVideoSetGraphicsCap: failed to allocate a request, rc=%Rrc\n", rc));
2102 else
2103 {
2104 req->u32OrMask = isEnabled ? VMMDEV_GUEST_SUPPORTS_GRAPHICS : 0;
2105 req->u32NotMask = isEnabled ? 0 : VMMDEV_GUEST_SUPPORTS_GRAPHICS;
2106
2107 rc = VbglGRPerform (&req->header);
2108 if (!RT_SUCCESS(rc) || !RT_SUCCESS(req->header.rc))
2109 dprintf(("VBoxVideoSetGraphicsCap: request failed, rc = %Rrc, VMMDev rc = %Rrc\n", rc, req->header.rc));
2110 if (RT_SUCCESS(rc))
2111 rc = req->header.rc;
2112 }
2113 if (req != NULL)
2114 VbglGRFree (&req->header);
2115 return RT_SUCCESS(rc);
2116}
2117
2118/**
2119 * VBoxVideoSetCurrentMode
2120 *
2121 * Sets the adapter to the specified operating mode.
2122 */
2123BOOLEAN FASTCALL VBoxVideoSetCurrentMode(PDEVICE_EXTENSION DeviceExtension,
2124 PVIDEO_MODE RequestedMode, PSTATUS_BLOCK StatusBlock)
2125{
2126 PVIDEO_MODE_INFORMATION ModeInfo;
2127
2128 dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: mode = %d\n", RequestedMode->RequestedMode));
2129
2130 DeviceExtension->CurrentMode = RequestedMode->RequestedMode;
2131 ModeInfo = &VideoModes[DeviceExtension->CurrentMode - 1];
2132 dprintf(("VBoxVideoSetCurrentMode: width: %d, height: %d, bpp: %d\n", ModeInfo->VisScreenWidth,
2133 ModeInfo->VisScreenHeight, ModeInfo->BitsPerPlane));
2134
2135 DeviceExtension->CurrentModeWidth = ModeInfo->VisScreenWidth;
2136 DeviceExtension->CurrentModeHeight = ModeInfo->VisScreenHeight;
2137 DeviceExtension->CurrentModeBPP = ModeInfo->BitsPerPlane;
2138
2139 if (DeviceExtension->iDevice > 0)
2140 {
2141 dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: Skipping for non-primary display %d\n",
2142 DeviceExtension->iDevice));
2143 return TRUE;
2144 }
2145
2146 /* set the mode characteristics */
2147#ifndef VBOX_WITH_HGSMI
2148 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
2149 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenWidth);
2150 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
2151 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenHeight);
2152 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
2153 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->BitsPerPlane);
2154 /* enable the mode */
2155 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2156 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
2157 /** @todo read from the port to see if the mode switch was successful */
2158#else
2159 VBoxVideoHostWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_XRES, (USHORT)ModeInfo->VisScreenWidth);
2160 VBoxVideoHostWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_YRES, (USHORT)ModeInfo->VisScreenHeight);
2161 VBoxVideoHostWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_BPP, (USHORT)ModeInfo->BitsPerPlane);
2162 VBoxVideoHostWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
2163#endif
2164
2165 /* Tell the host that we now support graphics in the additions.
2166 * @todo: Keep old behaviour, because VBoxVideoResetDevice is called on every graphics
2167 * mode switch and causes an OFF/ON sequence which is not handled by frontends
2168 * (for example Qt GUI debug build asserts when seamless is being enabled).
2169 */
2170 // VBoxVideoSetGraphicsCap(TRUE);
2171 return TRUE;
2172}
2173
2174/*
2175 * VBoxVideoResetDevice
2176 *
2177 * Resets the video hardware to the default mode, to which it was initialized
2178 * at system boot.
2179 */
2180
2181BOOLEAN FASTCALL VBoxVideoResetDevice(
2182 PDEVICE_EXTENSION DeviceExtension,
2183 PSTATUS_BLOCK StatusBlock)
2184{
2185 dprintf(("VBoxVideo::VBoxVideoResetDevice\n"));
2186
2187 if (DeviceExtension->iDevice > 0)
2188 {
2189 /* If the device is the secondary display, however, it is recommended that no action be taken. */
2190 dprintf(("VBoxVideo::VBoxVideoResetDevice: Skipping for non-primary display %d\n",
2191 DeviceExtension->iDevice));
2192 return TRUE;
2193 }
2194
2195#if 0
2196 /* Don't disable the extended video mode. This would only switch the video mode
2197 * to <current width> x <current height> x 0 bpp which is not what we want. And
2198 * even worse, it causes an disturbing additional mode switch */
2199 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2200 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
2201#endif
2202
2203 /* Tell the host that we no longer support graphics in the additions
2204 * @todo: Keep old behaviour, see similar comment in VBoxVideoSetCurrentMode for details.
2205 */
2206 // VBoxVideoSetGraphicsCap(FALSE);
2207 return TRUE;
2208}
2209
2210/**
2211 * VBoxVideoMapVideoMemory
2212 *
2213 * Maps the video hardware frame buffer and video RAM into the virtual address
2214 * space of the requestor.
2215 */
2216BOOLEAN FASTCALL VBoxVideoMapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
2217 PVIDEO_MEMORY RequestedAddress,
2218 PVIDEO_MEMORY_INFORMATION MapInformation,
2219 PSTATUS_BLOCK StatusBlock)
2220{
2221 PHYSICAL_ADDRESS FrameBuffer;
2222 ULONG inIoSpace = 0;
2223 VP_STATUS Status;
2224
2225 dprintf(("VBoxVideo::VBoxVideoMapVideoMemory\n"));
2226
2227 FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + DeviceExtension->ulFrameBufferOffset;
2228
2229 MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
2230#ifndef VBOX_WITH_HGSMI
2231 MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize
2232 + DeviceExtension->pPrimary->u.primary.ulDisplayInformationSize;
2233#else
2234 MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
2235#endif /* VBOX_WITH_HGSMI */
2236
2237 Status = VideoPortMapMemory(DeviceExtension, FrameBuffer,
2238 &MapInformation->VideoRamLength, &inIoSpace,
2239 &MapInformation->VideoRamBase);
2240
2241 if (Status == NO_ERROR)
2242 {
2243 MapInformation->FrameBufferBase = (PUCHAR)MapInformation->VideoRamBase;
2244 MapInformation->FrameBufferLength =
2245 VideoModes[DeviceExtension->CurrentMode - 1].VisScreenHeight *
2246 VideoModes[DeviceExtension->CurrentMode - 1].ScreenStride;
2247 StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
2248
2249 /* Save the new framebuffer size */
2250 DeviceExtension->ulFrameBufferSize = MapInformation->FrameBufferLength;
2251#ifdef VBOX_WITH_HGSMI
2252 HGSMIAreaInitialize (&DeviceExtension->areaDisplay,
2253 MapInformation->FrameBufferBase,
2254 MapInformation->FrameBufferLength,
2255 DeviceExtension->ulFrameBufferOffset);
2256#endif /* VBOX_WITH_HGSMI */
2257 return TRUE;
2258 }
2259
2260 return FALSE;
2261}
2262
2263/**
2264 * VBoxVideoUnmapVideoMemory
2265 *
2266 * Releases a mapping between the virtual address space and the adapter's
2267 * frame buffer and video RAM.
2268 */
2269BOOLEAN FASTCALL VBoxVideoUnmapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
2270 PVIDEO_MEMORY VideoMemory, PSTATUS_BLOCK StatusBlock)
2271{
2272 dprintf(("VBoxVideo::VBoxVideoUnmapVideoMemory\n"));
2273#ifdef VBOX_WITH_HGSMI
2274 HGSMIAreaClear (&DeviceExtension->areaDisplay);
2275#endif /* VBOX_WITH_HGSMI */
2276 VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress, NULL);
2277 return TRUE;
2278}
2279
2280/**
2281 * VBoxVideoQueryNumAvailModes
2282 *
2283 * Returns the number of video modes supported by the adapter and the size
2284 * in bytes of the video mode information, which can be used to allocate a
2285 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
2286 */
2287BOOLEAN FASTCALL VBoxVideoQueryNumAvailModes(PDEVICE_EXTENSION DeviceExtension,
2288 PVIDEO_NUM_MODES Modes, PSTATUS_BLOCK StatusBlock)
2289{
2290 dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes\n"));
2291 /* calculate the video modes table */
2292 VBoxBuildModesTable(DeviceExtension);
2293 Modes->NumModes = gNumVideoModes;
2294 Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
2295 StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
2296 dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes: number of modes: %d\n", Modes->NumModes));
2297 return TRUE;
2298}
2299
2300/**
2301 * VBoxVideoQueryAvailModes
2302 *
2303 * Returns information about each video mode supported by the adapter.
2304 */
2305BOOLEAN FASTCALL VBoxVideoQueryAvailModes(PDEVICE_EXTENSION DeviceExtension,
2306 PVIDEO_MODE_INFORMATION ReturnedModes,
2307 PSTATUS_BLOCK StatusBlock)
2308{
2309 ULONG Size;
2310
2311 dprintf(("VBoxVideo::VBoxVideoQueryAvailModes\n"));
2312
2313 Size = gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION);
2314 VideoPortMoveMemory(ReturnedModes, VideoModes, Size);
2315 StatusBlock->Information = Size;
2316
2317 return TRUE;
2318}
2319
2320/**
2321 * VBoxVideoQueryCurrentMode
2322 *
2323 * Returns information about current video mode.
2324 */
2325BOOLEAN FASTCALL VBoxVideoQueryCurrentMode(PDEVICE_EXTENSION DeviceExtension,
2326 PVIDEO_MODE_INFORMATION VideoModeInfo,
2327 PSTATUS_BLOCK StatusBlock)
2328{
2329 dprintf(("VBoxVideo::VBoxVideoQueryCurrentMode\n"));
2330
2331 StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
2332 VideoPortMoveMemory(VideoModeInfo, VideoModes + DeviceExtension->CurrentMode - 1, 1);
2333
2334 return TRUE;
2335}
2336
2337/*
2338 * VBoxVideoSetColorRegisters
2339 *
2340 * Sets the adapter's color registers to the specified RGB values. There
2341 * are code paths in this function, one generic and one for VGA compatible
2342 * controllers. The latter is needed for Bochs, where the generic one isn't
2343 * yet implemented.
2344 */
2345
2346BOOLEAN FASTCALL VBoxVideoSetColorRegisters(
2347 PDEVICE_EXTENSION DeviceExtension,
2348 PVIDEO_CLUT ColorLookUpTable,
2349 PSTATUS_BLOCK StatusBlock)
2350{
2351 LONG Entry;
2352
2353 dprintf(("VBoxVideo::VBoxVideoSetColorRegisters first entry %d num entries %d\n", ColorLookUpTable->FirstEntry, ColorLookUpTable->NumEntries));
2354
2355 if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256)
2356 return FALSE;
2357
2358 for (Entry = ColorLookUpTable->FirstEntry;
2359 Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
2360 Entry++)
2361 {
2362 VideoPortWritePortUchar((PUCHAR)0x03c8, (UCHAR)Entry);
2363 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red);
2364 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
2365 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
2366 }
2367
2368 return TRUE;
2369}
2370
2371VP_STATUS VBoxVideoGetChildDescriptor(
2372 PVOID HwDeviceExtension,
2373 PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
2374 PVIDEO_CHILD_TYPE VideoChildType,
2375 PUCHAR pChildDescriptor,
2376 PULONG pUId,
2377 PULONG pUnused)
2378{
2379 dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor: HwDeviceExtension = %p, ChildEnumInfo = %p\n",
2380 HwDeviceExtension, ChildEnumInfo));
2381
2382 DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)HwDeviceExtension;
2383
2384 if (ChildEnumInfo->ChildIndex > 0)
2385 {
2386 if ((int)ChildEnumInfo->ChildIndex <= pDevExt->pPrimary->u.primary.cDisplays)
2387 {
2388 *VideoChildType = Monitor;
2389 *pUId = ChildEnumInfo->ChildIndex;
2390
2391 return VIDEO_ENUM_MORE_DEVICES;
2392 }
2393 }
2394
2395 return ERROR_NO_MORE_DEVICES;
2396}
2397
2398
2399static DECLCALLBACK(void) vboxVbvaFlush (void *pvFlush)
2400{
2401 DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)pvFlush;
2402 DEVICE_EXTENSION *pPrimaryDevExt = pDevExt? pDevExt->pPrimary: NULL;
2403
2404 if (pPrimaryDevExt)
2405 {
2406 VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pPrimaryDevExt->u.primary.pvReqFlush;
2407
2408 if (req)
2409 {
2410 int rc = VbglGRPerform (&req->header);
2411
2412 if (RT_FAILURE(rc) || RT_FAILURE(req->header.rc))
2413 {
2414 dprintf(("VBoxVideo::vbvaFlush: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
2415 }
2416 }
2417 }
2418
2419 return;
2420}
2421
2422int vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult)
2423{
2424 int rc = VINF_SUCCESS;
2425
2426 dprintf(("VBoxVideo::vboxVbvaEnable: ulEnable = %08X, pVbvaResult = %p\n", ulEnable, pVbvaResult));
2427
2428 /*
2429 * Query the VMMDev memory pointer. There we need VBVAMemory.
2430 */
2431 VMMDevMemory *pVMMDevMemory = NULL;
2432
2433 rc = VbglQueryVMMDevMemory (&pVMMDevMemory);
2434
2435 dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %d, pVMMDevMemory = %p\n", rc, pVMMDevMemory));
2436
2437 if (pDevExt->iDevice > 0)
2438 {
2439 DEVICE_EXTENSION *pPrimaryDevExt = pDevExt->pPrimary;
2440
2441 dprintf(("VBoxVideo::vboxVbvaEnable: Skipping for non-primary display %d\n",
2442 pDevExt->iDevice));
2443
2444 if ( ulEnable
2445 && pPrimaryDevExt->u.primary.ulVbvaEnabled)
2446 {
2447 pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
2448 pVbvaResult->pfnFlush = vboxVbvaFlush;
2449 pVbvaResult->pvFlush = pDevExt;
2450 }
2451 else
2452 {
2453 VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
2454 }
2455
2456 return rc;
2457 }
2458
2459 if (RT_SUCCESS(rc))
2460 {
2461 /* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */
2462 if (pDevExt->u.primary.pvReqFlush == NULL)
2463 {
2464 VMMDevVideoAccelFlush *req = NULL;
2465
2466 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2467 sizeof (VMMDevVideoAccelFlush),
2468 VMMDevReq_VideoAccelFlush);
2469
2470 if (RT_SUCCESS (rc))
2471 {
2472 pDevExt->u.primary.pvReqFlush = req;
2473 }
2474 else
2475 {
2476 dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc (VMMDevReq_VideoAccelFlush) rc = %Rrc!!!\n", rc));
2477 }
2478 }
2479 }
2480 else
2481 {
2482 dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %Rrc!!!\n", rc));
2483 }
2484
2485 if (RT_SUCCESS(rc))
2486 {
2487 ULONG ulEnabled = 0;
2488
2489 /*
2490 * Tell host that VBVA status is changed.
2491 */
2492 VMMDevVideoAccelEnable *req = NULL;
2493
2494 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2495 sizeof (VMMDevVideoAccelEnable),
2496 VMMDevReq_VideoAccelEnable);
2497
2498 if (RT_SUCCESS(rc))
2499 {
2500 req->u32Enable = ulEnable;
2501 req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
2502 req->fu32Status = 0;
2503
2504 rc = VbglGRPerform (&req->header);
2505
2506 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
2507 {
2508 if (req->fu32Status & VBVA_F_STATUS_ACCEPTED)
2509 {
2510 /*
2511 * Initialize the result information and VBVA memory.
2512 */
2513 if (req->fu32Status & VBVA_F_STATUS_ENABLED)
2514 {
2515 pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
2516 pVbvaResult->pfnFlush = vboxVbvaFlush;
2517 pVbvaResult->pvFlush = pDevExt;
2518 ulEnabled = 1;
2519 }
2520 else
2521 {
2522 VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
2523 }
2524
2525 dprintf(("VBoxVideo::vboxVbvaEnable: success.\n"));
2526 }
2527 else
2528 {
2529 dprintf(("VBoxVideo::vboxVbvaEnable: not accepted.\n"));
2530
2531 /* Disable VBVA for old hosts. */
2532 req->u32Enable = 0;
2533 req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
2534 req->fu32Status = 0;
2535
2536 VbglGRPerform (&req->header);
2537
2538 rc = VERR_NOT_SUPPORTED;
2539 }
2540 }
2541 else
2542 {
2543 dprintf(("VBoxVideo::vboxVbvaEnable: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
2544
2545 if (RT_SUCCESS(rc))
2546 {
2547 rc = req->header.rc;
2548 }
2549 }
2550
2551 VbglGRFree (&req->header);
2552 }
2553 else
2554 {
2555 dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc rc = %Rrc!!!\n", rc));
2556 }
2557
2558 pDevExt->pPrimary->u.primary.ulVbvaEnabled = ulEnabled;
2559 }
2560
2561 return rc;
2562}
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