VirtualBox

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

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

64-bit alignment.

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