VirtualBox

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

Last change on this file since 22547 was 22547, checked in by vboxsync, 16 years ago

Windows guest VBoxVideo logging, uninitialized variable.

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