VirtualBox

source: vbox/trunk/src/VBox/Main/VMMDevInterface.cpp@ 31164

Last change on this file since 31164 was 31024, checked in by vboxsync, 14 years ago

Main: Follow up to r63855 (use enums).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.3 KB
Line 
1/* $Id: VMMDevInterface.cpp 31024 2010-07-22 20:39:31Z vboxsync $ */
2/** @file
3 * VirtualBox Driver Interface to VMM device.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VMMDev.h"
19#include "ConsoleImpl.h"
20#include "DisplayImpl.h"
21#include "GuestImpl.h"
22#include "MouseImpl.h"
23
24#include "Logging.h"
25
26#include <VBox/pdmdrv.h>
27#include <VBox/VMMDev.h>
28#include <VBox/shflsvc.h>
29#include <iprt/asm.h>
30
31#ifdef VBOX_WITH_HGCM
32#include "hgcm/HGCM.h"
33#include "hgcm/HGCMObjects.h"
34# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_CROGL)
35# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
36# endif
37#endif
38
39//
40// defines
41//
42
43#ifdef RT_OS_OS2
44# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
45#else
46# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
47#endif
48
49//
50// globals
51//
52
53
54/**
55 * VMMDev driver instance data.
56 */
57typedef struct DRVMAINVMMDEV
58{
59 /** Pointer to the VMMDev object. */
60 VMMDev *pVMMDev;
61 /** Pointer to the driver instance structure. */
62 PPDMDRVINS pDrvIns;
63 /** Pointer to the VMMDev port interface of the driver/device above us. */
64 PPDMIVMMDEVPORT pUpPort;
65 /** Our VMM device connector interface. */
66 PDMIVMMDEVCONNECTOR Connector;
67
68#ifdef VBOX_WITH_HGCM
69 /** Pointer to the HGCM port interface of the driver/device above us. */
70 PPDMIHGCMPORT pHGCMPort;
71 /** Our HGCM connector interface. */
72 PDMIHGCMCONNECTOR HGCMConnector;
73#endif
74} DRVMAINVMMDEV, *PDRVMAINVMMDEV;
75
76/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
77#define PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, Connector)) )
78
79#ifdef VBOX_WITH_HGCM
80/** Converts PDMIHGCMCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
81#define PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, HGCMConnector)) )
82#endif
83
84//
85// constructor / destructor
86//
87VMMDev::VMMDev(Console *console)
88 : mpDrv(NULL),
89 mParent(console)
90{
91 int rc = RTSemEventCreate(&mCredentialsEvent);
92 AssertRC(rc);
93#ifdef VBOX_WITH_HGCM
94 rc = HGCMHostInit ();
95 AssertRC(rc);
96 m_fHGCMActive = true;
97#endif /* VBOX_WITH_HGCM */
98 mu32CredentialsFlags = 0;
99}
100
101VMMDev::~VMMDev()
102{
103#ifdef VBOX_WITH_HGCM
104 if (hgcmIsActive())
105 {
106 ASMAtomicWriteBool(&m_fHGCMActive, false);
107 HGCMHostShutdown();
108 }
109#endif /* VBOX_WITH_HGCM */
110 RTSemEventDestroy (mCredentialsEvent);
111 if (mpDrv)
112 mpDrv->pVMMDev = NULL;
113 mpDrv = NULL;
114}
115
116PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
117{
118 AssertReturn(mpDrv, NULL);
119 return mpDrv->pUpPort;
120}
121
122
123
124//
125// public methods
126//
127
128/**
129 * Wait on event semaphore for guest credential judgement result.
130 */
131int VMMDev::WaitCredentialsJudgement (uint32_t u32Timeout, uint32_t *pu32CredentialsFlags)
132{
133 if (u32Timeout == 0)
134 {
135 u32Timeout = 5000;
136 }
137
138 int rc = RTSemEventWait (mCredentialsEvent, u32Timeout);
139
140 if (RT_SUCCESS(rc))
141 {
142 *pu32CredentialsFlags = mu32CredentialsFlags;
143 }
144
145 return rc;
146}
147
148int VMMDev::SetCredentialsJudgementResult (uint32_t u32Flags)
149{
150 mu32CredentialsFlags = u32Flags;
151
152 int rc = RTSemEventSignal (mCredentialsEvent);
153 AssertRC(rc);
154
155 return rc;
156}
157
158
159/**
160 * Reports Guest Additions status.
161 * Called whenever the Additions issue a guest status report request or the VM is reset.
162 *
163 * @param pInterface Pointer to this interface.
164 * @param guestInfo Pointer to guest information structure
165 * @thread The emulation thread.
166 */
167DECLCALLBACK(void) vmmdevUpdateGuestStatus(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestStatus *guestStatus)
168{
169 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
170
171 Assert(guestStatus);
172 if (!guestStatus)
173 return;
174
175 /* Store that information in IGuest */
176 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
177 Assert(guest);
178 if (!guest)
179 return;
180
181 guest->setAdditionsStatus(guestStatus->facility, guestStatus->status, guestStatus->flags);
182 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
183}
184
185
186/**
187 * Reports Guest Additions API and OS version.
188 * Called whenever the Additions issue a guest version report request or the VM is reset.
189 *
190 * @param pInterface Pointer to this interface.
191 * @param guestInfo Pointer to guest information structure
192 * @thread The emulation thread.
193 */
194DECLCALLBACK(void) vmmdevUpdateGuestInfo(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestInfo *guestInfo)
195{
196 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
197
198 Assert(guestInfo);
199 if (!guestInfo)
200 return;
201
202 /* Store that information in IGuest */
203 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
204 Assert(guest);
205 if (!guest)
206 return;
207
208 if (guestInfo->additionsVersion != 0)
209 {
210 char version[20];
211 RTStrPrintf(version, sizeof(version), "%d", guestInfo->additionsVersion);
212 guest->setAdditionsInfo(Bstr(version), guestInfo->osType);
213
214 /*
215 * Tell the console interface about the event
216 * so that it can notify its consumers.
217 */
218 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
219
220 if (guestInfo->additionsVersion < VMMDEV_VERSION)
221 pDrv->pVMMDev->getParent()->onAdditionsOutdated();
222 }
223 else
224 {
225 /*
226 * The guest additions was disabled because of a reset
227 * or driver unload.
228 */
229 guest->setAdditionsInfo(Bstr(), guestInfo->osType);
230 guest->setAdditionsStatus(VBoxGuestStatusFacility_Unknown,
231 VBoxGuestStatusCurrent_Disabled,
232 0); /* Flags; not used. */
233 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
234 }
235}
236
237/**
238 * Update the guest additions capabilities.
239 * This is called when the guest additions capabilities change. The new capabilities
240 * are given and the connector should update its internal state.
241 *
242 * @param pInterface Pointer to this interface.
243 * @param newCapabilities New capabilities.
244 * @thread The emulation thread.
245 */
246DECLCALLBACK(void) vmmdevUpdateGuestCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
247{
248 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
249
250 /* store that information in IGuest */
251 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
252 Assert(guest);
253 if (!guest)
254 return;
255
256 /*
257 * Report our current capabilites (and assume none is active yet).
258 */
259 guest->setSupportedFeatures((ULONG64)newCapabilities, 0 /* Active capabilities, not used here. */);
260
261 /*
262 * Tell the console interface about the event
263 * so that it can notify its consumers.
264 */
265 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
266
267}
268
269/**
270 * Update the mouse capabilities.
271 * This is called when the mouse capabilities change. The new capabilities
272 * are given and the connector should update its internal state.
273 *
274 * @param pInterface Pointer to this interface.
275 * @param newCapabilities New capabilities.
276 * @thread The emulation thread.
277 */
278DECLCALLBACK(void) vmmdevUpdateMouseCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
279{
280 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
281 /*
282 * Tell the console interface about the event
283 * so that it can notify its consumers.
284 */
285 Mouse *pMouse = pDrv->pVMMDev->getParent()->getMouse();
286 if (pMouse) /** @todo and if not? Can that actually happen? */
287 {
288 pMouse->onVMMDevCanAbsChange(!!(newCapabilities & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE));
289 pMouse->onVMMDevNeedsHostChange(!!(newCapabilities & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR));
290 }
291}
292
293
294/**
295 * Update the pointer shape or visibility.
296 *
297 * This is called when the mouse pointer shape changes or pointer is hidden/displaying.
298 * The new shape is passed as a caller allocated buffer that will be freed after returning.
299 *
300 * @param pInterface Pointer to this interface.
301 * @param fVisible Whether the pointer is visible or not.
302 * @param fAlpha Alpha channel information is present.
303 * @param xHot Horizontal coordinate of the pointer hot spot.
304 * @param yHot Vertical coordinate of the pointer hot spot.
305 * @param width Pointer width in pixels.
306 * @param height Pointer height in pixels.
307 * @param pShape The shape buffer. If NULL, then only pointer visibility is being changed.
308 * @thread The emulation thread.
309 */
310DECLCALLBACK(void) vmmdevUpdatePointerShape(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
311 uint32_t xHot, uint32_t yHot,
312 uint32_t width, uint32_t height,
313 void *pShape)
314{
315 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
316
317 /* tell the console about it */
318 size_t cbShapeSize = 0;
319
320 if (pShape)
321 {
322 cbShapeSize = (width + 7) / 8 * height; /* size of the AND mask */
323 cbShapeSize = ((cbShapeSize + 3) & ~3) + width * 4 * height; /* + gap + size of the XOR mask */
324 }
325 com::SafeArray<BYTE> shapeData(cbShapeSize);
326 if (pShape)
327 ::memcpy(shapeData.raw(), pShape, cbShapeSize);
328 pDrv->pVMMDev->getParent()->onMousePointerShapeChange(fVisible, fAlpha,
329 xHot, yHot, width, height, ComSafeArrayAsInParam(shapeData));
330}
331
332DECLCALLBACK(int) iface_VideoAccelEnable(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, VBVAMEMORY *pVbvaMemory)
333{
334 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
335
336 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
337
338 if (display)
339 {
340 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelEnable: %d, %p\n", fEnable, pVbvaMemory));
341 return display->VideoAccelEnable (fEnable, pVbvaMemory);
342 }
343
344 return VERR_NOT_SUPPORTED;
345}
346DECLCALLBACK(void) iface_VideoAccelFlush(PPDMIVMMDEVCONNECTOR pInterface)
347{
348 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
349
350 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
351
352 if (display)
353 {
354 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelFlush\n"));
355 display->VideoAccelFlush ();
356 }
357}
358
359DECLCALLBACK(int) vmmdevVideoModeSupported(PPDMIVMMDEVCONNECTOR pInterface, uint32_t display, uint32_t width, uint32_t height,
360 uint32_t bpp, bool *fSupported)
361{
362 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
363
364 if (!fSupported)
365 return VERR_INVALID_PARAMETER;
366#ifdef DEBUG_sunlover
367 Log(("vmmdevVideoModeSupported: [%d]: %dx%dx%d\n", display, width, height, bpp));
368#endif
369 IFramebuffer *framebuffer = NULL;
370 LONG xOrigin = 0;
371 LONG yOrigin = 0;
372 HRESULT hrc = pDrv->pVMMDev->getParent()->getDisplay()->GetFramebuffer(display, &framebuffer, &xOrigin, &yOrigin);
373 if (SUCCEEDED(hrc) && framebuffer)
374 {
375 framebuffer->VideoModeSupported(width, height, bpp, (BOOL*)fSupported);
376 framebuffer->Release();
377 }
378 else
379 {
380#ifdef DEBUG_sunlover
381 Log(("vmmdevVideoModeSupported: hrc %x, framebuffer %p!!!\n", hrc, framebuffer));
382#endif
383 *fSupported = true;
384 }
385 return VINF_SUCCESS;
386}
387
388DECLCALLBACK(int) vmmdevGetHeightReduction(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *heightReduction)
389{
390 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
391
392 if (!heightReduction)
393 return VERR_INVALID_PARAMETER;
394 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
395 if (framebuffer)
396 framebuffer->COMGETTER(HeightReduction)((ULONG*)heightReduction);
397 else
398 *heightReduction = 0;
399 return VINF_SUCCESS;
400}
401
402DECLCALLBACK(int) vmmdevSetCredentialsJudgementResult(PPDMIVMMDEVCONNECTOR pInterface, uint32_t u32Flags)
403{
404 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
405
406 int rc = pDrv->pVMMDev->SetCredentialsJudgementResult (u32Flags);
407
408 return rc;
409}
410
411DECLCALLBACK(int) vmmdevSetVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect)
412{
413 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
414
415 if (!cRect)
416 return VERR_INVALID_PARAMETER;
417#ifdef MMSEAMLESS
418 /* Forward to Display, which calls corresponding framebuffers. */
419 pDrv->pVMMDev->getParent()->getDisplay()->handleSetVisibleRegion(cRect, pRect);
420#else
421 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
422 if (framebuffer)
423 {
424 framebuffer->SetVisibleRegion((BYTE *)pRect, cRect);
425#if defined(RT_OS_DARWIN) && defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
426 {
427 BOOL is3denabled;
428
429 pDrv->pVMMDev->getParent()->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
430
431 if (is3denabled)
432 {
433 VBOXHGCMSVCPARM parms[2];
434
435 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
436 parms[0].u.pointer.addr = pRect;
437 parms[0].u.pointer.size = 0; /* We don't actually care. */
438 parms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
439 parms[1].u.uint32 = cRect;
440
441 int rc = pDrv->pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VISIBLE_REGION, 2, &parms[0]);
442 return rc;
443 }
444 }
445#endif
446 }
447#endif
448
449 return VINF_SUCCESS;
450}
451
452DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRect, PRTRECT pRect)
453{
454 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
455
456#ifdef MMSEAMLESS
457 /* Forward to Display, which calls corresponding framebuffers. */
458 pDrv->pVMMDev->getParent()->getDisplay()->handleQueryVisibleRegion(pcRect, pRect);
459#else
460 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
461 if (framebuffer)
462 {
463 ULONG cRect = 0;
464 framebuffer->GetVisibleRegion((BYTE *)pRect, cRect, &cRect);
465
466 *pcRect = cRect;
467 }
468#endif
469
470 return VINF_SUCCESS;
471}
472
473/**
474 * Request the statistics interval
475 *
476 * @returns VBox status code.
477 * @param pInterface Pointer to this interface.
478 * @param pulInterval Pointer to interval in seconds
479 * @thread The emulation thread.
480 */
481DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
482{
483 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
484 ULONG val = 0;
485
486 if (!pulInterval)
487 return VERR_INVALID_POINTER;
488
489 /* store that information in IGuest */
490 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
491 Assert(guest);
492 if (!guest)
493 return VERR_INVALID_PARAMETER; /** @todo wrong error */
494
495 guest->COMGETTER(StatisticsUpdateInterval)(&val);
496 *pulInterval = val;
497 return VINF_SUCCESS;
498}
499
500/**
501 * Query the current balloon size
502 *
503 * @returns VBox status code.
504 * @param pInterface Pointer to this interface.
505 * @param pcbBalloon Balloon size
506 * @thread The emulation thread.
507 */
508DECLCALLBACK(int) vmmdevQueryBalloonSize(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon)
509{
510 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
511 ULONG val = 0;
512
513 if (!pcbBalloon)
514 return VERR_INVALID_POINTER;
515
516 /* store that information in IGuest */
517 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
518 Assert(guest);
519 if (!guest)
520 return VERR_INVALID_PARAMETER; /** @todo wrong error */
521
522 guest->COMGETTER(MemoryBalloonSize)(&val);
523 *pcbBalloon = val;
524 return VINF_SUCCESS;
525}
526
527/**
528 * Query the current page fusion setting
529 *
530 * @returns VBox status code.
531 * @param pInterface Pointer to this interface.
532 * @param pfPageFusionEnabled Pointer to boolean
533 * @thread The emulation thread.
534 */
535DECLCALLBACK(int) vmmdevIsPageFusionEnabled(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled)
536{
537 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
538 BOOL val = 0;
539
540 if (!pfPageFusionEnabled)
541 return VERR_INVALID_POINTER;
542
543 /* store that information in IGuest */
544 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
545 Assert(guest);
546 if (!guest)
547 return VERR_INVALID_PARAMETER; /** @todo wrong error */
548
549 guest->COMGETTER(PageFusionEnabled)(&val);
550 *pfPageFusionEnabled = !!val;
551 return VINF_SUCCESS;
552}
553
554/**
555 * Report new guest statistics
556 *
557 * @returns VBox status code.
558 * @param pInterface Pointer to this interface.
559 * @param pGuestStats Guest statistics
560 * @thread The emulation thread.
561 */
562DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
563{
564 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
565
566 Assert(pGuestStats);
567 if (!pGuestStats)
568 return VERR_INVALID_POINTER;
569
570 /* store that information in IGuest */
571 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
572 Assert(guest);
573 if (!guest)
574 return VERR_INVALID_PARAMETER; /** @todo wrong error */
575
576 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
577 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUIDLE, pGuestStats->u32CpuLoad_Idle);
578
579 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
580 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUKERNEL, pGuestStats->u32CpuLoad_Kernel);
581
582 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
583 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUUSER, pGuestStats->u32CpuLoad_User);
584
585
586 /** @todo r=bird: Convert from 4KB to 1KB units?
587 * CollectorGuestHAL::getGuestMemLoad says it returns KB units to
588 * preCollect(). I might be wrong ofc, this is convoluted code... */
589 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
590 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMTOTAL, pGuestStats->u32PhysMemTotal);
591
592 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
593 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMFREE, pGuestStats->u32PhysMemAvail);
594
595 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
596 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMBALLOON, pGuestStats->u32PhysMemBalloon);
597
598 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
599 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMCACHE, pGuestStats->u32MemSystemCache);
600
601 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
602 guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_PAGETOTAL, pGuestStats->u32PageFileSize);
603
604 return VINF_SUCCESS;
605}
606
607#ifdef VBOX_WITH_HGCM
608
609/* HGCM connector interface */
610
611static DECLCALLBACK(int) iface_hgcmConnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID)
612{
613 LogSunlover(("Enter\n"));
614
615 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
616
617 if ( !pServiceLocation
618 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost
619 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
620 {
621 return VERR_INVALID_PARAMETER;
622 }
623
624 if (!pDrv->pVMMDev->hgcmIsActive ())
625 {
626 return VERR_INVALID_STATE;
627 }
628
629 return HGCMGuestConnect (pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
630}
631
632static DECLCALLBACK(int) iface_hgcmDisconnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
633{
634 LogSunlover(("Enter\n"));
635
636 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
637
638 if (!pDrv->pVMMDev->hgcmIsActive ())
639 {
640 return VERR_INVALID_STATE;
641 }
642
643 return HGCMGuestDisconnect (pDrv->pHGCMPort, pCmd, u32ClientID);
644}
645
646static DECLCALLBACK(int) iface_hgcmCall (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
647 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
648{
649 LogSunlover(("Enter\n"));
650
651 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
652
653 if (!pDrv->pVMMDev->hgcmIsActive ())
654 {
655 return VERR_INVALID_STATE;
656 }
657
658 return HGCMGuestCall (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms);
659}
660
661/**
662 * Execute state save operation.
663 *
664 * @returns VBox status code.
665 * @param pDrvIns Driver instance of the driver which registered the data unit.
666 * @param pSSM SSM operation handle.
667 */
668static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
669{
670 LogSunlover(("Enter\n"));
671 return HGCMHostSaveState (pSSM);
672}
673
674
675/**
676 * Execute state load operation.
677 *
678 * @returns VBox status code.
679 * @param pDrvIns Driver instance of the driver which registered the data unit.
680 * @param pSSM SSM operation handle.
681 * @param uVersion Data layout version.
682 * @param uPass The data pass.
683 */
684static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
685{
686 LogFlowFunc(("Enter\n"));
687
688 if (uVersion != HGCM_SSM_VERSION)
689 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
690 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
691
692 return HGCMHostLoadState (pSSM);
693}
694
695int VMMDev::hgcmLoadService (const char *pszServiceLibrary, const char *pszServiceName)
696{
697 if (!hgcmIsActive ())
698 {
699 return VERR_INVALID_STATE;
700 }
701 return HGCMHostLoad (pszServiceLibrary, pszServiceName);
702}
703
704int VMMDev::hgcmHostCall (const char *pszServiceName, uint32_t u32Function,
705 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
706{
707 if (!hgcmIsActive ())
708 {
709 return VERR_INVALID_STATE;
710 }
711 return HGCMHostCall (pszServiceName, u32Function, cParms, paParms);
712}
713
714void VMMDev::hgcmShutdown (void)
715{
716 ASMAtomicWriteBool(&m_fHGCMActive, false);
717 HGCMHostShutdown ();
718}
719
720#endif /* HGCM */
721
722
723/**
724 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
725 */
726DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
727{
728 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
729 PDRVMAINVMMDEV pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
730
731 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
732 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVMMDEVCONNECTOR, &pDrv->Connector);
733#ifdef VBOX_WITH_HGCM
734 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHGCMCONNECTOR, &pDrv->HGCMConnector);
735#endif
736 return NULL;
737}
738
739/**
740 * Destruct a VMMDev driver instance.
741 *
742 * @returns VBox status.
743 * @param pDrvIns The driver instance data.
744 */
745DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
746{
747 PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
748 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
749#ifdef VBOX_WITH_HGCM
750 /* HGCM is shut down on the VMMDev destructor. */
751#endif /* VBOX_WITH_HGCM */
752 if (pData->pVMMDev)
753 {
754 pData->pVMMDev->mpDrv = NULL;
755 }
756}
757
758/**
759 * Reset notification.
760 *
761 * @returns VBox status.
762 * @param pDrvIns The driver instance data.
763 */
764DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
765{
766 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
767#ifdef VBOX_WITH_HGCM
768 HGCMHostReset ();
769#endif /* VBOX_WITH_HGCM */
770}
771
772/**
773 * Construct a VMMDev driver instance.
774 *
775 * @copydoc FNPDMDRVCONSTRUCT
776 */
777DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
778{
779 PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
780 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
781
782 /*
783 * Validate configuration.
784 */
785 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
786 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
787 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
788 ("Configuration error: Not possible to attach anything to this driver!\n"),
789 VERR_PDM_DRVINS_NO_ATTACH);
790
791 /*
792 * IBase.
793 */
794 pDrvIns->IBase.pfnQueryInterface = VMMDev::drvQueryInterface;
795
796 pData->Connector.pfnUpdateGuestStatus = vmmdevUpdateGuestStatus;
797 pData->Connector.pfnUpdateGuestInfo = vmmdevUpdateGuestInfo;
798 pData->Connector.pfnUpdateGuestCapabilities = vmmdevUpdateGuestCapabilities;
799 pData->Connector.pfnUpdateMouseCapabilities = vmmdevUpdateMouseCapabilities;
800 pData->Connector.pfnUpdatePointerShape = vmmdevUpdatePointerShape;
801 pData->Connector.pfnVideoAccelEnable = iface_VideoAccelEnable;
802 pData->Connector.pfnVideoAccelFlush = iface_VideoAccelFlush;
803 pData->Connector.pfnVideoModeSupported = vmmdevVideoModeSupported;
804 pData->Connector.pfnGetHeightReduction = vmmdevGetHeightReduction;
805 pData->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
806 pData->Connector.pfnSetVisibleRegion = vmmdevSetVisibleRegion;
807 pData->Connector.pfnQueryVisibleRegion = vmmdevQueryVisibleRegion;
808 pData->Connector.pfnReportStatistics = vmmdevReportStatistics;
809 pData->Connector.pfnQueryStatisticsInterval = vmmdevQueryStatisticsInterval;
810 pData->Connector.pfnQueryBalloonSize = vmmdevQueryBalloonSize;
811 pData->Connector.pfnIsPageFusionEnabled = vmmdevIsPageFusionEnabled;
812
813#ifdef VBOX_WITH_HGCM
814 pData->HGCMConnector.pfnConnect = iface_hgcmConnect;
815 pData->HGCMConnector.pfnDisconnect = iface_hgcmDisconnect;
816 pData->HGCMConnector.pfnCall = iface_hgcmCall;
817#endif
818
819 /*
820 * Get the IVMMDevPort interface of the above driver/device.
821 */
822 pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
823 AssertMsgReturn(pData->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
824
825#ifdef VBOX_WITH_HGCM
826 pData->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
827 AssertMsgReturn(pData->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
828#endif
829
830 /*
831 * Get the Console object pointer and update the mpDrv member.
832 */
833 void *pv;
834 int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
835 if (RT_FAILURE(rc))
836 {
837 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
838 return rc;
839 }
840
841 pData->pVMMDev = (VMMDev*)pv; /** @todo Check this cast! */
842 pData->pVMMDev->mpDrv = pData;
843
844#ifdef VBOX_WITH_HGCM
845 rc = pData->pVMMDev->hgcmLoadService (VBOXSHAREDFOLDERS_DLL,
846 "VBoxSharedFolders");
847 pData->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
848 if (RT_SUCCESS(rc))
849 {
850 PPDMLED pLed;
851 PPDMILEDPORTS pLedPort;
852
853 LogRel(("Shared Folders service loaded.\n"));
854 pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
855 AssertMsgReturn(pLedPort, ("Configuration error: No LED port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
856 rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
857 if (RT_SUCCESS(rc) && pLed)
858 {
859 VBOXHGCMSVCPARM parm;
860
861 parm.type = VBOX_HGCM_SVC_PARM_PTR;
862 parm.u.pointer.addr = pLed;
863 parm.u.pointer.size = sizeof(*pLed);
864
865 rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
866 }
867 else
868 AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
869 }
870 else
871 LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
872
873 rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SSM_VERSION, 4096 /* bad guess */,
874 NULL, NULL, NULL,
875 NULL, iface_hgcmSave, NULL,
876 NULL, iface_hgcmLoad, NULL);
877 if (RT_FAILURE(rc))
878 return rc;
879
880#endif /* VBOX_WITH_HGCM */
881
882 return VINF_SUCCESS;
883}
884
885
886/**
887 * VMMDevice driver registration record.
888 */
889const PDMDRVREG VMMDev::DrvReg =
890{
891 /* u32Version */
892 PDM_DRVREG_VERSION,
893 /* szName */
894 "HGCM",
895 /* szRCMod */
896 "",
897 /* szR0Mod */
898 "",
899 /* pszDescription */
900 "Main VMMDev driver (Main as in the API).",
901 /* fFlags */
902 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
903 /* fClass. */
904 PDM_DRVREG_CLASS_VMMDEV,
905 /* cMaxInstances */
906 ~0,
907 /* cbInstance */
908 sizeof(DRVMAINVMMDEV),
909 /* pfnConstruct */
910 VMMDev::drvConstruct,
911 /* pfnDestruct */
912 VMMDev::drvDestruct,
913 /* pfnRelocate */
914 NULL,
915 /* pfnIOCtl */
916 NULL,
917 /* pfnPowerOn */
918 NULL,
919 /* pfnReset */
920 VMMDev::drvReset,
921 /* pfnSuspend */
922 NULL,
923 /* pfnResume */
924 NULL,
925 /* pfnAttach */
926 NULL,
927 /* pfnDetach */
928 NULL,
929 /* pfnPowerOff */
930 NULL,
931 /* pfnSoftReset */
932 NULL,
933 /* u32EndVersion */
934 PDM_DRVREG_VERSION
935};
936/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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