VirtualBox

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

Last change on this file since 65381 was 65381, checked in by vboxsync, 8 years ago

bugref:8282: Additions/linux: submit DRM driver to the Linux kernel: move all graphics device-related header files to a separate sub-directory and add that to the include path where they are needed. The intention is too be able to remove the VBox/ include folder in the DRM driver package.

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

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