VirtualBox

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

Last change on this file since 45037 was 45037, checked in by vboxsync, 12 years ago

VBoxVideo: multimonitor resize fixes.

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

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