VirtualBox

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

Last change on this file was 99828, checked in by vboxsync, 12 months ago

*: A bunch of adjustments that allows using /permissive- with Visual C++ (qt 6.x necessity).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use