DrvHostBase.cpp revision 727cf0d6c794dffee1023d2bbb6e94eda7f35ca9
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * DrvHostBase - Host base drive access driver.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Copyright (C) 2006-2007 innotek GmbH
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * available from http://www.virtualbox.org. This file is free software;
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * General Public License as published by the Free Software Foundation,
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*******************************************************************************
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync* Header Files *
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync*******************************************************************************/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync# include <IOKit/storage/IOStorageDeviceCharacteristics.h>
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync# include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync /* Nothing special requires... yeah, right. */
/* from ntdef.h */
/* from ntddk.h */
typedef struct _IO_STATUS_BLOCK {
/* from ntinternals.com */
typedef enum _FS_INFORMATION_CLASS {
typedef struct _FILE_FS_SIZE_INFORMATION {
#include "DrvHostBase.h"
static DECLCALLBACK(int) drvHostBaseRead(PPDMIBLOCK pInterface, uint64_t off, void *pvBuf, size_t cbRead)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, off, pvBuf, cbRead, pThis->pszDevice));
int rc;
#ifdef RT_OS_DARWIN
#ifdef RT_OS_DARWIN
SCSI_READ_12, 0,
Log(("%s-%d: drvHostBaseRead: RTFileSeek(%d,%#llx,) -> %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName,
LogFlow(("%s-%d: drvHostBaseRead: returns %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) drvHostBaseWrite(PPDMIBLOCK pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, off, pvBuf, cbWrite, pThis->pszDevice));
int rc;
#ifdef RT_OS_DARWIN
LogFlow(("%s-%d: drvHostBaseWrite: returns %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
int rc;
#ifdef RT_OS_DARWIN
LogFlow(("%s-%d: drvHostBaseFlush: returns %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
LogFlow(("%s-%d: drvHostBaseGetSize: returns %llu\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, cb));
return cb;
LogFlow(("%s-%d: drvHostBaseGetType: returns %d\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->enmType));
LogFlow(("%s-%d: drvHostBaseGetUuid: returns VINF_SUCCESS *pUuid=%Vuuid\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pUuid));
return VINF_SUCCESS;
#define PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface) ( (PDRVHOSTBASE((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTBASE, IBlockBios))) )
static DECLCALLBACK(int) drvHostBaseGetGeometry(PPDMIBLOCKBIOS pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc, *pcCylinders, *pcHeads, *pcSectors));
return rc;
static DECLCALLBACK(int) drvHostBaseSetGeometry(PPDMIBLOCKBIOS pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)
return rc;
static DECLCALLBACK(int) drvHostBaseGetTranslation(PPDMIBLOCKBIOS pInterface, PPDMBIOSTRANSLATION penmTranslation)
return rc;
static DECLCALLBACK(int) drvHostBaseSetTranslation(PPDMIBLOCKBIOS pInterface, PDMBIOSTRANSLATION enmTranslation)
return rc;
static DECLCALLBACK(int) drvHostBaseMount(PPDMIMOUNT pInterface, const char *pszFilename, const char *pszCoreDriver)
return VERR_PDM_MEDIA_MOUNTED;
return VERR_NOT_SUPPORTED;
return fRc;
LogFlow(("%s-%d: drvHostBaseLock: already locked\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
LogFlow(("%s-%d: drvHostBaseLock: returns %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
LogFlow(("%s-%d: drvHostBaseUnlock: not locked\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
LogFlow(("%s-%d: drvHostBaseUnlock: returns %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
return fRc;
static DECLCALLBACK(void *) drvHostBaseQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
switch (enmInterface)
case PDMINTERFACE_BASE:
case PDMINTERFACE_BLOCK:
case PDMINTERFACE_BLOCK_BIOS:
case PDMINTERFACE_MOUNT:
return NULL;
#ifdef RT_OS_DARWIN
CFStringRef BSDNameStrRef = (CFStringRef)IORegistryEntryCreateCFProperty(Child, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0);
if (BSDNameStrRef)
AssertFailed();
return rc;
static void drvHostBaseDADoneCallback(DADiskRef DiskRef, DADissenterRef DissenterRef, void *pvContext)
if (!DissenterRef)
*prc = 0;
SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, false, 0,
return VINF_SUCCESS;
return VERR_DRIVE_LOCKED;
Log(("%s-%d: calling DADiskClaim on '%s'.\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
DADiskClaim(pThis->pDADisk, kDADiskClaimOptionDefault, NULL, NULL, drvHostBaseDADoneCallback, &rcDA);
&& !rcDA)
Log(("%s-%d: calling DADiskUnmount on '%s'.\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
&& !rcDA)
Log(("%s-%d: umount => rc32=%d & rcDA=%#x\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc32, rcDA));
Log(("%s-%d: claim => rc32=%d & rcDA=%#x\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc32, rcDA));
Log(("%s-%d: failed to open disk '%s'!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
#ifndef RT_OS_SOLARIS
#ifdef RT_OS_DARWIN
* (This enumeration must be identical to the one performed in DrvHostBase.cpp.)
kern_return_t krc = IORegistryEntryCreateCFProperties(DVDService, &PropsRef, kCFAllocatorDefault, kNilOptions);
CFDictionaryRef DevCharRef = (CFDictionaryRef)CFDictionaryGetValue(PropsRef, CFSTR(kIOPropertyDeviceCharacteristicsKey));
if (DevCharRef)
if ( ValueRef
if ( ValueRef
krc = IOCreatePlugInInterfaceForService(DVDService, kIOMMCDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
return rc;
int FileDevice = open(pThis->pszDeviceOpen, (pThis->fReadOnlyConfig ? O_RDONLY : O_RDWR) | O_NONBLOCK);
if (FileDevice < 0)
return VINF_SUCCESS;
static int drvHostBaseOpen(PDRVHOSTBASE pThis, PRTFILE pBlockFileDevice, PRTFILE pFileRawDevice, bool fReadOnly)
unsigned fFlags = (pThis->fReadOnlyConfig ? RTFILE_O_READ : RTFILE_O_READWRITE) | RTFILE_O_NON_BLOCK;
return rc;
LogFlow(("%s-%d: drvHostBaseReopen: '%s'\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->pszDeviceOpen));
#ifdef RT_OS_SOLARIS
LogFlow(("%s-%d: drvHostBaseReopen: '%s' - retry readonly (%Vrc)\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->pszDeviceOpen, rc));
#ifdef RT_OS_SOLARIS
return rc;
#ifdef RT_OS_SOLARIS
return VINF_SUCCESS;
#ifdef RT_OS_DARWIN
} Buf = {0, 0};
SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0,
// Buf.cbBlock = 2048;
return rc;
return VINF_SUCCESS;
if (rcNt >= 0)
return VINF_SUCCESS;
switch (rcNt)
return rc;
#ifdef RT_OS_DARWIN
DECLCALLBACK(int) DRVHostBaseScsiCmd(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMBLOCKTXDIR enmTxDir,
Assert(enmTxDir == PDMBLOCKTXDIR_NONE || enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE || enmTxDir == PDMBLOCKTXDIR_TO_DEVICE);
if (pcbBuf)
*pcbBuf = 0;
# ifdef RT_OS_DARWIN
if (!ppScsiTaskI)
return VERR_NO_MEMORY;
irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, NULL, 0, 0, kSCSIDataTransfer_NoDataTransfer);
irc = (*ppScsiTaskI)->SetTimeoutDuration(ppScsiTaskI, cTimeoutMillies ? cTimeoutMillies : 30000 /*ms*/);
if (pcbBuf)
&& pbSense)
return rc;
return rc;
return rc;
return VINF_SUCCESS;
#ifdef RT_OS_WINDOWS
if (pThis)
PostQuitMessage(0);
switch (wParam)
case DBT_DEVICEARRIVAL:
case DBT_DEVICEREMOVECOMPLETE:
return TRUE;
#ifdef RT_OS_WINDOWS
if (s_hAtomDeviceChange == 0)
HWND hwnd = CreateWindow((LPCTSTR)s_hAtomDeviceChange, "", WS_POPUP, 0, 0, 0, 0, 0, 0, s_classDeviceChange.hInstance, 0);
if (!hwnd)
LogFlow(("%s-%d: drvHostBaseMediaThread: returns VERR_GENERAL_FAILURE\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VERR_GENERAL_FAILURE;
LogFlow(("%s-%d: drvHostBaseMediaThread: Created hwndDeviceChange=%p\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, hwnd));
bool fFirst = true;
&& cRetries-- > 0)
if (fFirst)
fFirst = false;
return rc;
LogFlow(("%s-%d: drvHostBaseMediaThread: returns VINF_SUCCESS\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VINF_SUCCESS;
LogFlow(("%s-%d: drvHostBaseMediaThread:\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VINF_SUCCESS;
LogFlow(("%s-%d: drvHostBaseDestruct: iInstance=%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pDrvIns->iInstance));
int rc;
#ifdef RT_OS_WINDOWS
PostMessage(pThis->hwndDeviceChange, WM_CLOSE, 0, 0); /* default win proc will destroy the window */
if (!rc)
#ifdef RT_OS_DARWIN
* (We're currently not unlocking the device after use. See todo in DevATA.cpp.) */
#ifdef RT_OS_WINDOWS
PostMessage(pThis->hwndDeviceChange, WM_CLOSE, 0, 0); /* default win proc will destroy the window */
#ifdef RT_OS_DARWIN
LogFlow(("%s-%d: releasing exclusive scsi access!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: releasing the MMC object!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: releasing the DA session!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
#ifdef RT_OS_SOLARIS
LogFlow(("%s-%d: drvHostBaseDestruct completed\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: DRVHostBaseInitData: iInstance=%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pDrvIns->iInstance));
#ifdef RT_OS_DARWIN
#ifdef RT_OS_SOLARIS
pThis->pDrvBlockPort = (PPDMIBLOCKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_BLOCK_PORT);
return VERR_PDM_MISSING_INTERFACE_ABOVE;
pThis->pDrvMountNotify = (PPDMIMOUNTNOTIFY)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MOUNT_NOTIFY);
return rc;
return rc;
pThis->fReadOnlyConfig = enmType == PDMBLOCKTYPE_DVD || enmType == PDMBLOCKTYPE_CDROM ? true : false;
return rc;
return rc;
return rc;
char *psz;
return rc;
return rc;
bool fAttachFailError;
fAttachFailError = true;
#ifdef RT_OS_WINDOWS
return VERR_INVALID_PARAMETER;
if (!pszBlockDevName)
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
Log(("%s-%d: pszDevice='%s' (%s) cMilliesPoller=%d fReadOnlyConfig=%d fLocked=%d fBIOSVisible=%d Uuid=%Vuuid\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pThis->pszDevice, pThis->pszDeviceOpen, pThis->cMilliesPoller,
return VERR_PDM_DRVINS_NO_ATTACH;
rc = pDrvIns->pDrvHlp->pfnSSMRegister(pDrvIns, pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, 1, 0,
return rc;
#ifdef RT_OS_WINDOWS
case PDMBLOCKTYPE_FLOPPY_360:
case PDMBLOCKTYPE_FLOPPY_720:
case PDMBLOCKTYPE_FLOPPY_1_20:
case PDMBLOCKTYPE_FLOPPY_1_44:
case PDMBLOCKTYPE_FLOPPY_2_88:
return VERR_INVALID_PARAMETER;
case PDMBLOCKTYPE_CDROM:
case PDMBLOCKTYPE_DVD:
return VERR_INVALID_PARAMETER;
case PDMBLOCKTYPE_HARD_DISK:
return VERR_INVALID_PARAMETER;
#ifdef RT_OS_DARWIN
#ifndef RT_OS_DARWIN
#ifdef RT_OS_SOLARIS
switch (rc)
case VERR_ACCESS_DENIED:
#ifdef RT_OS_LINUX
return rc;
#ifdef RT_OS_WINDOWS
return rc;
#ifndef RT_OS_WINDOWS
return rc;
return rc;
return rc;
#ifdef RT_OS_WINDOWS
return VERR_GENERAL_FAILURE;
return src;
return rc;