VirtualBox

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

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

Log the video mode hint only when it is actually delivered to the guest.

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