Exemple #1
0
/**
 * @interface_method_impl(PDMDRVREG,pfnConstruct)
 */
DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    LogFlowFunc(("iInstance/#d, pCfg:%p, fFlags:%x\n", pDrvIns->iInstance, pCfg, fFlags));
    PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);

    if (!CFGMR3AreValuesValid(pCfg, "Object\0"
                                    "PermanentSave\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
    pThis->pNvram = (Nvram *)pv;

    bool fPermanentSave = false;
    rc = CFGMR3QueryBool(pCfg, "PermanentSave", &fPermanentSave);
    if (   RT_SUCCESS(rc)
        || rc == VERR_CFGM_VALUE_NOT_FOUND)
        pThis->fPermanentSave = fPermanentSave;
    else
        AssertRCReturn(rc, rc);

    pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface;
    pThis->INvram.pfnFlushNvramStorage = drvNvram_pfnFlushNvramStorage;
    pThis->INvram.pfnStoreNvramValue = drvNvram_pfnStoreNvramValue;
    pThis->INvram.pfnLoadNvramValue = drvNvram_pfnLoadNvramValue;

    return VINF_SUCCESS;
}
Exemple #2
0
/**
 * Construct a mouse driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
    LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface        = Mouse::drvQueryInterface;

    pData->IConnector.pfnReportModes        = Mouse::mouseReportModes;

    /*
     * Get the IMousePort interface of the above driver/device.
     */
    pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
    if (!pData->pUpPort)
    {
        AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    }

    /*
     * Get the Mouse object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }
    pData->pMouse = (Mouse *)pv;        /** @todo Check this cast! */
    unsigned cDev;
    {
        AutoReadLock mouseLock(pData->pMouse COMMA_LOCKVAL_SRC_POS);

        for (cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
            if (!pData->pMouse->mpDrv[cDev])
            {
                pData->pMouse->mpDrv[cDev] = pData;
                break;
            }
    }
    if (cDev == MOUSE_MAX_DEVICES)
        return VERR_NO_MORE_HANDLES;

    return VINF_SUCCESS;
}
/**
 * Construct a keyboard driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) Keyboard::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg,
                                         uint32_t fFlags)
{
    PDRVMAINKEYBOARD pData = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
    LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface        = Keyboard::drvQueryInterface;

    pData->IConnector.pfnLedStatusChange    = keyboardLedStatusChange;
    pData->IConnector.pfnSetActive          = keyboardSetActive;

    /*
     * Get the IKeyboardPort interface of the above driver/device.
     */
    pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIKEYBOARDPORT);
    if (!pData->pUpPort)
    {
        AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    }

    /*
     * Get the Keyboard object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }
    pData->pKeyboard = (Keyboard *)pv;        /** @todo Check this cast! */
    unsigned cDev;
    for (cDev = 0; cDev < KEYBOARD_MAX_DEVICES; ++cDev)
        if (!pData->pKeyboard->mpDrv[cDev])
        {
            pData->pKeyboard->mpDrv[cDev] = pData;
            break;
        }
    if (cDev == KEYBOARD_MAX_DEVICES)
        return VERR_NO_MORE_HANDLES;

    return VINF_SUCCESS;
}
/**
 * Construct a AudioSniffer driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) AudioSniffer::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVAUDIOSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOSNIFFER);

    LogFlow(("AudioSniffer::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface            = AudioSniffer::drvQueryInterface;

    /* Audio Sniffer connector. */
    pThis->Connector.pfnAudioSamplesOut         = iface_AudioSamplesOut;
    pThis->Connector.pfnAudioVolumeOut          = iface_AudioVolumeOut;
    pThis->Connector.pfnAudioInputBegin         = iface_AudioInputBegin;
    pThis->Connector.pfnAudioInputEnd           = iface_AudioInputEnd;

    /*
     * Get the Audio Sniffer Port interface of the above driver/device.
     */
    pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOSNIFFERPORT);
    if (!pThis->pUpPort)
    {
        AssertMsgFailed(("Configuration error: No Audio Sniffer port interface above!\n"));
        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    }

    /*
     * Get the Console object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }
    pThis->pAudioSniffer = (AudioSniffer *)pv;        /** @todo Check this cast! */
    pThis->pAudioSniffer->mpDrv = pThis;

    return VINF_SUCCESS;
}
Exemple #5
0
/**
 * @interface_method_impl{PDMDRVREG,pfnConstruct}
 */
DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    RT_NOREF(fFlags);
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    LogFlowFunc(("iInstance/#%d pCfg=%p fFlags=%x\n", pDrvIns->iInstance, pCfg, fFlags));
    PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);

    /*
     * Initalize instance data variables first.
     */
    //pThis->pNvram                               = NULL;
    //pThis->cLoadedVariables                     = 0;
    //pThis->fPermanentSave                       = false;
    pThis->pCfgVarRoot                          = CFGMR3GetChild(pCfg, "Vars");
    //pThis->pLastVarNode                         = NULL;
    pThis->idxLastVar                           = UINT32_MAX / 2;

    pDrvIns->IBase.pfnQueryInterface            = Nvram::drvNvram_QueryInterface;
    pThis->INvramConnector.pfnVarQueryByIndex   = drvNvram_VarQueryByIndex;
    pThis->INvramConnector.pfnVarStoreSeqBegin  = drvNvram_VarStoreSeqBegin;
    pThis->INvramConnector.pfnVarStoreSeqPut    = drvNvram_VarStoreSeqPut;
    pThis->INvramConnector.pfnVarStoreSeqEnd    = drvNvram_VarStoreSeqEnd;

    /*
     * Validate and read configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"
                              "PermanentSave\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    int rc = CFGMR3QueryPtr(pCfg, "Object", (void **)&pThis->pNvram);
    AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);

    rc = CFGMR3QueryBoolDef(pCfg, "PermanentSave", &pThis->fPermanentSave, false);
    AssertRCReturn(rc, rc);

    /*
     * Let the associated class instance know about us.
     */
    pThis->pNvram->mpDrv = pThis;

    return VINF_SUCCESS;
}
Exemple #6
0
/**
 * @interface_method_impl{PDMDRVREG,pfnConstruct}
 */
DECLCALLBACK(int) PCIRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
{
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    PDRVMAINPCIRAWDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINPCIRAWDEV);

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;

    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface = PCIRawDev::drvQueryInterface;

    /*
     * IConnector.
     */
    pThis->IConnector.pfnDeviceConstructComplete = PCIRawDev::drvDeviceConstructComplete;

    /*
     * Get the object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }

    pThis->pPCIRawDev = (PCIRawDev *)pv;
    pThis->pPCIRawDev->mpDrv = pThis;

    return VINF_SUCCESS;
}
/**
 * @interface_method_impl{PDMDRVREG,pfnConstruct}
 */
DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
{
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    PDRVMAINVMMDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
    LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface                  = VMMDev::drvQueryInterface;

    pThis->Connector.pfnUpdateGuestStatus             = vmmdevUpdateGuestStatus;
    pThis->Connector.pfnUpdateGuestUserState          = vmmdevUpdateGuestUserState;
    pThis->Connector.pfnUpdateGuestInfo               = vmmdevUpdateGuestInfo;
    pThis->Connector.pfnUpdateGuestInfo2              = vmmdevUpdateGuestInfo2;
    pThis->Connector.pfnUpdateGuestCapabilities       = vmmdevUpdateGuestCapabilities;
    pThis->Connector.pfnUpdateMouseCapabilities       = vmmdevUpdateMouseCapabilities;
    pThis->Connector.pfnUpdatePointerShape            = vmmdevUpdatePointerShape;
    pThis->Connector.pfnVideoAccelEnable              = iface_VideoAccelEnable;
    pThis->Connector.pfnVideoAccelFlush               = iface_VideoAccelFlush;
    pThis->Connector.pfnVideoModeSupported            = vmmdevVideoModeSupported;
    pThis->Connector.pfnGetHeightReduction            = vmmdevGetHeightReduction;
    pThis->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
    pThis->Connector.pfnSetVisibleRegion              = vmmdevSetVisibleRegion;
    pThis->Connector.pfnQueryVisibleRegion            = vmmdevQueryVisibleRegion;
    pThis->Connector.pfnReportStatistics              = vmmdevReportStatistics;
    pThis->Connector.pfnQueryStatisticsInterval       = vmmdevQueryStatisticsInterval;
    pThis->Connector.pfnQueryBalloonSize              = vmmdevQueryBalloonSize;
    pThis->Connector.pfnIsPageFusionEnabled           = vmmdevIsPageFusionEnabled;

#ifdef VBOX_WITH_HGCM
    pThis->HGCMConnector.pfnConnect                   = iface_hgcmConnect;
    pThis->HGCMConnector.pfnDisconnect                = iface_hgcmDisconnect;
    pThis->HGCMConnector.pfnCall                      = iface_hgcmCall;
#endif

    /*
     * Get the IVMMDevPort interface of the above driver/device.
     */
    pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
    AssertMsgReturn(pThis->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);

#ifdef VBOX_WITH_HGCM
    pThis->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
    AssertMsgReturn(pThis->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
#endif

    /*
     * Get the Console object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }

    pThis->pVMMDev = (VMMDev*)pv;        /** @todo Check this cast! */
    pThis->pVMMDev->mpDrv = pThis;

#ifdef VBOX_WITH_HGCM
    rc = pThis->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL,
                                         "VBoxSharedFolders");
    pThis->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
    if (RT_SUCCESS(rc))
    {
        PPDMLED       pLed;
        PPDMILEDPORTS pLedPort;

        LogRel(("Shared Folders service loaded.\n"));
        pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
        AssertMsgReturn(pLedPort, ("Configuration error: No LED port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
        rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
        if (RT_SUCCESS(rc) && pLed)
        {
            VBOXHGCMSVCPARM  parm;

            parm.type = VBOX_HGCM_SVC_PARM_PTR;
            parm.u.pointer.addr = pLed;
            parm.u.pointer.size = sizeof(*pLed);

            rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
        }
        else
            AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
    }
    else
        LogRel(("Failed to load Shared Folders service %Rrc\n", rc));

    rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SSM_VERSION, 4096 /* bad guess */,
                                NULL, NULL, NULL,
                                NULL, iface_hgcmSave, NULL,
                                NULL, iface_hgcmLoad, NULL);
    if (RT_FAILURE(rc))
        return rc;

#endif /* VBOX_WITH_HGCM */

    return VINF_SUCCESS;
}
Exemple #8
0
/**
 * Construct a status driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) VMStatus::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVMAINSTATUS pData = PDMINS_2_DATA(pDrvIns, PDRVMAINSTATUS);
    LogFlow(("VMStatus::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "papLeds\0First\0Last\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * Data.
     */
    pDrvIns->IBase.pfnQueryInterface        = VMStatus::drvQueryInterface;
    pData->ILedConnectors.pfnUnitChanged    = VMStatus::drvUnitChanged;

    /*
     * Read config.
     */
    int rc = CFGMR3QueryPtr(pCfg, "papLeds", (void **)&pData->papLeds);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: Failed to query the \"papLeds\" value! rc=%Rrc\n", rc));
        return rc;
    }

    rc = CFGMR3QueryU32(pCfg, "First", &pData->iFirstLUN);
    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
        pData->iFirstLUN = 0;
    else if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: Failed to query the \"First\" value! rc=%Rrc\n", rc));
        return rc;
    }

    rc = CFGMR3QueryU32(pCfg, "Last", &pData->iLastLUN);
    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
        pData->iLastLUN = 0;
    else if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: Failed to query the \"Last\" value! rc=%Rrc\n", rc));
        return rc;
    }
    if (pData->iFirstLUN > pData->iLastLUN)
    {
        AssertMsgFailed(("Configuration error: Invalid unit range %u-%u\n", pData->iFirstLUN, pData->iLastLUN));
        return VERR_GENERAL_FAILURE;
    }

    /*
     * Get the ILedPorts interface of the above driver/device and
     * query the LEDs we want.
     */
    pData->pLedPorts = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
    AssertMsgReturn(pData->pLedPorts, ("Configuration error: No led ports interface above!\n"),
                    VERR_PDM_MISSING_INTERFACE_ABOVE);

    for (unsigned i = pData->iFirstLUN; i <= pData->iLastLUN; i++)
        VMStatus::drvUnitChanged(&pData->ILedConnectors, i);

    return VINF_SUCCESS;
}
Exemple #9
0
/**
 * Construct a display driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
    LogFlow(("Display::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * Init Interfaces.
     */
    pDrvIns->IBase.pfnQueryInterface    = Display::drvQueryInterface;

    pData->Connector.pfnResize          = Display::displayResizeCallback;
    pData->Connector.pfnUpdateRect      = Display::displayUpdateCallback;
    pData->Connector.pfnRefresh         = Display::displayRefreshCallback;
    pData->Connector.pfnReset           = Display::displayResetCallback;
    pData->Connector.pfnLFBModeChange   = Display::displayLFBModeChangeCallback;
    pData->Connector.pfnProcessAdapterData = Display::displayProcessAdapterDataCallback;
    pData->Connector.pfnProcessDisplayData = Display::displayProcessDisplayDataCallback;

    /*
     * Get the IDisplayPort interface of the above driver/device.
     */
    pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
    if (!pData->pUpPort)
    {
        AssertMsgFailed(("Configuration error: No display port interface above!\n"));
        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    }

    /*
     * Get the Display object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }
    pData->pDisplay = (Display *)pv;        /** @todo Check this cast! */
    pData->pDisplay->mpDrv = pData;

    /*
     * If there is a Framebuffer, we have to update our display information
     */
    if (pData->pDisplay->mFramebuffer)
        pData->pDisplay->updateDisplayData();

    /*
     * Start periodic screen refreshes
     */
    pData->pUpPort->pfnSetRefreshRate(pData->pUpPort, 50);

    return VINF_SUCCESS;
}
/**
 * Construct a VMMDev driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
    LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));

    /*
     * Validate configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    /*
     * IBase.
     */
    pDrvIns->IBase.pfnQueryInterface            = VMMDev::drvQueryInterface;

    pData->Connector.pfnUpdateGuestStatus       = VMMDev::UpdateGuestStatus;
    pData->Connector.pfnUpdateGuestInfo         = VMMDev::UpdateGuestInfo;
    pData->Connector.pfnUpdateGuestCapabilities = VMMDev::UpdateGuestCapabilities;
    pData->Connector.pfnUpdateMouseCapabilities = VMMDev::UpdateMouseCapabilities;
    pData->Connector.pfnUpdatePointerShape      = VMMDev::UpdatePointerShape;
    pData->Connector.pfnVideoAccelEnable        = iface_VideoAccelEnable;
    pData->Connector.pfnVideoAccelFlush         = iface_VideoAccelFlush;
    pData->Connector.pfnVideoModeSupported      = VMMDev::VideoModeSupported;
    pData->Connector.pfnGetHeightReduction      = VMMDev::GetHeightReduction;
    pData->Connector.pfnSetVisibleRegion        = iface_SetVisibleRegion;
    pData->Connector.pfnQueryVisibleRegion      = iface_QueryVisibleRegion;
    pData->Connector.pfnQueryBalloonSize        = VMMDev::QueryBalloonSize;

