DrvSCSI.cpp revision 29914189ae23645ef08a2f8477f28fd6f440a936
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * VBox storage drivers: Generic SCSI command parser and execution driver
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * available from http://www.virtualbox.org. This file is free software;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * General Public License (GPL) as published by the Free Software
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/*******************************************************************************
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync* Header Files *
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync*******************************************************************************/
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync//#define DEBUG
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/** The maximum number of release log entries per device. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * SCSI driver instance data.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @implements PDMISCSICONNECTOR
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @implements PDMIBLOCKASYNCPORT
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @implements PDMIMOUNTNOTIFY
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsynctypedef struct DRVSCSI
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Pointer driver instance. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the attached driver's base interface. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the attached driver's block interface. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the attached driver's async block interface. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the attached driver's block bios interface. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the attached driver's mount interface. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** Pointer to the SCSI port interface of the device above. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** pointer to the Led port interface of the dveice above. */
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync /** The scsi connector interface .*/
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** The block port interface. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** The optional block async port interface. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** The mount notify interface. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Fallback status LED state for this drive.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * This is used in case the device doesn't has a LED interface. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Pointer to the status LED for this drive. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** VSCSI device handle. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** VSCSI LUN handle. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** I/O callbacks. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** The dedicated I/O thread for the non async approach. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Queue for passing the requests to the thread. */
09e11be404479b989812ad9da85a16f3654ab320vboxsync /** Request that we've left pending on wakeup or reset. */
09e11be404479b989812ad9da85a16f3654ab320vboxsync /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by
09e11be404479b989812ad9da85a16f3654ab320vboxsync * any of the dummy functions. */
09e11be404479b989812ad9da85a16f3654ab320vboxsync bool volatile fDummySignal;
09e11be404479b989812ad9da85a16f3654ab320vboxsync /** Release statistics: number of bytes written. */
09e11be404479b989812ad9da85a16f3654ab320vboxsync /** Release statistics: number of bytes read. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Release statistics: Current I/O depth. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Errors printed in the release log. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /** Medium is readonly */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/** Converts a pointer to DRVSCSI::ISCSIConnector to a PDRVSCSI. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync#define PDMISCSICONNECTOR_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, ISCSIConnector)) )
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/** Converts a pointer to DRVSCSI::IPortAsync to a PDRVSCSI. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync#define PDMIBLOCKASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) )
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/** Converts a pointer to DRVSCSI::IMountNotify to PDRVSCSI. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync#define PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IMountNotify)) )
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync/** Converts a pointer to DRVSCSI::IPort to a PDRVSCSI. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync#define PDMIBLOCKPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPort)) )
704377ab2f9056b54fb01a500448f54b38bb3001vboxsync return true;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync return false;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync unsigned cSeg = 0;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync size_t cbProcess = (cbTransfer < paSeg->cbSeg) ? cbTransfer : paSeg->cbSeg;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync Log(("%s: uOffset=%llu cbProcess=%u\n", __FUNCTION__, uOffset, cbProcess));
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync rc = pThis->pDrvBlock->pfnRead(pThis->pDrvBlock, uOffset,
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = pThis->pDrvBlock->pfnWrite(pThis->pDrvBlock, uOffset,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync /* Go to the next entry. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, paRanges, cRanges);
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync AssertMsgFailed(("Invalid transfer direction %d\n", enmTxDir));
4bfa7b58e362a1bca0628643c352c137900bf01avboxsync VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync *pcbSize = pThis->pDrvBlock->pfnGetSize(pThis->pDrvBlock);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic DECLCALLBACK(int) drvscsiSetLock(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic int drvscsiTransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rc)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync PDRVSCSI pThis = PDMIBLOCKASYNCPORT_2_DRVSCSI(pInterface);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync VSCSIIOREQTXDIR enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync LogFlowFunc(("Request hVScsiIoReq=%#p completed\n", hVScsiIoReq));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync unsigned cSeg = 0;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
09e11be404479b989812ad9da85a16f3654ab320vboxsync VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun,
09e11be404479b989812ad9da85a16f3654ab320vboxsync /* async I/O path. */
09e11be404479b989812ad9da85a16f3654ab320vboxsync LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = pThis->pDrvBlockAsync->pfnStartFlush(pThis->pDrvBlockAsync, hVScsiIoReq);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = pThis->pDrvBlockAsync->pfnStartDiscard(pThis->pDrvBlockAsync, paRanges, cRanges, hVScsiIoReq);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync unsigned cSeg = 0;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer,
5a7561300d631625bc381bcc85dd2087f34d0bf9vboxsync pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = pThis->pDrvBlockAsync->pfnStartRead(pThis->pDrvBlockAsync, uOffset,
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer);
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync rc = pThis->pDrvBlockAsync->pfnStartWrite(pThis->pDrvBlockAsync, uOffset,
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer);
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc));
c7ff622115966b69b482bd2896662e40d823b22fvboxsync /* I/O thread. */
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync rc = RTReqQueueCallEx(pThis->hQueueRequests, NULL, 0, RTREQFLAGS_NO_WAIT,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync (PFNRT)drvscsiProcessRequestOne, 2, pThis, hVScsiIoReq);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic void drvscsiVScsiReqCompleted(VSCSIDEVICE hVScsiDevice, void *pVScsiDeviceUser,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, (PPDMSCSIREQUEST)pVScsiReqUser,
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync if (RT_UNLIKELY(pThis->fDummySignal) && !pThis->StatIoDepth)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * Dummy request function used by drvscsiReset to wait for all pending requests
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * to complete prior to the device reset.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @param pThis Pointer to the instance data.
64babf0f32eaf36212d54af4a3ce5fe193b24825vboxsync * @returns VINF_SUCCESS.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic int drvscsiAsyncIOLoopSyncCallback(PDRVSCSI pThis)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * Request function to wakeup the thread.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @param pThis Pointer to the instance data.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @returns VWRN_STATE_CHANGED.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsyncstatic int drvscsiAsyncIOLoopWakeupFunc(PDRVSCSI pThis)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * The thread function which processes the requests asynchronously.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @returns VBox status code.
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync * @param pDrvIns Pointer to the driver instance data.
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync * @param pThread Pointer to the thread instance data.
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsyncstatic int drvscsiAsyncIOLoop(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync while (pThread->enmState == PDMTHREADSTATE_RUNNING)
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync rc = RTReqQueueProcess(pThis->hQueueRequests, RT_INDEFINITE_WAIT);
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync AssertMsg(rc == VWRN_STATE_CHANGED, ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n", rc));
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync * Deals with any pending dummy request
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync * @returns true if no pending dummy request, false if still pending.
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync * @param pThis The instance data.
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync * @param cMillies The number of milliseconds to wait for any
21a96ae495634bdc8bbcc6ed7d8d727a1b9430f5vboxsync * pending request to finish.
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsyncstatic bool drvscsiAsyncIOLoopNoPendingDummy(PDRVSCSI pThis, uint32_t cMillies)
66b15150e35f27f9499bb0a8399e452d6a04895dvboxsync return true;
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync int rc = RTReqWait(pThis->pPendingDummyReq, cMillies);
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync return false;
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync return true;
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsyncstatic int drvscsiAsyncIOLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync AssertMsgReturn(pThis->hQueueRequests != NIL_RTREQQUEUE, ("hQueueRequests is NULL\n"), VERR_INVALID_STATE);
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 10000 /* 10 sec */))
db2893e30b129fbadd201b8f56cd7bc1974b395dvboxsync LogRel(("drvscsiAsyncIOLoopWakeup#%u: previous dummy request is still pending\n", pDrvIns->iInstance));
rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);
return rc;
#ifdef DEBUG
static DECLCALLBACK(int) drvscsiRequestSend(PPDMISCSICONNECTOR pInterface, PPDMSCSIREQUEST pSCSIRequest)
int rc;
#ifdef DEBUG
return rc;
return rc;
return NULL;
static DECLCALLBACK(int) drvscsiQueryDeviceLocation(PPDMIBLOCKPORT pInterface, const char **ppcszController,
static void drvscsiR3ResetOrSuspendOrPowerOff(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
int rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 0 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 1, pThis);
AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE);
return VERR_PDM_MISSING_INTERFACE;
return VERR_PDM_MISSING_INTERFACE;
switch (enmType)
case PDMBLOCKTYPE_HARD_DISK:
case PDMBLOCKTYPE_CDROM:
case PDMBLOCKTYPE_DVD:
enmType);
return VERR_INTERNAL_ERROR;
pThis);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
PDMDrvHlpSTAMRegisterF(pDrvIns, (void *)&pThis->StatIoDepth, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
return VINF_SUCCESS;
sizeof(DRVSCSI),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,