DrvVD.cpp revision cba6719bd64ec749967bbe931230452664109857
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * DrvVD - Generic VBox disk media driver.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Copyright (C) 2006-2008 Sun Microsystems, Inc.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * This file is part of VirtualBox Open Source Edition (OSE), as
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * available from http://www.virtualbox.org. This file is free software;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * you can redistribute it and/or modify it under the terms of the GNU
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * General Public License (GPL) as published by the Free Software
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Foundation, in version 2 as it comes in the "COPYING" file of the
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Clara, CA 95054 USA or visit http://www.sun.com if you need
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * additional information or have any questions.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Header files *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/* All lwip header files are not C++ safe. So hack around this. */
92e1ac0d7d0f8596dfc8b9e1302e1100e5b35efajj#endif /* VBOX_WITH_INIP */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/* Small hack to get at lwIP initialized status */
f8d2de6bd2421da1926f3daa456d161670decdf7jchuextern bool DevINIPConfigured(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yan#endif /* VBOX_WITH_INIP */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*******************************************************************************
269473047d747f7815af570197e4ef7322d3632cEvan Yan* Defined types, constants and macros *
269473047d747f7815af570197e4ef7322d3632cEvan Yan*******************************************************************************/
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** Converts a pointer to VDIDISK::IMedia to a PVBOXDISK. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
70025d765b044c6d8594bb965a2247a61e991a99johnny/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
70025d765b044c6d8594bb965a2247a61e991a99johnny ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
70025d765b044c6d8594bb965a2247a61e991a99johnny/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VBox disk container, image information, private part.
f8d2de6bd2421da1926f3daa456d161670decdf7jchutypedef struct VBOXIMAGE
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae /** Pointer to next image. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to list of VD interfaces. Per-image. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the configuration information interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Storage backend data.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** PDM async completion end point. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The template. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Event semaphore for synchronous operations. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether a synchronous operation is currently pending. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu volatile bool fSyncIoPending;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback routine */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VBox disk container media main structure, private part.
f8d2de6bd2421da1926f3daa456d161670decdf7jchutypedef struct VBOXDISK
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The VBox disk container. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The media interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to the driver instance. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether suspend has changed image open mode to read only. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether to use the runtime (true) or startup error facility. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to list of VD interfaces. Per-disk. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the supported error interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for error interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the supported TCP network stack interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for TCP network stack interface. */
337fc9e235877b459e389f54daf9833bbc645439anish /** Common structure for the supported async I/O interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for async I/O interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for the configuration information interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether opened disk suppports async I/O operations. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The async media interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The async media port interface above. */
70025d765b044c6d8594bb965a2247a61e991a99johnny /** Pointer to the list of data we need to keep per image. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Error reporting callback *
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * deadlock: We are probably executed in a thread context != EMT
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * and the EM thread would wait until every thread is suspended
0114761d17f41c0b83189e4bf95e6b789e7ba99eAlan Adamson, SD OSSD * but we would wait for the EM thread ... */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pDrvIns->pDrvHlp->pfnVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram * Internal: allocate new image descriptor and put it in the list
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Internal: free the list of images descriptors.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* VD Async I/O interface implementation *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
70025d765b044c6d8594bb965a2247a61e991a99johnny return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
70025d765b044c6d8594bb965a2247a61e991a99johnny PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
f94c602698937f2fc025056c894e5a769f39d8fejj /* Wait */
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
70025d765b044c6d8594bb965a2247a61e991a99johnny size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
70025d765b044c6d8594bb965a2247a61e991a99johnny PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Wait */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
70025d765b044c6d8594bb965a2247a61e991a99johnny int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Wait */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
269473047d747f7815af570197e4ef7322d3632cEvan Yan#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*******************************************************************************
269473047d747f7815af570197e4ef7322d3632cEvan Yan* VD Configuration interface implementation *
269473047d747f7815af570197e4ef7322d3632cEvan Yan*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic bool drvvdCfgAreKeysValid(void *pvUser, const char *pszzValid)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3AreValuesValid((PCFGMNODE)pvUser, pszzValid);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
337fc9e235877b459e389f54daf9833bbc645439anish* VD TCP network stack interface implementation - INIP case *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
337fc9e235877b459e389f54daf9833bbc645439anish/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
337fc9e235877b459e389f54daf9833bbc645439anishstatic DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
337fc9e235877b459e389f54daf9833bbc645439anish /* First check whether lwIP is set up in this VM instance. */
337fc9e235877b459e389f54daf9833bbc645439anish /* Resolve hostname. As there is no standard resolver for lwIP yet,
337fc9e235877b459e389f54daf9833bbc645439anish * just accept numeric IP addresses for now. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Create socket and connect. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnClientClose */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return VINF_SUCCESS; /** @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPSelectOne(RTSOCKET Sock, unsigned cMillies)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnRead */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Do params checking */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Read loop.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * If pcbRead is NULL we have to fill the entire buffer!
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** @todo this clipping here is just in case (the send function
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * needed it, so I added it here, too). Didn't investigate if this
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * really has issues. Better be safe than sorry. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* return partial data */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* read more? */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnWrite */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** @todo lwip send only supports up to 65535 bytes in a single
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * send (stupid limitation buried in the code), so make sure we
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * don't get any wraparounds. This should be moved to DevINIP
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * stack interface once that's implemented. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnFlush */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#endif /* VBOX_WITH_INIP */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Media interface methods *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnRead */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda/** @copydoc PDMIMEDIA::pfnWrite */
665a7fca9fb82b4c029eb6763aefcc9bc563a486govindastatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
269473047d747f7815af570197e4ef7322d3632cEvan Yan LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
269473047d747f7815af570197e4ef7322d3632cEvan Yan Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** @copydoc PDMIMEDIA::pfnFlush */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnGetSize */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnIsReadOnly */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet Log(("%s: geometry not available.\n", __FUNCTION__));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnGetUuid */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Async Media interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Async transport port interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Base interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIBASE::pfnQueryInterface */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Driver methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Construct a VBox disk media driver instance.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * @copydoc FNPDMDRVCONSTRUCT
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *pszName = NULL; /**< The path of the disk image file. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *pszFormat = NULL; /**< The format backed to use for this image. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bool fReadOnly; /**< True if the media is readonly. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bool fHonorZeroWrites; /**< True if zero blocks should be written. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Init the static parts.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* IMedia */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* IMediaAsync */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Initialize supported VD interfaces. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
pThis->pDrvMediaAsyncPort = (PPDMIMEDIAASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MEDIA_ASYNC_PORT);
bool fHostIP = false;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
fHostIP = true;
fHonorZeroWrites = false;
fReadOnly = false;
if (!pParent)
iLevel++;
if (fHostIP)
#ifndef VBOX_WITH_INIP
if (!pImage)
unsigned uOpenFlags;
if (fHonorZeroWrites)
&& !fReadOnly
&& iLevel == 0)
iLevel--;
return rc;
return rc;
unsigned uOpenFlags;
unsigned uOpenFlags;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,