VirtualBox

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

Last change on this file since 2272 was 2053, checked in by vboxsync, 18 years ago

Pass the rc from poweroff and suspend around!

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