DrvBlock.cpp revision 0abd77741a608f6c41c8dfcd4781b8b84adf1044
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @file
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * VBox storage devices:
af062818b47340eef15700d2f0211576ba3506eevboxsync * Generic block driver
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync * additional information or have any questions.
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Header Files *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#define LOG_GROUP LOG_GROUP_DRV_BLOCK
af062818b47340eef15700d2f0211576ba3506eevboxsync#include <VBox/pdmdrv.h>
af062818b47340eef15700d2f0211576ba3506eevboxsync#include <iprt/assert.h>
af062818b47340eef15700d2f0211576ba3506eevboxsync#include <iprt/uuid.h>
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#include <string.h>
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#include "Builtins.h"
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @def VBOX_PERIODIC_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync * Enable support for periodically flushing the VDI to disk. This may prove
af062818b47340eef15700d2f0211576ba3506eevboxsync * useful for those nasty problems with the ultra-slow host filesystems.
af062818b47340eef15700d2f0211576ba3506eevboxsync * If this is enabled, it can be configured via the CFGM key
af062818b47340eef15700d2f0211576ba3506eevboxsync * "VBoxInternal/Devices/piix3ide/0/LUN#<x>/Config/FlushInterval". <x>
af062818b47340eef15700d2f0211576ba3506eevboxsync * must be replaced with the correct LUN number of the disk that should
af062818b47340eef15700d2f0211576ba3506eevboxsync * do the periodic flushes. The value of the key is the number of bytes
af062818b47340eef15700d2f0211576ba3506eevboxsync * written between flushes. A value of 0 (the default) denotes no flushes. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define VBOX_PERIODIC_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @def VBOX_IGNORE_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync * Enable support for ignoring VDI flush requests. This can be useful for
af062818b47340eef15700d2f0211576ba3506eevboxsync * filesystems that show bad guest IDE write performance (especially with
af062818b47340eef15700d2f0211576ba3506eevboxsync * Windows guests). NOTE that this does not disable the flushes caused by
af062818b47340eef15700d2f0211576ba3506eevboxsync * the periodic flush cache feature above.
af062818b47340eef15700d2f0211576ba3506eevboxsync * If this feature is enabled, it can be configured via the CFGM key
af062818b47340eef15700d2f0211576ba3506eevboxsync * "VBoxInternal/Devices/piix3ide/0/LUN#<x>/Config/IgnoreFlush". <x>
af062818b47340eef15700d2f0211576ba3506eevboxsync * must be replaced with the correct LUN number of the disk that should
af062818b47340eef15700d2f0211576ba3506eevboxsync * ignore flush requests. The value of the key is a boolean. The default
af062818b47340eef15700d2f0211576ba3506eevboxsync * is to ignore flushes, i.e. true. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define VBOX_IGNORE_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Structures and Typedefs *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/**
af062818b47340eef15700d2f0211576ba3506eevboxsync * Block driver instance data.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct DRVBLOCK
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer driver instance. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMDRVINS pDrvIns;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Drive type. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMBLOCKTYPE enmType;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Locked indicator. */
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fLocked;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Mountable indicator. */
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fMountable;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Visible to the BIOS. */
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fBiosVisible;
af062818b47340eef15700d2f0211576ba3506eevboxsync#ifdef VBOX_PERIODIC_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync /** HACK: Configuration value for number of bytes written after which to flush. */
af062818b47340eef15700d2f0211576ba3506eevboxsync uint32_t cbFlushInterval;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** HACK: Current count for the number of bytes written since the last flush. */
af062818b47340eef15700d2f0211576ba3506eevboxsync uint32_t cbDataWritten;
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_PERIODIC_FLUSH */
af062818b47340eef15700d2f0211576ba3506eevboxsync#ifdef VBOX_IGNORE_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync /** HACK: Disable flushes for this drive. */
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fIgnoreFlush;
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_IGNORE_FLUSH */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the media driver below us.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This is NULL if the media is not mounted. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIMEDIA pDrvMedia;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the block port interface above us. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIBLOCKPORT pDrvBlockPort;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the mount notify interface above us. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIMOUNTNOTIFY pDrvMountNotify;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Our block interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMIBLOCK IBlock;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Our block interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMIBLOCKBIOS IBlockBios;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Our mountable interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMIMOUNT IMount;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the async media driver below us.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This is NULL if the media is not mounted. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIMEDIAASYNC pDrvMediaAsync;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Our media async port. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMIMEDIAASYNCPORT IMediaAsyncPort;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the async block port interface above us. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIBLOCKASYNCPORT pDrvBlockAsyncPort;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Our async block interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMIBLOCKASYNC IBlockAsync;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Uuid of the drive. */
af062818b47340eef15700d2f0211576ba3506eevboxsync RTUUID Uuid;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /** BIOS PCHS Geometry. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMMEDIAGEOMETRY PCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** BIOS LCHS Geometry. */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMMEDIAGEOMETRY LCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync} DRVBLOCK, *PDRVBLOCK;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/* -=-=-=-=- IBlock -=-=-=-=- */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Makes a PDRVBLOCK out of a PPDMIBLOCK. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define PDMIBLOCK_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlock)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnRead */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockRead(PPDMIBLOCK pInterface, uint64_t off, void *pvBuf, size_t cbRead)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnRead(pData->pDrvMedia, off, pvBuf, cbRead);
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnWrite */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockWrite(PPDMIBLOCK pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnWrite(pData->pDrvMedia, off, pvBuf, cbWrite);
af062818b47340eef15700d2f0211576ba3506eevboxsync#ifdef VBOX_PERIODIC_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->cbFlushInterval)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->cbDataWritten += cbWrite;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->cbDataWritten > pData->cbFlushInterval)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->cbDataWritten = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->pDrvMedia->pfnFlush(pData->pDrvMedia);
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_PERIODIC_FLUSH */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnFlush */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockFlush(PPDMIBLOCK pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#ifdef VBOX_IGNORE_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->fIgnoreFlush)
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_IGNORE_FLUSH */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnFlush(pData->pDrvMedia);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (rc == VERR_NOT_IMPLEMENTED)
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnIsReadOnly */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(bool) drvblockIsReadOnly(PPDMIBLOCK pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync return false;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fRc = pData->pDrvMedia->pfnIsReadOnly(pData->pDrvMedia);
af062818b47340eef15700d2f0211576ba3506eevboxsync return fRc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnGetSize */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(uint64_t) drvblockGetSize(PPDMIBLOCK pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync return 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync uint64_t cb = pData->pDrvMedia->pfnGetSize(pData->pDrvMedia);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("drvblockGetSize: returns %llu\n", cb));
af062818b47340eef15700d2f0211576ba3506eevboxsync return cb;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnGetType */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(PDMBLOCKTYPE) drvblockGetType(PPDMIBLOCK pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("drvblockGetType: returns %d\n", pData->enmType));
af062818b47340eef15700d2f0211576ba3506eevboxsync return pData->enmType;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCK::pfnGetUuid */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockGetUuid(PPDMIBLOCK pInterface, PRTUUID pUuid)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCK_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copy the uuid.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync *pUuid = pData->Uuid;
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/* -=-=-=-=- IBlockAsync -=-=-=-=- */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Makes a PDRVBLOCK out of a PPDMIBLOCKASYNC. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define PDMIBLOCKASYNC_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlockAsync)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKASYNC::pfnRead */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockAsyncReadStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMediaAsync)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMediaAsync->pfnStartRead(pData->pDrvMediaAsync, off, pSeg, cSeg, cbRead, pvUser);
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKASYNC::pfnWrite */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockAsyncWriteStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMediaAsync)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMediaAsync->pfnStartWrite(pData->pDrvMediaAsync, off, pSeg, cSeg, cbWrite, pvUser);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/* -=-=-=-=- IMediaAsyncPort -=-=-=-=- */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Makes a PDRVBLOCKASYNC out of a PPDMIMEDIAASYNCPORT. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface) ( (PDRVBLOCK((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IMediaAsyncPort))) )
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return pData->pDrvBlockAsyncPort->pfnTransferCompleteNotify(pData->pDrvBlockAsyncPort, pvUser);
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/* -=-=-=-=- IBlockBios -=-=-=-=- */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Makes a PDRVBLOCK out of a PPDMIBLOCKBIOS. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define PDMIBLOCKBIOS_2_DRVBLOCK(pInterface) ( (PDRVBLOCK((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlockBios))) )
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnGetPCHSGeometry */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockGetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Use configured/cached values if present.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if ( pData->PCHSGeometry.cCylinders > 0
af062818b47340eef15700d2f0211576ba3506eevboxsync && pData->PCHSGeometry.cHeads > 0
af062818b47340eef15700d2f0211576ba3506eevboxsync && pData->PCHSGeometry.cSectors > 0)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync *pPCHSGeometry = pData->PCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pData->PCHSGeometry.cCylinders, pData->PCHSGeometry.cHeads, pData->PCHSGeometry.cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Call media.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnBiosGetPCHSGeometry(pData->pDrvMedia, &pData->PCHSGeometry);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_SUCCESS(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync *pPCHSGeometry = pData->PCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns %Vrc {%d,%d,%d}\n", __FUNCTION__, rc, pData->PCHSGeometry.cCylinders, pData->PCHSGeometry.cHeads, pData->PCHSGeometry.cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync else if (rc == VERR_NOT_IMPLEMENTED)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnSetPCHSGeometry */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockSetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Call media. Ignore the not implemented return code.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnBiosSetPCHSGeometry(pData->pDrvMedia, pPCHSGeometry);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if ( RT_SUCCESS(rc)
af062818b47340eef15700d2f0211576ba3506eevboxsync || rc == VERR_NOT_IMPLEMENTED)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->PCHSGeometry = *pPCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnGetLCHSGeometry */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockGetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Use configured/cached values if present.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if ( pData->LCHSGeometry.cCylinders > 0
af062818b47340eef15700d2f0211576ba3506eevboxsync && pData->LCHSGeometry.cHeads > 0
af062818b47340eef15700d2f0211576ba3506eevboxsync && pData->LCHSGeometry.cSectors > 0)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync *pLCHSGeometry = pData->LCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pData->LCHSGeometry.cCylinders, pData->LCHSGeometry.cHeads, pData->LCHSGeometry.cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Call media.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnBiosGetLCHSGeometry(pData->pDrvMedia, &pData->LCHSGeometry);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_SUCCESS(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync *pLCHSGeometry = pData->LCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns %Vrc {%d,%d,%d}\n", __FUNCTION__, rc, pData->LCHSGeometry.cCylinders, pData->LCHSGeometry.cHeads, pData->LCHSGeometry.cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync else if (rc == VERR_NOT_IMPLEMENTED)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnSetLCHSGeometry */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockSetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check the state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid state! Not mounted!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Call media. Ignore the not implemented return code.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvMedia->pfnBiosSetLCHSGeometry(pData->pDrvMedia, pLCHSGeometry);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if ( RT_SUCCESS(rc)
af062818b47340eef15700d2f0211576ba3506eevboxsync || rc == VERR_NOT_IMPLEMENTED)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->LCHSGeometry = *pLCHSGeometry;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnIsVisible */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(bool) drvblockIsVisible(PPDMIBLOCKBIOS pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("drvblockIsVisible: returns %d\n", pData->fBiosVisible));
af062818b47340eef15700d2f0211576ba3506eevboxsync return pData->fBiosVisible;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIBLOCKBIOS::pfnGetType */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(PDMBLOCKTYPE) drvblockBiosGetType(PPDMIBLOCKBIOS pInterface)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("drvblockBiosGetType: returns %d\n", pData->enmType));
af062818b47340eef15700d2f0211576ba3506eevboxsync return pData->enmType;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/* -=-=-=-=- IMount -=-=-=-=- */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Makes a PDRVBLOCK out of a PPDMIMOUNT. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define PDMIMOUNT_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IMount)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIMOUNT::pfnMount */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockMount(PPDMIMOUNT pInterface, const char *pszFilename, const char *pszCoreDriver)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("drvblockMount: pszFilename=%p:{%s} pszCoreDriver=%p:{%s}\n", pszFilename, pszFilename, pszCoreDriver, pszCoreDriver));
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Already mounted\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Prepare configuration.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pszFilename)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvIns->pDrvHlp->pfnMountPrepare(pData->pDrvIns, pszFilename, pszCoreDriver);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_FAILURE(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockMount: Prepare failed for \"%s\" rc=%Vrc\n", pszFilename, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Attach the media driver and query it's interface.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync PPDMIBASE pBase;
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvIns->pDrvHlp->pfnAttach(pData->pDrvIns, &pBase);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_FAILURE(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockMount: Attach failed rc=%Vrc\n", rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->pDrvMedia = (PPDMIMEDIA)pBase->pfnQueryInterface(pBase, PDMINTERFACE_MEDIA);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Initialize state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->fLocked = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->PCHSGeometry.cCylinders = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->PCHSGeometry.cHeads = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->PCHSGeometry.cSectors = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->LCHSGeometry.cCylinders = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->LCHSGeometry.cHeads = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->LCHSGeometry.cSectors = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync#ifdef VBOX_PERIODIC_FLUSH
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->cbDataWritten = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_PERIODIC_FLUSH */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Notify driver/device above us.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->pDrvMountNotify)
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->pDrvMountNotify->pfnMountNotify(pData->pDrvMountNotify);
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockMount: Success\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync else
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VERR_PDM_MISSING_INTERFACE_BELOW;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Failed, detatch the media driver.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("No media interface!\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc2 = pData->pDrvIns->pDrvHlp->pfnDetach(pData->pDrvIns);
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertRC(rc2);
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->pDrvMedia = NULL;
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @copydoc PDMIMOUNT::pfnUnmount */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) drvblockUnmount(PPDMIMOUNT pInterface, bool fForce)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate state.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pData->pDrvMedia)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockUmount: Not mounted\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_NOT_MOUNTED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pData->fLocked && !fForce)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockUmount: Locked\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_MEDIA_LOCKED;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Media is no longer locked even if it was previously. */
af062818b47340eef15700d2f0211576ba3506eevboxsync pData->fLocked = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Detach the media driver and query it's interface.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pData->pDrvIns->pDrvHlp->pfnDetach(pData->pDrvIns);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_FAILURE(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("drvblockUnmount: Detach failed rc=%Vrc\n", rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync return rc;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync Assert(!pData->pDrvMedia);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Notify driver/device above us.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
if (pData->pDrvMountNotify)
pData->pDrvMountNotify->pfnUnmountNotify(pData->pDrvMountNotify);
Log(("drvblockUnmount: success\n"));
return VINF_SUCCESS;
}
/** @copydoc PDMIMOUNT::pfnIsMounted */
static DECLCALLBACK(bool) drvblockIsMounted(PPDMIMOUNT pInterface)
{
PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
return pData->pDrvMedia != NULL;
}
/** @copydoc PDMIMOUNT::pfnLock */
static DECLCALLBACK(int) drvblockLock(PPDMIMOUNT pInterface)
{
PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
Log(("drvblockLock: %d -> %d\n", pData->fLocked, true));
pData->fLocked = true;
return VINF_SUCCESS;
}
/** @copydoc PDMIMOUNT::pfnUnlock */
static DECLCALLBACK(int) drvblockUnlock(PPDMIMOUNT pInterface)
{
PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
Log(("drvblockUnlock: %d -> %d\n", pData->fLocked, false));
pData->fLocked = false;
return VINF_SUCCESS;
}
/** @copydoc PDMIMOUNT::pfnIsLocked */
static DECLCALLBACK(bool) drvblockIsLocked(PPDMIMOUNT pInterface)
{
PDRVBLOCK pData = PDMIMOUNT_2_DRVBLOCK(pInterface);
return pData->fLocked;
}
/* -=-=-=-=- IBase -=-=-=-=- */
/** @copydoc PDMIBASE::pfnQueryInterface. */
static DECLCALLBACK(void *) drvblockQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
{
PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
PDRVBLOCK pData = PDMINS_2_DATA(pDrvIns, PDRVBLOCK);
switch (enmInterface)
{
case PDMINTERFACE_BASE:
return &pDrvIns->IBase;
case PDMINTERFACE_BLOCK:
return &pData->IBlock;
case PDMINTERFACE_BLOCK_BIOS:
return pData->fBiosVisible ? &pData->IBlockBios : NULL;
case PDMINTERFACE_MOUNT:
return pData->fMountable ? &pData->IMount : NULL;
case PDMINTERFACE_BLOCK_ASYNC:
return pData->pDrvMediaAsync ? &pData->IBlockAsync : NULL;
case PDMINTERFACE_MEDIA_ASYNC_PORT:
return pData->pDrvBlockAsyncPort ? &pData->IMediaAsyncPort : NULL;
default:
return NULL;
}
}
/* -=-=-=-=- driver interface -=-=-=-=- */
/** @copydoc FNPDMDRVDETACH. */
static DECLCALLBACK(void) drvblockDetach(PPDMDRVINS pDrvIns)
{
PDRVBLOCK pData = PDMINS_2_DATA(pDrvIns, PDRVBLOCK);
pData->pDrvMedia = NULL;
pData->pDrvMediaAsync = NULL;
}
/**
* Reset notification.
*
* @returns VBox status.
* @param pDevIns The driver instance data.
*/
static DECLCALLBACK(void) drvblockReset(PPDMDRVINS pDrvIns)
{
PDRVBLOCK pData = PDMINS_2_DATA(pDrvIns, PDRVBLOCK);
pData->fLocked = false;
}
/**
* Construct a block driver instance.
*
* @returns VBox status.
* @param pDrvIns The driver instance data.
* If the registration structure is needed, pDrvIns->pDrvReg points to it.
* @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
* of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
* iInstance it's expected to be used a bit in this function.
*/
static DECLCALLBACK(int) drvblockConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
{
PDRVBLOCK pData = PDMINS_2_DATA(pDrvIns, PDRVBLOCK);
LogFlow(("drvblockConstruct: iInstance=%d\n", pDrvIns->iInstance));
/*
* Validate configuration.
*/
#if defined(VBOX_PERIODIC_FLUSH) || defined(VBOX_IGNORE_FLUSH)
if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0FlushInterval\0IgnoreFlush\0"))
#else /* !(VBOX_PERIODIC_FLUSH || VBOX_IGNORE_FLUSH) */
if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0"))
#endif /* !(VBOX_PERIODIC_FLUSH || VBOX_IGNORE_FLUSH) */
return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
/*
* Initialize most of the data members.
*/
pData->pDrvIns = pDrvIns;
/* IBase. */
pDrvIns->IBase.pfnQueryInterface = drvblockQueryInterface;
/* IBlock. */
pData->IBlock.pfnRead = drvblockRead;
pData->IBlock.pfnWrite = drvblockWrite;
pData->IBlock.pfnFlush = drvblockFlush;
pData->IBlock.pfnIsReadOnly = drvblockIsReadOnly;
pData->IBlock.pfnGetSize = drvblockGetSize;
pData->IBlock.pfnGetType = drvblockGetType;
pData->IBlock.pfnGetUuid = drvblockGetUuid;
/* IBlockBios. */
pData->IBlockBios.pfnGetPCHSGeometry = drvblockGetPCHSGeometry;
pData->IBlockBios.pfnSetPCHSGeometry = drvblockSetPCHSGeometry;
pData->IBlockBios.pfnGetLCHSGeometry = drvblockGetLCHSGeometry;
pData->IBlockBios.pfnSetLCHSGeometry = drvblockSetLCHSGeometry;
pData->IBlockBios.pfnIsVisible = drvblockIsVisible;
pData->IBlockBios.pfnGetType = drvblockBiosGetType;
/* IMount. */
pData->IMount.pfnMount = drvblockMount;
pData->IMount.pfnUnmount = drvblockUnmount;
pData->IMount.pfnIsMounted = drvblockIsMounted;
pData->IMount.pfnLock = drvblockLock;
pData->IMount.pfnUnlock = drvblockUnlock;
pData->IMount.pfnIsLocked = drvblockIsLocked;
/* IBlockAsync. */
pData->IBlockAsync.pfnStartRead = drvblockAsyncReadStart;
pData->IBlockAsync.pfnStartWrite = drvblockAsyncWriteStart;
/* IMediaAsyncPort. */
pData->IMediaAsyncPort.pfnTransferCompleteNotify = drvblockAsyncTransferCompleteNotify;
/*
* Get the IBlockPort & IMountNotify interfaces of the above driver/device.
*/
pData->pDrvBlockPort = (PPDMIBLOCKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_BLOCK_PORT);
if (!pData->pDrvBlockPort)
return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
N_("No block port interface above"));
/* Try to get the optional async block port interface above. */
pData->pDrvBlockAsyncPort = (PPDMIBLOCKASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_BLOCK_ASYNC_PORT);
pData->pDrvMountNotify = (PPDMIMOUNTNOTIFY)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MOUNT_NOTIFY);
/*
* Query configuration.
*/
/* type */
char *psz;
int rc = CFGMR3QueryStringAlloc(pCfgHandle, "Type", &psz);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_BLOCK_NO_TYPE, N_("Failed to obtain the type"));
if (!strcmp(psz, "HardDisk"))
pData->enmType = PDMBLOCKTYPE_HARD_DISK;
else if (!strcmp(psz, "DVD"))
pData->enmType = PDMBLOCKTYPE_DVD;
else if (!strcmp(psz, "CDROM"))
pData->enmType = PDMBLOCKTYPE_CDROM;
else if (!strcmp(psz, "Floppy 2.88"))
pData->enmType = PDMBLOCKTYPE_FLOPPY_2_88;
else if (!strcmp(psz, "Floppy 1.44"))
pData->enmType = PDMBLOCKTYPE_FLOPPY_1_44;
else if (!strcmp(psz, "Floppy 1.20"))
pData->enmType = PDMBLOCKTYPE_FLOPPY_1_20;
else if (!strcmp(psz, "Floppy 720"))
pData->enmType = PDMBLOCKTYPE_FLOPPY_720;
else if (!strcmp(psz, "Floppy 360"))
pData->enmType = PDMBLOCKTYPE_FLOPPY_360;
else
{
PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_BLOCK_UNKNOWN_TYPE, RT_SRC_POS,
N_("Unknown type \"%s\""), psz);
MMR3HeapFree(psz);
return VERR_PDM_BLOCK_UNKNOWN_TYPE;
}
Log2(("drvblockConstruct: enmType=%d\n", pData->enmType));
MMR3HeapFree(psz); psz = NULL;
/* Mountable */
rc = CFGMR3QueryBoolDef(pCfgHandle, "Mountable", &pData->fMountable, false);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Mountable\" from the config"));
/* Locked */
rc = CFGMR3QueryBoolDef(pCfgHandle, "Locked", &pData->fLocked, false);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Locked\" from the config"));
/* BIOS visible */
rc = CFGMR3QueryBoolDef(pCfgHandle, "BIOSVisible", &pData->fBiosVisible, true);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"BIOSVisible\" from the config"));
/** @todo AttachFailError is currently completely ignored. */
/* Cylinders */
rc = CFGMR3QueryU32Def(pCfgHandle, "Cylinders", &pData->LCHSGeometry.cCylinders, 0);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Cylinders\" from the config"));
/* Heads */
rc = CFGMR3QueryU32Def(pCfgHandle, "Heads", &pData->LCHSGeometry.cHeads, 0);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Heads\" from the config"));
/* Sectors */
rc = CFGMR3QueryU32Def(pCfgHandle, "Sectors", &pData->LCHSGeometry.cSectors, 0);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Sectors\" from the config"));
/* Uuid */
rc = CFGMR3QueryStringAlloc(pCfgHandle, "Uuid", &psz);
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
RTUuidClear(&pData->Uuid);
else if (RT_SUCCESS(rc))
{
rc = RTUuidFromStr(&pData->Uuid, psz);
if (RT_FAILURE(rc))
{
PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, "%s",
N_("Uuid from string failed on \"%s\""), psz);
MMR3HeapFree(psz);
return rc;
}
MMR3HeapFree(psz); psz = NULL;
}
else
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Uuid\" from the config"));
#ifdef VBOX_PERIODIC_FLUSH
rc = CFGMR3QueryU32Def(pCfgHandle, "FlushInterval", &pData->cbFlushInterval, 0);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"FlushInterval\" from the config"));
#endif /* VBOX_PERIODIC_FLUSH */
#ifdef VBOX_IGNORE_FLUSH
rc = CFGMR3QueryBoolDef(pCfgHandle, "IgnoreFlush", &pData->fIgnoreFlush, true);
if (RT_FAILURE(rc))
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"IgnoreFlush\" from the config"));
#endif /* VBOX_IGNORE_FLUSH */
/*
* Try attach driver below and query it's media interface.
*/
PPDMIBASE pBase;
rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBase);
if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
&& pData->enmType != PDMBLOCKTYPE_HARD_DISK)
return VINF_SUCCESS;
if (RT_FAILURE(rc))
{
AssertLogRelMsgFailed(("Failed to attach driver below us! rc=%Vra\n", rc));
return rc;
}
pData->pDrvMedia = (PPDMIMEDIA)pBase->pfnQueryInterface(pBase, PDMINTERFACE_MEDIA);
if (!pData->pDrvMedia)
return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
N_("No media or async media interface below"));
/* Try to get the optional async interface. */
pData->pDrvMediaAsync = (PPDMIMEDIAASYNC)pBase->pfnQueryInterface(pBase, PDMINTERFACE_MEDIA_ASYNC);
if (RTUuidIsNull(&pData->Uuid))
{
if (pData->enmType == PDMBLOCKTYPE_HARD_DISK)
pData->pDrvMedia->pfnGetUuid(pData->pDrvMedia, &pData->Uuid);
}
return VINF_SUCCESS;
}
/**
* Block driver registration record.
*/
const PDMDRVREG g_DrvBlock =
{
/* u32Version */
PDM_DRVREG_VERSION,
/* szDriverName */
"Block",
/* pszDescription */
"Generic block driver.",
/* fFlags */
PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
/* fClass. */
PDM_DRVREG_CLASS_BLOCK,
/* cMaxInstances */
~0,
/* cbInstance */
sizeof(DRVBLOCK),
/* pfnConstruct */
drvblockConstruct,
/* pfnDestruct */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
drvblockReset,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnDetach */
drvblockDetach
};