static int drvscsiAsyncIOLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
{
    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    PRTREQ pReq;
    int rc;

    AssertMsgReturn(pThis->hQueueRequests != NIL_RTREQQUEUE, ("hQueueRequests is NULL\n"), VERR_INVALID_STATE);

    if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 10000 /* 10 sec */))
    {
        LogRel(("drvscsiAsyncIOLoopWakeup#%u: previous dummy request is still pending\n", pDrvIns->iInstance));
        return VERR_TIMEOUT;
    }

    rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);
    if (RT_SUCCESS(rc))
        RTReqRelease(pReq);
    else
    {
        pThis->pPendingDummyReq = pReq;
        LogRel(("drvscsiAsyncIOLoopWakeup#%u: %Rrc pReq=%p\n", pDrvIns->iInstance, rc, pReq));
    }

    return rc;
}
/**
 * Destruct a driver instance.
 *
 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
 * resources can be freed correctly.
 *
 * @param   pDrvIns     The driver instance data.
 */
static DECLCALLBACK(void) drvscsiDestruct(PPDMDRVINS pDrvIns)
{
    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);

    if (pThis->hQueueRequests != NIL_RTREQQUEUE)
    {
        if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 100 /*ms*/))
            LogRel(("drvscsiDestruct#%u: previous dummy request is still pending\n", pDrvIns->iInstance));

        int rc = RTReqQueueDestroy(pThis->hQueueRequests);
        AssertMsgRC(rc, ("Failed to destroy queue rc=%Rrc\n", rc));
        pThis->hQueueRequests = NIL_RTREQQUEUE;
    }

    /* Free the VSCSI device and LUN handle. */
    if (pThis->hVScsiDevice)
    {
        VSCSILUN hVScsiLun;
        int rc = VSCSIDeviceLunDetach(pThis->hVScsiDevice, 0, &hVScsiLun);
        AssertRC(rc);

        Assert(hVScsiLun == pThis->hVScsiLun);
        rc = VSCSILunDestroy(hVScsiLun);
        AssertRC(rc);
        rc = VSCSIDeviceDestroy(pThis->hVScsiDevice);
        AssertRC(rc);

        pThis->hVScsiDevice = NULL;
        pThis->hVScsiLun    = NULL;
    }
}
Beispiel #3
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;
}
/**
 * @copydoc FNPDMDRVDESTRUCT
 */
static DECLCALLBACK(void) drvdiskintDestruct(PPDMDRVINS pDrvIns)
{
    PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);

    if (pThis->pTreeSegments)
    {
        RTAvlrFileOffsetDestroy(pThis->pTreeSegments, drvdiskintTreeDestroy, NULL);
        RTMemFree(pThis->pTreeSegments);
    }

    if (pThis->fTraceRequests)
    {
        pThis->fRunning = false;
        RTSemEventSignal(pThis->SemEvent);
        RTSemEventDestroy(pThis->SemEvent);
    }

    if (pThis->fCheckDoubleCompletion)
    {
        /* Free all requests */
        while (pThis->papIoReq[pThis->iEntry])
        {
            RTMemFree(pThis->papIoReq[pThis->iEntry]);
            pThis->papIoReq[pThis->iEntry] = NULL;
            pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
        }
    }

    if (pThis->hIoLogger)
        VDDbgIoLogDestroy(pThis->hIoLogger);
}
/**
 * R0 mode function to write byte value to parallel port control
 * register.
 * @returns VBox status code.
 * @param   pDrvIns     Driver instance.
 * @param   u64Arg      Data to be written to control register.
 */
static int drvR0HostParallelReqWriteControl(PPDMDRVINS pDrvIns, uint64_t u64Arg)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    LogFlowFunc(("write to ctrl port=%#x val=%#x\n", pThis->u32LptAddrControl, u64Arg));
    ASMOutU8(pThis->u32LptAddrControl, (uint8_t)(u64Arg));
    return VINF_SUCCESS;
}
Beispiel #6
0
/* return the pic wanted interrupt. return -1 if none */
static int pic_get_irq(PicState *s)
{
    PicState *pics = &(PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC))->aPics[0];
    int mask, cur_priority, priority;
    Log(("pic_get_irq%d: mask=%x\n", (s == pics) ? 0 : 1, s->irr & ~s->imr));
    DumpPICState(s, "pic_get_irq");

    mask = s->irr & ~s->imr;
    priority = get_priority(s, mask);
    Log(("pic_get_irq: priority=%x\n", priority));
    if (priority == 8)
        return -1;
    /* compute current priority. If special fully nested mode on the
       master, the IRQ coming from the slave is not taken into account
       for the priority computation. */
    mask = s->isr;
    if (s->special_fully_nested_mode && s == &pics[0])
        mask &= ~(1 << 2);
    cur_priority = get_priority(s, mask);
    Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", (s == pics) ? 0 : 1, cur_priority, (priority == 8) ? -1 : (priority + s->priority_add) & 7));
    if (priority < cur_priority) {
        /* higher priority found: an irq should be generated */
        return (priority + s->priority_add) & 7;
    } else {
        return -1;
    }
}
Beispiel #7
0
static DECLCALLBACK(void) drvNicPowerOn(PPDMDRVINS pDrvIns)
{
	PDRVNIC pThis = PDMINS_2_DATA(pDrvIns, PDRVNIC);

	if (pThis && pThis->nic_client)
		pThis->nic_client->enable_signals();
}
static int usbProxyVrdpUrbQueue(PVUSBURB pUrb)
{
    LogFlow(("usbProxyVrdpUrbQueue: pUrb=%p\n", pUrb));

    /** @todo implement isochronous transfers for USB over VRDP. */
    if (pUrb->enmType == VUSBXFERTYPE_ISOC)
    {
        Log(("usbproxy: isochronous transfers aren't implemented yet.\n"));
        return false;
    }

    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
    PUSBPROXYDEVVRDP pDevVrdp = (PUSBPROXYDEVVRDP)pProxyDev->Backend.pv;

    int rc = pDevVrdp->pCallback->pfnQueueURB (pDevVrdp->pDevice, pUrb->enmType, pUrb->EndPt, pUrb->enmDir, pUrb->cbData,
                                               pUrb->abData, pUrb, (PREMOTEUSBQURB *)&pUrb->Dev.pvPrivate);

    if (rc == VERR_VUSB_DEVICE_NOT_ATTACHED)
    {
        Log(("usb-vrdp: remote device %p unplugged!!\n", pDevVrdp->pDevice));
        pProxyDev->fDetached = true;
    }

    return RT_SUCCESS(rc);
}
/**
 * Power off a TCP socket stream driver instance.
 *
 * This does most of the destruction work, to avoid ordering dependencies.
 *
 * @param   pDrvIns     The driver instance data.
 */
static DECLCALLBACK(void) drvTCPPowerOff(PPDMDRVINS pDrvIns)
{
    PDRVTCP pThis = PDMINS_2_DATA(pDrvIns, PDRVTCP);
    LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));

    drvTCPShutdownListener(pThis);
}
Beispiel #10
0
/**
 * Queue callback for processing a queued item.
 *
 * @returns Success indicator.
 *          If false the item will not be removed and the flushing will stop.
 * @param   pDrvIns         The driver instance.
 * @param   pItemCore       Pointer to the queue item to process.
 */
static DECLCALLBACK(bool) drvKbdQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
{
    PDRVKBDQUEUE        pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
    PDRVKBDQUEUEITEM    pItem = (PDRVKBDQUEUEITEM)pItemCore;
    int rc = pThis->pUpPort->pfnPutEventHid(pThis->pUpPort, pItem->u32UsageCode);
    return RT_SUCCESS(rc);
}
Beispiel #11
0
/**
 * Destruct a host parallel driver instance.
 *
 * Most VM resources are freed by the VM. This callback is provided so that
 * any non-VM resources can be freed correctly.
 *
 * @param   pDrvIns     The driver instance data.
 */
static DECLCALLBACK(void) drvHostParallelDestruct(PPDMDRVINS pDrvIns)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);

#ifndef VBOX_WITH_WIN_PARPORT_SUP

    int rc;

    if (pThis->hFileDevice != NIL_RTFILE)
        ioctl(RTFileToNative(pThis->hFileDevice), PPRELEASE);

    rc = RTPipeClose(pThis->hWakeupPipeW); AssertRC(rc);
    pThis->hWakeupPipeW = NIL_RTPIPE;

    rc = RTPipeClose(pThis->hWakeupPipeR); AssertRC(rc);
    pThis->hWakeupPipeR = NIL_RTPIPE;

    rc = RTFileClose(pThis->hFileDevice); AssertRC(rc); /** @todo r=bird: Why aren't this closed on Windows? */
    pThis->hFileDevice = NIL_RTFILE;

    if (pThis->pszDevicePath)
    {
        MMR3HeapFree(pThis->pszDevicePath);
        pThis->pszDevicePath = NULL;
    }
