VBoxSCSI.cpp revision b7a04f3d42ada4fd6106ef61c28f7ef0a64af878
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* $Id$ */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @file
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VBox storage devices:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Simple SCSI interface for BIOS access
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2009 Oracle Corporation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
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 */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync//#define DEBUG
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#define LOG_GROUP LOG_GROUP_DEV_BUSLOGIC /* @todo: Create extra group. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#if defined(IN_R0) || defined(IN_RC)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync# error This device has no R0 or GC components
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmdev.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pgm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/asm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/mem.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/thread.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/string.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include "VBoxSCSI.h"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
060711075893fd64c1eaaefe41f318d83011e4e3vboxsyncstatic void vboxscsiReset(PVBOXSCSI pVBoxSCSI)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->regIdentify = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->cbCDB = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->iCDB = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->fBusy = false;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->rcCompletion = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->uTargetDevice = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->cbBuf = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->iBuf = 0;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync if (pVBoxSCSI->pBuf)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync RTMemFree(pVBoxSCSI->pBuf);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->pBuf = NULL;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync}
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync/**
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * Initializes the state for the SCSI interface.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync *
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @returns VBox status code.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @param pVBoxSCSI Pointer to the unitialized SCSI state.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync */
060711075893fd64c1eaaefe41f318d83011e4e3vboxsyncint vboxscsiInitialize(PVBOXSCSI pVBoxSCSI)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync{
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync pVBoxSCSI->pBuf = NULL;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync vboxscsiReset(pVBoxSCSI);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Reads a register value.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVBoxSCSI Pointer to the SCSI state.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param iRegister Index of the register to read.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pu32Value Where to store the content of the register.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint8_t uVal = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync switch (iRegister)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 0:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (ASMAtomicReadBool(&pVBoxSCSI->fBusy) == true)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uVal |= VBOX_SCSI_BUSY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* There is an I/O operation in progress.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Yield the execution thread to let the I/O thread make progress.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTThreadYield();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync if (pVBoxSCSI->rcCompletion)
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync uVal |= VBOX_SCSI_ERROR;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 1:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync /* If we're not in the 'command ready' state, there may not even be a buffer yet. */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync if ((pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY) && pVBoxSCSI->cbBuf > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pVBoxSCSI->pBuf, ("pBuf is NULL\n"));
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync Assert(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY);
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync Assert(!pVBoxSCSI->fBusy);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uVal = pVBoxSCSI->pBuf[pVBoxSCSI->iBuf];
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iBuf++;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->cbBuf--;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->cbBuf == 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The guest read the last byte from the data in buffer.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Clear everything and reset command buffer.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pVBoxSCSI->pBuf);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->pBuf = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->cbCDB = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iCDB = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iBuf = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->rcCompletion = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->uTargetDevice = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 2:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uVal = pVBoxSCSI->regIdentify;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync case 3:
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync {
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync uVal = pVBoxSCSI->rcCompletion;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync break;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync default:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Invalid register to read from %u\n", iRegister));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pu32Value = uVal;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Writes to a register.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VERR_MORE_DATA if a command is ready to be sent to the SCSI driver.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVBoxSCSI Pointer to the SCSI state.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param iRegister Index of the register to write to.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param uVal Value to write.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync switch (iRegister)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 0:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->enmState == VBOXSCSISTATE_NO_COMMAND)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_READ_TXDIR;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->uTargetDevice = uVal;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_TXDIR)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync if (uVal != VBOXSCSI_TXDIR_FROM_DEVICE && uVal != VBOXSCSI_TXDIR_TO_DEVICE)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync vboxscsiReset(pVBoxSCSI);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync else
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_READ_CDB_SIZE_BUFHI;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync pVBoxSCSI->uTxDir = uVal;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_CDB_SIZE_BUFHI)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync uint8_t cbCDB = uVal & 0x0F;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync if (cbCDB > VBOXSCSI_CDB_SIZE_MAX)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync vboxscsiReset(pVBoxSCSI);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync else
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_READ_BUFFER_SIZE_LSB;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbCDB = cbCDB;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbBuf = (uVal & 0xF0) << 12; /* Bits 16-19 of buffer size. */
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_BUFFER_SIZE_LSB)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_READ_BUFFER_SIZE_MID;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbBuf |= uVal; /* Bits 0-7 of buffer size. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_BUFFER_SIZE_MID)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_READ_COMMAND;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbBuf |= (((uint16_t)uVal) << 8); /* Bits 8-15 of buffer size. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_COMMAND)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->aCDB[pVBoxSCSI->iCDB] = uVal;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iCDB++;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /* Check if we have all necessary command data. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->iCDB == pVBoxSCSI->cbCDB)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("%s: Command ready for processing\n", __FUNCTION__));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_COMMAND_READY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* This is a write allocate buffer. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->pBuf = (uint8_t *)RTMemAllocZ(pVBoxSCSI->cbBuf);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pVBoxSCSI->pBuf)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_NO_MEMORY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* This is a read from the device. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ASMAtomicXchgBool(&pVBoxSCSI->fBusy, true);
8b90eb0585fa16024709ca374c69f1eb5d5a5a7cvboxsync rc = VERR_MORE_DATA; /** @todo Better return value to indicate ready command? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Invalid state %d\n", pVBoxSCSI->enmState));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 1:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync if ( pVBoxSCSI->enmState != VBOXSCSISTATE_COMMAND_READY
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync || pVBoxSCSI->uTxDir != VBOXSCSI_TXDIR_TO_DEVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync /* Reset the state */
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync vboxscsiReset(pVBoxSCSI);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync }
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync else
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync pVBoxSCSI->pBuf[pVBoxSCSI->iBuf++] = uVal;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync if (pVBoxSCSI->iBuf == pVBoxSCSI->cbBuf)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync rc = VERR_MORE_DATA;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync ASMAtomicXchgBool(&pVBoxSCSI->fBusy, true);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case 2:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->regIdentify = uVal;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync case 3:
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync {
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync /* Reset */
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync vboxscsiReset(pVBoxSCSI);
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync break;
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync default:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("Invalid register to write to %u\n", iRegister));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Sets up a SCSI request which the owning SCSI device can process.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVBoxSCSI Pointer to the SCSI state.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pScsiRequest Pointer to a scsi request to setup.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param puTargetDevice Where to store the target device ID.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p puTargetDevice=%#p\n", pVBoxSCSI, pScsiRequest, puTargetDevice));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, ("Invalid state %u\n", pVBoxSCSI->enmState));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync /* Clear any errors from a previous request. */
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->rcCompletion = 0;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync if (pVBoxSCSI->pBuf)
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync RTMemFree(pVBoxSCSI->pBuf);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->pBuf = (uint8_t *)RTMemAllocZ(pVBoxSCSI->cbBuf);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pVBoxSCSI->pBuf)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_NO_MEMORY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync /* Allocate scatter gather element. */
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pScsiRequest->paScatterGatherHead)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pVBoxSCSI->pBuf);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->pBuf = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_NO_MEMORY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync /* Allocate sense buffer. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->cbSenseBuffer = 18;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->cbCDB = pVBoxSCSI->cbCDB;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->pbCDB = pVBoxSCSI->aCDB;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->uLogicalUnit = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->cbScatterGather = pVBoxSCSI->cbBuf;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->cScatterGatherEntries = 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->paScatterGatherHead[0].cbSeg = pVBoxSCSI->cbBuf;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pScsiRequest->paScatterGatherHead[0].pvSeg = pVBoxSCSI->pBuf;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *puTargetDevice = pVBoxSCSI->uTargetDevice;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Notifies the device that a request finished and the incoming data
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * is ready at the incoming data port.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsyncint vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p\n", pVBoxSCSI, pScsiRequest));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pScsiRequest->paScatterGatherHead);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pScsiRequest->pbSenseBuffer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pVBoxSCSI->pBuf)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pVBoxSCSI->pBuf);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->pBuf = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->cbBuf = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->cbCDB = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iCDB = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->iBuf = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->uTargetDevice = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync pVBoxSCSI->rcCompletion = rcCompletion;
b7a04f3d42ada4fd6106ef61c28f7ef0a64af878vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ASMAtomicXchgBool(&pVBoxSCSI->fBusy, false);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxscsiReadString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTGCPTR GCDst = *pGCPtrDst;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t cbTransfer = *pcTransfer * cb;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlowFunc(("pDevIns=%#p pVBoxSCSI=%#p iRegister=%d cTransfer=%u cb=%u\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pDevIns, pVBoxSCSI, iRegister, *pcTransfer, cb));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Read string only valid for data in register. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsg(iRegister == 1, ("Hey only register 1 can be read from with string\n"));
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync /* Accesses without a valid buffer will be ignored. */
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync if (!pVBoxSCSI->pBuf)
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync /* Also ignore attempts to read more data than is available. */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync Assert(cbTransfer <= pVBoxSCSI->cbBuf);
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync if (cbTransfer > pVBoxSCSI->cbBuf)
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync cbTransfer = pVBoxSCSI->cbBuf; /* Ignore excess data (not supposed to happen). */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync int rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, pVBoxSCSI->pBuf + pVBoxSCSI->iBuf, cbTransfer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pcTransfer = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync /* Advance current buffer position. */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->iBuf += cbTransfer;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbBuf -= cbTransfer;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync if (pVBoxSCSI->cbBuf == 0)
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync {
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync /** The guest read the last byte from the data in buffer.
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync * Clear everything and reset command buffer.
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync RTMemFree(pVBoxSCSI->pBuf);
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->pBuf = NULL;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbCDB = 0;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->iCDB = 0;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->iBuf = 0;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->uTargetDevice = 0;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
8b90eb0585fa16024709ca374c69f1eb5d5a5a7cvboxsync RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTGCPTR GCSrc = *pGCPtrSrc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t cbTransfer = *pcTransfer * cb;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
a898eb6a3ace2594099a60b478ae5cc164bfe3dcvboxsync /* Write string only valid for data in/out register. */
a898eb6a3ace2594099a60b478ae5cc164bfe3dcvboxsync AssertMsg(iRegister == 1, ("Hey only register 1 can be written to with string\n"));
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync /* Accesses without a valid buffer will be ignored. */
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync if (!pVBoxSCSI->pBuf)
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync return VINF_SUCCESS;
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync Assert(cbTransfer <= pVBoxSCSI->cbBuf);
a898eb6a3ace2594099a60b478ae5cc164bfe3dcvboxsync if (cbTransfer > pVBoxSCSI->cbBuf)
a898eb6a3ace2594099a60b478ae5cc164bfe3dcvboxsync cbTransfer = pVBoxSCSI->cbBuf; /* Ignore excess data (not supposed to happen). */
8b90eb0585fa16024709ca374c69f1eb5d5a5a7cvboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync int rc = PDMDevHlpPhysReadGCVirt(pDevIns, pVBoxSCSI->pBuf + pVBoxSCSI->iBuf, GCSrc, cbTransfer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRC(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync /* Advance current buffer position. */
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->iBuf += cbTransfer;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync pVBoxSCSI->cbBuf -= cbTransfer;
370a24407d54e42d100a4b9d314a805ed82d0840vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pcTransfer = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
6b539f36e5988ef31d4a7341eeb40efe12585388vboxsync ASMAtomicXchgBool(&pVBoxSCSI->fBusy, true);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_MORE_DATA;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsyncvoid vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest)
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync{
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n"));
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync RTMemFree(pScsiRequest->paScatterGatherHead);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync RTMemFree(pScsiRequest->pbSenseBuffer);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync {
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync AssertPtr(pVBoxSCSI->pBuf);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync }
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync}