DrvSCSIHost.cpp revision a9f41cb889f53e8407561a6155052c441eb0fc5f
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * VBox storage drivers: Host SCSI access driver.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * available from http://www.virtualbox.org. This file is free software;
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * additional information or have any questions.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync/*******************************************************************************
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync* Header Files *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync*******************************************************************************/
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync//#define DEBUG
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * SCSI driver instance data.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * @implements PDMISCSICONNECTOR
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsynctypedef struct DRVSCSIHOST
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** Pointer driver instance. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** Pointer to the SCSI port interface of the device above. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** The SCSI connector interface . */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** PAth to the device file. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** Handle to the device. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** The dedicated I/O thread. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /** Queue for passing the requests to the thread. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync/** Converts a pointer to DRVSCSIHOST::ISCSIConnecotr to a PDRVSCSIHOST. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync#define PDMISCSICONNECTOR_2_DRVSCSIHOST(pInterface) ( (PDRVSCSIHOST)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSIHOST, ISCSIConnector)) )
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * Dumps a SCSI request structure for debugging purposes.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * @returns nothing.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * @param pRequest Pointer to the request to dump.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsyncstatic void drvscsihostDumpScsiRequest(PPDMSCSIREQUEST pRequest)
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync Log(("Dump for pRequest=%#p Command: %s\n", pRequest, SCSICmdText(pRequest->pbCDB[0])));
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync Log(("cbScatterGather=%u\n", pRequest->cbScatterGather));
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync Log(("cScatterGatherEntries=%u\n", pRequest->cScatterGatherEntries));
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync /* Print all scatter gather entries. */
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync for (uint32_t i = 0; i < pRequest->cScatterGatherEntries; i++)
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync Log(("ScatterGatherEntry[%u].cbSeg=%u\n", i, pRequest->paScatterGatherHead[i].cbSeg));
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync Log(("ScatterGatherEntry[%u].pvSeg=%#p\n", i, pRequest->paScatterGatherHead[i].pvSeg));
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * Copy the content of a buffer to a scatter gather list
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * copying only the amount of data which fits into the
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * scatter gather list.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * @returns VBox status code.
5326ed3cdf88641d5299b2c70c2c0aa7e78e8acfvboxsync * @param pRequest Pointer to the request which contains the S/G list entries.
static int drvscsihostScatterGatherListCopyFromBuffer(PPDMSCSIREQUEST pRequest, void *pvBuf, size_t cbBuf)
unsigned cSGEntry = 0;
if (!cbBuf)
pSGEntry++;
cSGEntry++;
return VINF_SUCCESS;
switch (uCommand)
case SCSI_INQUIRY:
case SCSI_REPORT_LUNS:
case SCSI_MODE_SENSE_6:
case SCSI_READ_TOC_PMA_ATIP:
case SCSI_READ_CAPACITY:
case SCSI_MODE_SENSE_10:
case SCSI_GET_CONFIGURATION:
case SCSI_READ_10:
case SCSI_READ_12:
case SCSI_READ_BUFFER:
case SCSI_READ_DVD_STRUCTURE:
case SCSI_READ_SUBCHANNEL:
case SCSI_READ_CD:
case SCSI_READ_CD_MSF:
return PDMSCSIREQUESTTXDIR_FROM_DEVICE;
case SCSI_TEST_UNIT_READY:
case SCSI_START_STOP_UNIT:
return PDMSCSIREQUESTTXDIR_NONE;
case SCSI_WRITE_10:
case SCSI_WRITE_12:
case SCSI_WRITE_BUFFER:
return PDMSCSIREQUESTTXDIR_TO_DEVICE;
unsigned uTxDir;
#ifdef DEBUG
case SCSI_INQUIRY:
ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
#if defined(RT_OS_LINUX)
if (rc < 0)
return rc;
static int drvscsihostAsyncIOLoopWakeupFunc(void)
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;
rc = RTReqCall(pThis->pQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsihostAsyncIOLoopWakeupFunc, 0);
return rc;
static DECLCALLBACK(int) drvscsihostRequestSend(PPDMISCSICONNECTOR pInterface, PPDMSCSIREQUEST pSCSIRequest)
int rc;
rc = RTReqCallEx(pThis->pQueueRequests, &pReq, 0, RTREQFLAGS_NO_WAIT, (PFNRT)drvscsihostProcessRequestOne, 2, pThis, pSCSIRequest);
return VINF_SUCCESS;
return NULL;
AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE);
rc = RTFileOpen(&pThis->DeviceFile, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
return VINF_SUCCESS;
sizeof(DRVSCSIHOST),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,