VirtualBox

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

Last change on this file since 450 was 446, checked in by vboxsync, 18 years ago

Added configuration option GetHostTimeDisabled (boolean).

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