VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp@ 108641

Last change on this file since 108641 was 108641, checked in by vboxsync, 2 months ago

Removed 2D video acceleration (aka VHWA / VBOX_WITH_VIDEOHWACCEL). bugref:10756

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.1 KB
Line 
1/* $Id: VBoxMPDriver.cpp 108641 2025-03-20 12:48:42Z vboxsync $ */
2/** @file
3 * VBox XPDM Miniport driver interface functions
4 */
5
6/*
7 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include "VBoxMPInternal.h"
33#include <VBoxVideoVBE.h>
34#include <VBox/VBoxGuestLib.h>
35#include <VBoxVideo.h>
36#include "common/VBoxMPHGSMI.h"
37#include "common/VBoxMPCommon.h"
38#include "VBoxDisplay.h"
39#include <iprt/initterm.h>
40#include <VBox/version.h>
41
42
43/*********************************************************************************************************************************
44* Global Variables *
45*********************************************************************************************************************************/
46/** Legacy VGA resource list. */
47static VIDEO_ACCESS_RANGE g_aVBoxLegacyVGAResources[] =
48{
49 /* RangeInIoSpace
50 | RangeVisible
51 | | RangeShareable
52 | | | RangePassive
53 RangeStart RangeLength v v v v */
54 { {{0x000003B0, 0x00000000}}, 0x0000000C, 1, 1, 1, 0 }, /* VGA regs (0x3B0-0x3BB) */
55 { {{0x000003C0, 0x00000000}}, 0x00000020, 1, 1, 1, 0 }, /* VGA regs (0x3C0-0x3DF) */
56 { {{0x000A0000, 0x00000000}}, 0x00020000, 0, 0, 1, 0 }, /* Frame buffer (0xA0000-0xBFFFF) */
57};
58
59/* Card info for property dialog */
60static WCHAR g_wszVBoxChipType[] = L"VBOX";
61static WCHAR g_wszVBoxDACType[] = L"Integrated RAMDAC";
62static WCHAR g_wszVBoxAdapterString[] = L"VirtualBox Video Adapter";
63static WCHAR g_wszVBoxBiosString[] = L"Version 0xB0C2 or later";
64
65
66/* Checks if we have a device supported by our driver and initialize
67 * our driver/card specific information.
68 * In particular we obtain VM monitors configuration and configure related structures.
69 */
70static VP_STATUS
71VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString,
72 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again)
73{
74 RT_NOREF(HwContext, ArgumentString, Again);
75 PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
76 VP_STATUS rc;
77 USHORT DispiId;
78 ULONG cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
79 PHYSICAL_ADDRESS phVRAM = {{0,0}};
80 ULONG ulApertureSize = 0;
81
82 PAGED_CODE();
83 LOGF_ENTER();
84
85 /* Init video port api */
86 VBoxSetupVideoPortAPI(pExt, ConfigInfo);
87
88 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
89 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
90 DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
91
92 if (DispiId != VBE_DISPI_ID2)
93 {
94 WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST"));
95 return ERROR_DEV_NOT_EXIST;
96 }
97 LOG(("found the VBE card"));
98
99 /*
100 * Query the adapter's memory size. It's a bit of a hack, we just read
101 * an ULONG from the data port without setting an index before.
102 */
103 cbVRAM = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
104
105 /* Write hw information to registry, so that it's visible in windows property dialog */
106 rc = VideoPortSetRegistryParameters(pExt, (PWSTR)L"HardwareInformation.ChipType",
107 g_wszVBoxChipType, sizeof(g_wszVBoxChipType));
108 VBOXMP_WARN_VPS(rc);
109 rc = VideoPortSetRegistryParameters(pExt, (PWSTR)L"HardwareInformation.DacType",
110 g_wszVBoxDACType, sizeof(g_wszVBoxDACType));
111 VBOXMP_WARN_VPS(rc);
112 rc = VideoPortSetRegistryParameters(pExt, (PWSTR)L"HardwareInformation.MemorySize",
113 &cbVRAM, sizeof(ULONG));
114 VBOXMP_WARN_VPS(rc);
115 rc = VideoPortSetRegistryParameters(pExt, (PWSTR)L"HardwareInformation.AdapterString",
116 g_wszVBoxAdapterString, sizeof(g_wszVBoxAdapterString));
117 VBOXMP_WARN_VPS(rc);
118 rc = VideoPortSetRegistryParameters(pExt, (PWSTR)L"HardwareInformation.BiosString",
119 g_wszVBoxBiosString, sizeof(g_wszVBoxBiosString));
120 VBOXMP_WARN_VPS(rc);
121
122 /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up
123 * and to get LFB aperture data.
124 */
125 {
126 VIDEO_ACCESS_RANGE tmpRanges[4];
127 ULONG slot = 0;
128
129 VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges));
130
131 if (VBoxQueryWinVersion(NULL) == WINVERSION_NT4)
132 {
133 /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL,
134 * and needs PCI ids for a successful VideoPortGetAccessRanges call.
135 */
136 ULONG vendorId = 0x80EE;
137 ULONG deviceId = 0xBEEF;
138 rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges,
139 &vendorId, &deviceId, &slot);
140 }
141 else
142 {
143 rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot);
144 }
145 VBOXMP_WARN_VPS(rc);
146 if (rc != NO_ERROR) {
147 return rc;
148 }
149
150 /* The first non-IO range is the framebuffer. We require that information. */
151 for (int iRange = 0; iRange < RT_ELEMENTS(tmpRanges); ++iRange)
152 {
153 if (!tmpRanges[iRange].RangeInIoSpace)
154 {
155 phVRAM = tmpRanges[iRange].RangeStart;
156 ulApertureSize = tmpRanges[iRange].RangeLength;
157 break;
158 }
159 }
160 }
161
162 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
163 rc = VbglR0InitClient();
164 VBOXMP_WARN_VPS(rc);
165
166 /* Preinitialize the primary extension. */
167 pExt->pNext = NULL;
168 pExt->pPrimary = pExt;
169 pExt->iDevice = 0;
170 pExt->ulFrameBufferOffset = 0;
171 pExt->ulFrameBufferSize = 0;
172 pExt->u.primary.ulVbvaEnabled = 0;
173 VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA));
174
175 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old
176 * code will be ifdef'ed and later removed.
177 * The host will however support both old and new interface to keep compatibility
178 * with old guest additions.
179 */
180 VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0);
181
182 /* Check if the chip restricts horizontal resolution or not.
183 * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure.
184 */
185 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
186 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
187 DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
188
189 if (DispiId == VBE_DISPI_ID_ANYX)
190 VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE;
191 else
192 VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE;
193
194 if (pExt->u.primary.commonInfo.bHGSMI)
195 {
196 LOGREL(("using HGSMI"));
197 VBoxCreateDisplays(pExt, ConfigInfo);
198 }
199
200 /** @todo pretend success to make the driver work. */
201 rc = NO_ERROR;
202
203 LOGF_LEAVE();
204 VBOXMP_WARN_VPS(rc);
205 return rc;
206}
207
208/* Initial device configuration. */
209static BOOLEAN
210VBoxDrvInitialize(PVOID HwDeviceExtension)
211{
212 PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
213
214 PAGED_CODE();
215 LOGF_ENTER();
216
217 /* Initialize the request pointer. */
218 pExt->u.primary.pvReqFlush = NULL;
219
220 VBoxMPCmnInitCustomVideoModes(pExt);
221
222 LOGF_LEAVE();
223 return TRUE;
224}
225
226/* VBoxDrvStartIO parameter check helper macros */
227#define STARTIO_IN(_type, _name) \
228 _type *_name = (_type*) RequestPacket->InputBuffer; \
229 if (RequestPacket->InputBufferLength < sizeof(_type)) \
230 { \
231 WARN(("Input buffer too small %d/%d bytes", \
232 RequestPacket->InputBufferLength, sizeof(_type))); \
233 pStatus->Status = ERROR_INSUFFICIENT_BUFFER; \
234 break; \
235 }
236
237#define STARTIO_OUT(_type, _name) \
238 _type *_name = (_type*) RequestPacket->OutputBuffer; \
239 if (RequestPacket->OutputBufferLength < sizeof(_type)) \
240 { \
241 WARN(("Output buffer too small %d/%d bytes", \
242 RequestPacket->OutputBufferLength, sizeof(_type))); \
243 pStatus->Status = ERROR_INSUFFICIENT_BUFFER; \
244 break; \
245 }
246
247/* Process Video Request Packet. */
248static BOOLEAN
249VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket)
250{
251 PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
252 PSTATUS_BLOCK pStatus = RequestPacket->StatusBlock;
253 BOOLEAN bResult = FALSE;
254
255 PAGED_CODE();
256
257 LOGF(("IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF));
258
259 pStatus->Status = NO_ERROR;
260
261 switch (RequestPacket->IoControlCode)
262 {
263 /* ==================== System VRPs ==================== */
264
265 /*Maps FrameBuffer and video RAM to a caller's virtual adress space.*/
266 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
267 {
268 STARTIO_IN(VIDEO_MEMORY, pMemory);
269 STARTIO_OUT(VIDEO_MEMORY_INFORMATION, pMemInfo);
270
271 bResult = VBoxMPMapVideoMemory(pExt, pMemory, pMemInfo, pStatus);
272 break;
273 }
274
275 /*Unmaps previously mapped FrameBuffer and video RAM from caller's virtual adress space.*/
276 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
277 {
278 STARTIO_IN(VIDEO_MEMORY, pMemory);
279
280 bResult = VBoxMPUnmapVideoMemory(pExt, pMemory, pStatus);
281 break;
282 }
283
284 /*Maps FrameBuffer as a linear frame buffer to a caller's virtual adress space. (obsolete)*/
285 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
286 {
287 STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory);
288 STARTIO_OUT(VIDEO_SHARE_MEMORY_INFORMATION, pShareMemInfo);
289
290 bResult = VBoxMPShareVideoMemory(pExt, pShareMemory, pShareMemInfo, pStatus);
291 break;
292 }
293
294 /*Unmaps framebuffer previously mapped with IOCTL_VIDEO_SHARE_VIDEO_MEMORY*/
295 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
296 {
297 STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory);
298
299 bResult = VBoxMPUnshareVideoMemory(pExt, pShareMemory, pStatus);
300 break;
301 }
302
303 /*Reset device to a state it comes at system boot time.*/
304 case IOCTL_VIDEO_RESET_DEVICE:
305 {
306 bResult = VBoxMPResetDevice(pExt, pStatus);
307 break;
308 }
309
310 /*Set adapter video mode.*/
311 case IOCTL_VIDEO_SET_CURRENT_MODE:
312 {
313 STARTIO_IN(VIDEO_MODE, pMode);
314
315 bResult = VBoxMPSetCurrentMode(pExt, pMode, pStatus);
316 break;
317 }
318
319 /*Returns information about current video mode.*/
320 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
321 {
322 STARTIO_OUT(VIDEO_MODE_INFORMATION, pModeInfo);
323
324 bResult = VBoxMPQueryCurrentMode(pExt, pModeInfo, pStatus);
325 break;
326 }
327
328 /* Returns count of supported video modes and structure size in bytes,
329 * used to allocate buffer for the following IOCTL_VIDEO_QUERY_AVAIL_MODES call.
330 */
331 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
332 {
333 STARTIO_OUT(VIDEO_NUM_MODES, pNumModes);
334
335 bResult = VBoxMPQueryNumAvailModes(pExt, pNumModes, pStatus);
336 break;
337 }
338
339 /* Returns information about supported video modes. */
340 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
341 {
342 PVIDEO_MODE_INFORMATION pModes = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;
343
344 if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION))
345 {
346 pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
347 break;
348 }
349
350 bResult = VBoxMPQueryAvailModes(pExt, pModes, pStatus);
351 break;
352 }
353
354 /* Sets adapter's color registers, have to be implemented if we support palette based modes. */
355 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
356 {
357 STARTIO_IN(VIDEO_CLUT, pClut);
358
359 if (RequestPacket->InputBufferLength < (sizeof(VIDEO_CLUT) + pClut->NumEntries * sizeof(ULONG)))
360 {
361 pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
362 break;
363 }
364
365 bResult = VBoxMPSetColorRegisters(pExt, pClut, pStatus);
366 break;
367 }
368
369 /* Sets pointer attributes. */
370 case IOCTL_VIDEO_SET_POINTER_ATTR:
371 {
372 STARTIO_IN(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs);
373
374 bResult = VBoxMPSetPointerAttr(pExt, pPointerAttrs, RequestPacket->InputBufferLength, pStatus);
375 break;
376 }
377
378 /* Makes pointer visible. */
379 case IOCTL_VIDEO_ENABLE_POINTER:
380 {
381 bResult = VBoxMPEnablePointer(pExt, TRUE, pStatus);
382 break;
383 }
384
385 /* Hides pointer. */
386 case IOCTL_VIDEO_DISABLE_POINTER:
387 {
388 bResult = VBoxMPEnablePointer(pExt, FALSE, pStatus);
389 break;
390 }
391
392 /* Sets (reports) pointer position, is called after IOCTL_VIDEO_ENABLE_POINTER. */
393 case IOCTL_VIDEO_SET_POINTER_POSITION:
394 {
395 STARTIO_IN(VIDEO_POINTER_POSITION, pPos);
396
397 bResult = VBoxMPReportCursorPosition(pExt, pPos, pStatus);
398 break;
399 }
400
401 /* Query pointer position. */
402 case IOCTL_VIDEO_QUERY_POINTER_POSITION:
403 {
404 STARTIO_OUT(VIDEO_POINTER_POSITION, pPos);
405
406 bResult = VBoxMPQueryPointerPosition(pExt, pPos, pStatus);
407 break;
408 }
409
410 /* Query supported hardware pointer feaures. */
411 case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
412 {
413 STARTIO_OUT(VIDEO_POINTER_CAPABILITIES, pCaps);
414
415 bResult = VBoxMPQueryPointerCapabilities(pExt, pCaps, pStatus);
416 break;
417 }
418
419 /* Query pointer attributes. (optional) */
420 case IOCTL_VIDEO_QUERY_POINTER_ATTR:
421 {
422 STARTIO_OUT(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs);
423
424 NOREF(pPointerAttrs); /* Not Implemented */
425 pStatus->Status = ERROR_INVALID_FUNCTION;
426
427 bResult = FALSE;
428 break;
429 }
430
431 /* Called when a secondary adapter is about to be enabled/disabled. */
432 case IOCTL_VIDEO_SWITCH_DUALVIEW:
433 {
434 STARTIO_IN(ULONG, pAttach);
435
436 LOGF(("IOCTL_VIDEO_SWITCH_DUALVIEW: [%d] attach = %d", pExt->iDevice, *pAttach));
437
438 if (pExt->iDevice>0)
439 {
440 pExt->u.secondary.bEnabled = (BOOLEAN)(*pAttach);
441
442 /* Inform the host.
443 * Currently only about secondary devices, because the driver does not support
444 * disconnecting the primary display (it does not allow to change the primary display).
445 */
446 if (!pExt->u.secondary.bEnabled)
447 {
448 PVBOXMP_COMMON pCommon = VBoxCommonFromDeviceExt(pExt);
449 if (pCommon->bHGSMI)
450 {
451 VBoxHGSMIProcessDisplayInfo(&pCommon->guestCtx, pExt->iDevice,
452 /* cOriginX = */ 0, /* cOriginY = */ 0,
453 /* offStart = */ 0, /* cbPitch = */ 0,
454 /* cWidth = */ 0, /* cHeight = */ 0, /* cBPP = */ 0,
455 VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
456 }
457 }
458 }
459
460 bResult = TRUE;
461 break;
462 }
463
464 /* Called to get child device status */
465 case IOCTL_VIDEO_GET_CHILD_STATE:
466 {
467 STARTIO_IN(ULONG, pChildIndex);
468 STARTIO_OUT(ULONG, pChildState);
469
470 LOGF(("IOCTL_VIDEO_GET_CHILD_STATE: [%d] idx = %d", pExt->iDevice, *pChildIndex));
471
472 if (*pChildIndex>0 && *pChildIndex<=(ULONG)VBoxCommonFromDeviceExt(pExt)->cDisplays)
473 {
474 *pChildState = VIDEO_CHILD_ACTIVE;
475 pStatus->Information = sizeof(ULONG);
476 bResult = TRUE;
477 }
478 else
479 {
480 pStatus->Status = ERROR_INVALID_PARAMETER;
481 bResult = FALSE;
482 }
483
484 break;
485 }
486
487 /* ==================== VirtualBox specific VRPs ==================== */
488
489 /* Called by the display driver when it is ready to switch to VBVA operation mode. */
490 case IOCTL_VIDEO_VBVA_ENABLE:
491 {
492 STARTIO_IN(ULONG, pEnable);
493 STARTIO_OUT(VBVAENABLERESULT, pResult);
494
495 bResult = VBoxMPVBVAEnable(pExt, (BOOLEAN)*pEnable, pResult, pStatus);
496 break;
497 }
498
499 /* Called by the display driver when it recieves visible regions information. */
500 case IOCTL_VIDEO_VBOX_SETVISIBLEREGION:
501 {
502 STARTIO_IN(RTRECT, pRects);
503
504 uint32_t cRects = RequestPacket->InputBufferLength/sizeof(RTRECT);
505 /*Sanity check*/
506 if ( cRects > _1M
507 || RequestPacket->InputBufferLength != cRects * sizeof(RTRECT))
508 {
509 pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
510 break;
511 }
512
513 bResult = VBoxMPSetVisibleRegion(cRects, pRects, pStatus);
514 break;
515 }
516
517 /* Returns video port api function pointers. */
518 case IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS:
519 {
520 STARTIO_OUT(HGSMIQUERYCPORTPROCS, pProcs);
521
522 bResult = VBoxMPHGSMIQueryPortProcs(pExt, pProcs, pStatus);
523 break;
524 }
525
526 /* Returns HGSMI related callbacks. */
527 case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS:
528 {
529 STARTIO_OUT(HGSMIQUERYCALLBACKS, pCallbacks);
530
531 bResult = VBoxMPHGSMIQueryCallbacks(pExt, pCallbacks, pStatus);
532 break;
533 }
534
535 /* Returns hgsmi info for this adapter. */
536 case IOCTL_VIDEO_QUERY_HGSMI_INFO:
537 {
538 STARTIO_OUT(QUERYHGSMIRESULT, pResult);
539
540 bResult = VBoxMPQueryHgsmiInfo(pExt, pResult, pStatus);
541 break;
542 }
543
544 /* Enables HGSMI miniport channel. */
545 case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE:
546 {
547 STARTIO_IN(HGSMIHANDLERENABLE, pChannel);
548
549 bResult = VBoxMPHgsmiHandlerEnable(pExt, pChannel, pStatus);
550 break;
551 }
552
553 case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE:
554 {
555 /** @todo not implemented */
556 break;
557 }
558
559 case IOCTL_VIDEO_VBOX_ISANYX:
560 {
561 STARTIO_OUT(uint32_t, pu32AnyX);
562 *pu32AnyX = VBoxCommonFromDeviceExt(pExt)->fAnyX;
563 pStatus->Information = sizeof (uint32_t);
564 bResult = TRUE;
565 break;
566 }
567
568 case IOCTL_VIDEO_QUERY_VBOXVIDEO_INFO:
569 {
570 STARTIO_IN(ULONG, pulInfoLevel);
571 if (*pulInfoLevel == VBOXVIDEO_INFO_LEVEL_REGISTRY_FLAGS)
572 {
573 STARTIO_OUT(ULONG, pulFlags);
574 bResult = VBoxMPQueryRegistryFlags(pExt, pulFlags, pStatus);
575 }
576 else
577 {
578 pStatus->Status = ERROR_INVALID_PARAMETER;
579 bResult = FALSE;
580 }
581
582 break;
583 }
584
585 default:
586 {
587 WARN(("unsupported IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF));
588 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
589 }
590 }
591
592 if (!bResult)
593 {
594 pStatus->Information = NULL;
595 }
596
597 VBOXMP_WARN_VPS(pStatus->Status);
598 LOGF_LEAVE();
599 return TRUE;
600}
601
602/* Called to set out hardware into desired power state, not supported at the moment.
603 * Required to return NO_ERROR always.
604 */
605static VP_STATUS
606VBoxDrvSetPowerState(PVOID HwDeviceExtension, ULONG HwId, PVIDEO_POWER_MANAGEMENT VideoPowerControl)
607{
608 PAGED_CODE();
609 LOGF_ENTER();
610
611 /*Not implemented*/
612 RT_NOREF(HwDeviceExtension, HwId, VideoPowerControl);
613
614 LOGF_LEAVE();
615 return NO_ERROR;
616}
617
618/* Called to check if our hardware supports given power state. */
619static VP_STATUS
620VBoxDrvGetPowerState(PVOID HwDeviceExtension, ULONG HwId, PVIDEO_POWER_MANAGEMENT VideoPowerControl)
621{
622 PAGED_CODE();
623 LOGF_ENTER();
624
625 /*Not implemented*/
626 RT_NOREF(HwDeviceExtension, HwId, VideoPowerControl);
627
628 LOGF_LEAVE();
629 return NO_ERROR;
630}
631
632/* Called to enumerate child devices of our adapter, attached monitor(s) in our case */
633static VP_STATUS
634VBoxDrvGetVideoChildDescriptor(PVOID HwDeviceExtension, PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
635 PVIDEO_CHILD_TYPE VideoChildType, PUCHAR pChildDescriptor, PULONG pUId,
636 PULONG pUnused)
637{
638 RT_NOREF(pChildDescriptor, pUnused);
639 PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
640
641 PAGED_CODE();
642 LOGF_ENTER();
643
644 if (ChildEnumInfo->ChildIndex>0)
645 {
646 if ((int)ChildEnumInfo->ChildIndex <= VBoxCommonFromDeviceExt(pExt)->cDisplays)
647 {
648 *VideoChildType = Monitor;
649 *pUId = ChildEnumInfo->ChildIndex;
650
651 LOGF_LEAVE();
652 return VIDEO_ENUM_MORE_DEVICES;
653 }
654 }
655 LOGF_LEAVE();
656 return ERROR_NO_MORE_DEVICES;
657}
658
659/* Called to reset adapter to a given character mode. */
660static BOOLEAN
661VBoxDrvResetHW(PVOID HwDeviceExtension, ULONG Columns, ULONG Rows)
662{
663 RT_NOREF(Columns, Rows);
664 PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
665
666 LOGF_ENTER();
667
668 if (pExt->iDevice==0) /* Primary device */
669 {
670 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
671 VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
672
673#if 0
674 /* ResetHW is not the place to do such cleanup. See MSDN. */
675 if (pExt->u.primary.pvReqFlush != NULL)
676 {
677 VbglR0GRFree((VMMDevRequestHeader *)pExt->u.primary.pvReqFlush);
678 pExt->u.primary.pvReqFlush = NULL;
679 }
680
681 VbglR0TerminateClient();
682
683 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pExt));
684#endif
685 }
686 else
687 {
688 LOG(("ignoring non primary device %d", pExt->iDevice));
689 }
690
691 LOGF_LEAVE();
692 /* Tell the system to use VGA BIOS to set the text video mode. */
693 return FALSE;
694}
695
696/* Video Miniport Driver entry point */
697ULONG DriverEntry(IN PVOID Context1, IN PVOID Context2)
698{
699 PAGED_CODE();
700
701 int irc = RTR0Init(0);
702 if (RT_FAILURE(irc))
703 {
704 LogRel(("VBoxMP::failed to init IPRT (rc=%#x)", irc));
705 return ERROR_INVALID_FUNCTION;
706 }
707
708 LOGF_ENTER();
709
710 LOGREL(("VBox XPDM Driver for Windows version %d.%d.%dr%d, %d bit; Built %s %s",
711 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV,
712 (sizeof (void*) << 3), __DATE__, __TIME__));
713
714 VIDEO_HW_INITIALIZATION_DATA vhwData;
715
716 /*Zero the structure*/
717 VideoPortZeroMemory(&vhwData, sizeof(vhwData));
718
719 /*Required driver callbacks*/
720 vhwData.HwFindAdapter = VBoxDrvFindAdapter;
721 vhwData.HwInitialize = VBoxDrvInitialize;
722 vhwData.HwStartIO = VBoxDrvStartIO;
723 vhwData.HwSetPowerState = VBoxDrvSetPowerState;
724 vhwData.HwGetPowerState = VBoxDrvGetPowerState;
725 vhwData.HwGetVideoChildDescriptor = VBoxDrvGetVideoChildDescriptor;
726
727 /*Optional callbacks*/
728 vhwData.HwResetHw = VBoxDrvResetHW;
729
730 /*Our private storage space*/
731 vhwData.HwDeviceExtensionSize = sizeof(VBOXMP_DEVEXT);
732
733 /*Claim legacy VGA resource ranges*/
734 vhwData.HwLegacyResourceList = g_aVBoxLegacyVGAResources;
735 vhwData.HwLegacyResourceCount = RT_ELEMENTS(g_aVBoxLegacyVGAResources);
736
737 /*Size of this structure changes between windows/ddk versions,
738 *so we query current version and report the expected size
739 *to allow our driver to be loaded.
740 */
741 switch (VBoxQueryWinVersion(NULL))
742 {
743 case WINVERSION_NT4:
744 LOG(("WINVERSION_NT4"));
745 vhwData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
746 break;
747 case WINVERSION_2K:
748 LOG(("WINVERSION_2K"));
749 vhwData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
750 break;
751 default:
752 vhwData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
753 break;
754 }
755
756 /*Even though msdn claims that this field is ignored and should remain zero-initialized,
757 windows NT4 SP0 dies without the following line.
758 */
759 vhwData.AdapterInterfaceType = PCIBus;
760
761 /*Allocate system resources*/
762 ULONG rc = VideoPortInitialize(Context1, Context2, &vhwData, NULL);
763 if (rc != NO_ERROR)
764 LOG(("VideoPortInitialize failed with %#x", rc));
765
766 LOGF_LEAVE();
767 return rc;
768}
Note: See TracBrowser for help on using the repository browser.

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