VirtualBox

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

Last change on this file since 4150 was 4150, checked in by vboxsync, 17 years ago

Safety precaution

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