VSCSILunSbc.cpp revision f4aad55f8addd816ef005845842a2418bbdc3ea2
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/* $Id$ */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** @file
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Virtual SCSI driver: SBC LUN implementation (hard disks)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync */
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2011 Oracle Corporation
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * available from http://www.virtualbox.org. This file is free software;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * General Public License (GPL) as published by the Free Software
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync */
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/*******************************************************************************
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync* Header Files *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync*******************************************************************************/
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define LOG_GROUP LOG_GROUP_VSCSI
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/log.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#include <VBox/err.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/types.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#include <VBox/vscsi.h>
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync#include <iprt/cdefs.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#include <iprt/asm.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#include <iprt/assert.h>
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync#include <iprt/mem.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#include <iprt/string.h>
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync#include "VSCSIInternal.h"
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync/** Maximum of amount of LBAs to unmap with one command. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define VSCSI_UNMAP_LBAS_MAX ((10*_1M) / 512)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/**
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * SBC LUN instance
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync */
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsynctypedef struct VSCSILUNSBC
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync{
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** Core LUN structure */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSILUNINT Core;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** Size of the virtual disk. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint64_t cSectors;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** VPD page pool. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSIVPDPOOL VpdPagePool;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync} VSCSILUNSBC;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Pointer to a SBC LUN instance */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsynctypedef VSCSILUNSBC *PVSCSILUNSBC;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsyncstatic int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync{
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint64_t cbDisk = 0;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync int rc = VINF_SUCCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync int cVpdPages = 0;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync if (RT_SUCCESS(rc))
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync pVScsiLunSbc->cSectors = cbDisk / 512; /* Fixed sector size */
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolInit(&pVScsiLunSbc->VpdPagePool);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Create device identification page - mandatory. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSIVPDPAGEDEVID pDevIdPage;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_DEVID_NUMBER,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSI_VPD_DEVID_SIZE, (uint8_t **)&pDevIdPage);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** @todo: Not conforming to the SPC spec but Solaris needs at least a stub to work. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pDevIdPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pDevIdPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pDevIdPage->u16PageLength = RT_H2BE_U16(0x0);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cVpdPages++;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if ( RT_SUCCESS(rc)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync && (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSIVPDPAGEBLOCKLIMITS pBlkPage;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSIVPDPAGEBLOCKPROV pBlkProvPage;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Create the page and fill it. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_LIMITS_NUMBER,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSI_VPD_BLOCK_LIMITS_SIZE, (uint8_t **)&pBlkPage);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u16PageLength = RT_H2BE_U16(0x3c);
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u8MaxCmpWriteLength = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u16OptTrfLengthGran = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32MaxTrfLength = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32OptTrfLength = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32MaxPreXdTrfLength = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32MaxUnmapLbaCount = RT_H2BE_U32(VSCSI_UNMAP_LBAS_MAX);
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32MaxUnmapBlkDescCount = UINT32_C(0xffffffff);
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32OptUnmapGranularity = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync pBlkPage->u32UnmapGranularityAlignment = 0;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync cVpdPages++;
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_PROV_NUMBER,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSI_VPD_BLOCK_PROV_SIZE, (uint8_t **)&pBlkProvPage);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkProvPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync pBlkProvPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync pBlkProvPage->u16PageLength = RT_H2BE_U16(0x4);
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync pBlkProvPage->u8ThresholdExponent = 1;
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync pBlkProvPage->fLBPU = true;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cVpdPages++;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if ( RT_SUCCESS(rc)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync && (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_NON_ROTATIONAL))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSIVPDPAGEBLOCKCHARACTERISTICS pBlkPage;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Create the page and fill it. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_CHARACTERISTICS_NUMBER,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSI_VPD_BLOCK_CHARACTERISTICS_SIZE, (uint8_t **)&pBlkPage);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pBlkPage->u16PageLength = RT_H2BE_U16(0x3c);
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync pBlkPage->u16MediumRotationRate = RT_H2BE_U16(VSCSI_VPD_BLOCK_CHARACT_MEDIUM_ROTATION_RATE_NON_ROTATING);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cVpdPages++;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if ( RT_SUCCESS(rc)
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync && cVpdPages)
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSIVPDPAGESUPPORTEDPAGES pVpdPages;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_SUPPORTED_PAGES_NUMBER,
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync VSCSI_VPD_SUPPORTED_PAGES_SIZE + cVpdPages, (uint8_t **)&pVpdPages);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_SUCCESS(rc))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync unsigned idxVpdPage = 0;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync pVpdPages->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->u16PageLength = RT_H2BE_U16(cVpdPages);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_DEVID_NUMBER;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_LIMITS_NUMBER;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_PROV_NUMBER;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_NON_ROTATIONAL)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_CHARACTERISTICS_NUMBER;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync return rc;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync}
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic int vscsiLunSbcDestroy(PVSCSILUNINT pVScsiLun)
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync{
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync vscsiVpdPagePoolDestroy(&pVScsiLunSbc->VpdPagePool);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync return VINF_SUCCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync}
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync{
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync int rc = VINF_SUCCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync int rcReq = SCSI_STATUS_OK;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync uint64_t uLbaStart = 0;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t cSectorTransfer = 0;
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync VSCSIIOREQTXDIR enmTxDir = VSCSIIOREQTXDIR_INVALID;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync switch(pVScsiReq->pbCDB[0])
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case SCSI_INQUIRY:
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync /* Check for EVPD bit. */
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync if (pVScsiReq->pbCDB[1] & 0x1)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiVpdPagePoolQueryPage(&pVScsiLunSbc->VpdPagePool, pVScsiReq, pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_UNLIKELY(rc == VERR_NOT_FOUND))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = VINF_SUCCESS;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else if (pVScsiReq->pbCDB[2] != 0) /* A non zero page code is an error. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync SCSIINQUIRYDATA ScsiInquiryReply;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync ScsiInquiryReply.cbAdditional = 31;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync ScsiInquiryReply.fWBus16 = 1;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8);
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync vscsiPadStr(ScsiInquiryReply.achProductId, "HARDDISK", 16);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync case SCSI_READ_CAPACITY:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t aReply[8];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync memset(aReply, 0, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /*
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * If sector size exceeds the maximum value that is
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * able to be stored in 4 bytes return 0xffffffff in this field
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (pVScsiLunSbc->cSectors > UINT32_C(0xffffffff))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiH2BEU32(aReply, UINT32_C(0xffffffff));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiH2BEU32(aReply, pVScsiLunSbc->cSectors - 1);
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync vscsiH2BEU32(&aReply[4], 512);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case SCSI_MODE_SENSE_6:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t aReply[24];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t *pu8ReplyPos;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync memset(aReply, 0, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[0] = 4; /* Reply length 4. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[1] = 0; /* Default media type. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[2] = RT_BIT(4); /* Caching supported. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[3] = 0; /* Block descriptor length. */
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync pu8ReplyPos = aReply + 4;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if ((uModePage == 0x08) || (uModePage == 0x3f))
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync {
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync memset(pu8ReplyPos, 0, 20);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync *pu8ReplyPos++ = 0x08; /* Page code. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync *pu8ReplyPos++ = 0x12; /* Size of the page. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync *pu8ReplyPos++ = 0x4; /* Write cache enabled. */
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync break;
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync }
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync case SCSI_READ_6:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
2e5aced57476316542e80047953840c7b4887337vboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync | (pVScsiReq->pbCDB[2] << 8)
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync cSectorTransfer = pVScsiReq->pbCDB[4];
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync case SCSI_READ_10:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_READ_12:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_READ_16:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_WRITE_6:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_WRITE;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync | (pVScsiReq->pbCDB[2] << 8)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = pVScsiReq->pbCDB[4];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_WRITE_10:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_WRITE;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_WRITE_12:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_WRITE;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_WRITE_16:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync enmTxDir = VSCSIIOREQTXDIR_WRITE;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_SYNCHRONIZE_CACHE:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break; /* Handled below */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_READ_BUFFER:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync switch (uDataMode)
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case 0x00:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case 0x01:
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case 0x02:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case 0x03:
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case 0x0a:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case 0x0b:
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync uint8_t aReply[4];
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync /* We do not implement an echo buffer. */
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync memset(aReply, 0, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case 0x1a:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case 0x1c:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync default:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync AssertMsgFailed(("Invalid data mode\n"));
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_VERIFY_10:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_START_STOP_UNIT:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_LOG_SENSE:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
af5224eb6b6676bc892a3f5abeb21f602547d31cvboxsync uint16_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
af5224eb6b6676bc892a3f5abeb21f602547d31cvboxsync uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync switch (uPageCode)
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync {
af5224eb6b6676bc892a3f5abeb21f602547d31cvboxsync case 0x00:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (uSubPageCode == 0)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t aReply[4];
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync aReply[0] = 0;
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync aReply[1] = 0;
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync aReply[2] = 0;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[3] = 0;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync default:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_SERVICE_ACTION_IN_16:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync switch (pVScsiReq->pbCDB[1] & 0x1f)
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case SCSI_SVC_ACTION_IN_READ_CAPACITY_16:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t aReply[32];
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync memset(aReply, 0, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiH2BEU64(aReply, pVScsiLunSbc->cSectors - 1);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiH2BEU32(&aReply[8], 512);
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync aReply[14] = 0x80; /* LPME enabled */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Leave the rest 0 */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync default:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync break;
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync }
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync case SCSI_UNMAP:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint8_t abHdr[8];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync size_t cbCopied;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync size_t cbList = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync /* Copy the header. */
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abHdr[0], sizeof(abHdr));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Using the anchor bit is not supported. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if ( !(pVScsiReq->pbCDB[1] & 0x01)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync && cbCopied == sizeof(abHdr)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync && cbList >= 8)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync size_t cBlkDesc = vscsiBE2HU16(&abHdr[2]) / 16;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (cBlkDesc)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync PRTRANGE paRanges;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync paRanges = (PRTRANGE)RTMemAllocZ(cBlkDesc * sizeof(RTRANGE));
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync if (paRanges)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync for (unsigned i = 0; i < cBlkDesc; i++)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync uint8_t abBlkDesc[16];
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abBlkDesc[0], sizeof(abBlkDesc));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_UNLIKELY(cbCopied != sizeof(abBlkDesc)))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync break;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync paRanges[i].offStart = vscsiBE2HU64(&abBlkDesc[0]) * 512;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync paRanges[i].cbRange = vscsiBE2HU32(&abBlkDesc[8]) * 512;
ac6445a70a26cb69d08734f1d9dbc171cec86cd8vboxsync }
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (rcReq == SCSI_STATUS_OK)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiIoReqUnmapEnqueue(pVScsiLun, pVScsiReq, paRanges, cBlkDesc);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else /* Out of memory. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_HARDWARE_ERROR, SCSI_ASC_SYSTEM_RESOURCE_FAILURE,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync SCSI_ASCQ_SYSTEM_BUFFER_FULL);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else /* No block descriptors is not an error condition. */
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else /* Invalid CDB. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync break;
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync default:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0])));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (enmTxDir != VSCSIIOREQTXDIR_INVALID)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync LogFlow(("%s: uLbaStart=%llu cSectorTransfer=%u\n",
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync __FUNCTION__, uLbaStart, cSectorTransfer));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunSbc->cSectors))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else if (!cSectorTransfer)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* A 0 transfer length is not an error. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync {
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync /* Enqueue new I/O request */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiIoReqTransferEnqueue(pVScsiLun, pVScsiReq, enmTxDir,
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync uLbaStart * 512, cSectorTransfer * 512);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else if (pVScsiReq->pbCDB[0] == SCSI_SYNCHRONIZE_CACHE)
ff03d550549cfd2458dcac64202de635eb8d07cdvboxsync {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Enqueue flush */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync rc = vscsiIoReqFlushEnqueue(pVScsiLun, pVScsiReq);
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync }
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync else if (pVScsiReq->pbCDB[0] != SCSI_UNMAP) /* Request completed */
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync return rc;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync}
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncVSCSILUNDESC g_VScsiLunTypeSbc =
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync{
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** enmLunType */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync VSCSILUNTYPE_SBC,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** pcszDescName */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync "SBC",
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** cbLun */
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync sizeof(VSCSILUNSBC),
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** pfnVScsiLunInit */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vscsiLunSbcInit,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** pfnVScsiLunDestroy */
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync vscsiLunSbcDestroy,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /** pfnVScsiLunReqProcess */
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync vscsiLunSbcReqProcess
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync};
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync