VSCSILunMmc.cpp revision bdec40b10acfe9f798021b508a0a7b8c786fc193
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/* $Id$ */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** @file
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Virtual SCSI driver: MMC LUN implementation (CD/DVD-ROM)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
00550544656e1a1537bad42c4f4bacef814637cavboxsync/*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2006-2011 Oracle Corporation
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License (GPL) as published by the Free Software
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Header Files *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#define LOG_GROUP LOG_GROUP_VSCSI
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <VBox/log.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <VBox/err.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <VBox/types.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <VBox/vscsi.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/assert.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/mem.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/string.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include "VSCSIInternal.h"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * MMC LUN instance
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsynctypedef struct VSCSILUNMMC
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Core LUN structure */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync VSCSILUNINT Core;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Size of the virtual disk. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t cSectors;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Sector size. */
101e4426c962b6d124219de44d4fd2cf2a23b178vboxsync uint32_t cbSector;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Medium locked indicator. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync bool fLocked;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync} VSCSILUNMMC, *PVSCSILUNMMC;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic int vscsiLunMmcInit(PVSCSILUNINT pVScsiLun)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t cbDisk = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = VINF_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pVScsiLunMmc->cbSector = 2048; /* Default to 2K sectors. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_SUCCESS(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pVScsiLunMmc->cSectors = cbDisk / pVScsiLunMmc->cbSector;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic int vscsiLunMmcDestroy(PVSCSILUNINT pVScsiLun)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return VINF_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic int vscsiLunMmcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync VSCSIIOREQTXDIR enmTxDir = VSCSIIOREQTXDIR_INVALID;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t uLbaStart = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint32_t cSectorTransfer = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = VINF_SUCCESS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rcReq = SCSI_STATUS_OK;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync switch(pVScsiReq->pbCDB[0])
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync case SCSI_INQUIRY:
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync {
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync SCSIINQUIRYDATA ScsiInquiryReply;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.cbAdditional = 31;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.fRMB = 1; /* Removable. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.u3AnsiVersion = 0x05; /* MMC-?? compliant */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ScsiInquiryReply.fWBus16 = 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiPadStr(ScsiInquiryReply.achProductId, "CD-ROM", 16);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_CAPACITY:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync uint8_t aReply[8];
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync memset(aReply, 0, sizeof(aReply));
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * If sector size exceeds the maximum value that is
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * able to be stored in 4 bytes return 0xffffffff in this field
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pVScsiLunMmc->cSectors > UINT32_C(0xffffffff))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiH2BEU32(aReply, UINT32_C(0xffffffff));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiH2BEU32(aReply, pVScsiLunMmc->cSectors - 1);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiH2BEU32(&aReply[4], pVScsiLunMmc->cbSector);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync break;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_MODE_SENSE_6:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t aReply[24];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t *pu8ReplyPos;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync memset(aReply, 0, sizeof(aReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[0] = 4; /* Reply length 4. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[1] = 0; /* Default media type. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[2] = RT_BIT(4); /* Caching supported. */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync aReply[3] = 0; /* Block descriptor length. */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pu8ReplyPos = aReply + 4;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if ((uModePage == 0x08) || (uModePage == 0x3f))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync memset(pu8ReplyPos, 0, 20);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pu8ReplyPos++ = 0x08; /* Page code. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pu8ReplyPos++ = 0x12; /* Size of the page. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pu8ReplyPos++ = 0x4; /* Write cache enabled. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_MODE_SELECT_6:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* @todo: implement!! */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_6:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync | (pVScsiReq->pbCDB[2] << 8)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cSectorTransfer = pVScsiReq->pbCDB[4];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_10:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
6bea637fe631bf8f14128c36c5da0fe98c0fa4edvboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_12:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_16:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync enmTxDir = VSCSIIOREQTXDIR_READ;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_READ_BUFFER:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync switch (uDataMode)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x00:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x01:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x02:
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync case 0x03:
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync case 0x0a:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x0b:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t aReply[4];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* We do not implement an echo buffer. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync memset(aReply, 0, sizeof(aReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x1a:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x1c:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync default:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailed(("Invalid data mode\n"));
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync }
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_VERIFY_10:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_START_STOP_UNIT:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_LOG_SENSE:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint16_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync switch (uPageCode)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case 0x00:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (uSubPageCode == 0)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t aReply[4];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[0] = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[1] = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[2] = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync aReply[3] = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync default:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync break;
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync }
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync case SCSI_SERVICE_ACTION_IN_16:
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync {
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync switch (pVScsiReq->pbCDB[1] & 0x1f)
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync {
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync case SCSI_SVC_ACTION_IN_READ_CAPACITY_16:
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync {
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync uint8_t aReply[32];
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync memset(aReply, 0, sizeof(aReply));
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync vscsiH2BEU64(aReply, pVScsiLunMmc->cSectors - 1);
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync vscsiH2BEU32(&aReply[8], pVScsiLunMmc->cbSector);
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync /* Leave the rest 0 */
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync default:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pVScsiLunMmc->fLocked = pVScsiReq->pbCDB[4] & 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync default:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0])));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (enmTxDir != VSCSIIOREQTXDIR_INVALID)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync LogFlow(("%s: uLbaStart=%llu cSectorTransfer=%u\n",
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync __FUNCTION__, uLbaStart, cSectorTransfer));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunMmc->cSectors))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else if (!cSectorTransfer)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* A 0 transfer length is not an error. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync {
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /* Enqueue new I/O request */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = vscsiIoReqTransferEnqueue(pVScsiLun, pVScsiReq, enmTxDir,
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync uLbaStart * pVScsiLunMmc->cbSector,
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync cSectorTransfer * pVScsiLunMmc->cbSector);
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync }
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync }
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync else /* Request completed */
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync return rc;
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync}
1823a2b6757096c699825898c33f8d93089a1b4bvboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsyncVSCSILUNDESC g_VScsiLunTypeMmc =
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** enmLunType */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync VSCSILUNTYPE_MMC,
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /** pcszDescName */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync "MMC",
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /** cbLun */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync sizeof(VSCSILUNMMC),
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** pfnVScsiLunInit */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync vscsiLunMmcInit,
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /** pfnVScsiLunDestroy */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync vscsiLunMmcDestroy,
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /** pfnVScsiLunReqProcess */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync vscsiLunMmcReqProcess
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync};
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync