VirtualBox

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

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

VBoxVideo/win: proper handling OS version information for win > XP & make VideoPort be properly initialized for win > XP

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 103.4 KB
Line 
1/*
2 * VirtualBox Video miniport driver for NT/2k/XP
3 *
4 * Based on DDK sample code.
5 *
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
17 * Clara, CA 95054 USA or visit http://www.sun.com if you need
18 * additional information or have any questions.
19 */
20
21#include "VBoxVideo.h"
22#include "Helper.h"
23
24#include <iprt/log.h>
25#include <VBox/VMMDev.h>
26#include <VBox/VBoxGuest.h>
27#include <VBox/VBoxVideo.h>
28
29#include <VBox/VBoxGuestLib.h>
30#include <VBoxDisplay.h>
31
32#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\n"));
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 LogRelFlowFunc(("\n"));
1376 BOOLEAN Result;
1377
1378 if (DEV_MOUSE_HIDDEN((PDEVICE_EXTENSION)HwDeviceExtension))
1379 {
1380 // tell the host to use the guest's pointer
1381 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
1382
1383 /* Visible and No Shape means Show the pointer.
1384 * It is enough to init only this field.
1385 */
1386 PointerAttributes.Enable = VBOX_MOUSE_POINTER_VISIBLE;
1387
1388#ifndef VBOX_WITH_HGSMI
1389 Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
1390#else
1391 Result = vboxUpdatePointerShape(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, &PointerAttributes, sizeof (PointerAttributes));
1392#endif /* VBOX_WITH_HGSMI */
1393
1394 if (Result)
1395 DEV_SET_MOUSE_SHOWN((PDEVICE_EXTENSION)HwDeviceExtension);
1396 else
1397 dprintf(("VBoxVideo::ShowPointer: Could not show the hardware pointer -> fallback\n"));
1398 }
1399 LogRelFlowFunc(("returning %d\n", Result));
1400 return Result;
1401}
1402
1403/**
1404 * VBoxVideoStartIO
1405 *
1406 * Processes the specified Video Request Packet.
1407 */
1408BOOLEAN VBoxVideoStartIO(PVOID HwDeviceExtension,
1409 PVIDEO_REQUEST_PACKET RequestPacket)
1410{
1411 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
1412
1413 BOOLEAN Result;
1414
1415// dprintf(("VBoxVideo::VBoxVideoStartIO: Code %08X\n", RequestPacket->IoControlCode));
1416
1417 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1418
1419 switch (RequestPacket->IoControlCode)
1420 {
1421 case IOCTL_VIDEO_SET_CURRENT_MODE:
1422 {
1423 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
1424 {
1425 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1426 return TRUE;
1427 }
1428 Result = VBoxVideoSetCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
1429 (PVIDEO_MODE)RequestPacket->InputBuffer,
1430 RequestPacket->StatusBlock);
1431 break;
1432 }
1433
1434 case IOCTL_VIDEO_RESET_DEVICE:
1435 {
1436 Result = VBoxVideoResetDevice((PDEVICE_EXTENSION)HwDeviceExtension,
1437 RequestPacket->StatusBlock);
1438 break;
1439 }
1440
1441 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
1442 {
1443 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
1444 RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
1445 {
1446 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1447 return TRUE;
1448 }
1449 Result = VBoxVideoMapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
1450 (PVIDEO_MEMORY)RequestPacket->InputBuffer,
1451 (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer,
1452 RequestPacket->StatusBlock);
1453 break;
1454 }
1455
1456 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
1457 {
1458 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
1459 {
1460 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1461 return TRUE;
1462 }
1463 Result = VBoxVideoUnmapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
1464 (PVIDEO_MEMORY)RequestPacket->InputBuffer,
1465 RequestPacket->StatusBlock);
1466 break;
1467 }
1468
1469 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
1470 {
1471 PVIDEO_SHARE_MEMORY pShareMemory;
1472 PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
1473 PHYSICAL_ADDRESS shareAddress;
1474 PVOID virtualAddress = NULL;
1475 ULONG sharedViewSize;
1476 ULONG inIoSpace = 0;
1477 VP_STATUS status;
1478
1479 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY\n"));
1480
1481 if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION))
1482 || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
1483
1484 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
1485 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1486 Result = FALSE;
1487 break;
1488 }
1489
1490 pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
1491
1492 if ( (pShareMemory->ViewOffset > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize)
1493 || ((pShareMemory->ViewOffset + pShareMemory->ViewSize) > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize) ) {
1494
1495 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));
1496 RequestPacket->StatusBlock->Status = ERROR_INVALID_PARAMETER;
1497 Result = FALSE;
1498 break;
1499 }
1500
1501 RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
1502
1503 virtualAddress = pShareMemory->ProcessHandle;
1504 sharedViewSize = pShareMemory->ViewSize;
1505
1506 shareAddress.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + pDevExt->ulFrameBufferOffset;
1507
1508 status = VideoPortMapMemory(HwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress);
1509 if (status != NO_ERROR)
1510 dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortMapMemory failed with %x\n", status));
1511 Result = (status == NO_ERROR);
1512
1513 pShareMemoryInformation = (PVIDEO_SHARE_MEMORY_INFORMATION)RequestPacket->OutputBuffer;
1514 pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
1515 pShareMemoryInformation->VirtualAddress = virtualAddress;
1516 pShareMemoryInformation->SharedViewSize = sharedViewSize;
1517 break;
1518 }
1519
1520 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
1521 {
1522 PVIDEO_SHARE_MEMORY pShareMemory;
1523 VP_STATUS status;
1524
1525 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY\n"));
1526
1527 if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
1528 {
1529 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
1530 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1531 Result = FALSE;
1532 break;
1533 }
1534
1535 pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
1536
1537 status = VideoPortUnmapMemory(HwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle);
1538 if (status != NO_ERROR)
1539 dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortUnmapMemory failed with %x\n", status));
1540 Result = (status == NO_ERROR);
1541 break;
1542 }
1543
1544 /*
1545 * The display driver asks us how many video modes we support
1546 * so that it can supply an appropriate buffer for the next call.
1547 */
1548 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
1549 {
1550 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
1551 {
1552 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1553 return TRUE;
1554 }
1555 Result = VBoxVideoQueryNumAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
1556 (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer,
1557 RequestPacket->StatusBlock);
1558 break;
1559 }
1560
1561 /*
1562 * The display driver asks us to provide a list of supported video modes
1563 * into a buffer it has allocated.
1564 */
1565 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
1566 {
1567 if (RequestPacket->OutputBufferLength <
1568 gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION))
1569 {
1570 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1571 return TRUE;
1572 }
1573 Result = VBoxVideoQueryAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
1574 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
1575 RequestPacket->StatusBlock);
1576 break;
1577 }
1578
1579 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
1580 {
1581 if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) ||
1582 RequestPacket->InputBufferLength <
1583 (((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) +
1584 sizeof(VIDEO_CLUT))
1585 {
1586 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1587 return TRUE;
1588 }
1589 Result = VBoxVideoSetColorRegisters((PDEVICE_EXTENSION)HwDeviceExtension,
1590 (PVIDEO_CLUT)RequestPacket->InputBuffer,
1591 RequestPacket->StatusBlock);
1592 break;
1593 }
1594
1595 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
1596 {
1597 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
1598 {
1599 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1600 return TRUE;
1601 }
1602 Result = VBoxVideoQueryCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
1603 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
1604 RequestPacket->StatusBlock);
1605 break;
1606 }
1607
1608 // show the pointer
1609 case IOCTL_VIDEO_ENABLE_POINTER:
1610 {
1611 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_ENABLE_POINTER\n"));
1612 // find out whether the host wants absolute positioning
1613 /// @todo this is now obsolete - remove it?
1614 if (vboxQueryHostWantsAbsolute())
1615 Result = ShowPointer(HwDeviceExtension);
1616 else
1617 {
1618 // fallback to software pointer
1619 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1620 Result = FALSE;
1621 }
1622 break;
1623 }
1624
1625 // hide the pointer
1626 case IOCTL_VIDEO_DISABLE_POINTER:
1627 {
1628 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_DISABLE_POINTER\n"));
1629 // find out whether the host wants absolute positioning
1630 if (vboxQueryHostWantsAbsolute())
1631 {
1632 // tell the host to hide pointer
1633 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
1634
1635 /* Enable == 0 means no shape, not visible.
1636 * It is enough to init only this field.
1637 */
1638 PointerAttributes.Enable = 0;
1639
1640#ifndef VBOX_WITH_HGSMI
1641 Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
1642#else
1643 Result = vboxUpdatePointerShape(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, &PointerAttributes, sizeof (PointerAttributes));
1644#endif /* VBOX_WITH_HGSMI */
1645
1646 if (Result)
1647 DEV_SET_MOUSE_HIDDEN((PDEVICE_EXTENSION)HwDeviceExtension);
1648 else
1649 dprintf(("VBoxVideo::VBoxVideoStartIO: Could not hide hardware pointer -> fallback\n"));
1650 } else
1651 {
1652 // fallback to software pointer
1653 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1654 Result = FALSE;
1655 }
1656 break;
1657 }
1658
1659 /*
1660 * Change the pointer shape
1661 */
1662 case IOCTL_VIDEO_SET_POINTER_ATTR:
1663 {
1664 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_ATTR\n"));
1665 if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_ATTRIBUTES))
1666 {
1667 dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small (%d bytes)\n", RequestPacket->InputBufferLength));
1668 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1669 return TRUE;
1670 }
1671 // find out whether the host wants absolute positioning
1672 if (vboxQueryHostWantsAbsolute())
1673 {
1674 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)RequestPacket->InputBuffer;
1675#if 0
1676 dprintf(("Pointer shape information:\n"
1677 "\tFlags: %d\n"
1678 "\tWidth: %d\n"
1679 "\tHeight: %d\n"
1680 "\tWidthInBytes: %d\n"
1681 "\tEnable: %d\n"
1682 "\tColumn: %d\n"
1683 "\tRow: %d\n",
1684 pPointerAttributes->Flags, pPointerAttributes->Width, pPointerAttributes->Height,
1685 pPointerAttributes->WidthInBytes, pPointerAttributes->Enable, pPointerAttributes->Column,
1686 pPointerAttributes->Row));
1687 dprintf(("\tBytes attached: %d\n", RequestPacket->InputBufferLength - sizeof(VIDEO_POINTER_ATTRIBUTES)));
1688#endif
1689#ifndef VBOX_WITH_HGSMI
1690 Result = vboxUpdatePointerShape(pPointerAttributes, RequestPacket->InputBufferLength);
1691#else
1692 Result = vboxUpdatePointerShape(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, pPointerAttributes, RequestPacket->InputBufferLength);
1693#endif /* VBOX_WITH_HGSMI */
1694 if (!Result)
1695 dprintf(("VBoxVideo::VBoxVideoStartIO: Could not set hardware pointer -> fallback\n"));
1696 } else
1697 {
1698 dprintf(("VBoxVideo::VBoxVideoStartIO: Fallback to software pointer\n"));
1699 // fallback to software pointer
1700 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1701 Result = FALSE;
1702 }
1703 break;
1704 }
1705
1706 // query pointer information
1707 case IOCTL_VIDEO_QUERY_POINTER_ATTR:
1708 {
1709 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_ATTR\n"));
1710 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1711 Result = FALSE;
1712 break;
1713 }
1714
1715 // set the pointer position
1716 case IOCTL_VIDEO_SET_POINTER_POSITION:
1717 {
1718 // find out whether the host wants absolute positioning
1719 /// @todo this is now obsolete - remove it?
1720 if (vboxQueryHostWantsAbsolute())
1721 Result = ShowPointer(HwDeviceExtension);
1722 else
1723 {
1724 // fallback to software pointer
1725 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1726 Result = FALSE;
1727 }
1728 break;
1729 }
1730
1731 // query the pointer position
1732 case IOCTL_VIDEO_QUERY_POINTER_POSITION:
1733 {
1734 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_POSITION\n"));
1735 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION))
1736 {
1737 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
1738 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1739 return TRUE;
1740 }
1741 Result = FALSE;
1742 uint16_t mousePosX;
1743 uint16_t mousePosY;
1744 if (vboxQueryPointerPos(&mousePosX, &mousePosY))
1745 {
1746 PVIDEO_POINTER_POSITION pointerPos = (PVIDEO_POINTER_POSITION)RequestPacket->OutputBuffer;
1747 PVIDEO_MODE_INFORMATION ModeInfo;
1748 ModeInfo = &VideoModes[((PDEVICE_EXTENSION)HwDeviceExtension)->CurrentMode - 1];
1749 // map from 0xFFFF to the current resolution
1750 pointerPos->Column = (SHORT)(mousePosX / (0xFFFF / ModeInfo->VisScreenWidth));
1751 pointerPos->Row = (SHORT)(mousePosY / (0xFFFF / ModeInfo->VisScreenHeight));
1752 RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_POSITION);
1753 Result = TRUE;
1754 }
1755 if (!Result)
1756 {
1757 // fallback to software pointer
1758 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1759 }
1760 break;
1761 }
1762
1763 // Determine hardware cursor capabilities. We will always report that we are
1764 // very capable even though the host might not want to do pointer integration.
1765 // This is done because we can still return errors on the actual calls later to
1766 // make the display driver go to the fallback routines.
1767 case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
1768 {
1769 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES\n"));
1770 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES))
1771 {
1772 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
1773 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1774 return TRUE;
1775 }
1776 PVIDEO_POINTER_CAPABILITIES pCaps = (PVIDEO_POINTER_CAPABILITIES)RequestPacket->OutputBuffer;
1777 pCaps->Flags = VIDEO_MODE_ASYNC_POINTER |
1778 VIDEO_MODE_COLOR_POINTER |
1779 VIDEO_MODE_MONO_POINTER;
1780 // for now we go with 64x64 cursors
1781 pCaps->MaxWidth = 64;
1782 pCaps->MaxHeight = 64;
1783 // that doesn't seem to be relevant, VBoxDisp doesn't use it
1784 pCaps->HWPtrBitmapStart = -1;
1785 pCaps->HWPtrBitmapEnd = -1;
1786 RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES);
1787 Result = TRUE;
1788 break;
1789 }
1790
1791 /* Attach/detach DualView devices */
1792 case IOCTL_VIDEO_SWITCH_DUALVIEW:
1793 {
1794 ULONG ulAttach;
1795
1796 ulAttach = *((PULONG)RequestPacket->InputBuffer);
1797 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SWITCH_DUALVIEW[%d] (%ld)\n", pDevExt->iDevice, ulAttach));
1798
1799 if (pDevExt->iDevice > 0)
1800 {
1801 pDevExt->u.secondary.bEnabled = (BOOLEAN)ulAttach;
1802 }
1803 Result = TRUE;
1804 break;
1805 }
1806
1807 case IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY:
1808 {
1809 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY\n"));
1810
1811 if (pDevExt->pPrimary->u.primary.bVBoxVideoSupported)
1812 {
1813 /* The display driver must have prepared the monitor information. */
1814#ifndef VBOX_WITH_HGSMI
1815 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
1816 VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
1817#else
1818 VBoxVideoVBEWriteUlong(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, VBE_DISPI_INDEX_VBOX_VIDEO, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
1819#endif
1820 }
1821 else
1822 {
1823 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1824 }
1825 Result = pDevExt->pPrimary->u.primary.bVBoxVideoSupported;
1826 break;
1827 }
1828
1829#ifndef VBOX_WITH_HGSMI
1830 case IOCTL_VIDEO_QUERY_DISPLAY_INFO:
1831 {
1832 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
1833
1834 if (RequestPacket->OutputBufferLength < sizeof(QUERYDISPLAYINFORESULT))
1835 {
1836 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1837 RequestPacket->OutputBufferLength, sizeof(QUERYDISPLAYINFORESULT)));
1838 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1839 return FALSE;
1840 }
1841
1842 QUERYDISPLAYINFORESULT *pDispInfo = (QUERYDISPLAYINFORESULT *)RequestPacket->OutputBuffer;
1843
1844 pDispInfo->iDevice = pDevExt->iDevice;
1845 pDispInfo->u32DisplayInfoSize = pDevExt->pPrimary->u.primary.ulDisplayInformationSize;
1846
1847 RequestPacket->StatusBlock->Information = sizeof(QUERYDISPLAYINFORESULT);
1848 Result = TRUE;
1849
1850 break;
1851 }
1852#endif /* !VBOX_WITH_HGSMI */
1853
1854 case IOCTL_VIDEO_VBVA_ENABLE:
1855 {
1856 int rc;
1857 ULONG ulEnable;
1858
1859 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE\n"));
1860
1861 if (RequestPacket->InputBufferLength < sizeof(ULONG))
1862 {
1863 dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small: %d needed: %d!!!\n",
1864 RequestPacket->InputBufferLength, sizeof(ULONG)));
1865 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1866 return FALSE;
1867 }
1868
1869 if (RequestPacket->OutputBufferLength < sizeof(VBVAENABLERESULT))
1870 {
1871 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1872 RequestPacket->OutputBufferLength, sizeof(VBVAENABLERESULT)));
1873 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1874 return FALSE;
1875 }
1876
1877 ulEnable = *(ULONG *)RequestPacket->InputBuffer;
1878 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE ulEnable = %08X\n", ulEnable));
1879
1880 rc = vboxVbvaEnable (pDevExt, ulEnable, (VBVAENABLERESULT *)RequestPacket->OutputBuffer);
1881 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE completed rc = %Rrc\n", rc));
1882
1883 if (RT_FAILURE (rc))
1884 {
1885 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE: failed to enable VBVA\n"));
1886 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1887 return FALSE;
1888 }
1889
1890 RequestPacket->StatusBlock->Information = sizeof(VBVAENABLERESULT);
1891 Result = TRUE;
1892
1893 break;
1894 }
1895
1896 /* Private ioctls */
1897 case IOCTL_VIDEO_VBOX_SETVISIBLEREGION:
1898 {
1899 uint32_t cRect = RequestPacket->InputBufferLength/sizeof(RTRECT);
1900 int rc;
1901
1902 dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRect=%d\n", cRect));
1903 if ( RequestPacket->InputBufferLength < sizeof(RTRECT)
1904 || RequestPacket->InputBufferLength != cRect*sizeof(RTRECT))
1905 {
1906 dprintf(("VBoxVideo::IOCTL_VIDEO_VBOX_SETVISIBLEREGION: Output buffer too small: %d needed: %d!!!\n",
1907 RequestPacket->OutputBufferLength, sizeof(RTRECT)));
1908 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1909 return FALSE;
1910 }
1911 /*
1912 * Inform the host about the visible region
1913 */
1914 VMMDevVideoSetVisibleRegion *req = NULL;
1915
1916 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
1917 sizeof (VMMDevVideoSetVisibleRegion) + (cRect-1)*sizeof(RTRECT),
1918 VMMDevReq_VideoSetVisibleRegion);
1919
1920 if (RT_SUCCESS(rc))
1921 {
1922 req->cRect = cRect;
1923 memcpy(&req->Rect, RequestPacket->InputBuffer, cRect*sizeof(RTRECT));
1924
1925 rc = VbglGRPerform (&req->header);
1926
1927 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
1928 {
1929 Result = TRUE;
1930 break;
1931 }
1932 }
1933 dprintf(("VBoxVideo::VBoxVideoStartIO: Failed with rc=%x (hdr.rc=%x)\n", rc, (req) ? req->header.rc : -1));
1934 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1935 return FALSE;
1936 }
1937
1938#ifdef VBOX_WITH_HGSMI
1939 case IOCTL_VIDEO_QUERY_HGSMI_INFO:
1940 {
1941 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_HGSMI_INFO\n"));
1942
1943 if (RequestPacket->OutputBufferLength < sizeof(QUERYHGSMIRESULT))
1944 {
1945 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1946 RequestPacket->OutputBufferLength, sizeof(QUERYHGSMIRESULT)));
1947 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1948 return FALSE;
1949 }
1950
1951 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1952 {
1953 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1954 return FALSE;
1955 }
1956
1957 QUERYHGSMIRESULT *pInfo = (QUERYHGSMIRESULT *)RequestPacket->OutputBuffer;
1958
1959 pInfo->iDevice = pDevExt->iDevice;
1960 pInfo->ulFlags = 0;
1961
1962 /* Describes VRAM chunk for this display device. */
1963 pInfo->areaDisplay = pDevExt->areaDisplay;
1964
1965 pInfo->u32DisplayInfoSize = VBVA_DISPLAY_INFORMATION_SIZE;
1966 pInfo->u32MinVBVABufferSize = VBVA_MIN_BUFFER_SIZE;
1967
1968 RequestPacket->StatusBlock->Information = sizeof(QUERYHGSMIRESULT);
1969 Result = TRUE;
1970
1971 break;
1972 }
1973 case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS:
1974 {
1975 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS\n"));
1976
1977 if (RequestPacket->OutputBufferLength < sizeof(HGSMIQUERYCALLBACKS))
1978 {
1979 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
1980 RequestPacket->OutputBufferLength, sizeof(HGSMIQUERYCALLBACKS)));
1981 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1982 return FALSE;
1983 }
1984
1985 if (!pDevExt->pPrimary->u.primary.bHGSMI)
1986 {
1987 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1988 return FALSE;
1989 }
1990
1991 HGSMIQUERYCALLBACKS *pInfo = (HGSMIQUERYCALLBACKS *)RequestPacket->OutputBuffer;
1992
1993 pInfo->hContext = pDevExt;
1994 pInfo->pfnHGSMIGHCommandPost = hgsmiGHCommandPost;
1995 pInfo->pfnCompletionHandler = hgsmiHostCmdComplete;
1996 pInfo->pfnRequestCommandsHandler = hgsmiHostCmdRequest;
1997
1998 RequestPacket->StatusBlock->Information = sizeof(HGSMIQUERYCALLBACKS);
1999 Result = TRUE;
2000 break;
2001 }
2002 case IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS:
2003 {
2004 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS\n"));
2005
2006 if (RequestPacket->OutputBufferLength < sizeof(HGSMIQUERYCPORTPROCS))
2007 {
2008 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
2009 RequestPacket->OutputBufferLength, sizeof(HGSMIQUERYCPORTPROCS)));
2010 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
2011 return FALSE;
2012 }
2013
2014 if (!pDevExt->pPrimary->u.primary.bHGSMI)
2015 {
2016 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
2017 return FALSE;
2018 }
2019
2020 HGSMIQUERYCPORTPROCS *pInfo = (HGSMIQUERYCPORTPROCS *)RequestPacket->OutputBuffer;
2021 pInfo->pContext = pDevExt->pPrimary;
2022 pInfo->VideoPortProcs = pDevExt->pPrimary->u.primary.VideoPortProcs;
2023
2024 RequestPacket->StatusBlock->Information = sizeof(HGSMIQUERYCPORTPROCS);
2025 Result = TRUE;
2026 break;
2027 }
2028 case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE:
2029 {
2030 dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_HANDLER_ENABLE\n"));
2031
2032 if (RequestPacket->InputBufferLength< sizeof(HGSMIHANDLERENABLE))
2033 {
2034 dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
2035 RequestPacket->InputBufferLength, sizeof(HGSMIHANDLERENABLE)));
2036 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
2037 return FALSE;
2038 }
2039
2040 if (!pDevExt->pPrimary->u.primary.bHGSMI)
2041 {
2042 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
2043 return FALSE;
2044 }
2045
2046 HGSMIHANDLERENABLE *pInfo = (HGSMIHANDLERENABLE *)RequestPacket->InputBuffer;
2047
2048 int rc = vboxVBVAChannelDisplayEnable(pDevExt->pPrimary,
2049 pDevExt->iDevice,
2050 pInfo->u8Channel);
2051 if(RT_FAILURE(rc))
2052 {
2053 RequestPacket->StatusBlock->Status = ERROR_INVALID_NAME;
2054 }
2055 Result = TRUE;
2056 break;
2057 }
2058 case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE:
2059 {
2060 /* TODO: implement */
2061 if (!pDevExt->pPrimary->u.primary.bHGSMI)
2062 {
2063 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
2064 return FALSE;
2065 }
2066 break;
2067 }
2068#endif /* VBOX_WITH_HGSMI */
2069
2070 default:
2071 dprintf(("VBoxVideo::VBoxVideoStartIO: Unsupported %p, fn %d(0x%x)\n",
2072 RequestPacket->IoControlCode,
2073 (RequestPacket->IoControlCode >> 2) & 0xFFF,
2074 (RequestPacket->IoControlCode >> 2) & 0xFFF));
2075 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
2076 return FALSE;
2077 }
2078
2079 if (Result)
2080 RequestPacket->StatusBlock->Status = NO_ERROR;
2081 else
2082 RequestPacket->StatusBlock->Information = 0;
2083
2084// dprintf(("VBoxVideo::VBoxVideoStartIO: Completed\n"));
2085
2086 return TRUE;
2087}
2088
2089/**
2090 * VBoxVideoReset HW
2091 *
2092 * Resets the video hardware.
2093 */
2094BOOLEAN VBoxVideoResetHW(PVOID HwDeviceExtension, ULONG Columns, ULONG Rows)
2095{
2096 dprintf(("VBoxVideo::VBoxVideoResetHW\n"));
2097
2098 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
2099
2100 if (pDevExt->iDevice > 0)
2101 {
2102 dprintf(("VBoxVideo::VBoxVideoResetHW: Skipping for non-primary display %d\n",
2103 pDevExt->iDevice));
2104 return TRUE;
2105 }
2106
2107#ifndef VBOX_WITH_HGSMI
2108 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2109 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
2110#else
2111 VBoxVideoVBEWriteUshort(((PDEVICE_EXTENSION)HwDeviceExtension)->pPrimary, VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
2112#endif
2113
2114 if (pDevExt->u.primary.pvReqFlush != NULL)
2115 {
2116 VbglGRFree ((VMMDevRequestHeader *)pDevExt->u.primary.pvReqFlush);
2117 pDevExt->u.primary.pvReqFlush = NULL;
2118 }
2119
2120 VbglTerminate ();
2121
2122 VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvMiniportHeap);
2123 VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvAdapterInformation);
2124
2125 return TRUE;
2126}
2127
2128/**
2129 * VBoxVideoGetPowerState
2130 *
2131 * Queries whether the device can support the requested power state.
2132 */
2133VP_STATUS VBoxVideoGetPowerState(PVOID HwDeviceExtension, ULONG HwId,
2134 PVIDEO_POWER_MANAGEMENT VideoPowerControl)
2135{
2136 dprintf(("VBoxVideo::VBoxVideoGetPowerState\n"));
2137 return NO_ERROR;
2138}
2139
2140/**
2141 * VBoxVideoSetPowerState
2142 *
2143 * Sets the power state of the specified device
2144 */
2145VP_STATUS VBoxVideoSetPowerState(PVOID HwDeviceExtension, ULONG HwId,
2146 PVIDEO_POWER_MANAGEMENT VideoPowerControl)
2147{
2148 dprintf(("VBoxVideo::VBoxVideoSetPowerState\n"));
2149 return NO_ERROR;
2150}
2151
2152/**
2153 * VBoxVideoSetGraphicsCap
2154 *
2155 * Tells the host whether or not we currently support graphics in the
2156 * additions
2157 */
2158BOOLEAN FASTCALL VBoxVideoSetGraphicsCap(BOOLEAN isEnabled)
2159{
2160 VMMDevReqGuestCapabilities2 *req = NULL;
2161 int rc;
2162
2163 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2164 sizeof (VMMDevReqGuestCapabilities2),
2165 VMMDevReq_SetGuestCapabilities);
2166
2167 if (!RT_SUCCESS(rc))
2168 dprintf(("VBoxVideoSetGraphicsCap: failed to allocate a request, rc=%Rrc\n", rc));
2169 else
2170 {
2171 req->u32OrMask = isEnabled ? VMMDEV_GUEST_SUPPORTS_GRAPHICS : 0;
2172 req->u32NotMask = isEnabled ? 0 : VMMDEV_GUEST_SUPPORTS_GRAPHICS;
2173
2174 rc = VbglGRPerform (&req->header);
2175 if (!RT_SUCCESS(rc) || !RT_SUCCESS(req->header.rc))
2176 dprintf(("VBoxVideoSetGraphicsCap: request failed, rc = %Rrc, VMMDev rc = %Rrc\n", rc, req->header.rc));
2177 if (RT_SUCCESS(rc))
2178 rc = req->header.rc;
2179 }
2180 if (req != NULL)
2181 VbglGRFree (&req->header);
2182 return RT_SUCCESS(rc);
2183}
2184
2185/**
2186 * VBoxVideoSetCurrentMode
2187 *
2188 * Sets the adapter to the specified operating mode.
2189 */
2190BOOLEAN FASTCALL VBoxVideoSetCurrentMode(PDEVICE_EXTENSION DeviceExtension,
2191 PVIDEO_MODE RequestedMode, PSTATUS_BLOCK StatusBlock)
2192{
2193 PVIDEO_MODE_INFORMATION ModeInfo;
2194
2195 dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: mode = %d\n", RequestedMode->RequestedMode));
2196
2197 DeviceExtension->CurrentMode = RequestedMode->RequestedMode;
2198 ModeInfo = &VideoModes[DeviceExtension->CurrentMode - 1];
2199 dprintf(("VBoxVideoSetCurrentMode: width: %d, height: %d, bpp: %d\n", ModeInfo->VisScreenWidth,
2200 ModeInfo->VisScreenHeight, ModeInfo->BitsPerPlane));
2201
2202 DeviceExtension->CurrentModeWidth = ModeInfo->VisScreenWidth;
2203 DeviceExtension->CurrentModeHeight = ModeInfo->VisScreenHeight;
2204 DeviceExtension->CurrentModeBPP = ModeInfo->BitsPerPlane;
2205
2206 if (DeviceExtension->iDevice > 0)
2207 {
2208 dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: Skipping for non-primary display %d\n",
2209 DeviceExtension->iDevice));
2210 return TRUE;
2211 }
2212
2213 /* set the mode characteristics */
2214#ifndef VBOX_WITH_HGSMI
2215 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
2216 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenWidth);
2217 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
2218 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenHeight);
2219 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
2220 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->BitsPerPlane);
2221 /* enable the mode */
2222 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2223 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
2224 /** @todo read from the port to see if the mode switch was successful */
2225#else
2226 VBoxVideoVBEWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_XRES, (USHORT)ModeInfo->VisScreenWidth);
2227 VBoxVideoVBEWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_YRES, (USHORT)ModeInfo->VisScreenHeight);
2228 VBoxVideoVBEWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_BPP, (USHORT)ModeInfo->BitsPerPlane);
2229 VBoxVideoVBEWriteUshort(DeviceExtension->pPrimary, VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
2230#endif
2231
2232 /* Tell the host that we now support graphics in the additions.
2233 * @todo: Keep old behaviour, because VBoxVideoResetDevice is called on every graphics
2234 * mode switch and causes an OFF/ON sequence which is not handled by frontends
2235 * (for example Qt GUI debug build asserts when seamless is being enabled).
2236 */
2237 // VBoxVideoSetGraphicsCap(TRUE);
2238 return TRUE;
2239}
2240
2241/*
2242 * VBoxVideoResetDevice
2243 *
2244 * Resets the video hardware to the default mode, to which it was initialized
2245 * at system boot.
2246 */
2247
2248BOOLEAN FASTCALL VBoxVideoResetDevice(
2249 PDEVICE_EXTENSION DeviceExtension,
2250 PSTATUS_BLOCK StatusBlock)
2251{
2252 dprintf(("VBoxVideo::VBoxVideoResetDevice\n"));
2253
2254 if (DeviceExtension->iDevice > 0)
2255 {
2256 /* If the device is the secondary display, however, it is recommended that no action be taken. */
2257 dprintf(("VBoxVideo::VBoxVideoResetDevice: Skipping for non-primary display %d\n",
2258 DeviceExtension->iDevice));
2259 return TRUE;
2260 }
2261
2262#if 0
2263 /* Don't disable the extended video mode. This would only switch the video mode
2264 * to <current width> x <current height> x 0 bpp which is not what we want. And
2265 * even worse, it causes an disturbing additional mode switch */
2266 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
2267 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
2268#endif
2269
2270 /* Tell the host that we no longer support graphics in the additions
2271 * @todo: Keep old behaviour, see similar comment in VBoxVideoSetCurrentMode for details.
2272 */
2273 // VBoxVideoSetGraphicsCap(FALSE);
2274 return TRUE;
2275}
2276
2277/**
2278 * VBoxVideoMapVideoMemory
2279 *
2280 * Maps the video hardware frame buffer and video RAM into the virtual address
2281 * space of the requestor.
2282 */
2283BOOLEAN FASTCALL VBoxVideoMapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
2284 PVIDEO_MEMORY RequestedAddress,
2285 PVIDEO_MEMORY_INFORMATION MapInformation,
2286 PSTATUS_BLOCK StatusBlock)
2287{
2288 PHYSICAL_ADDRESS FrameBuffer;
2289 ULONG inIoSpace = 0;
2290 VP_STATUS Status;
2291
2292 dprintf(("VBoxVideo::VBoxVideoMapVideoMemory: fb offset 0x%x\n", DeviceExtension->ulFrameBufferOffset));
2293
2294 FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + DeviceExtension->ulFrameBufferOffset;
2295
2296 MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
2297#ifndef VBOX_WITH_HGSMI
2298 MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize
2299 + DeviceExtension->pPrimary->u.primary.ulDisplayInformationSize;
2300#else
2301 MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
2302#endif /* VBOX_WITH_HGSMI */
2303
2304 Status = VideoPortMapMemory(DeviceExtension, FrameBuffer,
2305 &MapInformation->VideoRamLength, &inIoSpace,
2306 &MapInformation->VideoRamBase);
2307
2308 if (Status == NO_ERROR)
2309 {
2310 MapInformation->FrameBufferBase = (PUCHAR)MapInformation->VideoRamBase;
2311 MapInformation->FrameBufferLength =
2312 VideoModes[DeviceExtension->CurrentMode - 1].VisScreenHeight *
2313 VideoModes[DeviceExtension->CurrentMode - 1].ScreenStride;
2314 StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
2315
2316 /* Save the new framebuffer size */
2317 DeviceExtension->ulFrameBufferSize = MapInformation->FrameBufferLength;
2318#ifdef VBOX_WITH_HGSMI
2319 HGSMIAreaInitialize (&DeviceExtension->areaDisplay,
2320 MapInformation->FrameBufferBase,
2321 MapInformation->FrameBufferLength,
2322 DeviceExtension->ulFrameBufferOffset);
2323#endif /* VBOX_WITH_HGSMI */
2324 return TRUE;
2325 }
2326
2327 return FALSE;
2328}
2329
2330/**
2331 * VBoxVideoUnmapVideoMemory
2332 *
2333 * Releases a mapping between the virtual address space and the adapter's
2334 * frame buffer and video RAM.
2335 */
2336BOOLEAN FASTCALL VBoxVideoUnmapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
2337 PVIDEO_MEMORY VideoMemory, PSTATUS_BLOCK StatusBlock)
2338{
2339 dprintf(("VBoxVideo::VBoxVideoUnmapVideoMemory\n"));
2340#ifdef VBOX_WITH_HGSMI
2341 HGSMIAreaClear (&DeviceExtension->areaDisplay);
2342#endif /* VBOX_WITH_HGSMI */
2343 VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress, NULL);
2344 return TRUE;
2345}
2346
2347/**
2348 * VBoxVideoQueryNumAvailModes
2349 *
2350 * Returns the number of video modes supported by the adapter and the size
2351 * in bytes of the video mode information, which can be used to allocate a
2352 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
2353 */
2354BOOLEAN FASTCALL VBoxVideoQueryNumAvailModes(PDEVICE_EXTENSION DeviceExtension,
2355 PVIDEO_NUM_MODES Modes, PSTATUS_BLOCK StatusBlock)
2356{
2357 dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes\n"));
2358 /* calculate the video modes table */
2359 VBoxBuildModesTable(DeviceExtension);
2360 Modes->NumModes = gNumVideoModes;
2361 Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
2362 StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
2363 dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes: number of modes: %d\n", Modes->NumModes));
2364 return TRUE;
2365}
2366
2367/**
2368 * VBoxVideoQueryAvailModes
2369 *
2370 * Returns information about each video mode supported by the adapter.
2371 */
2372BOOLEAN FASTCALL VBoxVideoQueryAvailModes(PDEVICE_EXTENSION DeviceExtension,
2373 PVIDEO_MODE_INFORMATION ReturnedModes,
2374 PSTATUS_BLOCK StatusBlock)
2375{
2376 ULONG Size;
2377
2378 dprintf(("VBoxVideo::VBoxVideoQueryAvailModes\n"));
2379
2380 Size = gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION);
2381 VideoPortMoveMemory(ReturnedModes, VideoModes, Size);
2382 StatusBlock->Information = Size;
2383
2384 return TRUE;
2385}
2386
2387/**
2388 * VBoxVideoQueryCurrentMode
2389 *
2390 * Returns information about current video mode.
2391 */
2392BOOLEAN FASTCALL VBoxVideoQueryCurrentMode(PDEVICE_EXTENSION DeviceExtension,
2393 PVIDEO_MODE_INFORMATION VideoModeInfo,
2394 PSTATUS_BLOCK StatusBlock)
2395{
2396 dprintf(("VBoxVideo::VBoxVideoQueryCurrentMode\n"));
2397
2398 StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
2399 VideoPortMoveMemory(VideoModeInfo, VideoModes + DeviceExtension->CurrentMode - 1, 1);
2400
2401 return TRUE;
2402}
2403
2404/*
2405 * VBoxVideoSetColorRegisters
2406 *
2407 * Sets the adapter's color registers to the specified RGB values. There
2408 * are code paths in this function, one generic and one for VGA compatible
2409 * controllers. The latter is needed for Bochs, where the generic one isn't
2410 * yet implemented.
2411 */
2412
2413BOOLEAN FASTCALL VBoxVideoSetColorRegisters(
2414 PDEVICE_EXTENSION DeviceExtension,
2415 PVIDEO_CLUT ColorLookUpTable,
2416 PSTATUS_BLOCK StatusBlock)
2417{
2418 LONG Entry;
2419
2420 dprintf(("VBoxVideo::VBoxVideoSetColorRegisters first entry %d num entries %d\n", ColorLookUpTable->FirstEntry, ColorLookUpTable->NumEntries));
2421
2422 if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256)
2423 return FALSE;
2424
2425 for (Entry = ColorLookUpTable->FirstEntry;
2426 Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
2427 Entry++)
2428 {
2429 VideoPortWritePortUchar((PUCHAR)0x03c8, (UCHAR)Entry);
2430 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red);
2431 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
2432 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
2433 }
2434
2435 return TRUE;
2436}
2437
2438VP_STATUS VBoxVideoGetChildDescriptor(
2439 PVOID HwDeviceExtension,
2440 PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
2441 PVIDEO_CHILD_TYPE VideoChildType,
2442 PUCHAR pChildDescriptor,
2443 PULONG pUId,
2444 PULONG pUnused)
2445{
2446 dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor: HwDeviceExtension = %p, ChildEnumInfo = %p\n",
2447 HwDeviceExtension, ChildEnumInfo));
2448
2449 DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)HwDeviceExtension;
2450
2451 if (ChildEnumInfo->ChildIndex > 0)
2452 {
2453 if ((int)ChildEnumInfo->ChildIndex <= pDevExt->pPrimary->u.primary.cDisplays)
2454 {
2455 *VideoChildType = Monitor;
2456 *pUId = ChildEnumInfo->ChildIndex;
2457
2458 return VIDEO_ENUM_MORE_DEVICES;
2459 }
2460 }
2461
2462 return ERROR_NO_MORE_DEVICES;
2463}
2464
2465
2466static DECLCALLBACK(void) vboxVbvaFlush (void *pvFlush)
2467{
2468 DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)pvFlush;
2469 DEVICE_EXTENSION *pPrimaryDevExt = pDevExt? pDevExt->pPrimary: NULL;
2470
2471 if (pPrimaryDevExt)
2472 {
2473 VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pPrimaryDevExt->u.primary.pvReqFlush;
2474
2475 if (req)
2476 {
2477 int rc = VbglGRPerform (&req->header);
2478
2479 if (RT_FAILURE(rc) || RT_FAILURE(req->header.rc))
2480 {
2481 dprintf(("VBoxVideo::vbvaFlush: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
2482 }
2483 }
2484 }
2485
2486 return;
2487}
2488
2489int vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult)
2490{
2491 int rc = VINF_SUCCESS;
2492
2493 dprintf(("VBoxVideo::vboxVbvaEnable: ulEnable = %08X, pVbvaResult = %p\n", ulEnable, pVbvaResult));
2494
2495 /*
2496 * Query the VMMDev memory pointer. There we need VBVAMemory.
2497 */
2498 VMMDevMemory *pVMMDevMemory = NULL;
2499
2500 rc = VbglQueryVMMDevMemory (&pVMMDevMemory);
2501
2502 dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %d, pVMMDevMemory = %p\n", rc, pVMMDevMemory));
2503
2504 if (pDevExt->iDevice > 0)
2505 {
2506 DEVICE_EXTENSION *pPrimaryDevExt = pDevExt->pPrimary;
2507
2508 dprintf(("VBoxVideo::vboxVbvaEnable: Skipping for non-primary display %d\n",
2509 pDevExt->iDevice));
2510
2511 if ( ulEnable
2512 && pPrimaryDevExt->u.primary.ulVbvaEnabled)
2513 {
2514 pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
2515 pVbvaResult->pfnFlush = vboxVbvaFlush;
2516 pVbvaResult->pvFlush = pDevExt;
2517 }
2518 else
2519 {
2520 VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
2521 }
2522
2523 return rc;
2524 }
2525
2526 if (RT_SUCCESS(rc))
2527 {
2528 /* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */
2529 if (pDevExt->u.primary.pvReqFlush == NULL)
2530 {
2531 VMMDevVideoAccelFlush *req = NULL;
2532
2533 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2534 sizeof (VMMDevVideoAccelFlush),
2535 VMMDevReq_VideoAccelFlush);
2536
2537 if (RT_SUCCESS (rc))
2538 {
2539 pDevExt->u.primary.pvReqFlush = req;
2540 }
2541 else
2542 {
2543 dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc (VMMDevReq_VideoAccelFlush) rc = %Rrc!!!\n", rc));
2544 }
2545 }
2546 }
2547 else
2548 {
2549 dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %Rrc!!!\n", rc));
2550 }
2551
2552 if (RT_SUCCESS(rc))
2553 {
2554 ULONG ulEnabled = 0;
2555
2556 /*
2557 * Tell host that VBVA status is changed.
2558 */
2559 VMMDevVideoAccelEnable *req = NULL;
2560
2561 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2562 sizeof (VMMDevVideoAccelEnable),
2563 VMMDevReq_VideoAccelEnable);
2564
2565 if (RT_SUCCESS(rc))
2566 {
2567 req->u32Enable = ulEnable;
2568 req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
2569 req->fu32Status = 0;
2570
2571 rc = VbglGRPerform (&req->header);
2572
2573 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
2574 {
2575 if (req->fu32Status & VBVA_F_STATUS_ACCEPTED)
2576 {
2577 /*
2578 * Initialize the result information and VBVA memory.
2579 */
2580 if (req->fu32Status & VBVA_F_STATUS_ENABLED)
2581 {
2582 pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
2583 pVbvaResult->pfnFlush = vboxVbvaFlush;
2584 pVbvaResult->pvFlush = pDevExt;
2585 ulEnabled = 1;
2586 }
2587 else
2588 {
2589 VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
2590 }
2591
2592 dprintf(("VBoxVideo::vboxVbvaEnable: success.\n"));
2593 }
2594 else
2595 {
2596 dprintf(("VBoxVideo::vboxVbvaEnable: not accepted.\n"));
2597
2598 /* Disable VBVA for old hosts. */
2599 req->u32Enable = 0;
2600 req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
2601 req->fu32Status = 0;
2602
2603 VbglGRPerform (&req->header);
2604
2605 rc = VERR_NOT_SUPPORTED;
2606 }
2607 }
2608 else
2609 {
2610 dprintf(("VBoxVideo::vboxVbvaEnable: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
2611
2612 if (RT_SUCCESS(rc))
2613 {
2614 rc = req->header.rc;
2615 }
2616 }
2617
2618 VbglGRFree (&req->header);
2619 }
2620 else
2621 {
2622 dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc rc = %Rrc!!!\n", rc));
2623 }
2624
2625 pDevExt->pPrimary->u.primary.ulVbvaEnabled = ulEnabled;
2626 }
2627
2628 return rc;
2629}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette