/** * @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; }
/** * Construct an ACPI CPU driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvACPICpuConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Init the static parts. */ /* IBase */ pDrvIns->IBase.pfnQueryInterface = drvACPICpuQueryInterface; /* * Validate the config. */ if (!CFGMR3AreValuesValid(pCfg, "\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; /* * Check that no-one is attached to us. */ AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER, ("Configuration error: Not possible to attach anything to this driver!\n"), VERR_PDM_DRVINS_NO_ATTACH); return VINF_SUCCESS; }
/** * 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; }
/** * Construct a block driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvscsihostConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST); LogFlowFunc(("pDrvIns=%#p pCfg=%#p\n", pDrvIns, pCfg)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Initialize the instance data first because of the destructor. */ pDrvIns->IBase.pfnQueryInterface = drvscsihostQueryInterface; pThis->ISCSIConnector.pfnSCSIRequestSend = drvscsihostRequestSend; pThis->pDrvIns = pDrvIns; pThis->hDeviceFile = NIL_RTFILE; pThis->hQueueRequests = NIL_RTREQQUEUE; /* * Read the configuration. */ if (!CFGMR3AreValuesValid(pCfg, "DevicePath\0")) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, N_("Invalid configuration for host scsi access driver")); /* Query the SCSI port interface above. */ pThis->pDevScsiPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISCSIPORT); AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE); /* Create request queue. */ int rc = RTReqQueueCreate(&pThis->hQueueRequests); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n"), rc); /* Open the device. */ rc = CFGMR3QueryStringAlloc(pCfg, "DevicePath", &pThis->pszDevicePath); if (RT_FAILURE(rc)) return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Configuration error: Failed to get the \"DevicePath\" value")); rc = RTFileOpen(&pThis->hDeviceFile, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvSCSIHost#%d: Failed to open device '%s'"), pDrvIns->iInstance, pThis->pszDevicePath); /* Create I/O thread. */ rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsihostAsyncIOLoop, drvscsihostAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO"); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc); return VINF_SUCCESS; }
/** * @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; }
/** * @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{Construct a NAT network transport driver instance, * PDMDRVREG,pfnDestruct} */ static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER); LogFlow(("drvNetShaperConstruct:\n")); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Init the static parts. */ pThis->pDrvInsR3 = pDrvIns; pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns); /* IBase */ pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface; pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface; pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface; /* INetworkUp */ pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit; pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf; pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf; pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf; pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit; pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode; pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged; /* Resolve the ring-0 context interface addresses. */ int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0, sizeof(pThis->INetworkUpR0), "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST); AssertLogRelRCReturn(rc, rc); /* INetworkDown */ pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail; pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive; pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso; pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending; /* INetworkConfig */ pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac; pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState; pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState; /* * Create the locks. */ rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper"); AssertRCReturn(rc, rc); /* * Validate the config. */ if (!CFGMR3AreValuesValid(pCfg, "BwGroup\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; /* * Find the bandwidth group we have to attach to. */ rc = CFGMR3QueryStringAlloc(pCfg, "BwGroup", &pThis->pszBwGroup); if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND) { rc = PDMDRV_SET_ERROR(pDrvIns, rc, N_("DrvNetShaper: Configuration error: Querying \"BwGroup\" as string failed")); return rc; } else rc = VINF_SUCCESS; pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown; rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter); if (RT_FAILURE(rc)) { rc = PDMDRV_SET_ERROR(pDrvIns, rc, N_("DrvNetShaper: Configuration error: Failed to attach to bandwidth group")); return rc; } /* * Query the network port interface. */ pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN); if (!pThis->pIAboveNet) { AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Query the network config interface. */ pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG); if (!pThis->pIAboveConfig) { AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Query the network connector interface. */ PPDMIBASE pBaseDown; rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown); if ( rc == VERR_PDM_NO_ATTACHED_DRIVER || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) { pThis->pIBelowNetR3 = NULL; pThis->pIBelowNetR0 = NIL_RTR0PTR; } else if (RT_SUCCESS(rc)) { pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP); if (!pThis->pIBelowNetR3) { AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n")); return VERR_PDM_MISSING_INTERFACE_BELOW; } PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0); pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR; } else { AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc)); return rc; } /* * Register statistics. */ PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesRequested, "Bytes/Tx/Requested", STAMUNIT_BYTES, "Number of requested TX bytes."); PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesDenied, "Bytes/Tx/Denied", STAMUNIT_BYTES, "Number of denied TX bytes."); PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesGranted, "Bytes/Tx/Granted", STAMUNIT_BYTES, "Number of granted TX bytes."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsRequested, "Packets/Tx/Requested", "Number of requested TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsDenied, "Packets/Tx/Denied", "Number of denied TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsGranted, "Packets/Tx/Granted", "Number of granted TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPendingCalled, "Tx/WakeUp", "Number of wakeup TX calls."); return VINF_SUCCESS; }
/** * Construct a host parallel driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL); LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Init basic data members and interfaces. * * Must be done before returning any failure because we've got a destructor. */ pThis->hFileDevice = NIL_RTFILE; #ifndef VBOX_WITH_WIN_PARPORT_SUP pThis->hWakeupPipeR = NIL_RTPIPE; pThis->hWakeupPipeW = NIL_RTPIPE; #else pThis->hWinFileDevice = NIL_RTFILE; #endif pThis->pDrvInsR3 = pDrvIns; #ifdef VBOX_WITH_DRVINTNET_IN_R0 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns); #endif /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvHostParallelQueryInterface; /* IHostParallelConnector. */ pThis->IHostParallelConnectorR3.pfnWrite = drvHostParallelWrite; pThis->IHostParallelConnectorR3.pfnRead = drvHostParallelRead; pThis->IHostParallelConnectorR3.pfnSetPortDirection = drvHostParallelSetPortDirection; pThis->IHostParallelConnectorR3.pfnWriteControl = drvHostParallelWriteControl; pThis->IHostParallelConnectorR3.pfnReadControl = drvHostParallelReadControl; pThis->IHostParallelConnectorR3.pfnReadStatus = drvHostParallelReadStatus; /* * Validate the config. */ if (!CFGMR3AreValuesValid(pCfg, "DevicePath\0")) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, N_("Unknown host parallel configuration option, only supports DevicePath")); /* * Query configuration. */ /* Device */ int rc = CFGMR3QueryStringAlloc(pCfg, "DevicePath", &pThis->pszDevicePath); if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: query for \"DevicePath\" string returned %Rra.\n", rc)); return rc; } /* * Open the device */ rc = RTFileOpen(&pThis->hFileDevice, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Parallel#%d could not open '%s'"), pDrvIns->iInstance, pThis->pszDevicePath); #ifndef VBOX_WITH_WIN_PARPORT_SUP /* * Try to get exclusive access to parallel port */ rc = ioctl(RTFileToNative(pThis->hFileDevice), PPEXCL); if (rc < 0) return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("Parallel#%d could not get exclusive access for parallel port '%s'" "Be sure that no other process or driver accesses this port"), pDrvIns->iInstance, pThis->pszDevicePath); /* * Claim the parallel port */ rc = ioctl(RTFileToNative(pThis->hFileDevice), PPCLAIM); if (rc < 0) return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("Parallel#%d could not claim parallel port '%s'" "Be sure that no other process or driver accesses this port"), pDrvIns->iInstance, pThis->pszDevicePath); /* * Get the IHostParallelPort interface of the above driver/device. */ pThis->pDrvHostParallelPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHOSTPARALLELPORT); if (!pThis->pDrvHostParallelPort) return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"), pDrvIns->iInstance); /* * Create wakeup pipe. */ rc = RTPipeCreate(&pThis->hWakeupPipeR, &pThis->hWakeupPipeW, 0 /*fFlags*/); AssertRCReturn(rc, rc); /* * Start in SPP mode. */ pThis->enmModeCur = PDM_PARALLEL_PORT_MODE_INVALID; rc = drvHostParallelSetMode(pThis, PDM_PARALLEL_PORT_MODE_SPP); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot change mode of parallel mode to SPP"), pDrvIns->iInstance); /* * Start waiting for interrupts. */ rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0, RTTHREADTYPE_IO, "ParMon"); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance); #else /* VBOX_WITH_WIN_PARPORT_SUP */ pThis->fParportAvail = false; pThis->u32LptAddr = 0; pThis->u32LptAddrControl = 0; pThis->u32LptAddrStatus = 0; rc = drvWinHostGetparportAddr(pThis); /* If we have the char port availabe use it , else I am not getting exclusive access to parallel port. Read and write will be done only if addresses are available */ if (pThis->szParportName) { rc = RTFileOpen(&pThis->hWinFileDevice, (char *)pThis->szParportName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); } #endif return VINF_SUCCESS; }
/** * Construct a disk integrity driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { int rc = VINF_SUCCESS; PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY); LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Validate configuration. */ if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0" "TraceRequests\0" "CheckIntervalMs\0" "ExpireIntervalMs\0" "CheckDoubleCompletions\0" "HistorySize\0" "IoLog\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false); AssertRC(rc); rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false); AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */ AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */ AssertRC(rc); rc = CFGMR3QueryBoolDef(pCfg, "CheckDoubleCompletions", &pThis->fCheckDoubleCompletion, false); AssertRC(rc); rc = CFGMR3QueryU32Def(pCfg, "HistorySize", &pThis->cEntries, 512); AssertRC(rc); char *pszIoLogFilename = NULL; rc = CFGMR3QueryStringAlloc(pCfg, "IoLog", &pszIoLogFilename); Assert(RT_SUCCESS(rc) || rc == VERR_CFGM_VALUE_NOT_FOUND); /* * Initialize most of the data members. */ pThis->pDrvIns = pDrvIns; /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface; /* IMedia */ pThis->IMedia.pfnRead = drvdiskintRead; pThis->IMedia.pfnWrite = drvdiskintWrite; pThis->IMedia.pfnFlush = drvdiskintFlush; pThis->IMedia.pfnGetSize = drvdiskintGetSize; pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly; pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry; pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry; pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry; pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry; pThis->IMedia.pfnGetUuid = drvdiskintGetUuid; /* IMediaAsync */ pThis->IMediaAsync.pfnStartRead = drvdiskintStartRead; pThis->IMediaAsync.pfnStartWrite = drvdiskintStartWrite; pThis->IMediaAsync.pfnStartFlush = drvdiskintStartFlush; /* IMediaAsyncPort. */ pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvdiskintAsyncTransferCompleteNotify; /* IMediaPort. */ pThis->IMediaPort.pfnQueryDeviceLocation = drvdiskintQueryDeviceLocation; /* Query the media port interface above us. */ pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT); if (!pThis->pDrvMediaPort) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, N_("No media port inrerface above")); /* Try to attach async media port interface above.*/ pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT); /* * Try attach driver below and query it's media interface. */ PPDMIBASE pBase; rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Failed to attach driver below us! %Rrc"), rc); pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA); if (!pThis->pDrvMedia) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, N_("No media or async media interface below")); pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC); if (pThis->pDrvMedia->pfnDiscard) pThis->IMedia.pfnDiscard = drvdiskintDiscard; if ( pThis->pDrvMediaAsync && pThis->pDrvMediaAsync->pfnStartDiscard) pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard; if (pThis->fCheckConsistency) { /* Create the AVL tree. */ pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE)); if (!pThis->pTreeSegments) rc = VERR_NO_MEMORY; } if (pThis->fTraceRequests) { for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++) { pThis->apReqActive[i].pIoReq = NULL; pThis->apReqActive[i].tsStart = 0; } pThis->iNextFreeSlot = 0; /* Init event semaphore. */ rc = RTSemEventCreate(&pThis->SemEvent); AssertRC(rc); pThis->fRunning = true; rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis, 0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity"); AssertRC(rc); } if (pThis->fCheckDoubleCompletion) { pThis->iEntry = 0; pThis->papIoReq = (PDRVDISKAIOREQ *)RTMemAllocZ(pThis->cEntries * sizeof(PDRVDISKAIOREQ)); AssertPtr(pThis->papIoReq); } if (pszIoLogFilename) { rc = VDDbgIoLogCreate(&pThis->hIoLogger, pszIoLogFilename, VDDBG_IOLOG_LOG_DATA); MMR3HeapFree(pszIoLogFilename); } return rc; }
/** * Construct a keyboard driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvKbdQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVKBDQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE); LogFlow(("drvKbdQueueConstruct: iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Validate configuration. */ if (!CFGMR3AreValuesValid(pCfg, "QueueSize\0Interval\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; /* * Init basic data members and interfaces. */ pDrv->fInactive = true; pDrv->fSuspended = false; pDrv->XlatState = SS_IDLE; /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvKbdQueueQueryInterface; /* IKeyboardConnector. */ pDrv->IConnector.pfnLedStatusChange = drvKbdPassThruLedsChange; pDrv->IConnector.pfnSetActive = drvKbdPassThruSetActive; pDrv->IConnector.pfnFlushQueue = drvKbdFlushQueue; /* IKeyboardPort. */ pDrv->IPort.pfnPutEventScan = drvKbdQueuePutEventScan; /* * Get the IKeyboardPort interface of the above driver/device. */ pDrv->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIKEYBOARDPORT); if (!pDrv->pUpPort) { AssertMsgFailed(("Configuration error: No keyboard port interface above!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Attach driver below and query it's connector interface. */ PPDMIBASE pDownBase; int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pDownBase); if (RT_FAILURE(rc)) { AssertMsgFailed(("Failed to attach driver below us! rc=%Rra\n", rc)); return rc; } pDrv->pDownConnector = PDMIBASE_QUERY_INTERFACE(pDownBase, PDMIKEYBOARDCONNECTOR); if (!pDrv->pDownConnector) { AssertMsgFailed(("Configuration error: No keyboard connector interface below!\n")); return VERR_PDM_MISSING_INTERFACE_BELOW; } /* * Create the queue. */ uint32_t cMilliesInterval = 0; rc = CFGMR3QueryU32(pCfg, "Interval", &cMilliesInterval); if (rc == VERR_CFGM_VALUE_NOT_FOUND) cMilliesInterval = 0; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc)); return rc; } uint32_t cItems = 0; rc = CFGMR3QueryU32(pCfg, "QueueSize", &cItems); if (rc == VERR_CFGM_VALUE_NOT_FOUND) cItems = 128; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc)); return rc; } rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue); if (RT_FAILURE(rc)) { AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc)); return rc; } return VINF_SUCCESS; }
/** * Construct a block driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvscsiConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { int rc = VINF_SUCCESS; PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); LogFlowFunc(("pDrvIns=%#p pCfg=%#p\n", pDrvIns, pCfg)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Initialize the instance data. */ pThis->pDrvIns = pDrvIns; pThis->ISCSIConnector.pfnSCSIRequestSend = drvscsiRequestSend; pThis->ISCSIConnector.pfnQueryLUNType = drvscsiQueryLUNType; pDrvIns->IBase.pfnQueryInterface = drvscsiQueryInterface; pThis->IMountNotify.pfnMountNotify = drvscsiMountNotify; pThis->IMountNotify.pfnUnmountNotify = drvscsiUnmountNotify; pThis->IPort.pfnQueryDeviceLocation = drvscsiQueryDeviceLocation; pThis->IPortAsync.pfnTransferCompleteNotify = drvscsiTransferCompleteNotify; pThis->hQueueRequests = NIL_RTREQQUEUE; /* Query the SCSI port interface above. */ pThis->pDevScsiPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISCSIPORT); AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE); /* Query the optional LED interface above. */ pThis->pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS); if (pThis->pLedPort != NULL) { /* Get The Led. */ rc = pThis->pLedPort->pfnQueryStatusLed(pThis->pLedPort, 0, &pThis->pLed); if (RT_FAILURE(rc)) pThis->pLed = &pThis->Led; } else pThis->pLed = &pThis->Led; /* * Validate and read configuration. */ if (!CFGMR3AreValuesValid(pCfg, "NonRotationalMedium\0Readonly\0")) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, N_("SCSI configuration error: unknown option specified")); rc = CFGMR3QueryBoolDef(pCfg, "NonRotationalMedium", &pThis->fNonRotational, false); if (RT_FAILURE(rc)) return PDMDRV_SET_ERROR(pDrvIns, rc, N_("SCSI configuration error: failed to read \"NonRotationalMedium\" as boolean")); rc = CFGMR3QueryBoolDef(pCfg, "Readonly", &pThis->fReadonly, false); if (RT_FAILURE(rc)) return PDMDRV_SET_ERROR(pDrvIns, rc, N_("SCSI configuration error: failed to read \"Readonly\" as boolean")); /* * Try attach driver below and query it's block interface. */ rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pThis->pDrvBase); AssertMsgReturn(RT_SUCCESS(rc), ("Attaching driver below failed rc=%Rrc\n", rc), rc); /* * Query the block and blockbios interfaces. */ pThis->pDrvBlock = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCK); if (!pThis->pDrvBlock) { AssertMsgFailed(("Configuration error: No block interface!\n")); return VERR_PDM_MISSING_INTERFACE; } pThis->pDrvBlockBios = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCKBIOS); if (!pThis->pDrvBlockBios) { AssertMsgFailed(("Configuration error: No block BIOS interface!\n")); return VERR_PDM_MISSING_INTERFACE; } pThis->pDrvMount = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMOUNT); /* Try to get the optional async block interface. */ pThis->pDrvBlockAsync = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCKASYNC); PDMBLOCKTYPE enmType = pThis->pDrvBlock->pfnGetType(pThis->pDrvBlock); VSCSILUNTYPE enmLunType; switch (enmType) { case PDMBLOCKTYPE_HARD_DISK: enmLunType = VSCSILUNTYPE_SBC; break; case PDMBLOCKTYPE_CDROM: case PDMBLOCKTYPE_DVD: enmLunType = VSCSILUNTYPE_MMC; break; default: return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_UNSUPPORTED_BLOCK_TYPE, RT_SRC_POS, N_("Only hard disks and CD/DVD-ROMs are currently supported as SCSI devices (enmType=%d)"), enmType); } if ( ( enmType == PDMBLOCKTYPE_DVD || enmType == PDMBLOCKTYPE_CDROM) && !pThis->pDrvMount) { AssertMsgFailed(("Internal error: cdrom without a mountable interface\n")); return VERR_INTERNAL_ERROR; } /* Create VSCSI device and LUN. */ pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize = drvscsiGetSize; pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSectorSize = drvscsiGetSectorSize; pThis->VScsiIoCallbacks.pfnVScsiLunReqTransferEnqueue = drvscsiReqTransferEnqueue; pThis->VScsiIoCallbacks.pfnVScsiLunGetFeatureFlags = drvscsiGetFeatureFlags; pThis->VScsiIoCallbacks.pfnVScsiLunMediumSetLock = drvscsiSetLock; rc = VSCSIDeviceCreate(&pThis->hVScsiDevice, drvscsiVScsiReqCompleted, pThis); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create VSCSI device rc=%Rrc\n"), rc); rc = VSCSILunCreate(&pThis->hVScsiLun, enmLunType, &pThis->VScsiIoCallbacks, pThis); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create VSCSI LUN rc=%Rrc\n"), rc); rc = VSCSIDeviceLunAttach(pThis->hVScsiDevice, pThis->hVScsiLun, 0); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to attached the LUN to the SCSI device\n"), rc); //@todo: This is a very hacky way of telling the LUN whether a medium was mounted. // The mount/unmount interface doesn't work in a very sensible manner! if (pThis->pDrvMount) { if (pThis->pDrvBlock->pfnGetSize(pThis->pDrvBlock)) { rc = VINF_SUCCESS; VSCSILunMountNotify(pThis->hVScsiLun); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to notify the LUN of media being mounted\n"), rc); } else { rc = VINF_SUCCESS; VSCSILunUnmountNotify(pThis->hVScsiLun); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to notify the LUN of media being unmounted\n"), rc); } } /* Register statistics counter. */ /** @todo aeichner: Find a way to put the instance number of the attached * controller device when we support more than one controller of the same type. * At the moment we have the 0 hardcoded. */ PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data read.", "/Devices/SCSI0/%d/ReadBytes", pDrvIns->iInstance); PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data written.", "/Devices/SCSI0/%d/WrittenBytes", pDrvIns->iInstance); pThis->StatIoDepth = 0; PDMDrvHlpSTAMRegisterF(pDrvIns, (void *)&pThis->StatIoDepth, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of active tasks.", "/Devices/SCSI0/%d/IoDepth", pDrvIns->iInstance); if (!pThis->pDrvBlockAsync) { /* Create request queue. */ rc = RTReqQueueCreate(&pThis->hQueueRequests); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n"), rc); /* Create I/O thread. */ rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop, drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO"); AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc); LogRel(("SCSI#%d: using normal I/O\n", pDrvIns->iInstance)); } else LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance)); if ( pThis->pDrvBlock->pfnDiscard || ( pThis->pDrvBlockAsync && pThis->pDrvBlockAsync->pfnStartDiscard)) LogRel(("SCSI#%d: Enabled UNMAP support\n")); return VINF_SUCCESS; }
/** * 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; }
/** * 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; }
/** @interface_method_impl{PDMDEVREG,pfnConstruct} */ static DECLCALLBACK(int) ox958R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) { RT_NOREF(iInstance); PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958); bool fRCEnabled = true; bool fR0Enabled = true; bool fMsiXSupported = false; int rc; PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* * Validate and read configuration. */ if (!CFGMR3AreValuesValid(pCfg, "RCEnabled\0" "R0Enabled\0" "MsiXSupported\0" "UartCount\0")) return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, N_("OXPCIe958 configuration error: Unknown option specified")); rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: Failed to read \"RCEnabled\" as boolean")); rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"R0Enabled\" as boolean")); rc = CFGMR3QueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean")); rc = CFGMR3QueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX); if (RT_FAILURE(rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer")); if (!pThis->cUarts || pThis->cUarts > OX958_UARTS_MAX) return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("OXPCIe958 configuration error: \"UartCount\" has invalid value %u (must be in range [1 .. %u]"), pThis->cUarts, OX958_UARTS_MAX); /* * Init instance data. */ pThis->fR0Enabled = fR0Enabled; pThis->fRCEnabled = fRCEnabled; pThis->pDevInsR3 = pDevIns; pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); /* Fill PCI config space. */ PDMPciDevSetVendorId (&pThis->PciDev, OX958_PCI_VENDOR_ID); PDMPciDevSetDeviceId (&pThis->PciDev, OX958_PCI_DEVICE_ID); PDMPciDevSetCommand (&pThis->PciDev, 0x0000); #ifdef VBOX_WITH_MSI_DEVICES PDMPciDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); PDMPciDevSetCapabilityList (&pThis->PciDev, OX958_PCI_MSI_CAP_OFS); #else PDMPciDevSetCapabilityList (&pThis->PciDev, 0x70); #endif PDMPciDevSetRevisionId (&pThis->PciDev, 0x00); PDMPciDevSetClassBase (&pThis->PciDev, 0x07); /* Communication controller. */ PDMPciDevSetClassSub (&pThis->PciDev, 0x00); /* Serial controller. */ PDMPciDevSetClassProg (&pThis->PciDev, 0x02); /* 16550. */ PDMPciDevSetRevisionId (&pThis->PciDev, 0x00); PDMPciDevSetSubSystemVendorId(&pThis->PciDev, OX958_PCI_VENDOR_ID); PDMPciDevSetSubSystemId (&pThis->PciDev, OX958_PCI_DEVICE_ID); PDMPciDevSetInterruptLine (&pThis->PciDev, 0x00); PDMPciDevSetInterruptPin (&pThis->PciDev, 0x01); /** @todo More Capabilities. */ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); if (RT_FAILURE(rc)) return rc; /* * Register PCI device and I/O region. */ rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev); if (RT_FAILURE(rc)) return rc; #ifdef VBOX_WITH_MSI_DEVICES PDMMSIREG MsiReg; RT_ZERO(MsiReg); MsiReg.cMsiVectors = 1; MsiReg.iMsiCapOffset = OX958_PCI_MSI_CAP_OFS; MsiReg.iMsiNextOffset = OX958_PCI_MSIX_CAP_OFS; MsiReg.fMsi64bit = true; if (fMsiXSupported) { MsiReg.cMsixVectors = VBOX_MSIX_MAX_ENTRIES; MsiReg.iMsixCapOffset = OX958_PCI_MSIX_CAP_OFS; MsiReg.iMsixNextOffset = 0x00; MsiReg.iMsixBar = OX958_PCI_MSIX_BAR; } rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg); if (RT_FAILURE(rc)) { PCIDevSetCapabilityList(&pThis->PciDev, 0x0); /* That's OK, we can work without MSI */ } #endif rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, _16K, PCI_ADDRESS_SPACE_MEM, ox958R3Map); if (RT_FAILURE(rc)) return rc; PVM pVM = PDMDevHlpGetVM(pDevIns); RTR0PTR pfnSerialIrqReqR0 = NIL_RTR0PTR; RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR; if ( fRCEnabled && VM_IS_RAW_MODE_ENABLED(pVM)) { rc = PDMR3LdrGetSymbolRC(pVM, pDevIns->pReg->szRCMod, "ox958IrqReq", &pfnSerialIrqReqRC); if (RT_FAILURE(rc)) return rc; } if (fR0Enabled) { rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->szR0Mod, "ox958IrqReq", &pfnSerialIrqReqR0); if (RT_FAILURE(rc)) return rc; } for (uint32_t i = 0; i < pThis->cUarts; i++) { POX958UART pUart = &pThis->aUarts[i]; rc = uartR3Init(&pUart->UartCore, pDevIns, UARTTYPE_16550A, i, 0, ox958IrqReq, pfnSerialIrqReqR0, pfnSerialIrqReqRC); if (RT_FAILURE(rc)) return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("OXPCIe958 configuration error: failed to initialize UART %u"), i); } ox958R3Reset(pDevIns); 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; }
/** * 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; }