VirtualBox

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

Last change on this file since 75468 was 75468, checked in by vboxsync, 6 years ago

XPDM: miniport driver fix for vboxsvga.

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