VirtualBox

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

Last change on this file since 95009 was 93299, checked in by vboxsync, 3 years ago

Add/win: VC++ 19.2 update 11 build adjustments. bugref:8489

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