DrvVD.cpp revision 369a8817da53dbd5ea6ac360ca0376dba003cde4
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/* $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * DrvVD - Generic VBox disk media driver.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * additional information or have any questions.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
cd6f71bc352f550074f1ba2c830a2cf2f0b3dd46vboxsync/*******************************************************************************
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync* Header files *
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync*******************************************************************************/
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define LOG_GROUP LOG_GROUP_DRV_VD
16a9adc14900ca18e6909679a579f6833425e030vboxsync#include <VBox/VBoxHDD.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/pdmdrv.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/pdmasynccompletion.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/alloc.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/uuid.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include <iprt/file.h>
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#include <iprt/string.h>
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync#include <iprt/tcp.h>
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#include <iprt/semaphore.h>
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync#ifdef VBOX_WITH_INIP
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync/* All lwip header files are not C++ safe. So hack around this. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncRT_C_DECLS_BEGIN
efff36b306e370346025647a158689021df2e1d1vboxsync#include <lwip/inet.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include <lwip/tcp.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#include <lwip/sockets.h>
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncRT_C_DECLS_END
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif /* VBOX_WITH_INIP */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include "Builtins.h"
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync#ifdef VBOX_WITH_INIP
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/* Small hack to get at lwIP initialized status */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncextern bool DevINIPConfigured(void);
efff36b306e370346025647a158689021df2e1d1vboxsync#endif /* VBOX_WITH_INIP */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
efff36b306e370346025647a158689021df2e1d1vboxsync* Defined types, constants and macros *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync/** Converts a pointer to VBOXDISK::IMedia to a PVBOXDISK. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#define PDMIMEDIA_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIBASE_2_DRVINS(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIBASE_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync#define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \
9496f2d398b49813176939d7a339ae513d5175efvboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * VBox disk container, image information, private part.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsynctypedef struct VBOXIMAGE
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to next image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync struct VBOXIMAGE *pNext;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to list of VD interfaces. Per-image. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVDINTERFACE pVDIfsImage;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** Common structure for the configuration information interface. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACE VDIConfig;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync} VBOXIMAGE, *PVBOXIMAGE;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Storage backend data.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsynctypedef struct DRVVDSTORAGEBACKEND
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** PDM async completion end point. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PPDMASYNCCOMPLETIONENDPOINT pEndpoint;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** The template. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PPDMASYNCCOMPLETIONTEMPLATE pTemplate;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Event semaphore for synchronous operations. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTSEMEVENT EventSem;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Flag whether a synchronous operation is currently pending. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync volatile bool fSyncIoPending;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Callback routine */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PFNVDCOMPLETED pfnCompleted;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync /** Pointer to the optional thread synchronization interface of the disk. */
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync PVDINTERFACE pInterfaceThreadSync;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Pointer to the optional thread synchronization callbacks of the disk. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync} DRVVDSTORAGEBACKEND, *PDRVVDSTORAGEBACKEND;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media main structure, private part.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIMEDIA
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIMEDIAASYNC
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACEERROR
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACETCPNET
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACEASYNCIO
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACECONFIG
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct VBOXDISK
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The VBox disk container. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVBOXHDD pDisk;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The media interface. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PDMIMEDIA IMedia;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /** Pointer to the driver instance. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PPDMDRVINS pDrvIns;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether suspend has changed image open mode to read only. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync bool fTempReadOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether to use the runtime (true) or startup error facility. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync bool fErrorUseRuntime;
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Pointer to list of VD interfaces. Per-disk. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVDINTERFACE pVDIfsDisk;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the supported error interface. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACE VDIError;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** Callback table for error interface. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACEERROR VDIErrorCallbacks;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** Common structure for the supported TCP network stack interface. */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACE VDITcpNet;
c0a370e600bb60153a269fb32b5f709347c35768vboxsync /** Callback table for TCP network stack interface. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync VDINTERFACETCPNET VDITcpNetCallbacks;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** Common structure for the supported async I/O interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync VDINTERFACE VDIAsyncIO;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for async I/O interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for the configuration information interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACECONFIG VDIConfigCallbacks;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Flag whether opened disk suppports async I/O operations. */
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync bool fAsyncIOSupported;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** The async media interface. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync PDMIMEDIAASYNC IMediaAsync;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** The async media port interface above. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** Pointer to the list of data we need to keep per image. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXIMAGE pImages;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync} VBOXDISK, *PVBOXDISK;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/*******************************************************************************
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync* Internal Functions *
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync*******************************************************************************/
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * Internal: allocate new image descriptor and put it in the list
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic PVBOXIMAGE drvvdNewImage(PVBOXDISK pThis)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync AssertPtr(pThis);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pImage)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pImage->pVDIfsImage = NULL;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVBOXIMAGE *pp = &pThis->pImages;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync while (*pp != NULL)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pp = &(*pp)->pNext;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync *pp = pImage;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pImage->pNext = NULL;
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync return pImage;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Internal: free the list of images descriptors.
009d45aa55691312278d41edb20154dc208d9cd8vboxsync */
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic void drvvdFreeImages(PVBOXDISK pThis)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync while (pThis->pImages != NULL)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync {
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync PVBOXIMAGE p = pThis->pImages;
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync pThis->pImages = pThis->pImages->pNext;
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync RTMemFree(p);
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync }
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync}
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync/**
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync * Undo the temporary read-only status of the image.
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync *
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync * @returns VBox status code.
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync * @param pThis The driver instance data.
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic int drvvdSetWritable(PVBOXDISK pThis)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = VINF_SUCCESS;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pThis->fTempReadOnly)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned uOpenFlags;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertRC(rc);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync uOpenFlags &= ~VD_OPEN_FLAGS_READONLY;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (RT_SUCCESS(rc))
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync pThis->fTempReadOnly = false;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync else
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertRC(rc);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return rc;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Error reporting callback *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync const char *pszFormat, va_list va)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (pThis->fErrorUseRuntime)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * deadlock: We are probably executed in a thread context != EMT
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * and the EM thread would wait until every thread is suspended
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * but we would wait for the EM thread ... */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync else
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync* VD Async I/O interface implementation *
16a9adc14900ca18e6909679a579f6833425e030vboxsync*******************************************************************************/
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
16a9adc14900ca18e6909679a579f6833425e030vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pStorageBackend->fSyncIoPending)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pStorageBackend->fSyncIoPending = false;
16a9adc14900ca18e6909679a579f6833425e030vboxsync RTSemEventSignal(pStorageBackend->EventSem);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync int rc = VINF_VD_ASYNC_IO_FINISHED;
16a9adc14900ca18e6909679a579f6833425e030vboxsync void *pvCallerUser = NULL;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pStorageBackend->pfnCompleted)
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync pvCallerUser = pvUser;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* If thread synchronization is active, then signal the end of the
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * this disk read/write operation. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** @todo provide a way to determine the type of task (read/write)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * which was completed, see also VBoxHDD.cpp. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (RT_UNLIKELY(pStorageBackend->pInterfaceThreadSyncCallbacks))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc2 = pStorageBackend->pInterfaceThreadSyncCallbacks->pfnFinishWrite(pStorageBackend->pInterfaceThreadSync->pvUser);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AssertRC(rc2);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AssertRC(rc);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync unsigned uOpenFlags,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PFNVDCOMPLETED pfnCompleted,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PVDINTERFACE pVDIfsDisk,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync void **ppStorage)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = VINF_SUCCESS;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pStorageBackend)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pStorageBackend->fSyncIoPending = false;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pStorageBackend->pfnCompleted = pfnCompleted;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pStorageBackend->pInterfaceThreadSync = NULL;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pStorageBackend->pInterfaceThreadSyncCallbacks = NULL;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pStorageBackend->pInterfaceThreadSync = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_THREADSYNC);
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync if (RT_UNLIKELY(pStorageBackend->pInterfaceThreadSync))
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync pStorageBackend->pInterfaceThreadSyncCallbacks = VDGetInterfaceThreadSync(pStorageBackend->pInterfaceThreadSync);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync rc = RTSemEventCreate(&pStorageBackend->EventSem);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (RT_SUCCESS(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate,
9496f2d398b49813176939d7a339ae513d5175efvboxsync drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_SUCCESS(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
9496f2d398b49813176939d7a339ae513d5175efvboxsync : PDMACEP_FILE_FLAGS_CACHING,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_SUCCESS(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
aa834e89e076db44fa8fe82d177748f0a45d14c2vboxsync *ppStorage = pStorageBackend;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return VINF_SUCCESS;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync RTSemEventDestroy(pStorageBackend->EventSem);
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTMemFree(pStorageBackend);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = VERR_NO_MEMORY;
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync{
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync RTSemEventDestroy(pStorageBackend->EventSem);
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync RTMemFree(pStorageBackend);
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return VINF_SUCCESS;;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
9496f2d398b49813176939d7a339ae513d5175efvboxsync size_t cbRead, void *pvBuf, size_t *pcbRead)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync PDMDATASEG DataSeg;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PPDMASYNCCOMPLETIONTASK pTask;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
ffbe6daf773e38167f3cabaf1f063d84ecd063e9vboxsync Assert(!pStorageBackend->fSyncIoPending);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync DataSeg.cbSeg = cbRead;
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync DataSeg.pvSeg = pvBuf;
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_FAILURE(rc))
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync return rc;
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync if (rc == VINF_AIO_TASK_PENDING)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync {
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync /* Wait */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync AssertRC(rc);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync else
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
adefd5e9babba486cba0cfae52f5a0f6c8c4ef24vboxsync if (pcbRead)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync *pcbRead = cbRead;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VINF_SUCCESS;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync{
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync PDMDATASEG DataSeg;
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync PPDMASYNCCOMPLETIONTASK pTask;
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync Assert(!pStorageBackend->fSyncIoPending);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync DataSeg.cbSeg = cbWrite;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync DataSeg.pvSeg = (void *)pvBuf;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_FAILURE(rc))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return rc;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (rc == VINF_AIO_TASK_PENDING)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* Wait */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertRC(rc);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pcbWritten)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *pcbWritten = cbWrite;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PPDMASYNCCOMPLETIONTASK pTask;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(!pStorageBackend->fSyncIoPending);
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_FAILURE(rc))
16a9adc14900ca18e6909679a579f6833425e030vboxsync return rc;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync if (rc == VINF_AIO_TASK_PENDING)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Wait */
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync AssertRC(rc);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VINF_SUCCESS;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PCPDMDATASEG paSegments, size_t cSegments,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync size_t cbRead, void *pvCompletion,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync void **ppTask)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
9496f2d398b49813176939d7a339ae513d5175efvboxsync PCPDMDATASEG paSegments, size_t cSegments,
9496f2d398b49813176939d7a339ae513d5175efvboxsync size_t cbWrite, void *pvCompletion,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync void **ppTask)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
16a9adc14900ca18e6909679a579f6833425e030vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync void *pvCompletion, void **ppTask)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync (PPPDMASYNCCOMPLETIONTASK)ppTask);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync}
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = drvvdAsyncIOFlushSync(pvUser, pStorage);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_SUCCESS(rc))
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return rc;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync* VD Configuration interface implementation *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic bool drvvdCfgAreKeysValid(void *pvUser, const char *pszzValid)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return CFGMR3AreValuesValid((PCFGMNODE)pvUser, pszzValid);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncstatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync}
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#ifdef VBOX_WITH_INIP
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* VD TCP network stack interface implementation - INIP case *
16a9adc14900ca18e6909679a579f6833425e030vboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsyncstatic DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync{
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync int rc = VINF_SUCCESS;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync /* First check whether lwIP is set up in this VM instance. */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (!DevINIPConfigured())
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogRelFunc(("no IP stack\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync return VERR_NET_HOST_UNREACHABLE;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync /* Resolve hostname. As there is no standard resolver for lwIP yet,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * just accept numeric IP addresses for now. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync struct in_addr ip;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (!lwip_inet_aton(pszAddress, &ip))
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogRelFunc(("cannot resolve IP %s\n", pszAddress));
9496f2d398b49813176939d7a339ae513d5175efvboxsync return VERR_NET_HOST_UNREACHABLE;
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync /* Create socket and connect. */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync RTSOCKET Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (Sock != -1)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync struct sockaddr_in InAddr = {0};
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync InAddr.sin_family = AF_INET;
9496f2d398b49813176939d7a339ae513d5175efvboxsync InAddr.sin_port = htons(uPort);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync InAddr.sin_addr = ip;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pSock = Sock;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VINF_SUCCESS;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync lwip_close(Sock);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncstatic DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync lwip_close(Sock);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return VINF_SUCCESS; /** @todo real solution needed */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync}
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync fd_set fdsetR;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync FD_ZERO(&fdsetR);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync FD_SET(Sock, &fdsetR);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync fd_set fdsetE = fdsetR;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync int rc;
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync if (cMillies == RT_INDEFINITE_WAIT)
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync struct timeval timeout;
16a9adc14900ca18e6909679a579f6833425e030vboxsync timeout.tv_sec = cMillies / 1000;
16a9adc14900ca18e6909679a579f6833425e030vboxsync timeout.tv_usec = (cMillies % 1000) * 1000;
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (rc > 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (rc == 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VERR_TIMEOUT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Do params checking */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (!pvBuffer || !cbBuffer)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertMsgFailed(("Invalid params\n"));
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VERR_INVALID_PARAMETER;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /*
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Read loop.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * If pcbRead is NULL we have to fill the entire buffer!
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsync size_t cbRead = 0;
16a9adc14900ca18e6909679a579f6833425e030vboxsync size_t cbToRead = cbBuffer;
16a9adc14900ca18e6909679a579f6833425e030vboxsync for (;;)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** @todo this clipping here is just in case (the send function
16a9adc14900ca18e6909679a579f6833425e030vboxsync * needed it, so I added it here, too). Didn't investigate if this
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * really has issues. Better be safe than sorry. */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync RT_MIN(cbToRead, 32768), 0);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (cbBytesRead < 0)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (cbBytesRead == 0 && errno)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pcbRead)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync /* return partial data */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync *pcbRead = cbBytesRead;
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync break;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync /* read more? */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync cbRead += cbBytesRead;
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync if (cbRead == cbBuffer)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync break;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync /* next */
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync cbToRead = cbBuffer - cbRead;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync }
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync return VINF_SUCCESS;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsyncstatic DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync{
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync do
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync {
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /** @todo lwip send only supports up to 65535 bytes in a single
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * send (stupid limitation buried in the code), so make sure we
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * don't get any wraparounds. This should be moved to DevINIP
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync * stack interface once that's implemented. */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync ssize_t cbWritten = lwip_send(Sock, (void *)pvBuffer,
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync RT_MIN(cbBuffer, 32768), 0);
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync if (cbWritten < 0)
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync cbWritten, cbBuffer));
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync cbBuffer -= cbWritten;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync pvBuffer = (const char *)pvBuffer + cbWritten;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync } while (cbBuffer);
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync return VINF_SUCCESS;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync}
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsyncstatic DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock)
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync{
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync int fFlag = 1;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync (const char *)&fFlag, sizeof(fFlag));
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync fFlag = 0;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync (const char *)&fFlag, sizeof(fFlag));
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync return VINF_SUCCESS;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync}
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync{
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync union
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync {
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync struct sockaddr Addr;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync struct sockaddr_in Ipv4;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync } u;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync socklen_t cbAddr = sizeof(u);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync RT_ZERO(u);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync if (!lwip_getsockname(Sock, &u.Addr, &cbAddr))
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync {
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync /*
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync * Convert the address.
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync */
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync if ( cbAddr == sizeof(struct sockaddr_in)
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync && u.Addr.sa_family == AF_INET)
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync {
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync RT_ZERO(*pAddr);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync pAddr->enmType = RTNETADDRTYPE_IPV4;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync pAddr->uPort = RT_N2H_U16(u.Ipv4.sin_port);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync pAddr->uAddr.IPv4.u = u.Ipv4.sin_addr.s_addr;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync }
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync else
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
efff36b306e370346025647a158689021df2e1d1vboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_NET_OPERATION_NOT_SUPPORTED;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsyncstatic DECLCALLBACK(int) drvvdINIPGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync union
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync struct sockaddr Addr;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync struct sockaddr_in Ipv4;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync } u;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync socklen_t cbAddr = sizeof(u);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync RT_ZERO(u);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync if (!lwip_getpeername(Sock, &u.Addr, &cbAddr))
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Convert the address.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( cbAddr == sizeof(struct sockaddr_in)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && u.Addr.sa_family == AF_INET)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync RT_ZERO(*pAddr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pAddr->enmType = RTNETADDRTYPE_IPV4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pAddr->uPort = RT_N2H_U16(u.Ipv4.sin_port);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pAddr->uAddr.IPv4.u = u.Ipv4.sin_addr.s_addr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return VINF_SUCCESS;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return VERR_NET_OPERATION_NOT_SUPPORTED;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#endif /* VBOX_WITH_INIP */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/*******************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync* Media interface methods *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnRead */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint64_t off, void *pvBuf, size_t cbRead)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync off, pvBuf, cbRead));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync int rc = VDRead(pThis->pDisk, off, pvBuf, cbRead);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync off, pvBuf, cbRead, cbRead, pvBuf));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync/** @copydoc PDMIMEDIA::pfnWrite */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync uint64_t off, const void *pvBuf,
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync size_t cbWrite)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync off, pvBuf, cbWrite));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync off, pvBuf, cbWrite, cbWrite, pvBuf));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync return rc;
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync}
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDFlush(pThis->pDisk);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync}
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return cb;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s:\n", __FUNCTION__));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync bool f = VDIsReadOnly(pThis->pDisk);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s: returns %d\n", __FUNCTION__, f));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync return f;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync}
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s:\n", __FUNCTION__));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync if (RT_FAILURE(rc))
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync {
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync }
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (rc == VERR_VD_GEOMETRY_NOT_SET)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
251b3801f86afc901bee955a7e5a8d14b5836e74vboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rc == VERR_VD_GEOMETRY_NOT_SET)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDGetUuid(pThis->pDisk, 0, pUuid);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Async Media interface methods *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDATASEG paSeg, unsigned cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size_t cbRead, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uOffset, paSeg, cSeg, cbRead, pvUser));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDATASEG paSeg, unsigned cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size_t cbWrite, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uOffset, paSeg, cSeg, cbWrite, pvUser));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660vboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Async transport port interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_NOT_IMPLEMENTED;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Base interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface, const char *pszIID)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return NULL;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync* Saved state notification methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Load done callback for re-opening the image writable during teleportation.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * This is called both for successful and failed load runs, we only care about
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * successfull ones.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @returns VBox status code.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pDrvIns The driver instance.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pSSM The saved state handle.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncstatic DECLCALLBACK(int) drvvdLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(!pThis->fErrorUseRuntime);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Drop out if we don't have any work to do or if it's a failed load. */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if ( !pThis->fTempReadOnly
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync || RT_FAILURE(SSMR3HandleGetStatus(pSSM)))
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync return VINF_SUCCESS;
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync int rc = drvvdSetWritable(pThis);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (RT_FAILURE(rc)) /** @todo does the bugger set any errors? */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync return SSMR3SetLoadError(pSSM, rc, RT_SRC_POS,
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync N_("Failed to write lock the images"));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync return VINF_SUCCESS;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync}
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync/*******************************************************************************
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync* Driver methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * We must close the disk here to ensure that
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * the backend closes all files before the
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * async transport driver is destructed.
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync int rc = VDCloseAll(pThis->pDisk);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync AssertRC(rc);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * VM resume notification that we use to undo what the temporary read-only image
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * mode set by drvvdSuspend.
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Also switch to runtime error mode if we're resuming after a state load
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * without having been powered on first.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pDrvIns The driver instance data.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * we're making assumptions about Main behavior here!
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync{
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync LogFlow(("%s:\n", __FUNCTION__));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync drvvdSetWritable(pThis);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pThis->fErrorUseRuntime = true;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync/**
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * The VM is being suspended, temporarily change to read-only image mode.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * This is important for several reasons:
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * -# It makes sure that there are no pending writes to the image. Most
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * backends implements this by closing and reopening the image in read-only
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * mode.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * -# It allows Main to read the images during snapshotting without having
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * to account for concurrent writes.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * -# This is essential for making teleportation targets sharing images work
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * right. Both with regards to caching and with regards to file sharing
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * locks (RTFILE_O_DENY_*). (See also drvvdLoadDone.)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync *
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param pDrvIns The driver instance data.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s:\n", __FUNCTION__));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0a3a26a4065b9401681a8c99a11bd83e08f94ccvboxsync if (!VDIsReadOnly(pThis->pDisk))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync unsigned uOpenFlags;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync int rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync AssertRC(rc);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync uOpenFlags |= VD_OPEN_FLAGS_READONLY;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync AssertRC(rc);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->fTempReadOnly = true;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync/**
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * VM PowerOn notification for undoing the TempReadOnly config option and
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * changing to runtime error mode.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @param pDrvIns The driver instance data.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * we're making assumptions about Main behavior here!
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic DECLCALLBACK(void) drvvdPowerOn(PPDMDRVINS pDrvIns)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync{
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync LogFlow(("%s:\n", __FUNCTION__));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync drvvdSetWritable(pThis);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pThis->fErrorUseRuntime = true;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync}
a0a3a26a4065b9401681a8c99a11bd83e08f94ccvboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/**
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @copydoc FNPDMDRVDESTRUCT
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync LogFlow(("%s:\n", __FUNCTION__));
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if (VALID_PTR(pThis->pDisk))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync VDDestroy(pThis->pDisk);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pThis->pDisk = NULL;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync drvvdFreeImages(pThis);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Construct a VBox disk media driver instance.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @copydoc FNPDMDRVCONSTRUCT
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PCFGMNODE pCfg,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint32_t fFlags)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync LogFlow(("%s:\n", __FUNCTION__));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync int rc = VINF_SUCCESS;
efff36b306e370346025647a158689021df2e1d1vboxsync char *pszName = NULL; /**< The path of the disk image file. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync char *pszFormat = NULL; /**< The format backed to use for this image. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync bool fReadOnly; /**< True if the media is read-only. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Init the static parts.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->pDrvIns = pDrvIns;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->fTempReadOnly = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->pDisk = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->fAsyncIOSupported = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* IMedia */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnRead = drvvdRead;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnWrite = drvvdWrite;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnFlush = drvvdFlush;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnGetSize = drvvdGetSize;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnIsReadOnly = drvvdIsReadOnly;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pThis->IMedia.pfnGetUuid = drvvdGetUuid;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* IMediaAsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMediaAsync.pfnStartRead = drvvdStartRead;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Initialize supported VD interfaces. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->pVDIfsDisk = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIErrorCallbacks.pfnError = drvvdErrorCallback;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIErrorCallbacks.pfnMessage = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = VDInterfaceAdd(&pThis->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync &pThis->VDIErrorCallbacks, pDrvIns, &pThis->pVDIfsDisk);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertRC(rc);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* This is just prepared here, the actual interface is per-image, so it's
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * added later. No need to have separate callback tables. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIConfigCallbacks.pfnAreKeysValid = drvvdCfgAreKeysValid;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIConfigCallbacks.pfnQuery = drvvdCfgQuery;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* List of images is empty now. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->pImages = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Try to attach async media port interface above.*/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Validate configuration and find all parent images.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * It's sort of up side down from the image dependency tree.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync bool fHostIP = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync bool fUseNewIo = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unsigned iLevel = 0;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PCFGMNODE pCurNode = pCfg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync for (;;)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync bool fValid;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pCurNode == pCfg)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Toplevel configuration additionally contains the global image
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * open flags. Some might be converted to per-image flags later. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync fValid = CFGMR3AreValuesValid(pCurNode,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync "Format\0Path\0"
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync "ReadOnly\0TempReadOnly\0HonorZeroWrites\0"
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync "HostIPStack\0UseNewIo\0");
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync else
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* All other image configurations only contain image name and
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * the format information. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0");
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!fValid)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pCurNode == pCfg)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryBoolDef(pCurNode, "HostIPStack", &fHostIP, true);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"HostIPStack\" as boolean failed"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync rc = CFGMR3QueryBoolDef(pCurNode, "HonorZeroWrites", &fHonorZeroWrites, false);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"HonorZeroWrites\" as boolean failed"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryBoolDef(pCurNode, "ReadOnly", &fReadOnly, false);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"ReadOnly\" as boolean failed"));
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryBoolDef(pCurNode, "TempReadOnly", &pThis->fTempReadOnly, false);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"TempReadOnly\" as boolean failed"));
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync break;
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fReadOnly && pThis->fTempReadOnly)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Both \"ReadOnly\" and \"TempReadOnly\" are set"));
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryBoolDef(pCurNode, "UseNewIo", &fUseNewIo, false);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
51a01524909c95ee04b636218b6a89b29fb81825vboxsync N_("DrvVD: Configuration error: Querying \"UseNewIo\" as boolean failed"));
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PCFGMNODE pParent = CFGMR3GetChild(pCurNode, "Parent");
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (!pParent)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync break;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pCurNode = pParent;
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync iLevel++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Open the images.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* First of all figure out what kind of TCP networking stack interface
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * to use. This is done unconditionally, as backends which don't need
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * it will just ignore it. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fHostIP)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnClientConnect = RTTcpClientConnect;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnClientClose = RTTcpClientClose;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnSelectOne = RTTcpSelectOne;
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync pThis->VDITcpNetCallbacks.pfnRead = RTTcpRead;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnWrite = RTTcpWrite;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnFlush = RTTcpFlush;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnGetLocalAddress = RTTcpGetLocalAddress;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnGetPeerAddress = RTTcpGetPeerAddress;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#ifndef VBOX_WITH_INIP
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: TCP over Internal Networking not compiled in"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#else /* VBOX_WITH_INIP */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdINIPClientConnect;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnClientClose = drvvdINIPClientClose;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdINIPSelectOne;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnRead = drvvdINIPRead;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnWrite = drvvdINIPWrite;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnFlush = drvvdINIPFlush;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdINIPGetLocalAddress;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdINIPGetPeerAddress;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#endif /* VBOX_WITH_INIP */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = VDInterfaceAdd(&pThis->VDITcpNet, "DrvVD_INIP",
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync VDINTERFACETYPE_TCPNET,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync &pThis->VDITcpNetCallbacks, NULL,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync &pThis->pVDIfsDisk);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_SUCCESS(rc) && fUseNewIo)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnOpen = drvvdAsyncIOOpen;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnClose = drvvdAsyncIOClose;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnGetSize = drvvdAsyncIOGetSize;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnSetSize = drvvdAsyncIOSetSize;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnReadSync = drvvdAsyncIOReadSync;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnWriteSync = drvvdAsyncIOWriteSync;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnFlushSync = drvvdAsyncIOFlushSync;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnReadAsync = drvvdAsyncIOReadAsync;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->VDIAsyncIOCallbacks.pfnWriteAsync = drvvdAsyncIOWriteAsync;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pThis->VDIAsyncIOCallbacks.pfnFlushAsync = drvvdAsyncIOFlushAsync;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync rc = VDInterfaceAdd(&pThis->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
51a01524909c95ee04b636218b6a89b29fb81825vboxsync &pThis->VDIAsyncIOCallbacks, pThis, &pThis->pVDIfsDisk);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync#else /* !VBOX_WITH_PDM_ASYNC_COMPLETION */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
51a01524909c95ee04b636218b6a89b29fb81825vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: Async Completion Framework not compiled in"));
51a01524909c95ee04b636218b6a89b29fb81825vboxsync#endif /* !VBOX_WITH_PDM_ASYNC_COMPLETION */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /** @todo implement and set up the thread synchronization interface
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * if enabled by some CFGM key. If this is enabled then there also
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * needs to be a way for the console object to query the pDisk pointer
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * (so that it can perform the merge in parallel), or alternatively
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * some code needs to be added here which does the merge. The latter
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * might be preferred, as a running merge must block the destruction
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * of the disk, or things will go really wrong. */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (RT_SUCCESS(rc))
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync rc = VDCreate(pThis->pVDIfsDisk, &pThis->pDisk);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* Error message is already set correctly. */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pThis->pDrvMediaAsyncPort)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pThis->fAsyncIOSupported = true;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync while (pCurNode && RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Allocate per-image data. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PVBOXIMAGE pImage = drvvdNewImage(pThis);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!pImage)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = VERR_NO_MEMORY;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Read the image configuration.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"Path\" as string failed"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = CFGMR3QueryStringAlloc(pCurNode, "Format", &pszFormat);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_FAILURE(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync PCFGMNODE pCfgVDConfig = CFGMR3GetChild(pCurNode, "VDConfig");
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = VDInterfaceAdd(&pImage->VDIConfig, "DrvVD_Config", VDINTERFACETYPE_CONFIG,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync &pThis->VDIConfigCallbacks, pCfgVDConfig, &pImage->pVDIfsImage);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertRC(rc);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Open the image.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unsigned uOpenFlags;
217fa436516d137a409bb493cb7d350898f64666vboxsync if (fReadOnly || pThis->fTempReadOnly || iLevel != 0)
217fa436516d137a409bb493cb7d350898f64666vboxsync uOpenFlags = VD_OPEN_FLAGS_READONLY;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
51a01524909c95ee04b636218b6a89b29fb81825vboxsync uOpenFlags = VD_OPEN_FLAGS_NORMAL;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (fHonorZeroWrites)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (pThis->fAsyncIOSupported)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* Try to open backend in async I/O mode first. */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync rc = VDOpen(pThis->pDisk, pszFormat, pszName, uOpenFlags, pImage->pVDIfsImage);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (rc == VERR_NOT_SUPPORTED)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pThis->fAsyncIOSupported = false;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync uOpenFlags &= ~VD_OPEN_FLAGS_ASYNC_IO;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync rc = VDOpen(pThis->pDisk, pszFormat, pszName, uOpenFlags, pImage->pVDIfsImage);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync iLevel, pszName,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( VDIsReadOnly(pThis->pDisk)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && !fReadOnly
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && !pThis->fTempReadOnly
51a01524909c95ee04b636218b6a89b29fb81825vboxsync && iLevel == 0)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_VD_IMAGE_READ_ONLY, RT_SRC_POS,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync N_("Failed to open image '%s' for writing due to wrong permissions"),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pszName);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
51a01524909c95ee04b636218b6a89b29fb81825vboxsync N_("Failed to open image '%s' in %s mode rc=%Rrc"), pszName,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync (uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "read-only" : "read-write", rc);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync MMR3HeapFree(pszName);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pszName = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync MMR3HeapFree(pszFormat);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pszFormat = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* next */
217fa436516d137a409bb493cb7d350898f64666vboxsync iLevel--;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pCurNode = CFGMR3GetParent(pCurNode);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Register a load-done callback so we can undo TempReadOnly config before
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * we get to drvvdResume. Autoamtically deregistered upon destruction.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_SUCCESS(rc))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = PDMDrvHlpSSMRegisterEx(pDrvIns, 0 /* version */, 0 /* cbGuess */,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NULL /*pfnSavePrep*/, NULL /*pfnSaveExec*/, NULL /*pfnSaveDone*/,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NULL /*pfnDonePrep*/, NULL /*pfnLoadExec*/, drvvdLoadDone);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (RT_FAILURE(rc))
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (VALID_PTR(pszName))
b0b15690f00527424b2d5fb88456d747252322f7vboxsync MMR3HeapFree(pszName);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (VALID_PTR(pszFormat))
b0b15690f00527424b2d5fb88456d747252322f7vboxsync MMR3HeapFree(pszFormat);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* drvvdDestruct does the rest. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return rc;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync/**
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * VBox disk container media driver registration record.
b0b15690f00527424b2d5fb88456d747252322f7vboxsync */
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncconst PDMDRVREG g_DrvVD =
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* u32Version */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync PDM_DRVREG_VERSION,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* szName */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync "VD",
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* szRCMod */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync "",
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* szR0Mod */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync "",
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pszDescription */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync "Generic VBox disk media driver.",
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* fFlags */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* fClass. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync PDM_DRVREG_CLASS_MEDIA,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* cMaxInstances */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync ~0,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* cbInstance */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync sizeof(VBOXDISK),
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnConstruct */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdConstruct,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnDestruct */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdDestruct,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnRelocate */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnIOCtl */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnPowerOn */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdPowerOn,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnReset */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnSuspend */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdSuspend,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnResume */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdResume,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnAttach */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnDetach */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnPowerOff */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync drvvdPowerOff,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* pfnSoftReset */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NULL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* u32EndVersion */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync PDM_DRVREG_VERSION
b0b15690f00527424b2d5fb88456d747252322f7vboxsync};
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync