VirtualBox

source: vbox/trunk/src/VBox/Devices/VMMDev/VBoxDev.cpp@ 1959

Last change on this file since 1959 was 1681, checked in by vboxsync, 18 years ago

Implemented HGCM save/load state

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 67.2 KB
Line 
1/** @file
2 *
3 * VBox Guest/VMM/host communication:
4 * Virtual communication device
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23/* #define LOG_ENABLED */
24
25#include <stdio.h>
26#include <string.h>
27
28#include <VBox/VBoxDev.h>
29#include <VBox/VBoxGuest.h>
30#include <VBox/param.h>
31#include <VBox/mm.h>
32#include <VBox/pgm.h>
33#include <VBox/err.h>
34
35#define LOG_GROUP LOG_GROUP_DEV_VMM
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/time.h>
39
40#include "VMMDevState.h"
41
42#ifdef VBOX_HGCM
43#include "VMMDevHGCM.h"
44#endif
45
46#define PCIDEV_2_VMMDEVSTATE(pPciDev) ( (VMMDevState *)(pPciDev) )
47#define VMMDEVSTATE_2_DEVINS(pVMMDevState) ( (pVMMDevState)->pDevIns )
48
49#define VBOX_GUEST_ADDITIONS_VERSION_1_03(s) \
50 ((RT_HIWORD ((s)->guestInfo.additionsVersion) == 1) && \
51 (RT_LOWORD ((s)->guestInfo.additionsVersion) == 3))
52
53#define VBOX_GUEST_ADDITIONS_VERSION_OK(additionsVersion) \
54 (RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
55 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
56
57#define VBOX_GUEST_ADDITIONS_VERSION_OLD(additionsVersion) \
58 ((RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
59 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
60 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
61
62#define VBOX_GUEST_ADDITIONS_VERSION_TOO_OLD(additionsVersion) \
63 (RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION))
64
65#define VBOX_GUEST_ADDITIONS_VERSION_NEW(additionsVersion) \
66 ((RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
67 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
68 && RT_LOWORD(additionsVersion) > RT_LOWORD(VMMDEV_VERSION))
69
70#ifndef VBOX_DEVICE_STRUCT_TESTCASE
71
72/* Whenever host wants to inform guest about something
73 * an IRQ notification will be raised.
74 *
75 * VMMDev PDM interface will contain the guest notification method.
76 *
77 * There is a 32 bit event mask which will be read
78 * by guest on an interrupt. A non zero bit in the mask
79 * means that the specific event occured and requires
80 * processing on guest side.
81 *
82 * After reading the event mask guest must issue a
83 * generic request AcknowlegdeEvents.
84 *
85 * IRQ line is set to 1 (request) if there are unprocessed
86 * events, that is the event mask is not zero.
87 *
88 * After receiving an interrupt and checking event mask,
89 * the guest must process events using the event specific
90 * mechanism.
91 *
92 * That is if mouse capabilities were changed,
93 * guest will use VMMDev_GetMouseStatus generic request.
94 *
95 * Event mask is only a set of flags indicating that guest
96 * must proceed with a procedure.
97 *
98 * Unsupported events are therefore ignored.
99 * The guest additions must inform host which events they
100 * want to receive, to avoid unnecessary IRQ processing.
101 * By default no events are signalled to guest.
102 *
103 * This seems to be fast method. It requires
104 * only one context switch for an event processing.
105 *
106 */
107
108static void vmmdevSetIRQ_Legacy_EMT (VMMDevState *pVMMDevState)
109{
110 if (!pVMMDevState->fu32AdditionsOk)
111 {
112 Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
113 return;
114 }
115
116 uint32_t u32IRQLevel = 0;
117
118 /* Filter unsupported events */
119 uint32_t u32EventFlags =
120 pVMMDevState->u32HostEventFlags
121 & pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask;
122
123 Log(("vmmdevSetIRQ: u32EventFlags = 0x%08X, "
124 "pVMMDevState->u32HostEventFlags = 0x%08X, "
125 "pVMMDevState->pVMMDevRAMHC->u32GuestEventMask = 0x%08X\n",
126 u32EventFlags,
127 pVMMDevState->u32HostEventFlags,
128 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask));
129
130 /* Move event flags to VMMDev RAM */
131 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32HostEvents = u32EventFlags;
132
133 if (u32EventFlags)
134 {
135 /* Clear host flags which will be delivered to guest. */
136 pVMMDevState->u32HostEventFlags &= ~u32EventFlags;
137 Log(("vmmdevSetIRQ: pVMMDevState->u32HostEventFlags = 0x%08X\n",
138 pVMMDevState->u32HostEventFlags));
139 u32IRQLevel = 1;
140 }
141
142 /* Set IRQ level for pin 0 */
143 /** @todo make IRQ pin configurable, at least a symbolic constant */
144 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
145 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, u32IRQLevel);
146 Log(("vmmdevSetIRQ: IRQ set %d\n", u32IRQLevel));
147}
148
149static void vmmdevMaybeSetIRQ_EMT (VMMDevState *pVMMDevState)
150{
151 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS (pVMMDevState);
152
153#ifdef DEBUG_sunlover
154 Log(("vmmdevMaybeSetIRQ_EMT: u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
155 pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
156#endif /* DEBUG_sunlover */
157
158 if (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask)
159 {
160 pVMMDevState->pVMMDevRAMHC->V.V1_04.fHaveEvents = true;
161 PDMDevHlpPCISetIrqNoWait (pDevIns, 0, 1);
162#ifdef DEBUG_sunlover
163 Log(("vmmdevMaybeSetIRQ_EMT: IRQ set.\n"));
164#endif /* DEBUG_sunlover */
165 }
166}
167
168static void vmmdevNotifyGuest_EMT (VMMDevState *pVMMDevState, uint32_t u32EventMask)
169{
170#ifdef DEBUG_sunlover
171 Log(("VMMDevNotifyGuest_EMT: u32EventMask = 0x%08X.\n", u32EventMask));
172#endif /* DEBUG_sunlover */
173
174 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pVMMDevState))
175 {
176#ifdef DEBUG_sunlover
177 Log(("VMMDevNotifyGuest_EMT: Old additions detected.\n"));
178#endif /* DEBUG_sunlover */
179
180 pVMMDevState->u32HostEventFlags |= u32EventMask;
181 vmmdevSetIRQ_Legacy_EMT (pVMMDevState);
182 }
183 else
184 {
185#ifdef DEBUG_sunlover
186 Log(("VMMDevNotifyGuest_EMT: New additions detected.\n"));
187#endif /* DEBUG_sunlover */
188
189 if (!pVMMDevState->fu32AdditionsOk)
190 {
191 pVMMDevState->u32HostEventFlags |= u32EventMask;
192 Log(("vmmdevNotifyGuest_EMT: IRQ is not generated, guest has not yet reported to us.\n"));
193 return;
194 }
195
196 const bool fHadEvents =
197 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
198
199#ifdef DEBUG_sunlover
200 Log(("VMMDevNotifyGuest_EMT: fHadEvents = %d, u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
201 fHadEvents, pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
202#endif /* DEBUG_sunlover */
203
204 pVMMDevState->u32HostEventFlags |= u32EventMask;
205
206 if (!fHadEvents)
207 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
208 }
209}
210
211static void vmmdevCtlGuestFilterMask_EMT (VMMDevState *pVMMDevState,
212 uint32_t u32OrMask,
213 uint32_t u32NotMask)
214{
215 const bool fHadEvents =
216 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
217
218 if (fHadEvents)
219 {
220 if (!pVMMDevState->fNewGuestFilterMask)
221 pVMMDevState->u32NewGuestFilterMask = pVMMDevState->u32GuestFilterMask;
222
223 pVMMDevState->u32NewGuestFilterMask |= u32OrMask;
224 pVMMDevState->u32NewGuestFilterMask &= ~u32NotMask;
225 pVMMDevState->fNewGuestFilterMask = true;
226 }
227 else
228 {
229 pVMMDevState->u32GuestFilterMask |= u32OrMask;
230 pVMMDevState->u32GuestFilterMask &= ~u32NotMask;
231 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
232 }
233}
234
235void VMMDevNotifyGuest (VMMDevState *pVMMDevState, uint32_t u32EventMask)
236{
237 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
238 PVM pVM = PDMDevHlpGetVM(pDevIns);
239 int rc;
240 PVMREQ pReq;
241
242#ifdef DEBUG_sunlover
243 Log(("VMMDevNotifyGuest: u32EventMask = 0x%08X.\n", u32EventMask));
244#endif /* DEBUG_sunlover */
245
246 rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
247 (PFNRT) vmmdevNotifyGuest_EMT,
248 2, pVMMDevState, u32EventMask);
249 AssertReleaseRC (rc);
250 VMR3ReqFree (pReq);
251}
252
253/**
254 * Port I/O Handler for OUT operations.
255 *
256 * @returns VBox status code.
257 *
258 * @param pDevIns The device instance.
259 * @param pvUser User argument - ignored.
260 * @param uPort Port number used for the IN operation.
261 * @param u32 The value to output.
262 * @param cb The value size in bytes.
263 */
264#undef LOG_GROUP
265#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
266
267static DECLCALLBACK(int) vmmdevBackdoorLog(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
268{
269 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
270
271 if (!pData->fBackdoorLogDisabled && cb == 1 && Port == RTLOG_DEBUG_PORT)
272 {
273
274 /* The raw version. */
275 switch (u32)
276 {
277 case '\r': Log2(("vmmdev: <return>\n")); break;
278 case '\n': Log2(("vmmdev: <newline>\n")); break;
279 case '\t': Log2(("vmmdev: <tab>\n")); break;
280 default: Log2(("vmmdev: %c (%02x)\n", u32, u32)); break;
281 }
282
283 /* The readable, buffered version. */
284 if (u32 == '\n' || u32 == '\r')
285 {
286 pData->szMsg[pData->iMsg] = '\0';
287 if (pData->iMsg)
288 LogRel(("Guest Log: %s\n", pData->szMsg));
289 pData->iMsg = 0;
290 }
291 else
292 {
293 if (pData->iMsg >= sizeof(pData->szMsg)-1)
294 {
295 pData->szMsg[pData->iMsg] = '\0';
296 LogRel(("Guest Log: %s\n", pData->szMsg));
297 pData->iMsg = 0;
298 }
299 pData->szMsg[pData->iMsg] = (char )u32;
300 pData->szMsg[++pData->iMsg] = '\0';
301 }
302 }
303 return VINF_SUCCESS;
304}
305#undef LOG_GROUP
306#define LOG_GROUP LOG_GROUP_DEV_VMM
307
308#ifdef TIMESYNC_BACKDOOR
309/**
310 * Port I/O Handler for OUT operations.
311 *
312 * @returns VBox status code.
313 *
314 * @param pDevIns The device instance.
315 * @param pvUser User argument - ignored.
316 * @param uPort Port number used for the IN operation.
317 * @param u32 The value to output.
318 * @param cb The value size in bytes.
319 */
320static DECLCALLBACK(int) vmmdevTimesyncBackdoorWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
321{
322 NOREF(pvUser);
323 if (cb == 4)
324 {
325 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
326 switch (u32)
327 {
328 case 0:
329 pData->fTimesyncBackdoorLo = false;
330 break;
331 case 1:
332 pData->fTimesyncBackdoorLo = true;
333 }
334 return VINF_SUCCESS;
335
336 }
337 return VINF_SUCCESS;
338}
339
340/**
341 * Port I/O Handler for backdoor timesync IN operations.
342 *
343 * @returns VBox status code.
344 *
345 * @param pDevIns The device instance.
346 * @param pvUser User argument - ignored.
347 * @param uPort Port number used for the IN operation.
348 * @param pu32 Where to store the result.
349 * @param cb Number of bytes read.
350 */
351static DECLCALLBACK(int) vmmdevTimesyncBackdoorRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
352{
353 int rc;
354 NOREF(pvUser);
355 if (cb == 4)
356 {
357 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
358 RTTIMESPEC now;
359
360 if (pData->fTimesyncBackdoorLo)
361 {
362 *pu32 = (uint32_t)(pData->hostTime & (uint64_t)0xFFFFFFFF);
363 }
364 else
365 {
366 pData->hostTime = RTTimeSpecGetMilli(RTTimeNow(&now));
367 *pu32 = (uint32_t)(pData->hostTime >> 32);
368 }
369 rc = VINF_SUCCESS;
370 }
371 else
372 rc = VERR_IOM_IOPORT_UNUSED;
373 return rc;
374}
375#endif /* TIMESYNC_BACKDOOR */
376
377/**
378 * Port I/O Handler for the generic request interface
379 * @see FNIOMIOPORTOUT for details.
380 */
381static DECLCALLBACK(int) vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
382{
383 VMMDevState *pData = (VMMDevState*)pvUser;
384 int rc;
385
386 /*
387 * The caller has passed the guest context physical address
388 * of the request structure. Get the corresponding host virtual
389 * address.
390 */
391 VMMDevRequestHeader *requestHeader = NULL;
392 rc = PDMDevHlpPhys2HCVirt(pDevIns, (RTGCPHYS)u32, 0, (PRTHCPTR)&requestHeader);
393 if (VBOX_FAILURE(rc) || !requestHeader)
394 {
395 AssertMsgFailed(("VMMDev could not convert guest physical address to host virtual! rc = %Vrc\n", rc));
396 return VINF_SUCCESS;
397 }
398
399 /* the structure size must be greater or equal to the header size */
400 if (requestHeader->size < sizeof(VMMDevRequestHeader))
401 {
402 Log(("VMMDev request header size too small! size = %d\n", requestHeader->size));
403 return VINF_SUCCESS;
404 }
405
406 /* check the version of the header structure */
407 if (requestHeader->version != VMMDEV_REQUEST_HEADER_VERSION)
408 {
409 Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
410 return VINF_SUCCESS;
411 }
412
413 Log(("VMMDev request issued: %d\n", requestHeader->requestType));
414
415 if (requestHeader->requestType != VMMDevReq_ReportGuestInfo
416 && !pData->fu32AdditionsOk)
417 {
418 Log(("VMMDev: guest has not yet reported to us. Refusing operation.\n"));
419 requestHeader->rc = VERR_NOT_SUPPORTED;
420 return VINF_SUCCESS;
421 }
422
423 /* which request was sent? */
424 switch (requestHeader->requestType)
425 {
426 /*
427 * Guest wants to give up a timeslice
428 */
429 case VMMDevReq_Idle:
430 {
431 /* just return to EMT telling it that we want to halt */
432 return VINF_EM_HALT;
433 break;
434 }
435
436 /*
437 * Guest is reporting its information
438 */
439 case VMMDevReq_ReportGuestInfo:
440 {
441 if (requestHeader->size < sizeof(VMMDevReportGuestInfo))
442 {
443 AssertMsgFailed(("VMMDev guest information structure has invalid size!\n"));
444 requestHeader->rc = VERR_INVALID_PARAMETER;
445 }
446 else
447 {
448 VMMDevReportGuestInfo *guestInfo = (VMMDevReportGuestInfo*)requestHeader;
449
450 if (memcmp (&pData->guestInfo, &guestInfo->guestInfo, sizeof (guestInfo->guestInfo)) != 0)
451 {
452 /* make a copy of supplied information */
453 pData->guestInfo = guestInfo->guestInfo;
454
455 /* Check additions version */
456 pData->fu32AdditionsOk = VBOX_GUEST_ADDITIONS_VERSION_OK(pData->guestInfo.additionsVersion);
457
458 LogRel(("Guest Additions information report:\t"
459 " additionsVersion = 0x%08X\t"
460 " osType = 0x%08X\n",
461 pData->guestInfo.additionsVersion,
462 pData->guestInfo.osType));
463 pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
464 }
465
466 if (pData->fu32AdditionsOk)
467 {
468 requestHeader->rc = VINF_SUCCESS;
469 }
470 else
471 {
472 requestHeader->rc = VERR_VERSION_MISMATCH;
473 }
474 }
475 break;
476 }
477
478 /*
479 * Retrieve mouse information
480 */
481 case VMMDevReq_GetMouseStatus:
482 {
483 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
484 {
485 AssertMsgFailed(("VMMDev mouse status structure has invalid size!\n"));
486 requestHeader->rc = VERR_INVALID_PARAMETER;
487 }
488 else
489 {
490 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
491 mouseStatus->mouseFeatures = 0;
492 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS)
493 {
494 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE;
495 }
496 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
497 {
498 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE;
499 }
500 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
501 {
502 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CANNOT_HWPOINTER;
503 }
504 mouseStatus->pointerXPos = pData->mouseXAbs;
505 mouseStatus->pointerYPos = pData->mouseYAbs;
506 Log(("returning mouse status: features = %d, absX = %d, absY = %d\n", mouseStatus->mouseFeatures,
507 mouseStatus->pointerXPos, mouseStatus->pointerYPos));
508 requestHeader->rc = VINF_SUCCESS;
509 }
510 break;
511 }
512
513 /*
514 * Set mouse information
515 */
516 case VMMDevReq_SetMouseStatus:
517 {
518 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
519 {
520 AssertMsgFailed(("VMMDev mouse status structure has invalid size %d (%#x) version=%d!\n",
521 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
522 requestHeader->rc = VERR_INVALID_PARAMETER;
523 }
524 else
525 {
526 bool bCapsChanged = false;
527
528 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
529
530 /* check if the guest wants absolute coordinates */
531 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE)
532 {
533 /* set the capability flag and the changed flag if it's actually a change */
534 if (!(pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS))
535 {
536 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTWANTSABS;
537 bCapsChanged = true;
538 LogRel(("Guest requests mouse pointer integration\n"));
539 }
540 } else
541 {
542 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
543 {
544 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
545 bCapsChanged = true;
546 LogRel(("Guest disables mouse pointer integration\n"));
547 }
548 }
549 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_NEEDS_HOST_CURSOR)
550 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
551 else
552 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
553
554 /*
555 * Notify connector if something has changed
556 */
557 if (bCapsChanged)
558 {
559 Log(("VMMDevReq_SetMouseStatus: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
560 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
561 }
562 requestHeader->rc = VINF_SUCCESS;
563 }
564
565 break;
566 }
567
568 /*
569 * Set a new mouse pointer shape
570 */
571 case VMMDevReq_SetPointerShape:
572 {
573 if (requestHeader->size < sizeof(VMMDevReqMousePointer))
574 {
575 AssertMsg(requestHeader->size == 0x10028 && requestHeader->version == 10000, /* don't bitch about legacy!!! */
576 ("VMMDev mouse shape structure has invalid size %d (%#x) version=%d!\n",
577 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
578 requestHeader->rc = VERR_INVALID_PARAMETER;
579 }
580 else
581 {
582 VMMDevReqMousePointer *pointerShape = (VMMDevReqMousePointer*)requestHeader;
583
584 bool fVisible = (pointerShape->fFlags & VBOX_MOUSE_POINTER_VISIBLE) != 0;
585 bool fAlpha = (pointerShape->fFlags & VBOX_MOUSE_POINTER_ALPHA) != 0;
586 bool fShape = (pointerShape->fFlags & VBOX_MOUSE_POINTER_SHAPE) != 0;
587
588 Log(("VMMDevReq_SetPointerShape: visible: %d, alpha: %d, shape = %d, width: %d, height: %d\n",
589 fVisible, fAlpha, fShape, pointerShape->width, pointerShape->height));
590
591 /* forward call to driver */
592 if (fShape)
593 {
594 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
595 fVisible,
596 fAlpha,
597 pointerShape->xHot, pointerShape->yHot,
598 pointerShape->width, pointerShape->height,
599 pointerShape->pointerData);
600 }
601 else
602 {
603 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
604 fVisible,
605 0,
606 0, 0,
607 0, 0,
608 NULL);
609 }
610 requestHeader->rc = VINF_SUCCESS;
611 }
612 break;
613 }
614
615 /*
616 * Query the system time from the host
617 */
618 case VMMDevReq_GetHostTime:
619 {
620 if (requestHeader->size != sizeof(VMMDevReqHostTime))
621 {
622 AssertMsgFailed(("VMMDev host time structure has invalid size!\n"));
623 requestHeader->rc = VERR_INVALID_PARAMETER;
624 }
625 else if (RT_UNLIKELY(pData->fGetHostTimeDisabled))
626 requestHeader->rc = VERR_NOT_SUPPORTED;
627 else
628 {
629 VMMDevReqHostTime *hostTimeReq = (VMMDevReqHostTime*)requestHeader;
630 RTTIMESPEC now;
631 hostTimeReq->time = RTTimeSpecGetMilli(RTTimeNow(&now));
632 requestHeader->rc = VINF_SUCCESS;
633 }
634 break;
635 }
636
637 /*
638 * Query information about the hypervisor
639 */
640 case VMMDevReq_GetHypervisorInfo:
641 {
642 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
643 {
644 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
645 requestHeader->rc = VERR_INVALID_PARAMETER;
646 }
647 else
648 {
649 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
650 PVM pVM = PDMDevHlpGetVM(pDevIns);
651 size_t hypervisorSize = 0;
652 requestHeader->rc = PGMR3MappingsSize(pVM, &hypervisorSize);
653 hypervisorInfo->hypervisorSize = (uint32_t)hypervisorSize;
654 Assert(hypervisorInfo->hypervisorSize == hypervisorSize);
655 }
656 break;
657 }
658
659 /*
660 * Set hypervisor information
661 */
662 case VMMDevReq_SetHypervisorInfo:
663 {
664 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
665 {
666 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
667 requestHeader->rc = VERR_INVALID_PARAMETER;
668 }
669 else
670 {
671 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
672 PVM pVM = PDMDevHlpGetVM(pDevIns);
673 if (hypervisorInfo->hypervisorStart == 0)
674 {
675 requestHeader->rc = PGMR3MappingsUnfix(pVM);
676 } else
677 {
678 /* only if the client has queried the size before! */
679 size_t mappingsSize;
680 requestHeader->rc = PGMR3MappingsSize(pVM, &mappingsSize);
681 if (VBOX_SUCCESS(requestHeader->rc) && (hypervisorInfo->hypervisorSize == mappingsSize))
682 {
683 /* new reservation */
684 requestHeader->rc = PGMR3MappingsFix(pVM, hypervisorInfo->hypervisorStart,
685 hypervisorInfo->hypervisorSize);
686 LogRel(("Guest reported fixed hypervisor window at 0x%p (size = 0x%x, rc = %Vrc)\n",
687 hypervisorInfo->hypervisorStart,
688 hypervisorInfo->hypervisorSize,
689 requestHeader->rc));
690 }
691 }
692 }
693 break;
694 }
695
696 /*
697 * Set the system power status
698 */
699 case VMMDevReq_SetPowerStatus:
700 {
701 if (requestHeader->size != sizeof(VMMDevPowerStateRequest))
702 {
703 AssertMsgFailed(("VMMDev power state request structure has invalid size!\n"));
704 requestHeader->rc = VERR_INVALID_PARAMETER;
705 }
706 else
707 {
708 VMMDevPowerStateRequest *powerStateRequest = (VMMDevPowerStateRequest*)requestHeader;
709 switch(powerStateRequest->powerState)
710 {
711 case VMMDevPowerState_Pause:
712 {
713 LogRel(("Guest requests the VM to be suspended (paused)\n"));
714 requestHeader->rc = PDMDevHlpVMSuspend(pDevIns);
715 break;
716 }
717
718 case VMMDevPowerState_PowerOff:
719 {
720 LogRel(("Guest requests the VM to be turned off\n"));
721 requestHeader->rc = PDMDevHlpVMPowerOff(pDevIns); /** @todo pass the rc around! */
722 break;
723 }
724
725 case VMMDevPowerState_SaveState:
726 {
727 /** @todo no API for that yet */
728 requestHeader->rc = VERR_NOT_IMPLEMENTED;
729 break;
730 }
731
732 default:
733 AssertMsgFailed(("VMMDev invalid power state request: %d\n", powerStateRequest->powerState));
734 requestHeader->rc = VERR_INVALID_PARAMETER;
735 break;
736 }
737 }
738 break;
739 }
740
741 /*
742 * Get display change request
743 */
744 case VMMDevReq_GetDisplayChangeRequest:
745 {
746 if (requestHeader->size != sizeof(VMMDevDisplayChangeRequest))
747 {
748 /* Assert only if the size also not equal to a previous version size to prevent
749 * assertion with old additions.
750 */
751 AssertMsg(requestHeader->size == sizeof(VMMDevDisplayChangeRequest) - sizeof (uint32_t),
752 ("VMMDev display change request structure has invalid size!\n"));
753 requestHeader->rc = VERR_INVALID_PARAMETER;
754 }
755 else
756 {
757 VMMDevDisplayChangeRequest *displayChangeRequest = (VMMDevDisplayChangeRequest*)requestHeader;
758 /* just pass on the information */
759 Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d\n",
760 pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp));
761 displayChangeRequest->xres = pData->displayChangeRequest.xres;
762 displayChangeRequest->yres = pData->displayChangeRequest.yres;
763 displayChangeRequest->bpp = pData->displayChangeRequest.bpp;
764
765 if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
766 {
767 /* Remember which resolution the client have queried. */
768 pData->lastReadDisplayChangeRequest = pData->displayChangeRequest;
769 }
770
771 requestHeader->rc = VINF_SUCCESS;
772 }
773 break;
774 }
775
776 /*
777 * Query whether the given video mode is supported
778 */
779 case VMMDevReq_VideoModeSupported:
780 {
781 if (requestHeader->size != sizeof(VMMDevVideoModeSupportedRequest))
782 {
783 AssertMsgFailed(("VMMDev video mode supported request structure has invalid size!\n"));
784 requestHeader->rc = VERR_INVALID_PARAMETER;
785 }
786 else
787 {
788 VMMDevVideoModeSupportedRequest *videoModeSupportedRequest = (VMMDevVideoModeSupportedRequest*)requestHeader;
789 /* forward the call */
790 requestHeader->rc = pData->pDrv->pfnVideoModeSupported(pData->pDrv,
791 videoModeSupportedRequest->width,
792 videoModeSupportedRequest->height,
793 videoModeSupportedRequest->bpp,
794 &videoModeSupportedRequest->fSupported);
795 }
796 break;
797 }
798
799 /*
800 * Query the height reduction in pixels
801 */
802 case VMMDevReq_GetHeightReduction:
803 {
804 if (requestHeader->size != sizeof(VMMDevGetHeightReductionRequest))
805 {
806 AssertMsgFailed(("VMMDev height reduction request structure has invalid size!\n"));
807 requestHeader->rc = VERR_INVALID_PARAMETER;
808 }
809 else
810 {
811 VMMDevGetHeightReductionRequest *heightReductionRequest = (VMMDevGetHeightReductionRequest*)requestHeader;
812 /* forward the call */
813 requestHeader->rc = pData->pDrv->pfnGetHeightReduction(pData->pDrv,
814 &heightReductionRequest->heightReduction);
815 }
816 break;
817 }
818
819 /*
820 * Acknowledge VMMDev events
821 */
822 case VMMDevReq_AcknowledgeEvents:
823 {
824 if (requestHeader->size != sizeof(VMMDevEvents))
825 {
826 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
827 requestHeader->rc = VERR_INVALID_PARAMETER;
828 }
829 else
830 {
831 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pData))
832 {
833 vmmdevSetIRQ_Legacy_EMT (pData);
834 }
835 else
836 {
837 VMMDevEvents *pAckRequest;
838
839 if (pData->fNewGuestFilterMask)
840 {
841 pData->fNewGuestFilterMask = false;
842 pData->u32GuestFilterMask = pData->u32NewGuestFilterMask;
843 }
844
845 pAckRequest = (VMMDevEvents *) requestHeader;
846 pAckRequest->events =
847 pData->u32HostEventFlags & pData->u32GuestFilterMask;
848
849 pData->u32HostEventFlags &= ~pData->u32GuestFilterMask;
850 pData->pVMMDevRAMHC->V.V1_04.fHaveEvents = false;
851 PDMDevHlpPCISetIrqNoWait (pData->pDevIns, 0, 0);
852 }
853 requestHeader->rc = VINF_SUCCESS;
854 }
855 break;
856 }
857
858 /*
859 * Change guest filter mask
860 */
861 case VMMDevReq_CtlGuestFilterMask:
862 {
863 if (requestHeader->size != sizeof(VMMDevCtlGuestFilterMask))
864 {
865 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
866 requestHeader->rc = VERR_INVALID_PARAMETER;
867 }
868 else
869 {
870 VMMDevCtlGuestFilterMask *pCtlMaskRequest;
871
872 pCtlMaskRequest = (VMMDevCtlGuestFilterMask *) requestHeader;
873 vmmdevCtlGuestFilterMask_EMT (pData,
874 pCtlMaskRequest->u32OrMask,
875 pCtlMaskRequest->u32NotMask);
876 requestHeader->rc = VINF_SUCCESS;
877
878 }
879 break;
880 }
881
882#ifdef VBOX_HGCM
883 /*
884 * Process HGCM request
885 */
886 case VMMDevReq_HGCMConnect:
887 {
888 if (requestHeader->size < sizeof(VMMDevHGCMConnect))
889 {
890 AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
891 requestHeader->rc = VERR_INVALID_PARAMETER;
892 }
893 else if (!pData->pHGCMDrv)
894 {
895 Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
896 requestHeader->rc = VERR_NOT_SUPPORTED;
897 }
898 else
899 {
900 VMMDevHGCMConnect *pHGCMConnect = (VMMDevHGCMConnect *)requestHeader;
901
902 Log(("VMMDevReq_HGCMConnect\n"));
903
904 requestHeader->rc = vmmdevHGCMConnect (pData, pHGCMConnect, (RTGCPHYS)u32);
905 }
906 break;
907 }
908
909 case VMMDevReq_HGCMDisconnect:
910 {
911 if (requestHeader->size < sizeof(VMMDevHGCMDisconnect))
912 {
913 AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
914 requestHeader->rc = VERR_INVALID_PARAMETER;
915 }
916 else if (!pData->pHGCMDrv)
917 {
918 Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
919 requestHeader->rc = VERR_NOT_SUPPORTED;
920 }
921 else
922 {
923 VMMDevHGCMDisconnect *pHGCMDisconnect = (VMMDevHGCMDisconnect *)requestHeader;
924
925 Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
926 requestHeader->rc = vmmdevHGCMDisconnect (pData, pHGCMDisconnect, (RTGCPHYS)u32);
927 }
928 break;
929 }
930
931 case VMMDevReq_HGCMCall:
932 {
933 if (requestHeader->size < sizeof(VMMDevHGCMCall))
934 {
935 AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
936 requestHeader->rc = VERR_INVALID_PARAMETER;
937 }
938 else if (!pData->pHGCMDrv)
939 {
940 Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
941 requestHeader->rc = VERR_NOT_SUPPORTED;
942 }
943 else
944 {
945 VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)requestHeader;
946
947 Log(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
948
949 Log(("%.*Vhxd\n", requestHeader->size, requestHeader));
950
951 requestHeader->rc = vmmdevHGCMCall (pData, pHGCMCall, (RTGCPHYS)u32);
952 }
953 break;
954 }
955#endif
956
957 case VMMDevReq_VideoAccelEnable:
958 {
959 if (requestHeader->size < sizeof(VMMDevVideoAccelEnable))
960 {
961 Log(("VMMDevReq_VideoAccelEnable request size too small!!!\n"));
962 requestHeader->rc = VERR_INVALID_PARAMETER;
963 }
964 else if (!pData->pDrv)
965 {
966 Log(("VMMDevReq_VideoAccelEnable Connector is NULL!!!\n"));
967 requestHeader->rc = VERR_NOT_SUPPORTED;
968 }
969 else
970 {
971 VMMDevVideoAccelEnable *ptr = (VMMDevVideoAccelEnable *)requestHeader;
972
973 if (ptr->cbRingBuffer != VBVA_RING_BUFFER_SIZE)
974 {
975 /* The guest driver seems compiled with another headers. */
976 Log(("VMMDevReq_VideoAccelEnable guest ring buffer size %d, should be %d!!!\n", ptr->cbRingBuffer, VBVA_RING_BUFFER_SIZE));
977 requestHeader->rc = VERR_INVALID_PARAMETER;
978 }
979 else
980 {
981 /* The request is correct. */
982 ptr->fu32Status |= VBVA_F_STATUS_ACCEPTED;
983
984 LogFlow(("VMMDevReq_VideoAccelEnable ptr->u32Enable = %d\n", ptr->u32Enable));
985
986 requestHeader->rc = ptr->u32Enable?
987 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, true, &pData->pVMMDevRAMHC->vbvaMemory):
988 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, false, NULL);
989
990 if ( ptr->u32Enable
991 && VBOX_SUCCESS (requestHeader->rc))
992 {
993 ptr->fu32Status |= VBVA_F_STATUS_ENABLED;
994
995 /* Remember that guest successfully enabled acceleration.
996 * We need to reestablish it on restoring the VM from saved state.
997 */
998 pData->u32VideoAccelEnabled = 1;
999 }
1000 else
1001 {
1002 /* The acceleration was not enabled. Remember that. */
1003 pData->u32VideoAccelEnabled = 0;
1004 }
1005 }
1006 }
1007 break;
1008 }
1009
1010 case VMMDevReq_VideoAccelFlush:
1011 {
1012 if (requestHeader->size < sizeof(VMMDevVideoAccelFlush))
1013 {
1014 AssertMsgFailed(("VMMDevReq_VideoAccelFlush request size too small.\n"));
1015 requestHeader->rc = VERR_INVALID_PARAMETER;
1016 }
1017 else if (!pData->pDrv)
1018 {
1019 Log(("VMMDevReq_VideoAccelFlush Connector is NULL!\n"));
1020 requestHeader->rc = VERR_NOT_SUPPORTED;
1021 }
1022 else
1023 {
1024 pData->pDrv->pfnVideoAccelFlush (pData->pDrv);
1025
1026 requestHeader->rc = VINF_SUCCESS;
1027 }
1028 break;
1029 }
1030
1031 case VMMDevReq_QueryCredentials:
1032 {
1033 if (requestHeader->size != sizeof(VMMDevCredentials))
1034 {
1035 AssertMsgFailed(("VMMDevReq_QueryCredentials request size too small.\n"));
1036 requestHeader->rc = VERR_INVALID_PARAMETER;
1037 }
1038 else
1039 {
1040 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1041
1042 /* let's start by nulling out the data */
1043 memset(credentials->szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1044 memset(credentials->szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1045 memset(credentials->szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1046
1047 /* should we return whether we got credentials for a logon? */
1048 if (credentials->u32Flags & VMMDEV_CREDENTIALS_QUERYPRESENCE)
1049 {
1050 if ( pData->credentialsLogon.szUserName[0]
1051 || pData->credentialsLogon.szPassword[0]
1052 || pData->credentialsLogon.szDomain[0])
1053 {
1054 credentials->u32Flags |= VMMDEV_CREDENTIALS_PRESENT;
1055 }
1056 else
1057 {
1058 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_PRESENT;
1059 }
1060 }
1061
1062 /* does the guest want to read logon credentials? */
1063 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READ)
1064 {
1065 if (pData->credentialsLogon.szUserName[0])
1066 strcpy(credentials->szUserName, pData->credentialsLogon.szUserName);
1067 if (pData->credentialsLogon.szPassword[0])
1068 strcpy(credentials->szPassword, pData->credentialsLogon.szPassword);
1069 if (pData->credentialsLogon.szDomain[0])
1070 strcpy(credentials->szDomain, pData->credentialsLogon.szDomain);
1071 if (!pData->credentialsLogon.fAllowInteractiveLogon)
1072 credentials->u32Flags |= VMMDEV_CREDENTIALS_NOLOCALLOGON;
1073 else
1074 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_NOLOCALLOGON;
1075 }
1076
1077 /* does the caller want us to destroy the logon credentials? */
1078 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEAR)
1079 {
1080 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1081 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1082 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1083 }
1084
1085 /* does the guest want to read credentials for verification? */
1086 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READJUDGE)
1087 {
1088 if (pData->credentialsJudge.szUserName[0])
1089 strcpy(credentials->szUserName, pData->credentialsJudge.szUserName);
1090 if (pData->credentialsJudge.szPassword[0])
1091 strcpy(credentials->szPassword, pData->credentialsJudge.szPassword);
1092 if (pData->credentialsJudge.szDomain[0])
1093 strcpy(credentials->szDomain, pData->credentialsJudge.szDomain);
1094 }
1095
1096 /* does the caller want us to destroy the judgement credentials? */
1097 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEARJUDGE)
1098 {
1099 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1100 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1101 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1102 }
1103
1104 requestHeader->rc = VINF_SUCCESS;
1105 }
1106 break;
1107 }
1108
1109 case VMMDevReq_ReportCredentialsJudgement:
1110 {
1111 if (requestHeader->size != sizeof(VMMDevCredentials))
1112 {
1113 AssertMsgFailed(("VMMDevReq_ReportCredentialsJudgement request size too small.\n"));
1114 requestHeader->rc = VERR_INVALID_PARAMETER;
1115 }
1116 else
1117 {
1118 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1119
1120 /* what does the guest think about the credentials? (note: the order is important here!) */
1121 if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_DENY)
1122 {
1123 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_DENY);
1124 }
1125 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT)
1126 {
1127 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT);
1128 }
1129 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_OK)
1130 {
1131 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_OK);
1132 }
1133 else
1134 Log(("VMMDevReq_ReportCredentialsJudgement: invalid flags: %d!!!\n", credentials->u32Flags));
1135
1136 requestHeader->rc = VINF_SUCCESS;
1137 }
1138 break;
1139 }
1140
1141 default:
1142 {
1143 requestHeader->rc = VERR_NOT_IMPLEMENTED;
1144
1145 Log(("VMMDev unknown request type %d\n", requestHeader->requestType));
1146
1147 break;
1148 }
1149 }
1150
1151 return VINF_SUCCESS;
1152}
1153
1154/**
1155 * Callback function for mapping an PCI I/O region.
1156 *
1157 * @return VBox status code.
1158 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1159 * @param iRegion The region number.
1160 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1161 * I/O port, else it's a physical address.
1162 * This address is *NOT* relative to pci_mem_base like earlier!
1163 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1164 */
1165static DECLCALLBACK(int) vmmdevIORAMRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1166{
1167 int rc;
1168 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1169 LogFlow(("vmmdevR3IORAMRegionMap: iRegion=%d GCPhysAddress=%VGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
1170
1171
1172 Assert(pData->pVMMDevRAMHC != NULL);
1173
1174 memset (pData->pVMMDevRAMHC, 0, sizeof (VMMDevMemory));
1175 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
1176 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
1177
1178 /*
1179 * VMMDev RAM mapping.
1180 */
1181 if (iRegion == 1 && enmType == PCI_ADDRESS_SPACE_MEM)
1182 {
1183 /*
1184 * Register and lock the RAM.
1185 *
1186 * Windows usually re-initializes the PCI devices, so we have to check whether the memory was
1187 * already registered before trying to do that all over again.
1188 */
1189 PVM pVM = PDMDevHlpGetVM(pPciDev->pDevIns);
1190
1191 if (pData->GCPhysVMMDevRAM)
1192 {
1193 /*
1194 * Relocate the already registered VMMDevRAM.
1195 */
1196 rc = MMR3PhysRelocate(pVM, pData->GCPhysVMMDevRAM, GCPhysAddress, VMMDEV_RAM_SIZE);
1197 if (VBOX_SUCCESS(rc))
1198 {
1199 pData->GCPhysVMMDevRAM = GCPhysAddress;
1200 return VINF_SUCCESS;
1201 }
1202 AssertReleaseMsgFailed(("Failed to relocate VMMDev RAM from %VGp to %VGp! rc=%Vra\n", pData->GCPhysVMMDevRAM, GCPhysAddress, rc));
1203 }
1204 else
1205 {
1206 /*
1207 * Register and lock the VMMDevRAM.
1208 */
1209 /** @todo MM_RAM_FLAGS_MMIO2 seems to be appropriate for a RW memory.
1210 * Need to check. May be a RO memory is enough for the device.
1211 */
1212 rc = MMR3PhysRegister(pVM, pData->pVMMDevRAMHC, GCPhysAddress, VMMDEV_RAM_SIZE, MM_RAM_FLAGS_MMIO2, "VBoxDev");
1213 if (VBOX_SUCCESS(rc))
1214 {
1215 pData->GCPhysVMMDevRAM = GCPhysAddress;
1216 return VINF_SUCCESS;
1217 }
1218 AssertReleaseMsgFailed(("Failed to register VMMDev RAM! rc=%Vra\n", rc));
1219 }
1220 return rc;
1221 }
1222
1223 AssertReleaseMsgFailed(("VMMDev wrong region type: iRegion=%d enmType=%d\n", iRegion, enmType));
1224 return VERR_INTERNAL_ERROR;
1225}
1226
1227
1228/**
1229 * Callback function for mapping a PCI I/O region.
1230 *
1231 * @return VBox status code.
1232 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1233 * @param iRegion The region number.
1234 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1235 * I/O port, else it's a physical address.
1236 * This address is *NOT* relative to pci_mem_base like earlier!
1237 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1238 */
1239static DECLCALLBACK(int) vmmdevIOPortRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1240{
1241 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1242 int rc = VINF_SUCCESS;
1243
1244 Assert(enmType == PCI_ADDRESS_SPACE_IO);
1245 Assert(iRegion == 0);
1246 AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
1247
1248 /*
1249 * Save the base port address to simplify Port offset calculations.
1250 */
1251 pData->PortBase = (RTIOPORT)GCPhysAddress;
1252
1253 /*
1254 * Register our port IO handlers.
1255 */
1256 rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns,
1257 (RTIOPORT)GCPhysAddress + PORT_VMMDEV_REQUEST_OFFSET, 1,
1258 (void*)pData, vmmdevRequestHandler,
1259 NULL, NULL, NULL, "VMMDev Request Handler");
1260 AssertRC(rc);
1261 return rc;
1262}
1263
1264/**
1265 * Queries an interface to the driver.
1266 *
1267 * @returns Pointer to interface.
1268 * @returns NULL if the interface was not supported by the driver.
1269 * @param pInterface Pointer to this interface structure.
1270 * @param enmInterface The requested interface identification.
1271 * @thread Any thread.
1272 */
1273static DECLCALLBACK(void *) vmmdevPortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
1274{
1275 VMMDevState *pData = (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Base));
1276 switch (enmInterface)
1277 {
1278 case PDMINTERFACE_BASE:
1279 return &pData->Base;
1280 case PDMINTERFACE_VMMDEV_PORT:
1281 return &pData->Port;
1282#ifdef VBOX_HGCM
1283 case PDMINTERFACE_HGCM_PORT:
1284 return &pData->HGCMPort;
1285#endif
1286 default:
1287 return NULL;
1288 }
1289}
1290
1291/* -=-=-=-=-=- IVMMDevPort -=-=-=-=-=- */
1292
1293/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1294#define IVMMDEVPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Port)) )
1295
1296
1297/**
1298 * Return the current absolute mouse position in pixels
1299 *
1300 * @returns VBox status code
1301 * @param pAbsX Pointer of result value, can be NULL
1302 * @param pAbsY Pointer of result value, can be NULL
1303 */
1304static DECLCALLBACK(int) vmmdevQueryAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t *pAbsX, uint32_t *pAbsY)
1305{
1306 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1307 if (pAbsX)
1308 *pAbsX = pData->mouseXAbs;
1309 if (pAbsY)
1310 *pAbsY = pData->mouseYAbs;
1311 return VINF_SUCCESS;
1312}
1313
1314/**
1315 * Set the new absolute mouse position in pixels
1316 *
1317 * @returns VBox status code
1318 * @param absX New absolute X position
1319 * @param absY New absolute Y position
1320 */
1321static DECLCALLBACK(int) vmmdevSetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t absX, uint32_t absY)
1322{
1323 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1324 Log(("vmmdevSetAbsoluteMouse: settings absolute position to x = %d, y = %d\n", absX, absY));
1325 pData->mouseXAbs = absX;
1326 pData->mouseYAbs = absY;
1327 return VINF_SUCCESS;
1328}
1329
1330/**
1331 * Return the current mouse capability flags
1332 *
1333 * @returns VBox status code
1334 * @param pCapabilities Pointer of result value
1335 */
1336static DECLCALLBACK(int) vmmdevQueryMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t *pCapabilities)
1337{
1338 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1339 if (!pCapabilities)
1340 return VERR_INVALID_PARAMETER;
1341 *pCapabilities = pData->mouseCapabilities;
1342 return VINF_SUCCESS;
1343}
1344
1345/**
1346 * Set the current mouse capability flag (host side)
1347 *
1348 * @returns VBox status code
1349 * @param capabilities Capability mask
1350 */
1351static DECLCALLBACK(int) vmmdevSetMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t capabilities)
1352{
1353 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1354
1355 bool bCapsChanged = ((capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1356 != (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS));
1357
1358 Log(("vmmdevSetMouseCapabilities: bCapsChanged %d\n", bCapsChanged));
1359
1360 if (capabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
1361 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1362 else
1363 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1364
1365 if (capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1366 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTWANTSABS;
1367 else
1368 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTWANTSABS;
1369
1370 if (bCapsChanged)
1371 VMMDevNotifyGuest (pData, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
1372
1373 return VINF_SUCCESS;
1374}
1375
1376
1377static DECLCALLBACK(int) vmmdevRequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t xres, uint32_t yres, uint32_t bpp)
1378{
1379 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1380
1381 /* Verify that the new resolution is different and that guest does not yet know about it. */
1382 bool fSameResolution = (!xres || (pData->lastReadDisplayChangeRequest.xres == xres)) &&
1383 (!yres || (pData->lastReadDisplayChangeRequest.yres == yres)) &&
1384 (!bpp || (pData->lastReadDisplayChangeRequest.bpp == bpp));
1385
1386 if (!xres && !yres && !bpp)
1387 {
1388 /* Special case of reset video mode. */
1389 fSameResolution = false;
1390 }
1391
1392#ifdef DEBUG_sunlover
1393 Log(("vmmdevRequestDisplayChange: same=%d. new: xres=%d, yres=%d, bpp=%d. old: xres=%d, yres=%d, bpp=%d.\n",
1394 fSameResolution, xres, yres, bpp, pData->lastReadDisplayChangeRequest.xres, pData->lastReadDisplayChangeRequest.yres, pData->lastReadDisplayChangeRequest.bpp));
1395#endif /* DEBUG_sunlover */
1396
1397 if (!fSameResolution)
1398 {
1399 LogRel(("VMMDev::SetVideoModeHint: got a video mode hint (%dx%dx%d)\n",
1400 xres, yres, bpp));
1401
1402 /* we could validate the information here but hey, the guest can do that as well! */
1403 pData->displayChangeRequest.xres = xres;
1404 pData->displayChangeRequest.yres = yres;
1405 pData->displayChangeRequest.bpp = bpp;
1406
1407 /* IRQ so the guest knows what's going on */
1408 VMMDevNotifyGuest (pData, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
1409 }
1410
1411 return VINF_SUCCESS;
1412}
1413
1414static DECLCALLBACK(int) vmmdevSetCredentials(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
1415 const char *pszPassword, const char *pszDomain,
1416 uint32_t u32Flags)
1417{
1418 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1419
1420 /* logon mode? */
1421 if (u32Flags & VMMDEV_SETCREDENTIALS_GUESTLOGON)
1422 {
1423 /* memorize the data */
1424 strcpy(pData->credentialsLogon.szUserName, pszUsername);
1425 strcpy(pData->credentialsLogon.szPassword, pszPassword);
1426 strcpy(pData->credentialsLogon.szDomain, pszDomain);
1427 pData->credentialsLogon.fAllowInteractiveLogon = !(u32Flags & VMMDEV_SETCREDENTIALS_NOLOCALLOGON);
1428 }
1429 /* credentials verification mode? */
1430 else if (u32Flags & VMMDEV_SETCREDENTIALS_JUDGE)
1431 {
1432 /* memorize the data */
1433 strcpy(pData->credentialsJudge.szUserName, pszUsername);
1434 strcpy(pData->credentialsJudge.szPassword, pszPassword);
1435 strcpy(pData->credentialsJudge.szDomain, pszDomain);
1436
1437 VMMDevNotifyGuest (pData, VMMDEV_EVENT_JUDGE_CREDENTIALS);
1438 }
1439 else
1440 return VERR_INVALID_PARAMETER;
1441
1442 return VINF_SUCCESS;
1443}
1444
1445/**
1446 * Notification from the Display. Especially useful when
1447 * acceleration is disabled after a video mode change.
1448 *
1449 * @param fEnable Current acceleration status.
1450 */
1451static DECLCALLBACK(void) vmmdevVBVAChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1452{
1453 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1454
1455 Log(("vmmdevVBVAChange: fEnabled = %d\n", fEnabled));
1456
1457 if (pData)
1458 {
1459 pData->u32VideoAccelEnabled = fEnabled;
1460 }
1461
1462 return;
1463}
1464
1465
1466/* -=-=-=-=-=- IHGCMPort -=-=-=-=-=- */
1467
1468/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1469#define IHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
1470
1471
1472
1473#define VMMDEV_SSM_VERSION 3
1474
1475/**
1476 * Saves a state of the VMM device.
1477 *
1478 * @returns VBox status code.
1479 * @param pDevIns The device instance.
1480 * @param pSSMHandle The handle to save the state to.
1481 */
1482static DECLCALLBACK(int) vmmdevSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1483{
1484 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1485 SSMR3PutU32(pSSMHandle, pData->hypervisorSize);
1486 SSMR3PutU32(pSSMHandle, pData->mouseCapabilities);
1487 SSMR3PutU32(pSSMHandle, pData->mouseXAbs);
1488 SSMR3PutU32(pSSMHandle, pData->mouseYAbs);
1489
1490 SSMR3PutBool(pSSMHandle, pData->fNewGuestFilterMask);
1491 SSMR3PutU32(pSSMHandle, pData->u32NewGuestFilterMask);
1492 SSMR3PutU32(pSSMHandle, pData->u32GuestFilterMask);
1493 SSMR3PutU32(pSSMHandle, pData->u32HostEventFlags);
1494 // here be dragons (probably)
1495// SSMR3PutBool(pSSMHandle, pData->pVMMDevRAMHC->V.V1_04.fHaveEvents);
1496 SSMR3PutMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1497
1498 SSMR3PutMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1499 SSMR3PutU32(pSSMHandle, pData->fu32AdditionsOk);
1500 SSMR3PutU32(pSSMHandle, pData->u32VideoAccelEnabled);
1501
1502#ifdef VBOX_HGCM
1503 vmmdevHGCMSaveState (pData, pSSMHandle);
1504#endif /* VBOX_HGCM */
1505
1506 return VINF_SUCCESS;
1507}
1508
1509/**
1510 * Loads the saved VMM device state.
1511 *
1512 * @returns VBox status code.
1513 * @param pDevIns The device instance.
1514 * @param pSSMHandle The handle to the saved state.
1515 * @param u32Version The data unit version number.
1516 */
1517static DECLCALLBACK(int) vmmdevLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
1518{
1519 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1520 if (u32Version != VMMDEV_SSM_VERSION)
1521 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1522 SSMR3GetU32(pSSMHandle, &pData->hypervisorSize);
1523 SSMR3GetU32(pSSMHandle, &pData->mouseCapabilities);
1524 SSMR3GetU32(pSSMHandle, &pData->mouseXAbs);
1525 SSMR3GetU32(pSSMHandle, &pData->mouseYAbs);
1526
1527 SSMR3GetBool(pSSMHandle, &pData->fNewGuestFilterMask);
1528 SSMR3GetU32(pSSMHandle, &pData->u32NewGuestFilterMask);
1529 SSMR3GetU32(pSSMHandle, &pData->u32GuestFilterMask);
1530 SSMR3GetU32(pSSMHandle, &pData->u32HostEventFlags);
1531// SSMR3GetBool(pSSMHandle, &pData->pVMMDevRAMHC->fHaveEvents);
1532 // here be dragons (probably)
1533 SSMR3GetMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1534
1535 SSMR3GetMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1536 SSMR3GetU32(pSSMHandle, &pData->fu32AdditionsOk);
1537 SSMR3GetU32(pSSMHandle, &pData->u32VideoAccelEnabled);
1538
1539#ifdef VBOX_HGCM
1540 vmmdevHGCMLoadState (pData, pSSMHandle);
1541#endif /* VBOX_HGCM */
1542
1543 /*
1544 * On a resume, we send the capabilities changed message so
1545 * that listeners can sync their state again
1546 */
1547 Log(("vmmdevLoadState: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
1548 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
1549
1550 /* Reestablish the acceleration status. */
1551 if (pData->u32VideoAccelEnabled)
1552 {
1553 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, !!pData->u32VideoAccelEnabled, &pData->pVMMDevRAMHC->vbvaMemory);
1554 }
1555
1556 return VINF_SUCCESS;
1557}
1558
1559/**
1560 * Load state done callback. Notify guest of restore event.
1561 *
1562 * @returns VBox status code.
1563 * @param pDevIns The device instance.
1564 * @param pSSMHandle The handle to the saved state.
1565 */
1566static DECLCALLBACK(int) vmmdevLoadStateDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1567{
1568 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1569
1570#ifdef VBOX_HGCM
1571 vmmdevHGCMLoadStateDone (pData, pSSMHandle);
1572#endif /* VBOX_HGCM */
1573
1574 VMMDevNotifyGuest (pData, VMMDEV_EVENT_RESTORED);
1575
1576 return VINF_SUCCESS;
1577}
1578
1579/**
1580 * Construct a device instance for a VM.
1581 *
1582 * @returns VBox status.
1583 * @param pDevIns The device instance data.
1584 * If the registration structure is needed, pDevIns->pDevReg points to it.
1585 * @param iInstance Instance number. Use this to figure out which registers and such to use.
1586 * The device number is also found in pDevIns->iInstance, but since it's
1587 * likely to be freqently used PDM passes it as parameter.
1588 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
1589 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
1590 * iInstance it's expected to be used a bit in this function.
1591 */
1592static DECLCALLBACK(int) vmmdevConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1593{
1594 int rc;
1595 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
1596
1597 Assert(iInstance == 0);
1598
1599 /*
1600 * Validate and read the configuration.
1601 */
1602 if (!CFGMR3AreValuesValid(pCfgHandle, "GetHostTimeDisabled\0BackdoorLogDisabled\0"))
1603 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
1604
1605 rc = CFGMR3QueryBool(pCfgHandle, "GetHostTimeDisabled", &pData->fGetHostTimeDisabled);
1606 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1607 pData->fGetHostTimeDisabled = false;
1608 else if (VBOX_FAILURE(rc))
1609 return PDMDEV_SET_ERROR(pDevIns, rc,
1610 N_("Configuration error: Failed querying \"GetHostTimeDisabled\" as a boolean"));
1611
1612 rc = CFGMR3QueryBool(pCfgHandle, "BackdoorLogDisabled", &pData->fBackdoorLogDisabled);
1613 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1614 pData->fBackdoorLogDisabled = false;
1615 else if (VBOX_FAILURE(rc))
1616 return PDMDEV_SET_ERROR(pDevIns, rc,
1617 N_("Configuration error: Failed querying \"BackdoorLogDisabled\" as a boolean"));
1618
1619 /*
1620 * Initialize data (most of it anyway).
1621 */
1622 /* PCI vendor, just a free bogus value */
1623 pData->dev.config[0x00] = 0xee;
1624 pData->dev.config[0x01] = 0x80;
1625 /* device ID */
1626 pData->dev.config[0x02] = 0xfe;
1627 pData->dev.config[0x03] = 0xca;
1628 /* class sub code (other type of system peripheral) */
1629 pData->dev.config[0x0a] = 0x80;
1630 /* class base code (base system peripheral) */
1631 pData->dev.config[0x0b] = 0x08;
1632 /* header type */
1633 pData->dev.config[0x0e] = 0x00;
1634 /* interrupt on pin 0 */
1635 pData->dev.config[0x3d] = 0x01;
1636
1637 /*
1638 * Register the backdoor logging port
1639 */
1640 rc = PDMDevHlpIOPortRegister(pDevIns, RTLOG_DEBUG_PORT, 1, NULL, vmmdevBackdoorLog, NULL, NULL, NULL, "VMMDev backdoor logging");
1641
1642#ifdef TIMESYNC_BACKDOOR
1643 /*
1644 * Alternative timesync source (temporary!)
1645 */
1646 rc = PDMDevHlpIOPortRegister(pDevIns, 0x505, 1, NULL, vmmdevTimesyncBackdoorWrite, vmmdevTimesyncBackdoorRead, NULL, NULL, "VMMDev timesync backdoor");
1647#endif
1648
1649 /*
1650 * Register the PCI device.
1651 */
1652 rc = PDMDevHlpPCIRegister(pDevIns, &pData->dev);
1653 if (VBOX_FAILURE(rc))
1654 return rc;
1655 if (pData->dev.devfn == 32 || iInstance != 0)
1656 Log(("!!WARNING!!: pData->dev.devfn=%d (ignore if testcase or no started by Main)\n", pData->dev.devfn));
1657 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x20, PCI_ADDRESS_SPACE_IO, vmmdevIOPortRegionMap);
1658 if (VBOX_FAILURE(rc))
1659 return rc;
1660 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, VMMDEV_RAM_SIZE, PCI_ADDRESS_SPACE_MEM, vmmdevIORAMRegionMap);
1661 if (VBOX_FAILURE(rc))
1662 return rc;
1663
1664 /*
1665 * Interfaces
1666 */
1667 /* Base */
1668 pData->Base.pfnQueryInterface = vmmdevPortQueryInterface;
1669
1670 /* VMMDev port */
1671 pData->Port.pfnQueryAbsoluteMouse = vmmdevQueryAbsoluteMouse;
1672 pData->Port.pfnSetAbsoluteMouse = vmmdevSetAbsoluteMouse;
1673 pData->Port.pfnQueryMouseCapabilities = vmmdevQueryMouseCapabilities;
1674 pData->Port.pfnSetMouseCapabilities = vmmdevSetMouseCapabilities;
1675 pData->Port.pfnRequestDisplayChange = vmmdevRequestDisplayChange;
1676 pData->Port.pfnSetCredentials = vmmdevSetCredentials;
1677 pData->Port.pfnVBVAChange = vmmdevVBVAChange;
1678
1679
1680#ifdef VBOX_HGCM
1681 /* HGCM port */
1682 pData->HGCMPort.pfnCompleted = hgcmCompleted;
1683#endif
1684
1685 /* * Get the corresponding connector interface
1686 */
1687 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pData->Base, &pData->pDrvBase, "VMM Driver Port");
1688 if (VBOX_SUCCESS(rc))
1689 {
1690 pData->pDrv = (PPDMIVMMDEVCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_VMMDEV_CONNECTOR);
1691 if (!pData->pDrv)
1692 {
1693 AssertMsgFailed(("LUN #0 doesn't have a VMMDev connector interface! rc=%Vrc\n", rc));
1694 rc = VERR_PDM_MISSING_INTERFACE;
1695 }
1696#ifdef VBOX_HGCM
1697 else
1698 {
1699 pData->pHGCMDrv = (PPDMIHGCMCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_HGCM_CONNECTOR);
1700 if (!pData->pHGCMDrv)
1701 {
1702 Log(("LUN #0 doesn't have a HGCM connector interface, HGCM is not supported. rc=%Vrc\n", rc));
1703 /* this is not actually an error, just means that there is no support for HGCM */
1704 }
1705 }
1706#endif
1707 }
1708 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1709 {
1710 Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1711 rc = VINF_SUCCESS;
1712 }
1713 else
1714 AssertMsgFailed(("Failed to attach LUN #0! rc=%Vrc\n", rc));
1715
1716 rc = PDMDevHlpSSMRegister(pDevIns, "VMMDev", iInstance, VMMDEV_SSM_VERSION, sizeof(*pData),
1717 NULL, vmmdevSaveState, NULL,
1718 NULL, vmmdevLoadState, vmmdevLoadStateDone);
1719
1720 /* Save PDM device instance data for future reference. */
1721 pData->pDevIns = pDevIns;
1722
1723
1724 /*
1725 * Allocate the VMMDev RAM region.
1726 */
1727 /** @todo freeing of the RAM. */
1728 rc = SUPPageAlloc(VMMDEV_RAM_SIZE >> PAGE_SHIFT, (void **)&pData->pVMMDevRAMHC);
1729 if (VBOX_FAILURE(rc))
1730 {
1731 AssertMsgFailed(("VMMDev SUPPageAlloc(%#x,) -> %d\n", VMMDEV_RAM_SIZE, rc));
1732 }
1733
1734#ifdef VBOX_HGCM
1735 rc = RTCritSectInit(&pData->critsectHGCMCmdList);
1736 AssertRC(rc);
1737#endif /* VBOX_HGCM */
1738
1739 /* initialize the VMMDev memory */
1740 memset (pData->pVMMDevRAMHC, 0, sizeof (VMMDevMemory));
1741 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
1742 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
1743
1744 return rc;
1745}
1746
1747/**
1748 * Reset notification.
1749 *
1750 * @returns VBox status.
1751 * @param pDrvIns The driver instance data.
1752 */
1753static DECLCALLBACK(void) vmmdevReset(PPDMDEVINS pDevIns)
1754{
1755 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1756 /*
1757 * Reset the mouse integration feature bit
1758 */
1759 if (pData->mouseCapabilities & (VMMDEV_MOUSEGUESTWANTSABS|VMMDEV_MOUSEGUESTNEEDSHOSTCUR))
1760 {
1761 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
1762 /* notify the connector */
1763 Log(("vmmdevReset: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
1764 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
1765 }
1766
1767 pData->hypervisorSize = 0;
1768
1769 pData->u32HostEventFlags = 0;
1770
1771 if (pData->pVMMDevRAMHC)
1772 {
1773 memset (pData->pVMMDevRAMHC, 0, sizeof (VMMDevMemory));
1774 }
1775
1776 /* credentials have to go away */
1777 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1778 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1779 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1780 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1781 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1782 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1783
1784 /* Reset means that additions will report again. */
1785 pData->fu32AdditionsOk = false;
1786 memset (&pData->guestInfo, 0, sizeof (pData->guestInfo));
1787
1788 memset (&pData->lastReadDisplayChangeRequest, 0, sizeof (pData->lastReadDisplayChangeRequest));
1789
1790 /* Clear the event variables.
1791 *
1792 * Note: The pData->u32HostEventFlags is not cleared.
1793 * It is designed that way so host events do not
1794 * depend on guest resets.
1795 */
1796 pData->u32GuestFilterMask = 0;
1797 pData->u32NewGuestFilterMask = 0;
1798 pData->fNewGuestFilterMask = 0;
1799}
1800
1801
1802/**
1803 * The device registration structure.
1804 */
1805extern "C" const PDMDEVREG g_DeviceVMMDev =
1806{
1807 /* u32Version */
1808 PDM_DEVREG_VERSION,
1809 /* szDeviceName */
1810 "VMMDev",
1811 /* szGCMod */
1812 "",
1813 /* szR0Mod */
1814 "",
1815 /* pszDescription */
1816 "VirtualBox VMM Device\n",
1817 /* fFlags */
1818 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32,
1819 /* fClass */
1820 PDM_DEVREG_CLASS_VMM_DEV,
1821 /* cMaxInstances */
1822 1,
1823 /* cbInstance */
1824 sizeof(VMMDevState),
1825 /* pfnConstruct */
1826 vmmdevConstruct,
1827 /* pfnDestruct */
1828 NULL,
1829 /* pfnRelocate */
1830 NULL,
1831 /* pfnIOCtl */
1832 NULL,
1833 /* pfnPowerOn */
1834 NULL,
1835 /* pfnReset */
1836 vmmdevReset,
1837 /* pfnSuspend */
1838 NULL,
1839 /* pfnResume */
1840 NULL,
1841 /* pfnAttach */
1842 NULL,
1843 /* pfnDetach */
1844 NULL,
1845 /* pfnQueryInterface. */
1846 NULL
1847};
1848#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
1849
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