DrvHostDVD.cpp revision ab7b42fde10adc517cfb04c11c1ef90f105e4aca
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* $Id$ */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @file
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * DrvHostDVD - Host DVD block driver.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License (GPL) as published by the Free Software
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * additional information or have any questions.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync/*******************************************************************************
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync* Header Files *
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync*******************************************************************************/
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define LOG_GROUP LOG_GROUP_DRV_HOST_DVD
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define __STDC_LIMIT_MACROS
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define __STDC_CONSTANT_MACROS
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <mach/mach.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <Carbon/Carbon.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <IOKit/IOKitLib.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <IOKit/IOCFPlugIn.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <IOKit/scsi-commands/SCSITaskLib.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <IOKit/storage/IOStorageDeviceCharacteristics.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <mach/mach_error.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_L4)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* nothing (yet). */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined RT_OS_LINUX
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <sys/ioctl.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* This is a hack to work around conflicts between these linux kernel headers
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * and the GLIBC tcpip headers. They have different declarations of the 4
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * standard byte order functions. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define _LINUX_BYTEORDER_GENERIC_H
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* This is another hack for not bothering with C++ unfriendly byteswap macros. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define _LINUX_BYTEORDER_SWAB_H
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* Those macros that are needed are defined in the header below */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include "swab.h"
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <linux/cdrom.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <sys/fcntl.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <errno.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <limits.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <stropts.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <fcntl.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <ctype.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <errno.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <pwd.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <unistd.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <syslog.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# ifdef VBOX_WITH_SUID_WRAPPER
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <auth_attr.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <sys/dkio.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <sys/sockio.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <sys/scsi/scsi.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_WINDOWS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <Windows.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <winioctl.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <ntddscsi.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# undef USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# error "Unsupported Platform."
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <VBox/pdmdrv.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/assert.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/file.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/string.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/thread.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/critsect.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <VBox/scsi.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "Builtins.h"
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "DrvHostBase.h"
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* Forward declarations. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) drvHostDvdDoLock(PDRVHOSTBASE pThis, bool fLock);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef VBOX_WITH_SUID_WRAPPER
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisCheckUserAuth();
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisEnterRootMode(uid_t *pEffUserID);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisExitRootMode(uid_t *pEffUserID);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @copydoc PDMIMOUNT::pfnUnmount */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) drvHostDvdUnmount(PPDMIMOUNT pInterface, bool fForce)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDRVHOSTBASE pThis = PDMIMOUNT_2_DRVHOSTBASE(pInterface);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTCritSectEnter(&pThis->CritSect);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Validate state.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!pThis->fLocked || fForce)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Unlock drive if necessary. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pThis->fLocked)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync drvHostDvdDoLock(pThis, false);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Eject the disc.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t abCmd[16] =
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync SCSI_START_STOP_UNIT, 0, 0, 0, 2 /*eject+stop*/, 0,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync 0,0,0,0,0,0,0,0,0,0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync };
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, NULL, 0, 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_LINUX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = ioctl(pThis->FileDevice, CDROMEJECT, 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EBUSY)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_PDM_MEDIA_LOCKED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == ENOSYS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_NOT_SUPPORTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = ioctl(pThis->FileRawDevice, DKIOCEJECT, 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EBUSY)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_PDM_MEDIA_LOCKED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == ENOSYS || errno == ENOTSUP)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_NOT_SUPPORTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == ENODEV)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_PDM_MEDIA_NOT_MOUNTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_WINDOWS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTFILE FileDevice = pThis->FileDevice;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (FileDevice == NIL_RTFILE) /* obsolete crap */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTFileOpen(&FileDevice, pThis->pszDeviceOpen, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_SUCCESS(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* do ioctl */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DWORD cbReturned;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (DeviceIoControl((HANDLE)FileDevice, IOCTL_STORAGE_EJECT_MEDIA,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL, 0,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL, 0, &cbReturned,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromWin32(GetLastError());
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* clean up handle */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (FileDevice != pThis->FileDevice)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTFileClose(FileDevice);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailed(("Failed to open '%s' for ejecting this tray.\n", rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailed(("Eject is not implemented!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Media is no longer present.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DRVHostBaseMediaNotPresent(pThis); /** @todo This isn't thread safe! */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("drvHostDvdUnmount: Locked\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_PDM_MEDIA_LOCKED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTCritSectLeave(&pThis->CritSect);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDvdUnmount: returns %Rrc\n", rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Locks or unlocks the drive.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox status code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pThis The instance data.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param fLock True if the request is to lock the drive, false if to unlock.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) drvHostDvdDoLock(PDRVHOSTBASE pThis, bool fLock)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t abCmd[16] =
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, fLock, 0,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync 0,0,0,0,0,0,0,0,0,0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync };
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, NULL, 0, 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_LINUX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = ioctl(pThis->FileDevice, CDROM_LOCKDOOR, (int)fLock);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EBUSY)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_ACCESS_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == EDRIVE_CANT_DO_THIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_NOT_SUPPORTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = ioctl(pThis->FileRawDevice, fLock ? DKIOCLOCK : DKIOCUNLOCK, 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EBUSY)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_ACCESS_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == ENOTSUP || errno == ENOSYS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_NOT_SUPPORTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_WINDOWS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PREVENT_MEDIA_REMOVAL PreventMediaRemoval = {fLock};
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DWORD cbReturned;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (DeviceIoControl((HANDLE)pThis->FileDevice, IOCTL_STORAGE_MEDIA_REMOVAL,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync &PreventMediaRemoval, sizeof(PreventMediaRemoval),
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL, 0, &cbReturned,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** @todo figure out the return codes for already locked. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromWin32(GetLastError());
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailed(("Lock/Unlock is not implemented!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDvdDoLock(, fLock=%RTbool): returns %Rrc\n", fLock, rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_LINUX
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Get the media size.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox status code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pThis The instance data.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pcb Where to store the size.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int drvHostDvdGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Query the media size.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Clear the media-changed-since-last-call-thingy just to be on the safe side. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync ioctl(pThis->FileDevice, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return RTFileSeek(pThis->FileDevice, 0, RTFILE_SEEK_END, pcb);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif /* RT_OS_LINUX */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Do media change polling.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncDECLCALLBACK(int) drvHostDvdPoll(PDRVHOSTBASE pThis)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Poll for media change.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertReturn(pThis->ppScsiTaskDI, VERR_INTERNAL_ERROR);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Issue a TEST UNIT READY request.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaChanged = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaPresent = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t abCmd[16] = { SCSI_TEST_UNIT_READY, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t abSense[32];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc2 = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, abSense, sizeof(abSense), 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_SUCCESS(rc2))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaPresent = true;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if ( rc2 == VERR_UNRESOLVED_ERROR
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && abSense[2] == 6 /* unit attention */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && ( (abSense[12] == 0x29 && abSense[13] < 5 /* reset */)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || (abSense[12] == 0x2a && abSense[13] == 0 /* parameters changed */) //???
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || (abSense[12] == 0x3f && abSense[13] == 0 /* target operating conditions have changed */) //???
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || (abSense[12] == 0x3f && abSense[13] == 2 /* changed operating definition */) //???
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || (abSense[12] == 0x3f && abSense[13] == 3 /* inquery parameters changed */)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || (abSense[12] == 0x3f && abSense[13] == 5 /* device identifier changed */)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaPresent = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaChanged = true;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** @todo check this media chance stuff on Darwin. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_LINUX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaPresent = ioctl(pThis->FileDevice, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaPresent = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaChanged = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Need to pass the previous state and DKIO_NONE for the first time. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync static dkio_state s_DeviceState = DKIO_NONE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync dkio_state PreviousState = s_DeviceState;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc2 = ioctl(pThis->FileRawDevice, DKIOCSTATE, &s_DeviceState);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc2 == 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaPresent = (s_DeviceState == DKIO_INSERTED);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (PreviousState != s_DeviceState)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaChanged = true;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fMediaChanged = true;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# error "Unsupported platform."
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTCritSectEnter(&pThis->CritSect);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pThis->fMediaPresent != fMediaPresent)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDvdPoll: %d -> %d\n", pThis->fMediaPresent, fMediaPresent));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->fMediaPresent = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fMediaPresent)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = DRVHostBaseMediaPresent(pThis);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DRVHostBaseMediaNotPresent(pThis);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (fMediaPresent)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Poll for media change.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* taken care of above. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_LINUX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fMediaChanged = ioctl(pThis->FileDevice, CDROM_MEDIA_CHANGED, CDSL_CURRENT) == 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# error "Unsupported platform."
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fMediaChanged)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDVDMediaThread: Media changed!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DRVHostBaseMediaNotPresent(pThis);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = DRVHostBaseMediaPresent(pThis);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTCritSectLeave(&pThis->CritSect);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif /* USE_MEDIA_POLLING */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @copydoc PDMIBLOCK::pfnSendCmd */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int drvHostDvdSendCmd(PPDMIBLOCK pInterface, const uint8_t *pbCmd,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDMBLOCKTXDIR enmTxDir, void *pvBuf, size_t *pcbBuf,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t *pabSense, size_t cbSense, uint32_t cTimeoutMillies)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDRVHOSTBASE pThis = PDMIBLOCK_2_DRVHOSTBASE(pInterface);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("%s: cmd[0]=%#04x txdir=%d pcbBuf=%d timeout=%d\n", __FUNCTION__, pbCmd[0], enmTxDir, *pcbBuf, cTimeoutMillies));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Pass the request on to the internal scsi command interface.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The command seems to be 12 bytes long, the docs a bit copy&pasty on the command length point...
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(pvBuf, '\0', *pcbBuf); /* we got read size, but zero it anyway. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = DRVHostBaseScsiCmd(pThis, pbCmd, 12, PDMBLOCKTXDIR_FROM_DEVICE, pvBuf, pcbBuf, pabSense, cbSense, cTimeoutMillies);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc == VERR_UNRESOLVED_ERROR)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_L4)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Not really ported to L4 yet. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_INTERNAL_ERROR;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_LINUX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int direction;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync struct cdrom_generic_command cgc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync request_sense sense;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync switch (enmTxDir)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_NONE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf == 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = CGC_DATA_NONE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_FROM_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf != 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Make sure that the buffer is clear for commands reading
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data. The actually received data may be shorter than what
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * we expect, and due to the unreliable feedback about how much
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data the ioctl actually transferred, it's impossible to
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * prevent that. Returning previous buffer contents may cause
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * security problems inside the guest OS, if users can issue
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * commands to the CDROM device. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(pvBuf, '\0', *pcbBuf);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = CGC_DATA_READ;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_TO_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf != 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = CGC_DATA_WRITE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync default:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailed(("enmTxDir invalid!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = CGC_DATA_NONE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(&cgc, '\0', sizeof(cgc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memcpy(cgc.cmd, pbCmd, CDROM_PACKET_SIZE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.buffer = (unsigned char *)pvBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.buflen = *pcbBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.stat = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(cbSense >= sizeof(struct request_sense));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.sense = (struct request_sense *)pabSense;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.data_direction = direction;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.quiet = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.timeout = cTimeoutMillies;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = ioctl(pThis->FileDevice, CDROM_SEND_PACKET, &cgc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EBUSY)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_PDM_MEDIA_LOCKED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if (errno == ENOSYS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_NOT_SUPPORTED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc == VERR_ACCESS_DENIED && cgc.sense->sense_key == SCSI_SENSE_NONE)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cgc.sense->sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log2(("%s: error status %d, rc=%Rrc\n", __FUNCTION__, cgc.stat, rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log2(("%s: after ioctl: cgc.buflen=%d txlen=%d\n", __FUNCTION__, cgc.buflen, *pcbBuf));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* The value of cgc.buflen does not reliably reflect the actual amount
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * of data transferred (for packet commands with little data transfer
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * it's 0). So just assume that everything worked ok. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_SOLARIS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync struct uscsi_cmd usc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync union scsi_cdb scdb;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(&usc, 0, sizeof(struct uscsi_cmd));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(&scdb, 0, sizeof(scdb));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync switch (enmTxDir)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_NONE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf == 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_flags = USCSI_READ;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* nothing to do */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_FROM_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf != 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Make sure that the buffer is clear for commands reading
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data. The actually received data may be shorter than what
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * we expect, and due to the unreliable feedback about how much
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data the ioctl actually transferred, it's impossible to
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * prevent that. Returning previous buffer contents may cause
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * security problems inside the guest OS, if users can issue
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * commands to the CDROM device. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(pvBuf, '\0', *pcbBuf);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_flags = USCSI_READ;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_TO_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf != 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_flags = USCSI_WRITE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync default:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailedReturn(("%d\n", enmTxDir), VERR_INTERNAL_ERROR);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_flags |= USCSI_RQENABLE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_rqbuf = pabSense;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_rqlen = cbSense;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_cdb = (caddr_t)&scdb;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_cdblen = 12;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memcpy (usc.uscsi_cdb, pbCmd, usc.uscsi_cdblen);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_bufaddr = (caddr_t)pvBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_buflen = *pcbBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync usc.uscsi_timeout = (cTimeoutMillies + 999) / 1000;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* We need root privileges for user-SCSI under Solaris. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef VBOX_WITH_SUID_WRAPPER
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uid_t effUserID = geteuid();
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync solarisEnterRootMode(&effUserID); /** @todo check return code when this really works. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = ioctl(pThis->FileRawDevice, USCSICMD, &usc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef VBOX_WITH_SUID_WRAPPER
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync solarisExitRootMode(&effUserID);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (rc < 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (errno == EPERM)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_PERMISSION_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (usc.uscsi_status)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromErrno(errno);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log2(("%s: error status. rc=%Rrc\n", __FUNCTION__, rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log2(("%s: after ioctl: residual buflen=%d original buflen=%d\n", __FUNCTION__, usc.uscsi_resid, usc.uscsi_buflen));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_WINDOWS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int direction;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync struct _REQ
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync SCSI_PASS_THROUGH_DIRECT spt;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint8_t aSense[18];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync } Req;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DWORD cbReturned = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync switch (enmTxDir)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_NONE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = SCSI_IOCTL_DATA_UNSPECIFIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_FROM_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(*pcbBuf != 0);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Make sure that the buffer is clear for commands reading
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data. The actually received data may be shorter than what
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * we expect, and due to the unreliable feedback about how much
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * data the ioctl actually transferred, it's impossible to
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * prevent that. Returning previous buffer contents may cause
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * security problems inside the guest OS, if users can issue
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * commands to the CDROM device. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(pvBuf, '\0', *pcbBuf);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = SCSI_IOCTL_DATA_IN;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case PDMBLOCKTXDIR_TO_DEVICE:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = SCSI_IOCTL_DATA_OUT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync default:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertMsgFailed(("enmTxDir invalid!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync direction = SCSI_IOCTL_DATA_UNSPECIFIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(&Req, '\0', sizeof(Req));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.Length = sizeof(Req.spt);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.CdbLength = 12;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memcpy(Req.spt.Cdb, pbCmd, Req.spt.CdbLength);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.DataBuffer = pvBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.DataTransferLength = *pcbBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.DataIn = direction;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.TimeOutValue = (cTimeoutMillies + 999) / 1000; /* Convert to seconds */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(cbSense <= sizeof(Req.aSense));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.SenseInfoLength = cbSense;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Req.spt.SenseInfoOffset = RT_OFFSETOF(struct _REQ, aSense);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (DeviceIoControl((HANDLE)pThis->FileDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync &Req, sizeof(Req), &Req, sizeof(Req), &cbReturned, NULL))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (cbReturned > RT_OFFSETOF(struct _REQ, aSense))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memcpy(pabSense, Req.aSense, cbSense);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memset(pabSense, '\0', cbSense);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Windows shares the property of not properly reflecting the actually
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * transferred data size. See above. Assume that everything worked ok. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTErrConvertFromWin32(GetLastError());
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log2(("%s: scsistatus=%d bytes returned=%d tlength=%d\n", __FUNCTION__, Req.spt.ScsiStatus, cbReturned, Req.spt.DataTransferLength));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# error "Unsupported platform."
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("%s: rc=%Rrc\n", __FUNCTION__, rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef VBOX_WITH_SUID_WRAPPER
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* These functions would have to go into a seperate solaris binary with
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * the setuid permission set, which would run the user-SCSI ioctl and
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * return the value. BUT... this might be prohibitively slow.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_SOLARIS
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Checks if the current user is authorized using Solaris' role-based access control.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Made as a seperate function with so that it need not be invoked each time we need
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * to gain root access.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox error code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisCheckUserAuth()
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Uses Solaris' role-based access control (RBAC).*/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync struct passwd *pPass = getpwuid(getuid());
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pPass == NULL || chkauthattr("solaris.device.cdrw", pPass->pw_name) == 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_PERMISSION_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Setuid wrapper to gain root access.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox error code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pEffUserID Pointer to effective user ID.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisEnterRootMode(uid_t *pEffUserID)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Increase privilege if required */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (*pEffUserID != 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (seteuid(0) == 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pEffUserID = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_PERMISSION_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Setuid wrapper to relinquish root access.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox error code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pEffUserID Pointer to effective user ID.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int solarisExitRootMode(uid_t *pEffUserID)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Get back to user mode. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (*pEffUserID == 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uid_t realID = getuid();
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (seteuid(realID) == 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pEffUserID = realID;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_PERMISSION_DENIED;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif /* RT_OS_SOLARIS */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Construct a host dvd drive driver instance.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox status.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pDrvIns The driver instance data.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * If the registration structure is needed, pDrvIns->pDrvReg points to it.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * iInstance it's expected to be used a bit in this function.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) drvHostDvdConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDvdConstruct: iInstance=%d\n", pDrvIns->iInstance));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Validate configuration.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!CFGMR3AreValuesValid(pCfgHandle, "Path\0Interval\0Locked\0BIOSVisible\0AttachFailError\0Passthrough\0"))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Init instance data.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = DRVHostBaseInitData(pDrvIns, pCfgHandle, PDMBLOCKTYPE_DVD);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_SUCCESS(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Override stuff.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifndef RT_OS_L4 /* Passthrough is not supported on L4 yet */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fPassthrough;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = CFGMR3QueryBool(pCfgHandle, "Passthrough", &fPassthrough);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_SUCCESS(rc) && fPassthrough)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->IBlock.pfnSendCmd = drvHostDvdSendCmd;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Passthrough requires opening the device in R/W mode. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->fReadOnlyConfig = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# ifdef VBOX_WITH_SUID_WRAPPER /* Solaris setuid for Passthrough mode. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = solarisCheckUserAuth();
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DVD: solarisCheckUserAuth failed. Permission denied!\n"));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# endif /* VBOX_WITH_SUID_WRAPPER */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif /* !RT_OS_L4 */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->IMount.pfnUnmount = drvHostDvdUnmount;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->pfnDoLock = drvHostDvdDoLock;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef USE_MEDIA_POLLING
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!fPassthrough)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->pfnPoll = drvHostDvdPoll;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->pfnPoll = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_LINUX
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->pfnGetMediaSize = drvHostDvdGetMediaSize;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * 2nd init part.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = DRVHostBaseInitFinish(pThis);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!pThis->fAttachFailError)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Suppressing the attach failure error must not affect the normal
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * DRVHostBaseDestruct, so reset this flag below before leaving. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->fKeepInstance = true;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DRVHostBaseDestruct(pDrvIns);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->fKeepInstance = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("drvHostDvdConstruct: returns %Rrc\n", rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Block driver registration record.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncconst PDMDRVREG g_DrvHostDVD =
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* u32Version */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDM_DRVREG_VERSION,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* szDriverName */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync "HostDVD",
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* pszDescription */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync "Host DVD Block Driver.",
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* fFlags */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* fClass. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDM_DRVREG_CLASS_BLOCK,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* cMaxInstances */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync ~0,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* cbInstance */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync sizeof(DRVHOSTBASE),
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* pfnConstruct */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync drvHostDvdConstruct,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* pfnDestruct */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DRVHostBaseDestruct,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* pfnIOCtl */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* pfnPowerOn */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync NULL,
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync /* pfnReset */
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync NULL,
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync /* pfnSuspend */
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync NULL,
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync /* pfnResume */
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync NULL,
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync /* pfnDetach */
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync NULL
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync};
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync
75f41c9995e4a8d9ed39651503f229147318dbd2vboxsync