/**
 * @interface_method_impl{PDMDRVREG,pfnConstruct}
 */
static DECLCALLBACK(int) drvR3DedicatedNicConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVDEDICATEDNIC pThis = PDMINS_2_DATA(pDrvIns, PDRVDEDICATEDNIC);
    bool f;
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Init the static parts.
     */
    pThis->pDrvInsR3                                = pDrvIns;
    pThis->pDrvInsR0                                = PDMDRVINS_2_R0PTR(pDrvIns);
#if 0
    pThis->hRecvThread                              = NIL_RTTHREAD;
    pThis->hRecvEvt                                 = NIL_RTSEMEVENT;
    pThis->pXmitThread                              = NULL;
    pThis->hXmitEvt                                 = NIL_SUPSEMEVENT;
    pThis->pSupDrvSession                           = PDMDrvHlpGetSupDrvSession(pDrvIns);
    pThis->hSgCache                                 = NIL_RTMEMCACHE;
    pThis->enmRecvState                             = RECVSTATE_SUSPENDED;
    pThis->fActivateEarlyDeactivateLate             = false;
    /* IBase* */
    pDrvIns->IBase.pfnQueryInterface                = drvR3DedicatedNicIBase_QueryInterface;
    pThis->IBaseR0.pfnQueryInterface                = drvR3DedicatedNicIBaseR0_QueryInterface;
    pThis->IBaseRC.pfnQueryInterface                = drvR3DedicatedNicIBaseRC_QueryInterface;
    /* INetworkUp */
    pThis->INetworkUpR3.pfnBeginXmit                = drvDedicatedNic_BeginXmit;
    pThis->INetworkUpR3.pfnAllocBuf                 = drvDedicatedNic_AllocBuf;
    pThis->INetworkUpR3.pfnFreeBuf                  = drvDedicatedNic_FreeBuf;
    pThis->INetworkUpR3.pfnSendBuf                  = drvDedicatedNic_SendBuf;
    pThis->INetworkUpR3.pfnEndXmit                  = drvDedicatedNic_EndXmit;
    pThis->INetworkUpR3.pfnSetPromiscuousMode       = drvDedicatedNic_SetPromiscuousMode;
    pThis->INetworkUpR3.pfnNotifyLinkChanged        = drvR3DedicatedNicUp_NotifyLinkChanged;
#endif

    /** @todo
     * Need to create a generic way of calling into the ring-0 side of the driver so
     * we can initialize the thing as well as send and receive.  Hmm ... the
     * sending could be done more efficiently from a ring-0 kernel thread actually
     * (saves context switching and 1-2 copy operations).  Ditto for receive, except
     * we need to tie the thread to the process or we cannot access the guest ram so
     * easily.
     */

    return VERR_NOT_IMPLEMENTED;
}
Пример #2
0
/**
 * @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;
}