VBoxSCSI.cpp revision 43747b1f0bc8302a238fb35e55857a5e9aa1933d
/* $Id$ */
/** @file
*
* VBox storage devices:
* Simple SCSI interface for BIOS access
*/
/*
* Copyright (C) 2006-2009 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
//#define DEBUG
#endif
#include "VBoxSCSI.h"
{
pVBoxSCSI->regIdentify = 0;
}
/**
* Initializes the state for the SCSI interface.
*
* @returns VBox status code.
* @param pVBoxSCSI Pointer to the unitialized SCSI state.
*/
{
return VINF_SUCCESS;
}
/**
* Reads a register value.
*
* @returns VBox status code.
* @param pVBoxSCSI Pointer to the SCSI state.
* @param iRegister Index of the register to read.
* @param pu32Value Where to store the content of the register.
*/
{
switch (iRegister)
{
case 0:
{
{
uVal |= VBOX_SCSI_BUSY;
/* There is an I/O operation in progress.
* Yield the execution thread to let the I/O thread make progress.
*/
}
else
uVal &= ~VBOX_SCSI_BUSY;
break;
}
case 1:
{
{
{
/** The guest read the last byte from the data in buffer.
* Clear everything and reset command buffer.
*/
pVBoxSCSI->uTargetDevice = 0;
}
}
break;
}
case 2:
{
break;
}
default:
}
return VINF_SUCCESS;
}
/**
* Writes to a register.
*
* @returns VBox status code.
* VERR_MORE_DATA if a command is ready to be sent to the SCSI driver.
* @param pVBoxSCSI Pointer to the SCSI state.
* @param iRegister Index of the register to write to.
* @param uVal Value to write.
*/
{
int rc = VINF_SUCCESS;
switch (iRegister)
{
case 0:
{
{
}
{
else
{
}
}
{
if (uVal > VBOXSCSI_CDB_SIZE_MAX)
else
{
}
}
{
}
{
}
{
/* Check if we have all necessary command data. */
{
{
/* This is a write allocate buffer. */
return VERR_NO_MEMORY;
}
else
{
/* This is a read from the device. */
}
}
}
else
break;
}
case 1:
{
{
/* Reset the state */
}
else
{
{
rc = VERR_MORE_DATA;
}
}
break;
}
case 2:
{
break;
}
case 3:
{
/* Reset */
break;
}
default:
}
return rc;
}
/**
* Sets up a SCSI request which the owning SCSI device can process.
*
* @returns VBox status code.
* @param pVBoxSCSI Pointer to the SCSI state.
* @param pScsiRequest Pointer to a scsi request to setup.
* @param puTargetDevice Where to store the target device ID.
*/
int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice)
{
int rc = VINF_SUCCESS;
LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p puTargetDevice=%#p\n", pVBoxSCSI, pScsiRequest, puTargetDevice));
AssertMsg(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, ("Invalid state %u\n", pVBoxSCSI->enmState));
{
return VERR_NO_MEMORY;
}
/* Allocate scatter gather element. */
pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
if (!pScsiRequest->paScatterGatherHead)
{
return VERR_NO_MEMORY;
}
/* Allocate sense buffer. */
pScsiRequest->uLogicalUnit = 0;
return rc;
}
/**
* Notifies the device that a request finished and the incoming data
* is ready at the incoming data port.
*/
{
{
pVBoxSCSI->uTargetDevice = 0;
}
return VINF_SUCCESS;
}
{
LogFlowFunc(("pDevIns=%#p pVBoxSCSI=%#p iRegister=%d cTransfer=%u cb=%u\n",
/* Read string only valid for data in register. */
int rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, pVBoxSCSI->pBuf, cbTransfer);
*pcTransfer = 0;
pVBoxSCSI->uTargetDevice = 0;
return rc;
}
{
*pcTransfer = 0;
return VERR_MORE_DATA;
}
{
{
}
}