#ifdef VBOX_WITH_HGCM
    if (fActivateHGCM())
    {
        pData->HGCMConnector.pfnConnect         = iface_hgcmConnect;
        pData->HGCMConnector.pfnDisconnect      = iface_hgcmDisconnect;
        pData->HGCMConnector.pfnCall            = iface_hgcmCall;
    }
#endif

    /*
     * Get the IVMMDevPort interface of the above driver/device.
     */
    pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
    AssertMsgReturn(pData->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);

#ifdef VBOX_WITH_HGCM
    if (fActivateHGCM())
    {
        pData->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
        AssertMsgReturn(pData->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
    }
#endif

    /*
     * Get the VMMDev object pointer and update the mpDrv member.
     */
    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
        return rc;
    }

    pData->pVMMDev = (VMMDev*)pv;        /** @todo Check this cast! */
    pData->pVMMDev->mpDrv = pData;

#ifdef VBOX_WITH_HGCM
    if (fActivateHGCM())
    {
        rc = pData->pVMMDev->hgcmLoadService (VBOXSHAREDFOLDERS_DLL, "VBoxSharedFolders");
        pData->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
        if (RT_SUCCESS(rc))
            LogRel(("Shared Folders service loaded.\n"));
        else
            LogRel(("Failed to load Shared Folders service %Rrc\n", rc));


        rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SSM_VERSION, 4096 /* bad guess */,
                                    NULL, NULL, NULL,
                                    NULL, iface_hgcmSave, NULL,
                                    NULL, iface_hgcmLoad, NULL);
        if (RT_FAILURE(rc))
            return rc;

    }
#endif /* VBOX_WITH_HGCM */

    return VINF_SUCCESS;
}