a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/* $Id$ */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/** @file
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Virtual SCSI driver: LUN handling
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync *
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * available from http://www.virtualbox.org. This file is free software;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * General Public License (GPL) as published by the Free Software
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#define LOG_GROUP LOG_GROUP_VSCSI
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <VBox/log.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <VBox/err.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <VBox/types.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <VBox/vscsi.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <iprt/assert.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include <iprt/mem.h>
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync#include "VSCSIInternal.h"
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/** SBC descriptor */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncextern VSCSILUNDESC g_VScsiLunTypeSbc;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/** MMC descriptor */
8683cfdc9273dd77e1c4e89886a7052de103591avboxsyncextern VSCSILUNDESC g_VScsiLunTypeMmc;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/**
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Array of supported SCSI LUN types.
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync */
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsyncstatic PVSCSILUNDESC g_aVScsiLunTypesSupported[] =
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync{
8683cfdc9273dd77e1c4e89886a7052de103591avboxsync &g_VScsiLunTypeSbc,
8683cfdc9273dd77e1c4e89886a7052de103591avboxsync &g_VScsiLunTypeMmc,
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync};
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncVBOXDDU_DECL(int) VSCSILunCreate(PVSCSILUN phVScsiLun, VSCSILUNTYPE enmLunType,
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync PVSCSILUNIOCALLBACKS pVScsiLunIoCallbacks,
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync void *pvVScsiLunUser)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync{
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync PVSCSILUNINT pVScsiLun = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync PVSCSILUNDESC pVScsiLunDesc = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync AssertPtrReturn(phVScsiLun, VERR_INVALID_POINTER);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync AssertReturn( enmLunType > VSCSILUNTYPE_INVALID
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync && enmLunType < VSCSILUNTYPE_LAST, VERR_INVALID_PARAMETER);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync AssertPtrReturn(pVScsiLunIoCallbacks, VERR_INVALID_PARAMETER);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync for (unsigned idxLunType = 0; idxLunType < RT_ELEMENTS(g_aVScsiLunTypesSupported); idxLunType++)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync {
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync if (g_aVScsiLunTypesSupported[idxLunType]->enmLunType == enmLunType)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync {
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLunDesc = g_aVScsiLunTypesSupported[idxLunType];
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync break;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync }
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync }
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync if (!pVScsiLunDesc)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return VERR_VSCSI_LUN_TYPE_NOT_SUPPORTED;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun = (PVSCSILUNINT)RTMemAllocZ(pVScsiLunDesc->cbLun);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync if (!pVScsiLun)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return VERR_NO_MEMORY;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pVScsiDevice = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pvVScsiLunUser = pvVScsiLunUser;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pVScsiLunIoCallbacks = pVScsiLunIoCallbacks;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pVScsiLunDesc = pVScsiLunDesc;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
65697a26b524640b83828b715160c798c43a0424vboxsync int rc = vscsiLunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync if (RT_SUCCESS(rc))
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync {
65697a26b524640b83828b715160c798c43a0424vboxsync rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun);
65697a26b524640b83828b715160c798c43a0424vboxsync if (RT_SUCCESS(rc))
65697a26b524640b83828b715160c798c43a0424vboxsync {
65697a26b524640b83828b715160c798c43a0424vboxsync *phVScsiLun = pVScsiLun;
65697a26b524640b83828b715160c798c43a0424vboxsync return VINF_SUCCESS;
65697a26b524640b83828b715160c798c43a0424vboxsync }
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync }
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync RTMemFree(pVScsiLun);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return rc;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync}
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/**
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Destroy virtual SCSI LUN.
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync *
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * @returns VBox status code.
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @param hVScsiLun The virtual SCSI LUN handle to destroy.
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncVBOXDDU_DECL(int) VSCSILunDestroy(VSCSILUN hVScsiLun)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync{
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync PVSCSILUNINT pVScsiLun = (PVSCSILUNINT)hVScsiLun;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync AssertPtrReturn(pVScsiLun, VERR_INVALID_HANDLE);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync AssertReturn(!pVScsiLun->pVScsiDevice, VERR_VSCSI_LUN_ATTACHED_TO_DEVICE);
26947320577c481b4afefdb0afbb855181e5b2e8vboxsync AssertReturn(vscsiIoReqOutstandingCountGet(pVScsiLun) == 0, VERR_VSCSI_LUN_BUSY);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync int rc = pVScsiLun->pVScsiLunDesc->pfnVScsiLunDestroy(pVScsiLun);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync if (RT_FAILURE(rc))
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return rc;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync /* Make LUN invalid */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pvVScsiLunUser = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pVScsiLunIoCallbacks = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync pVScsiLun->pVScsiLunDesc = NULL;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync RTMemFree(pVScsiLun);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return VINF_SUCCESS;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync}
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync/**
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * Notify virtual SCSI LUN of media being mounted.
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync *
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * @returns VBox status code.
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync * @param hVScsiLun The virtual SCSI LUN
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * mounting the medium.
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync */
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsyncVBOXDDU_DECL(int) VSCSILunMountNotify(VSCSILUN hVScsiLun)
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync{
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync PVSCSILUNINT pVScsiLun = (PVSCSILUNINT)hVScsiLun;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync LogFlowFunc(("hVScsiLun=%p\n", hVScsiLun));
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync AssertPtrReturn(pVScsiLun, VERR_INVALID_HANDLE);
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync AssertReturn(vscsiIoReqOutstandingCountGet(pVScsiLun) == 0, VERR_VSCSI_LUN_BUSY);
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync /* Mark the LUN as not ready so that LUN specific code can do its job. */
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync pVScsiLun->fReady = false;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync pVScsiLun->fMediaPresent = true;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync return VINF_SUCCESS;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync}
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync/**
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * Notify virtual SCSI LUN of media being unmounted.
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync *
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * @returns VBox status code.
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync * @param hVScsiLun The virtual SCSI LUN
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync * mounting the medium.
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync */
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsyncVBOXDDU_DECL(int) VSCSILunUnmountNotify(VSCSILUN hVScsiLun)
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync{
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync PVSCSILUNINT pVScsiLun = (PVSCSILUNINT)hVScsiLun;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync LogFlowFunc(("hVScsiLun=%p\n", hVScsiLun));
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync AssertPtrReturn(pVScsiLun, VERR_INVALID_HANDLE);
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync AssertReturn(vscsiIoReqOutstandingCountGet(pVScsiLun) == 0, VERR_VSCSI_LUN_BUSY);
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync pVScsiLun->fReady = false;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync pVScsiLun->fMediaPresent = false;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync return VINF_SUCCESS;
5cece736b63cc917f3781c8c7e46fd3ea98c4e20vboxsync}