VirtualBox

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

Last change on this file since 41044 was 41044, checked in by vboxsync, 13 years ago

VBoxVideoXPDM: inform host about disabled monitors.

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