VirtualBox

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

Last change on this file since 15741 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.2 KB
Line 
1/** @file
2 *
3 * VirtualBox Driver Interface to VMM device
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "VMMDev.h"
23#include "ConsoleImpl.h"
24#include "DisplayImpl.h"
25#include "GuestImpl.h"
26
27#include "Logging.h"
28
29#include <VBox/pdmdrv.h>
30#include <VBox/VBoxDev.h>
31#include <VBox/VBoxGuest.h>
32#include <VBox/shflsvc.h>
33#include <iprt/asm.h>
34
35#ifdef VBOX_WITH_HGCM
36#include "hgcm/HGCM.h"
37#include "hgcm/HGCMObjects.h"
38#endif
39
40//
41// defines
42//
43
44#ifdef RT_OS_OS2
45# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
46#else
47# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
48#endif
49
50//
51// globals
52//
53
54
55/**
56 * VMMDev driver instance data.
57 */
58typedef struct DRVMAINVMMDEV
59{
60 /** Pointer to the VMMDev object. */
61 VMMDev *pVMMDev;
62 /** Pointer to the driver instance structure. */
63 PPDMDRVINS pDrvIns;
64 /** Pointer to the VMMDev port interface of the driver/device above us. */
65 PPDMIVMMDEVPORT pUpPort;
66 /** Our VMM device connector interface. */
67 PDMIVMMDEVCONNECTOR Connector;
68
69#ifdef VBOX_WITH_HGCM
70 /** Pointer to the HGCM port interface of the driver/device above us. */
71 PPDMIHGCMPORT pHGCMPort;
72 /** Our HGCM connector interface. */
73 PDMIHGCMCONNECTOR HGCMConnector;
74#endif
75} DRVMAINVMMDEV, *PDRVMAINVMMDEV;
76
77/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
78#define PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, Connector)) )
79
80#ifdef VBOX_WITH_HGCM
81/** Converts PDMIHGCMCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
82#define PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, HGCMConnector)) )
83#endif
84
85//
86// constructor / destructor
87//
88VMMDev::VMMDev(Console *console) : mpDrv(NULL)
89{
90 mParent = console;
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 RTSemEventDestroy (mCredentialsEvent);
104 if (mpDrv)
105 mpDrv->pVMMDev = NULL;
106 mpDrv = NULL;
107}
108
109PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
110{
111 Assert(mpDrv);
112 return mpDrv->pUpPort;
113}
114
115
116
117//
118// public methods
119//
120
121/**
122 * Wait on event semaphore for guest credential judgement result.
123 */
124int VMMDev::WaitCredentialsJudgement (uint32_t u32Timeout, uint32_t *pu32CredentialsFlags)
125{
126 if (u32Timeout == 0)
127 {
128 u32Timeout = 5000;
129 }
130
131 int rc = RTSemEventWait (mCredentialsEvent, u32Timeout);
132
133 if (RT_SUCCESS (rc))
134 {
135 *pu32CredentialsFlags = mu32CredentialsFlags;
136 }
137
138 return rc;
139}
140
141int VMMDev::SetCredentialsJudgementResult (uint32_t u32Flags)
142{
143 mu32CredentialsFlags = u32Flags;
144
145 int rc = RTSemEventSignal (mCredentialsEvent);
146 AssertRC(rc);
147
148 return rc;
149}
150
151
152/**
153 * Report guest OS version.
154 * Called whenever the Additions issue a guest version report request or the VM is reset.
155 *
156 * @param pInterface Pointer to this interface.
157 * @param guestInfo Pointer to guest information structure
158 * @thread The emulation thread.
159 */
160DECLCALLBACK(void) vmmdevUpdateGuestVersion(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestInfo *guestInfo)
161{
162 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
163
164 Assert(guestInfo);
165 if (!guestInfo)
166 return;
167
168 /* store that information in IGuest */
169 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
170 Assert(guest);
171 if (!guest)
172 return;
173
174 if (guestInfo->additionsVersion != 0)
175 {
176 char version[20];
177 RTStrPrintf(version, sizeof(version), "%d", guestInfo->additionsVersion);
178 guest->setAdditionsVersion(Bstr(version), guestInfo->osType);
179
180 /*
181 * Tell the console interface about the event
182 * so that it can notify its consumers.
183 */
184 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
185
186 if (guestInfo->additionsVersion < VMMDEV_VERSION)
187 pDrv->pVMMDev->getParent()->onAdditionsOutdated();
188 }
189 else
190 {
191 /*
192 * The guest additions was disabled because of a reset
193 * or driver unload.
194 */
195 guest->setAdditionsVersion (Bstr(), guestInfo->osType);
196 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
197 }
198}
199
200/**
201 * Update the guest additions capabilities.
202 * This is called when the guest additions capabilities change. The new capabilities
203 * are given and the connector should update its internal state.
204 *
205 * @param pInterface Pointer to this interface.
206 * @param newCapabilities New capabilities.
207 * @thread The emulation thread.
208 */
209DECLCALLBACK(void) vmmdevUpdateGuestCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
210{
211 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
212
213 /* store that information in IGuest */
214 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
215 Assert(guest);
216 if (!guest)
217 return;
218
219 guest->setSupportsSeamless(BOOL (newCapabilities & VMMDEV_GUEST_SUPPORTS_SEAMLESS));
220 guest->setSupportsGraphics(BOOL (newCapabilities & VMMDEV_GUEST_SUPPORTS_GRAPHICS));
221
222 /*
223 * Tell the console interface about the event
224 * so that it can notify its consumers.
225 */
226 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
227
228}
229
230/**
231 * Update the mouse capabilities.
232 * This is called when the mouse capabilities change. The new capabilities
233 * are given and the connector should update its internal state.
234 *
235 * @param pInterface Pointer to this interface.
236 * @param newCapabilities New capabilities.
237 * @thread The emulation thread.
238 */
239DECLCALLBACK(void) vmmdevUpdateMouseCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
240{
241 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
242 /*
243 * Tell the console interface about the event
244 * so that it can notify its consumers.
245 */
246 pDrv->pVMMDev->getParent()->onMouseCapabilityChange(BOOL (newCapabilities & VMMDEV_MOUSEGUESTWANTSABS),
247 BOOL (newCapabilities & VMMDEV_MOUSEGUESTNEEDSHOSTCUR));
248}
249
250
251/**
252 * Update the pointer shape or visibility.
253 *
254 * This is called when the mouse pointer shape changes or pointer is hidden/displaying.
255 * The new shape is passed as a caller allocated buffer that will be freed after returning.
256 *
257 * @param pInterface Pointer to this interface.
258 * @param fVisible Whether the pointer is visible or not.
259 * @param fAlpha Alpha channel information is present.
260 * @param xHot Horizontal coordinate of the pointer hot spot.
261 * @param yHot Vertical coordinate of the pointer hot spot.
262 * @param width Pointer width in pixels.
263 * @param height Pointer height in pixels.
264 * @param pShape The shape buffer. If NULL, then only pointer visibility is being changed.
265 * @thread The emulation thread.
266 */
267DECLCALLBACK(void) vmmdevUpdatePointerShape(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
268 uint32_t xHot, uint32_t yHot,
269 uint32_t width, uint32_t height,
270 void *pShape)
271{
272 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
273
274 /* tell the console about it */
275 pDrv->pVMMDev->getParent()->onMousePointerShapeChange(fVisible, fAlpha,
276 xHot, yHot, width, height, pShape);
277}
278
279DECLCALLBACK(int) iface_VideoAccelEnable(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, VBVAMEMORY *pVbvaMemory)
280{
281 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
282
283 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
284
285 if (display)
286 {
287 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelEnable: %d, %p\n", fEnable, pVbvaMemory));
288 return display->VideoAccelEnable (fEnable, pVbvaMemory);
289 }
290
291 return VERR_NOT_SUPPORTED;
292}
293DECLCALLBACK(void) iface_VideoAccelFlush(PPDMIVMMDEVCONNECTOR pInterface)
294{
295 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
296
297 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
298
299 if (display)
300 {
301 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelFlush\n"));
302 display->VideoAccelFlush ();
303 }
304}
305
306DECLCALLBACK(int) vmmdevVideoModeSupported(PPDMIVMMDEVCONNECTOR pInterface, uint32_t width, uint32_t height,
307 uint32_t bpp, bool *fSupported)
308{
309 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
310
311 if (!fSupported)
312 return VERR_INVALID_PARAMETER;
313 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
314 if (framebuffer)
315 framebuffer->VideoModeSupported(width, height, bpp, (BOOL*)fSupported);
316 else
317 *fSupported = true;
318 return VINF_SUCCESS;
319}
320
321DECLCALLBACK(int) vmmdevGetHeightReduction(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *heightReduction)
322{
323 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
324
325 if (!heightReduction)
326 return VERR_INVALID_PARAMETER;
327 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
328 if (framebuffer)
329 framebuffer->COMGETTER(HeightReduction)((ULONG*)heightReduction);
330 else
331 *heightReduction = 0;
332 return VINF_SUCCESS;
333}
334
335DECLCALLBACK(int) vmmdevSetCredentialsJudgementResult(PPDMIVMMDEVCONNECTOR pInterface, uint32_t u32Flags)
336{
337 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
338
339 int rc = pDrv->pVMMDev->SetCredentialsJudgementResult (u32Flags);
340
341 return rc;
342}
343
344DECLCALLBACK(int) vmmdevSetVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect)
345{
346 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
347
348 if (!cRect)
349 return VERR_INVALID_PARAMETER;
350 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
351 if (framebuffer)
352 framebuffer->SetVisibleRegion((BYTE *)pRect, cRect);
353
354 return VINF_SUCCESS;
355}
356
357DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRect, PRTRECT pRect)
358{
359 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
360
361 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
362 if (framebuffer)
363 {
364 ULONG cRect = 0;
365 framebuffer->GetVisibleRegion((BYTE *)pRect, cRect, &cRect);
366
367 *pcRect = cRect;
368 }
369
370 return VINF_SUCCESS;
371}
372
373/**
374 * Request the statistics interval
375 *
376 * @returns VBox status code.
377 * @param pInterface Pointer to this interface.
378 * @param pulInterval Pointer to interval in seconds
379 * @thread The emulation thread.
380 */
381DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
382{
383 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
384 ULONG val = 0;
385
386 if (!pulInterval)
387 return VERR_INVALID_POINTER;
388
389 /* store that information in IGuest */
390 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
391 Assert(guest);
392 if (!guest)
393 return VERR_INVALID_PARAMETER; /** @todo wrong error */
394
395 guest->COMGETTER(StatisticsUpdateInterval)(&val);
396 *pulInterval = val;
397 return VINF_SUCCESS;
398}
399
400/**
401 * Report new guest statistics
402 *
403 * @returns VBox status code.
404 * @param pInterface Pointer to this interface.
405 * @param pGuestStats Guest statistics
406 * @thread The emulation thread.
407 */
408DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
409{
410 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
411
412 Assert(pGuestStats);
413 if (!pGuestStats)
414 return VERR_INVALID_POINTER;
415
416 /* store that information in IGuest */
417 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
418 Assert(guest);
419 if (!guest)
420 return VERR_INVALID_PARAMETER; /** @todo wrong error */
421
422 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
423 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_Idle, pGuestStats->u32CpuLoad_Idle);
424
425 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
426 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_Kernel, pGuestStats->u32CpuLoad_Kernel);
427
428 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
429 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_User, pGuestStats->u32CpuLoad_User);
430
431 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_THREADS)
432 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Threads, pGuestStats->u32Threads);
433
434 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PROCESSES)
435 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Processes, pGuestStats->u32Processes);
436
437 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_HANDLES)
438 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Handles, pGuestStats->u32Handles);
439
440 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEMORY_LOAD)
441 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemoryLoad, pGuestStats->u32MemoryLoad);
442
443 /* Note that reported values are in pages; upper layers expect them in megabytes */
444 Assert(pGuestStats->u32PageSize == 4096);
445 if (pGuestStats->u32PageSize != 4096)
446 pGuestStats->u32PageSize = 4096;
447
448 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
449 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemTotal, (pGuestStats->u32PhysMemTotal + (_1M/pGuestStats->u32PageSize)-1) / (_1M/pGuestStats->u32PageSize));
450
451 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
452 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemAvailable, pGuestStats->u32PhysMemAvail / (_1M/pGuestStats->u32PageSize));
453
454 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
455 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemBalloon, pGuestStats->u32PhysMemBalloon / (_1M/pGuestStats->u32PageSize));
456
457 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_COMMIT_TOTAL)
458 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemCommitTotal, pGuestStats->u32MemCommitTotal / (_1M/pGuestStats->u32PageSize));
459
460 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_TOTAL)
461 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelTotal, pGuestStats->u32MemKernelTotal / (_1M/pGuestStats->u32PageSize));
462
463 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_PAGED)
464 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelPaged, pGuestStats->u32MemKernelPaged / (_1M/pGuestStats->u32PageSize));
465
466 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED)
467 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelNonpaged, pGuestStats->u32MemKernelNonPaged / (_1M/pGuestStats->u32PageSize));
468
469 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
470 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemSystemCache, pGuestStats->u32MemSystemCache / (_1M/pGuestStats->u32PageSize));
471
472 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
473 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PageFileSize, pGuestStats->u32PageFileSize / (_1M/pGuestStats->u32PageSize));
474
475 /* increase sample number */
476 ULONG sample;
477
478 int rc = guest->GetStatistic(0, GuestStatisticType_SampleNumber, &sample);
479 if (SUCCEEDED(rc))
480 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_SampleNumber, sample+1);
481
482 return VINF_SUCCESS;
483}
484
485/**
486 * Inflate or deflate the memory balloon
487 *
488 * @returns VBox status code.
489 * @param pInterface Pointer to this interface.
490 * @param fInflate Inflate or deflate
491 * @param cPages Number of physical pages (must be 256 as we allocate in 1 MB chunks)
492 * @param aPhysPage Array of physical page addresses
493 * @thread The emulation thread.
494 */
495DECLCALLBACK(int) vmmdevChangeMemoryBalloon(PPDMIVMMDEVCONNECTOR pInterface, bool fInflate, uint32_t cPages, RTGCPHYS *aPhysPage)
496{
497 if ( cPages != VMMDEV_MEMORY_BALLOON_CHUNK_PAGES
498 || !aPhysPage)
499 return VERR_INVALID_PARAMETER;
500
501 Log(("vmmdevChangeMemoryBalloon @todo\n"));
502 return VINF_SUCCESS;
503}
504
505#ifdef VBOX_WITH_HGCM
506
507/* HGCM connector interface */
508
509static DECLCALLBACK(int) iface_hgcmConnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID)
510{
511 LogSunlover(("Enter\n"));
512
513 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
514
515 if ( !pServiceLocation
516 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost
517 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
518 {
519 return VERR_INVALID_PARAMETER;
520 }
521
522 if (!pDrv->pVMMDev->hgcmIsActive ())
523 {
524 return VERR_INVALID_STATE;
525 }
526
527 return HGCMGuestConnect (pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
528}
529
530static DECLCALLBACK(int) iface_hgcmDisconnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
531{
532 LogSunlover(("Enter\n"));
533
534 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
535
536 if (!pDrv->pVMMDev->hgcmIsActive ())
537 {
538 return VERR_INVALID_STATE;
539 }
540
541 return HGCMGuestDisconnect (pDrv->pHGCMPort, pCmd, u32ClientID);
542}
543
544static DECLCALLBACK(int) iface_hgcmCall (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
545 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
546{
547 LogSunlover(("Enter\n"));
548
549 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
550
551 if (!pDrv->pVMMDev->hgcmIsActive ())
552 {
553 return VERR_INVALID_STATE;
554 }
555
556 return HGCMGuestCall (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms);
557}
558
559/**
560 * Execute state save operation.
561 *
562 * @returns VBox status code.
563 * @param pDrvIns Driver instance of the driver which registered the data unit.
564 * @param pSSM SSM operation handle.
565 */
566static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
567{
568 LogSunlover(("Enter\n"));
569 return HGCMHostSaveState (pSSM);
570}
571
572
573/**
574 * Execute state load operation.
575 *
576 * @returns VBox status code.
577 * @param pDrvIns Driver instance of the driver which registered the data unit.
578 * @param pSSM SSM operation handle.
579 * @param u32Version Data layout version.
580 */
581static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t u32Version)
582{
583 LogFlowFunc(("Enter\n"));
584
585 if (u32Version != HGCM_SSM_VERSION)
586 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
587
588 return HGCMHostLoadState (pSSM);
589}
590
591int VMMDev::hgcmLoadService (const char *pszServiceLibrary, const char *pszServiceName)
592{
593 if (!hgcmIsActive ())
594 {
595 return VERR_INVALID_STATE;
596 }
597 return HGCMHostLoad (pszServiceLibrary, pszServiceName);
598}
599
600int VMMDev::hgcmHostCall (const char *pszServiceName, uint32_t u32Function,
601 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
602{
603 if (!hgcmIsActive ())
604 {
605 return VERR_INVALID_STATE;
606 }
607 return HGCMHostCall (pszServiceName, u32Function, cParms, paParms);
608}
609
610void VMMDev::hgcmShutdown (void)
611{
612 ASMAtomicWriteBool(&m_fHGCMActive, false);
613 HGCMHostShutdown ();
614}
615
616#endif /* HGCM */
617
618
619/**
620 * Queries an interface to the driver.
621 *
622 * @returns Pointer to interface.
623 * @returns NULL if the interface was not supported by the driver.
624 * @param pInterface Pointer to this interface structure.
625 * @param enmInterface The requested interface identification.
626 */
627DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
628{
629 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
630 PDRVMAINVMMDEV pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
631 switch (enmInterface)
632 {
633 case PDMINTERFACE_BASE:
634 return &pDrvIns->IBase;
635 case PDMINTERFACE_VMMDEV_CONNECTOR:
636 return &pDrv->Connector;
637#ifdef VBOX_WITH_HGCM
638 case PDMINTERFACE_HGCM_CONNECTOR:
639 return &pDrv->HGCMConnector;
640#endif
641 default:
642 return NULL;
643 }
644}
645
646/**
647 * Destruct a VMMDev driver instance.
648 *
649 * @returns VBox status.
650 * @param pDrvIns The driver instance data.
651 */
652DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
653{
654 PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
655 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
656#ifdef VBOX_WITH_HGCM
657 /* HGCM is shut down on the VMMDev destructor. */
658#endif /* VBOX_WITH_HGCM */
659 if (pData->pVMMDev)
660 {
661 pData->pVMMDev->mpDrv = NULL;
662 }
663}
664
665/**
666 * Reset notification.
667 *
668 * @returns VBox status.
669 * @param pDrvIns The driver instance data.
670 */
671DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
672{
673 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
674#ifdef VBOX_WITH_HGCM
675 HGCMHostReset ();
676#endif /* VBOX_WITH_HGCM */
677}
678
679/**
680 * Construct a VMMDev driver instance.
681 *
682 * @returns VBox status.
683 * @param pDrvIns The driver instance data.
684 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
685 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
686 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
687 * iInstance it's expected to be used a bit in this function.
688 */
689DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
690{
691 PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
692 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
693
694 /*
695 * Validate configuration.
696 */
697 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0OpenGLEnabled\0crOpenGLEnabled\0"))
698 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
699 PPDMIBASE pBaseIgnore;
700 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
701 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
702 {
703 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
704 return VERR_PDM_DRVINS_NO_ATTACH;
705 }
706
707 /*
708 * IBase.
709 */
710 pDrvIns->IBase.pfnQueryInterface = VMMDev::drvQueryInterface;
711
712 pData->Connector.pfnUpdateGuestVersion = vmmdevUpdateGuestVersion;
713 pData->Connector.pfnUpdateGuestCapabilities = vmmdevUpdateGuestCapabilities;
714 pData->Connector.pfnUpdateMouseCapabilities = vmmdevUpdateMouseCapabilities;
715 pData->Connector.pfnUpdatePointerShape = vmmdevUpdatePointerShape;
716 pData->Connector.pfnVideoAccelEnable = iface_VideoAccelEnable;
717 pData->Connector.pfnVideoAccelFlush = iface_VideoAccelFlush;
718 pData->Connector.pfnVideoModeSupported = vmmdevVideoModeSupported;
719 pData->Connector.pfnGetHeightReduction = vmmdevGetHeightReduction;
720 pData->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
721 pData->Connector.pfnSetVisibleRegion = vmmdevSetVisibleRegion;
722 pData->Connector.pfnQueryVisibleRegion = vmmdevQueryVisibleRegion;
723 pData->Connector.pfnReportStatistics = vmmdevReportStatistics;
724 pData->Connector.pfnQueryStatisticsInterval = vmmdevQueryStatisticsInterval;
725 pData->Connector.pfnChangeMemoryBalloon = vmmdevChangeMemoryBalloon;
726
727#ifdef VBOX_WITH_HGCM
728 pData->HGCMConnector.pfnConnect = iface_hgcmConnect;
729 pData->HGCMConnector.pfnDisconnect = iface_hgcmDisconnect;
730 pData->HGCMConnector.pfnCall = iface_hgcmCall;
731#endif
732
733 /*
734 * Get the IVMMDevPort interface of the above driver/device.
735 */
736 pData->pUpPort = (PPDMIVMMDEVPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_VMMDEV_PORT);
737 if (!pData->pUpPort)
738 {
739 AssertMsgFailed(("Configuration error: No VMMDev port interface above!\n"));
740 return VERR_PDM_MISSING_INTERFACE_ABOVE;
741 }
742
743#ifdef VBOX_WITH_HGCM
744 pData->pHGCMPort = (PPDMIHGCMPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_HGCM_PORT);
745 if (!pData->pHGCMPort)
746 {
747 AssertMsgFailed(("Configuration error: No HGCM port interface above!\n"));
748 return VERR_PDM_MISSING_INTERFACE_ABOVE;
749 }
750#endif
751
752 /*
753 * Get the Console object pointer and update the mpDrv member.
754 */
755 void *pv;
756 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
757 if (RT_FAILURE(rc))
758 {
759 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
760 return rc;
761 }
762
763 pData->pVMMDev = (VMMDev*)pv; /** @todo Check this cast! */
764 pData->pVMMDev->mpDrv = pData;
765
766#ifdef VBOX_WITH_HGCM
767 rc = pData->pVMMDev->hgcmLoadService (VBOXSHAREDFOLDERS_DLL,
768 "VBoxSharedFolders");
769 pData->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
770 if (RT_SUCCESS(rc))
771 {
772 PPDMLED pLed;
773 PPDMILEDPORTS pLedPort;
774
775 LogRel(("Shared Folders service loaded.\n"));
776 pLedPort = (PPDMILEDPORTS)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_LED_PORTS);
777 if (!pLedPort)
778 {
779 AssertMsgFailed(("Configuration error: No LED port interface above!\n"));
780 return VERR_PDM_MISSING_INTERFACE_ABOVE;
781 }
782 rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
783 if (RT_SUCCESS(rc) && pLed)
784 {
785 VBOXHGCMSVCPARM parm;
786
787 parm.type = VBOX_HGCM_SVC_PARM_PTR;
788 parm.u.pointer.addr = pLed;
789 parm.u.pointer.size = sizeof(*pLed);
790
791 rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
792 }
793 else
794 AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
795 }
796 else
797 {
798 LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
799 }
800
801 bool fEnabled;
802
803 /* Check CFGM option. */
804 rc = CFGMR3QueryBool(pCfgHandle, "OpenGLEnabled", &fEnabled);
805 if ( RT_SUCCESS(rc)
806 && fEnabled)
807 {
808 rc = pData->pVMMDev->hgcmLoadService ("VBoxSharedOpenGL", "VBoxSharedOpenGL");
809 if (RT_SUCCESS(rc))
810 {
811 LogRel(("Shared OpenGL service loaded.\n"));
812 }
813 else
814 {
815 LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc));
816 }
817 }
818
819 pDrvIns->pDrvHlp->pfnSSMRegister(pDrvIns, "HGCM", 0, HGCM_SSM_VERSION, 4096/* bad guess */, NULL, iface_hgcmSave, NULL, NULL, iface_hgcmLoad, NULL);
820#endif /* VBOX_WITH_HGCM */
821
822 return VINF_SUCCESS;
823}
824
825
826/**
827 * VMMDevice driver registration record.
828 */
829const PDMDRVREG VMMDev::DrvReg =
830{
831 /* u32Version */
832 PDM_DRVREG_VERSION,
833 /* szDriverName */
834 "MainVMMDev",
835 /* pszDescription */
836 "Main VMMDev driver (Main as in the API).",
837 /* fFlags */
838 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
839 /* fClass. */
840 PDM_DRVREG_CLASS_VMMDEV,
841 /* cMaxInstances */
842 ~0,
843 /* cbInstance */
844 sizeof(DRVMAINVMMDEV),
845 /* pfnConstruct */
846 VMMDev::drvConstruct,
847 /* pfnDestruct */
848 VMMDev::drvDestruct,
849 /* pfnIOCtl */
850 NULL,
851 /* pfnPowerOn */
852 NULL,
853 /* pfnReset */
854 VMMDev::drvReset,
855 /* pfnSuspend */
856 NULL,
857 /* pfnResume */
858 NULL,
859 /* pfnDetach */
860 NULL
861};
862/* 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