DrvSCSI.cpp revision d5ea45cc92d7f1d3ade8189944531f665bfe8ed5
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * VBox storage drivers: Generic SCSI command parser and execution driver
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * available from http://www.virtualbox.org. This file is free software;
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * General Public License (GPL) as published by the Free Software
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * additional information or have any questions.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync/*******************************************************************************
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync* Header Files *
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync*******************************************************************************/
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync//#define DEBUG
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync * SCSI driver instance data.
18673eee0624b4581d3d56ab9ad9d10ebc7f5bddvboxsync * @implements PDMISCSICONNECTOR
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * @implements PDMIBLOCKASYNCPORT
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * @implements PDMIMOUNTNOTIFY
7bff28e0cedd8656acd24b420759649184d8cf00vboxsynctypedef struct DRVSCSI
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** Pointer driver instance. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** Pointer to the attached driver's base interface. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Pointer to the attached driver's block interface. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** Pointer to the attached driver's async block interface. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Pointer to the attached driver's block bios interface. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** Pointer to the attached driver's mount interface. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Pointer to the SCSI port interface of the device above. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** pointer to the Led port interface of the dveice above. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** The scsi connector interface .*/
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** The block port interface. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync /** The optional block async port interface. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync#if 0 /* these interfaces aren't implemented */
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync /** The mount notify interface. */
97674677e4f2aeae576c39f966568dd664ba7979vboxsync /** Fallback status LED state for this drive.
97674677e4f2aeae576c39f966568dd664ba7979vboxsync * This is used in case the device doesn't has a LED interface. */
eecfcc5748685e35d0d4d835fb30d5494ad62734vboxsync /** Pointer to the status LED for this drive. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** VSCSI device handle. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** VSCSI LUN handle. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** I/O callbacks. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** The dedicated I/O thread for the non async approach. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Queue for passing the requests to the thread. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Request that we've left pending on wakeup or reset. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by
907ba2c9b3d1821f95be17115ecad9fe8a2cae02vboxsync * any of the dummy functions. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync bool volatile fDummySignal;
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Release statistics: number of bytes written. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Release statistics: number of bytes read. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync /** Release statistics: Current I/O depth. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync/** Converts a pointer to DRVSCSI::ISCSIConnector to a PDRVSCSI. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync#define PDMISCSICONNECTOR_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, ISCSIConnector)) )
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync/** Converts a pointer to DRVSCSI::IPortAsync to a PDRVSCSI. */
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync#define PDMIBLOCKASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) )
771761cda2c81e899526a0dce22c8cd2510fff82vboxsyncstatic int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq)
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync unsigned cSeg = 0;
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg,
f6cc81e94c29cc9b39b896cf32ecfe0501b4a1e5vboxsync size_t cbProcess = (cbTransfer < paSeg->cbSeg) ? cbTransfer : paSeg->cbSeg;
9a1578b66f9e563cf99c75ffa881db476f477e3avboxsync Log(("%s: uOffset=%llu cbProcess=%u\n", __FUNCTION__, uOffset, cbProcess));
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync rc = pThis->pDrvBlock->pfnRead(pThis->pDrvBlock, uOffset,
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync AssertMsgFailed(("%s: Failed to read data %Rrc\n", __FUNCTION__, rc));
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess);
59816992ec770eb9c03fbc1233ae62114a026badvboxsync pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
9a1578b66f9e563cf99c75ffa881db476f477e3avboxsync rc = pThis->pDrvBlock->pfnWrite(pThis->pDrvBlock, uOffset,
72f66530e1bf87aa6894a5f55f1b4d36caa5761fvboxsync AssertMsgFailed(("%s: Failed to write data %Rrc\n", __FUNCTION__, rc));
97674677e4f2aeae576c39f966568dd664ba7979vboxsync STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess);
paSeg++;
cSeg--;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
void *pvScsiLunUser,
switch (enmTxDir)
case VSCSIIOREQTXDIR_FLUSH:
case VSCSIIOREQTXDIR_READ:
case VSCSIIOREQTXDIR_WRITE:
unsigned cSeg = 0;
return rc;
rcReq);
return VINF_SUCCESS;
return VWRN_STATE_CHANGED;
return VINF_SUCCESS;
AssertMsg(rc == VWRN_STATE_CHANGED, ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n", rc));
return VINF_SUCCESS;
int rc;
LogRel(("drvscsiAsyncIOLoopWakeup#%u: previous dummy request is still pending\n", pDrvIns->iInstance));
return VERR_TIMEOUT;
rc = RTReqCall(pThis->pQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);
return rc;
static DECLCALLBACK(int) drvscsiRequestSend(PPDMISCSICONNECTOR pInterface, PPDMSCSIREQUEST pSCSIRequest)
int rc;
return rc;
return rc;
return NULL;
static void drvscsiR3ResetOrSuspendOrPowerOff(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
int rc = RTReqCall(pThis->pQueueRequests, &pReq, 0 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 1, pThis);
return VERR_PDM_MISSING_INTERFACE;
return VERR_PDM_MISSING_INTERFACE;
AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE);
enmType);
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,