VirtualBox

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

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

HGSMI/VBVA use PCI IO ports.

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