summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp')
-rw-r--r--src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp65
1 files changed, 56 insertions, 9 deletions
diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
index 81b8ce25..d5a3e68f 100644
--- a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
+++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -32,7 +32,7 @@
#include "VSCSIInternal.h"
/** Maximum of amount of LBAs to unmap with one command. */
-#define VSCSI_UNMAP_LBAS_MAX ((10*_1M) / 512)
+#define VSCSI_UNMAP_LBAS_MAX(a_cbSector) ((10*_1M) / a_cbSector)
/**
* SBC LUN instance
@@ -41,6 +41,8 @@ typedef struct VSCSILUNSBC
{
/** Core LUN structure */
VSCSILUNINT Core;
+ /** Sector size of the medium. */
+ uint32_t cbSector;
/** Size of the virtual disk. */
uint64_t cSectors;
/** VPD page pool. */
@@ -56,9 +58,13 @@ static int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
int rc = VINF_SUCCESS;
int cVpdPages = 0;
- rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
+ rc = vscsiLunMediumGetSectorSize(pVScsiLun, &pVScsiLunSbc->cbSector);
if (RT_SUCCESS(rc))
- pVScsiLunSbc->cSectors = cbDisk / 512; /* Fixed sector size */
+ {
+ rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
+ if (RT_SUCCESS(rc))
+ pVScsiLunSbc->cSectors = cbDisk / pVScsiLunSbc->cbSector;
+ }
if (RT_SUCCESS(rc))
rc = vscsiVpdPagePoolInit(&pVScsiLunSbc->VpdPagePool);
@@ -99,7 +105,7 @@ static int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
pBlkPage->u32MaxTrfLength = 0;
pBlkPage->u32OptTrfLength = 0;
pBlkPage->u32MaxPreXdTrfLength = 0;
- pBlkPage->u32MaxUnmapLbaCount = RT_H2BE_U32(VSCSI_UNMAP_LBAS_MAX);
+ pBlkPage->u32MaxUnmapLbaCount = RT_H2BE_U32(VSCSI_UNMAP_LBAS_MAX(pVScsiLunSbc->cbSector));
pBlkPage->u32MaxUnmapBlkDescCount = UINT32_C(0xffffffff);
pBlkPage->u32OptUnmapGranularity = 0;
pBlkPage->u32UnmapGranularityAlignment = 0;
@@ -167,6 +173,9 @@ static int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
}
}
+ /* For SBC LUNs, there will be no ready state transitions. */
+ pVScsiLunSbc->Core.fReady = true;
+
return rc;
}
@@ -242,7 +251,7 @@ static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
vscsiH2BEU32(aReply, UINT32_C(0xffffffff));
else
vscsiH2BEU32(aReply, pVScsiLunSbc->cSectors - 1);
- vscsiH2BEU32(&aReply[4], 512);
+ vscsiH2BEU32(&aReply[4], pVScsiLunSbc->cbSector);
RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
break;
@@ -252,6 +261,7 @@ static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f;
uint8_t aReply[24];
uint8_t *pu8ReplyPos;
+ bool fValid = false;
memset(aReply, 0, sizeof(aReply));
aReply[0] = 4; /* Reply length 4. */
@@ -270,10 +280,47 @@ static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
*pu8ReplyPos++ = 0x08; /* Page code. */
*pu8ReplyPos++ = 0x12; /* Size of the page. */
*pu8ReplyPos++ = 0x4; /* Write cache enabled. */
+ fValid = true;
+ } else if (uModePage == 0) {
+ fValid = true;
}
- RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
- rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
+ /* Querying unknown pages must fail. */
+ if (fValid) {
+ RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
+ rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
+ } else {
+ rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
+ }
+ break;
+ }
+ case SCSI_MODE_SELECT_6:
+ {
+ uint8_t abParms[12];
+ size_t cbCopied;
+ size_t cbList = pVScsiReq->pbCDB[4];
+
+ /* Copy the parameters. */
+ cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abParms[0], sizeof(abParms));
+
+ /* Handle short LOGICAL BLOCK LENGTH parameter. */
+ if ( !(pVScsiReq->pbCDB[1] & 0x01)
+ && cbCopied == sizeof(abParms)
+ && cbList >= 12
+ && abParms[3] == 8)
+ {
+ uint32_t cbBlock;
+
+ cbBlock = vscsiBE2HU24(&abParms[4 + 5]);
+ Log2(("SBC: set LOGICAL BLOCK LENGTH to %u\n", cbBlock));
+ if (cbBlock == 512) /* Fixed block size. */
+ {
+ rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
+ break;
+ }
+ }
+ /* Fail any other requests. */
+ rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
break;
}
case SCSI_READ_6:
@@ -445,7 +492,7 @@ static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
&& cbCopied == sizeof(abHdr)
&& cbList >= 8)
{
- size_t cBlkDesc = vscsiBE2HU16(&abHdr[2]) / 16;
+ uint32_t cBlkDesc = vscsiBE2HU16(&abHdr[2]) / 16;
if (cBlkDesc)
{