#endif /* VBOX_WITH_WIN_PARPORT_SUP */
}
Beispiel #12
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;
}
Beispiel #13
0
DECLINLINE(void) DumpPICState(PPICSTATE pPic, const char *pszFn)
{
    PDEVPIC pThis = PDMINS_2_DATA(pPic->CTX_SUFF(pDevIns), PDEVPIC);

    Log2(("%s: pic%d: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
          pszFn, (&pThis->aPics[0] == pPic) ? 0 : 1,
          pPic->elcr, pPic->last_irr, pPic->irr, pPic->imr, pPic->isr, pPic->irq_base));
}
Beispiel #14
0
/** @callback_method_impl{FNSSMDEVSAVEEXEC} */
static DECLCALLBACK(int) smcSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
    PDEVSMC pThis = PDMINS_2_DATA(pDevIns, PDEVSMC);

    /** @todo  */

    return VINF_SUCCESS;
}
/**
 * @interface_method_impl{PDMDRVREG,pfnPowerOn}
 */
static DECLCALLBACK(void) drvR3DedicatedNicPowerOn(PPDMDRVINS pDrvIns)
{
    LogFlow(("drvR3DedicatedNicPowerOn\n"));
    PDRVDEDICATEDNIC pThis = PDMINS_2_DATA(pDrvIns, PDRVDEDICATEDNIC);

    int rc = PDMDrvHlpCallR0(pDrvIns, DRVDEDICATEDNICR0OP_RESUME, 0);
    AssertRC(rc);
}
Beispiel #16
0
/**
 * @interface_method_impl(PDMDRVREG,pfnDestruct)
 */
DECLCALLBACK(void) Nvram::drvNvram_Destruct(PPDMDRVINS pDrvIns)
{
    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    LogFlowFunc(("iInstance/#%d\n", pDrvIns->iInstance));
    PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
    if (pThis->pNvram != NULL)
        pThis->pNvram->mpDrv = NULL;
}
Beispiel #17
0
static inline void DumpPICState(PicState *s, const char *szFn)
{
    PDEVPIC pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);

    Log2(("%s: pic%d: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
        szFn, (&pThis->aPics[0] == s) ? 0 : 1,
          s->elcr, s->last_irr, s->irr, s->imr, s->isr, s->irq_base));
}
Beispiel #18
0
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
DECLCALLBACK(void *) AudioSniffer::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVAUDIOSNIFFER pDrv = PDMINS_2_DATA(pDrvIns, PDRVAUDIOSNIFFER);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOSNIFFERCONNECTOR, &pDrv->Connector);
    return NULL;
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
static DECLCALLBACK(void *) drvTCPQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS      pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVTCP         pThis   = PDMINS_2_DATA(pDrvIns, PDRVTCP);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
    return NULL;
}
Beispiel #20
0
/**
 * @interface_method_impl{PDMDRVREG,pfnReset}
 */
DECLCALLBACK(void) PCIRawDev::drvDestruct(PPDMDRVINS pDrvIns)
{
    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    PDRVMAINPCIRAWDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINPCIRAWDEV);

    if (pThis->pPCIRawDev)
        pThis->pPCIRawDev->mpDrv = NULL;
}
/**
 * Read a MMIO register.
 *
 * @returns VBox status code suitable for scheduling.
 * @param   pDevIns     The device instance.
 * @param   pvUser      A user argument (ignored).
 * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
 * @param   pv          Where to put the data we read.
 * @param   cb          The size of the read.
 */
PDMBOTHCBDECL(int) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
{
    PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958);
    uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
    int       rc = VINF_SUCCESS;
    RT_NOREF(pThis, pvUser);

    if (offReg < OX958_REG_UART_REGION_OFFSET)
    {
        uint32_t *pu32 = (uint32_t *)pv;
        Assert(cb == 4);

        switch (offReg)
        {
            case OX958_REG_CC_REV_ID:
                *pu32 = 0x00070002;
                break;
            case OX958_REG_UART_CNT:
                *pu32 = pThis->cUarts;
                break;
            case OX958_REG_UART_IRQ_STS:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob);
                break;
            case OX958_REG_UART_IRQ_ENABLE:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqEnGlob);
                break;
            case OX958_REG_UART_IRQ_DISABLE:
                *pu32 = ~ASMAtomicReadU32(&pThis->u32RegIrqEnGlob);
                break;
            case OX958_REG_UART_WAKE_IRQ_ENABLE:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqEnWake);
                break;
            case OX958_REG_UART_WAKE_IRQ_DISABLE:
                *pu32 = ~ASMAtomicReadU32(&pThis->u32RegIrqEnWake);
                break;
            default:
                rc = VINF_IOM_MMIO_UNUSED_00;
        }
    }
    else
    {
        /* Figure out the UART accessed from the offset. */
        offReg -= OX958_REG_UART_REGION_OFFSET;
        uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
        uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
        if (iUart < pThis->cUarts)
        {
            POX958UART pUart = &pThis->aUarts[iUart];
            rc = ox958UartRegRead(pThis, pUart, offUartReg, pv, cb);
            if (rc == VINF_IOM_R3_IOPORT_READ)
                rc = VINF_IOM_R3_MMIO_READ;
        }
        else
            rc = VINF_IOM_MMIO_UNUSED_00;
    }

    return rc;
}
static void usbProxyVrdpUrbCancel(PVUSBURB pUrb)
{
    LogFlow(("usbProxyVrdpUrbCancel: pUrb=%p\n", pUrb));

    PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
    PUSBPROXYDEVVRDP pDevVrdp = (PUSBPROXYDEVVRDP)pProxyDev->Backend.pv;

    pDevVrdp->pCallback->pfnCancelURB (pDevVrdp->pDevice, (PREMOTEUSBQURB)pUrb->Dev.pvPrivate);
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
static DECLCALLBACK(void *) drvCharQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS  pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVCHAR    pThis = PDMINS_2_DATA(pDrvIns, PDRVCHAR);

    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMICHARCONNECTOR, &pThis->ICharConnector);
    return NULL;
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
static DECLCALLBACK(void *) drvHostParallelQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS          pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVHOSTPARALLEL    pThis   = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);

    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTPARALLELCONNECTOR, &pThis->CTX_SUFF(IHostParallelConnector));
    return NULL;
}
/**
 * R0 mode function to ready byte value from the parallel port
 * status register.
 * @returns VBox status code.
 * @param   pDrvIns    Driver instance.
 * @param   u64Arg     Not used.
 */
static int drvR0HostParallelReqReadStatus(PPDMDRVINS pDrvIns, uint64_t u64Arg)
{
    uint8_t u8Data;
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    u8Data = ASMInU8(pThis->u32LptAddrStatus);
    LogFlowFunc(("read from status port=%#x val=%#x\n", pThis->u32LptAddr, u8Data));
    pThis->u8ReadInStatus = u8Data;
    return VINF_SUCCESS;
}
/** @interface_method_impl{PDMDEVREG,pfnRelocate} */
static DECLCALLBACK(void) ox958R3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
{
    PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958);
    RT_NOREF(offDelta);

    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    for (uint32_t i = 0; i < pThis->cUarts; i++)
        uartR3Relocate(&pThis->aUarts[i].UartCore, offDelta);
}
/** @interface_method_impl{PDMDEVREG,pfnDetach} */
static DECLCALLBACK(void) ox958R3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
{
    PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958);
    AssertReturnVoid(iLUN >= pThis->cUarts);

    RT_NOREF(fFlags);

    return uartR3Detach(&pThis->aUarts[iLUN].UartCore);
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
static DECLCALLBACK(void *)  drvscsihostQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS   pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVSCSIHOST pThis   = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);

    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSICONNECTOR, &pThis->ISCSIConnector);
    return NULL;
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
static DECLCALLBACK(void *) drvHostALSAAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVHOSTALSAAUDIO  pThis   = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);

    return NULL;
}
/**
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
 */
DECLCALLBACK(void *) Keyboard::i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
    PPDMDRVINS          pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    PDRVMAINKEYBOARD    pDrv    = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);

    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDCONNECTOR, &pDrv->IConnector);
    return NULL;
}