DrvSCSIHost.cpp revision 8bed792bc65abd39393889351f22263ce6c289bf
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VBox storage drivers:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Host SCSI access driver.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2009 Sun Microsystems, Inc.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * additional information or have any questions.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync//#define DEBUG
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * SCSI driver instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef struct DRVSCSIHOST
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer driver instance. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Pointer to the SCSI port interface of the device above. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The scsi connector interface .*/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** PAth to the device file. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Handle to the device. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The dedicated I/O thread. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Queue for passing the requests to the thread. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Converts a pointer to DRVSCSIHOST::ISCSIConnecotr to a PDRVSCSIHOST. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#define PDMISCSICONNECTOR_2_DRVSCSIHOST(pInterface) ( (PDRVSCSIHOST)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSIHOST, ISCSIConnector)) )
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Dumps a SCSI request structure for debugging purposes.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns nothing.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pRequest Pointer to the request to dump.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void drvscsihostDumpScsiRequest(PPDMSCSIREQUEST pRequest)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("Dump for pRequest=%#p Command: %s\n", pRequest, SCSICmdText(pRequest->pbCDB[0])));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("cbScatterGather=%u\n", pRequest->cbScatterGather));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("cScatterGatherEntries=%u\n", pRequest->cScatterGatherEntries));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Print all scatter gather entries. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (uint32_t i = 0; i < pRequest->cScatterGatherEntries; i++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("ScatterGatherEntry[%u].cbSeg=%u\n", i, pRequest->paScatterGatherHead[i].cbSeg));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("ScatterGatherEntry[%u].pvSeg=%#p\n", i, pRequest->paScatterGatherHead[i].pvSeg));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copy the content of a buffer to a scatter gather list
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * copying only the amount of data which fits into the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * scatter gather list.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pRequest Pointer to the request which contains the S/G list entries.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pvBuf Pointer to the buffer which should be copied.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param cbBuf Size of the buffer.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int drvscsihostScatterGatherListCopyFromBuffer(PPDMSCSIREQUEST pRequest, void *pvBuf, size_t cbBuf)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync unsigned cSGEntry = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMDATASEG pSGEntry = &pRequest->paScatterGatherHead[cSGEntry];
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync size_t cbToCopy = (cbBuf < pSGEntry->cbSeg) ? cbBuf : pSGEntry->cbSeg;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* We finished. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Advance the buffer. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Go to the next entry in the list. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Set the sense and advanced sense key in the buffer for error conditions.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns nothing.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pRequest Pointer to the request which contains the sense buffer.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param uSCSISenseKey The sense key to set.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param uSCSIASC The advanced sense key to set.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(void) drvscsiCmdError(PPDMSCSIREQUEST pRequest, uint8_t uSCSISenseKey, uint8_t uSCSIASC)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pRequest->cbSenseBuffer >= 2, ("Sense buffer is not big enough\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pRequest->pbSenseBuffer, ("Sense buffer pointer is NULL\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Sets the sense key for a status good condition.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns nothing.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pRequest Pointer to the request which contains the sense buffer.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(void) drvscsihostCmdOk(PPDMSCSIREQUEST pRequest)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pRequest->cbSenseBuffer >= 2, ("Sense buffer is not big enough\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pRequest->pbSenseBuffer, ("Sense buffer pointer is NULL\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Returns the transfer direction of the given command
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * in case the device does not provide this info.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns transfer direction of the command.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * SCSIHOSTTXDIR_NONE if no data is transfered.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * SCSIHOSTTXDIR_FROM_DEVICE if the data is read from the device.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * SCSIHOSTTXDIR_TO_DEVICE if the data is written to the device.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param uCommand The command byte.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic unsigned drvscsihostGetTransferDirectionFromCommand(uint8_t uCommand)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Command not known %#x\n", uCommand));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* We should never get here in debug mode. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return PDMSCSIREQUESTTXDIR_NONE; /* to make compilers happy. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int drvscsihostProcessRequestOne(PDRVSCSIHOST pThis, PPDMSCSIREQUEST pRequest)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* We implement only one device. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync drvscsihostScatterGatherListCopyFromBuffer(pRequest, &ScsiInquiryReply, sizeof(SCSIINQUIRYDATA));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Command not implemented for attached device\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync drvscsiCmdError(pRequest, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_NONE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Setup SCSI request. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pRequest->uDataDirection == PDMSCSIREQUESTTXDIR_UNKNOWN)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uTxDir = drvscsihostGetTransferDirectionFromCommand(pRequest->pbCDB[0]);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (uTxDir == PDMSCSIREQUESTTXDIR_FROM_DEVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Invalid transfer direction %u\n", uTxDir));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ScsiIoReq.dxferp = pRequest->paScatterGatherHead[0].pvSeg;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ScsiIoReq.iovec_count = pRequest->cScatterGatherEntries;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync paSG = (sg_iovec_t *)RTMemAllocZ(pRequest->cScatterGatherEntries * sizeof(sg_iovec_t));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (unsigned i = 0; i < pRequest->cScatterGatherEntries; i++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync paSG[i].iov_base = pRequest->paScatterGatherHead[i].pvSeg;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync paSG[i].iov_len = pRequest->paScatterGatherHead[i].cbSeg;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Issue command. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Ioctl failed with rc=%d\n", rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Request processed successfully. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Notify device that request finished. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgRC(rc, ("Notifying device above failed rc=%Rrc\n", rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Request function to wakeup the thread.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VWRN_STATE_CHANGED.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The thread function which processes the requests asynchronously.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pDrvIns Pointer to the device instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pThread Pointer to the thread instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int drvscsihostAsyncIOLoop(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (pThread->enmState == PDMTHREADSTATE_RUNNING)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTReqProcess(pThis->pQueueRequests, RT_INDEFINITE_WAIT);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(rc == VWRN_STATE_CHANGED, ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n", rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int drvscsihostAsyncIOLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(pThis->pQueueRequests, ("pQueueRequests is NULL\n"), VERR_INVALID_STATE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTReqCall(pThis->pQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsihostAsyncIOLoopWakeupFunc, 0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgRC(rc, ("Inserting request into queue failed rc=%Rrc\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* -=-=-=-=- ISCSIConnector -=-=-=-=- */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @copydoc PDMISCSICONNECTOR::pfnSCSIRequestSend. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(int) drvscsihostRequestSend(PPDMISCSICONNECTOR pInterface, PPDMSCSIREQUEST pSCSIRequest)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMISCSICONNECTOR_2_DRVSCSIHOST(pInterface);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(pThis->pQueueRequests, ("pQueueRequests is NULL\n"), VERR_INVALID_STATE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTReqCallEx(pThis->pQueueRequests, &pReq, 0, RTREQFLAGS_NO_WAIT, (PFNRT)drvscsihostProcessRequestOne, 2, pThis, pSCSIRequest);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(RT_SUCCESS(rc), ("Inserting request into queue failed rc=%Rrc\n", rc), rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* -=-=-=-=- IBase -=-=-=-=- */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @copydoc PDMIBASE::pfnQueryInterface. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(void *) drvscsihostQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Destruct a driver instance.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * resources can be freed correctly.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pDrvIns The driver instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(void) drvscsihostDestruct(PPDMDRVINS pDrvIns)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgRC(rc, ("Failed to destroy queue rc=%Rrc\n", rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Construct a block driver instance.
cba6719bd64ec749967bbe931230452664109857vboxsync * @copydoc FNPDMDRVCONSTRUCT
cba6719bd64ec749967bbe931230452664109857vboxsyncstatic DECLCALLBACK(int) drvscsihostConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDRVSCSIHOST pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSIHOST);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pDrvIns=%#p pCfgHandle=%#p\n", pDrvIns, pCfgHandle));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Read the configuration.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!CFGMR3AreValuesValid(pCfgHandle, "DevicePath\0"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
5530d99d77afedf5676a976e5135c89478b4e8d0vboxsync N_("Invalid configuration for host scsi access driver"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Initialize interfaces.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pDrvIns->IBase.pfnQueryInterface = drvscsihostQueryInterface;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pThis->ISCSIConnector.pfnSCSIRequestSend = drvscsihostRequestSend;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Query the SCSI port interface above. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pThis->pDevScsiPort = (PPDMISCSIPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_SCSI_PORT);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Create request queue. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n"), rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Open the device. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = CFGMR3QueryStringAlloc(pCfgHandle, "DevicePath", &pThis->pszDevicePath);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync N_("Configuration error: Failed to get the \"DevicePath\" value"));
8bed792bc65abd39393889351f22263ce6c289bfvboxsync rc = RTFileOpen(&pThis->DeviceFile, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync N_("DrvSCSIHost#%d: Failed to open device '%s'"), pDrvIns->iInstance, pThis->pszDevicePath);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Create I/O thread. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsihostAsyncIOLoop,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync drvscsihostAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * SCSI driver registration record.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* u32Version */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* szDriverName */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "SCSIHost",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pszDescription */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "Host SCSI driver.",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* fFlags */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* fClass. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* cMaxInstances */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* cbInstance */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnConstruct */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnDestruct */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnIOCtl */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnPowerOn */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnReset */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnSuspend */
be284093a5d9a46ac136e8d272fda9201eb8d048vboxsync /* pfnResume */
cba6719bd64ec749967bbe931230452664109857vboxsync /* pfnAttach */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* pfnDetach */
cba6719bd64ec749967bbe931230452664109857vboxsync /* pfnPowerOff */
cba6719bd64ec749967bbe931230452664109857vboxsync /* pfnSoftReset */
cba6719bd64ec749967bbe931230452664109857vboxsync /* u32EndVersion */