VirtualBox

source: vbox/trunk/src/VBox/Devices/Samples/DrvStorageFilter.cpp@ 60404

Last change on this file since 60404 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 KB
Line 
1/* $Id: DrvStorageFilter.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * VBox storage filter driver sample.
4 */
5
6/*
7 * Copyright (C) 2012-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_MISC
23#include <VBox/vmm/pdmifs.h>
24#include <VBox/vmm/pdmdrv.h>
25#include <VBox/log.h>
26
27#include <iprt/uuid.h>
28
29
30/*********************************************************************************************************************************
31* Structures and Typedefs *
32*********************************************************************************************************************************/
33/**
34 * Storage Filter Driver Instance Data.
35 */
36typedef struct DRVSTORAGEFILTER
37{
38 /** @name Interfaces exposed by this driver.
39 * @{ */
40 PDMIMEDIA IMedia;
41 PDMIMEDIAPORT IMediaPort;
42 PDMIMEDIAASYNC IMediaAsync;
43 PDMIMEDIAASYNCPORT IMediaAsyncPort;
44 /** @} */
45
46 /** @name Interfaces exposed by the driver below us.
47 * @{ */
48 PPDMIMEDIA pIMediaBelow;
49 PPDMIMEDIAASYNC pIMediaAsyncBelow;
50 /** @} */
51
52 /** @name Interfaces exposed by the driver/device above us.
53 * @{ */
54 PPDMIMEDIAPORT pIMediaPortAbove;
55 PPDMIMEDIAASYNCPORT pIMediaAsyncPortAbove;
56 /** @} */
57
58 /** If clear, then suppress Async support. */
59 bool fAsyncIOSupported;
60
61 /** @todo implement memfrob. */
62} DRVSTORAGEFILTER;
63/** Pointer to a storage filter driver instance. */
64typedef DRVSTORAGEFILTER *PDRVSTORAGEFILTER;
65
66
67
68/*
69 *
70 * IMediaAsyncPort Implementation.
71 *
72 */
73
74/** @interface_method_impl{PDMIMEDIAASYNCPORT,pfnTransferCompleteNotify} */
75static DECLCALLBACK(int)
76drvStorageFltIMediaAsyncPort_TransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq)
77{
78 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaAsyncPort);
79 int rc = pThis->pIMediaAsyncPortAbove->pfnTransferCompleteNotify(pThis->pIMediaAsyncPortAbove, pvUser, rcReq);
80 return rc;
81}
82
83
84/*
85 *
86 * IMediaAsync Implementation.
87 *
88 */
89
90/** @interface_method_impl{PDMIMEDIAASYNC,pfnStartRead} */
91static DECLCALLBACK(int) drvStorageFltIMediaAsync_StartRead(PPDMIMEDIAASYNC pInterface, uint64_t off,
92 PCRTSGSEG paSegs, unsigned cSegs, size_t cbRead, void *pvUser)
93{
94 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaAsync);
95 int rc = pThis->pIMediaAsyncBelow->pfnStartRead(pThis->pIMediaAsyncBelow, off, paSegs, cSegs, cbRead, pvUser);
96 return rc;
97}
98
99/** @interface_method_impl{PDMIMEDIAASYNC,pfnStartWrite} */
100static DECLCALLBACK(int) drvStorageFltIMediaAsync_StartWrite(PPDMIMEDIAASYNC pInterface, uint64_t off,
101 PCRTSGSEG paSegs, unsigned cSegs, size_t cbWrite, void *pvUser)
102{
103 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaAsync);
104 int rc = pThis->pIMediaAsyncBelow->pfnStartWrite(pThis->pIMediaAsyncBelow, off, paSegs, cSegs, cbWrite, pvUser);
105 return rc;
106}
107
108/** @interface_method_impl{PDMIMEDIAASYNC,pfnStartFlush} */
109static DECLCALLBACK(int) drvStorageFltIMediaAsync_StartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
110{
111 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaAsync);
112 int rc = pThis->pIMediaAsyncBelow->pfnStartFlush(pThis->pIMediaAsyncBelow, pvUser);
113 return rc;
114}
115
116
117/** @interface_method_impl{PDMIMEDIAASYNC,pfnStartDiscard} */
118static DECLCALLBACK(int) drvStorageFltIMediaAsync_StartDiscard(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges,
119 unsigned cRanges, void *pvUser)
120{
121 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaAsync);
122 int rc = pThis->pIMediaAsyncBelow->pfnStartDiscard(pThis->pIMediaAsyncBelow, paRanges, cRanges, pvUser);
123 return rc;
124}
125
126
127/*
128 *
129 * IMedia Implementation.
130 *
131 */
132
133/** @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation} */
134static DECLCALLBACK(int) drvStorageFltIMediaPort_QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
135 uint32_t *piInstance, uint32_t *piLUN)
136{
137 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaPort);
138 int rc = pThis->pIMediaPortAbove->pfnQueryDeviceLocation(pThis->pIMediaPortAbove, ppcszController, piInstance, piLUN);
139 return rc;
140}
141
142
143/*
144 *
145 * IMedia Implementation.
146 *
147 */
148
149/** @interface_method_impl{PDMIMEDIA,pfnRead} */
150static DECLCALLBACK(int) drvStorageFltIMedia_Read(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
151{
152 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
153 int rc = pThis->pIMediaBelow->pfnRead(pThis->pIMediaBelow, off, pvBuf, cbRead);
154 return rc;
155}
156
157/** @interface_method_impl{PDMIMEDIA,pfnWrite} */
158static DECLCALLBACK(int) drvStorageFltIMedia_Write(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
159{
160 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
161 int rc = pThis->pIMediaBelow->pfnWrite(pThis->pIMediaBelow, off, pvBuf, cbWrite);
162 return rc;
163}
164
165/** @interface_method_impl{PDMIMEDIA,pfnFlush} */
166static DECLCALLBACK(int) drvStorageFltIMedia_Flush(PPDMIMEDIA pInterface)
167{
168 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
169 int rc = pThis->pIMediaBelow->pfnFlush(pThis->pIMediaBelow);
170 return rc;
171}
172
173/** @interface_method_impl{PDMIMEDIA,pfnMerge} */
174static DECLCALLBACK(int) drvStorageFltIMedia_Merge(PPDMIMEDIA pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser)
175{
176 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
177 int rc = pThis->pIMediaBelow->pfnMerge(pThis->pIMediaBelow, pfnProgress, pvUser);
178 return rc;
179}
180
181/** @interface_method_impl{PDMIMEDIA,pfnGetSize} */
182static DECLCALLBACK(uint64_t) drvStorageFltIMedia_GetSize(PPDMIMEDIA pInterface)
183{
184 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
185 uint64_t cb = pThis->pIMediaBelow->pfnGetSize(pThis->pIMediaBelow);
186 return cb;
187}
188
189/** @interface_method_impl{PDMIMEDIA,pfnIsReadOnly} */
190static DECLCALLBACK(bool) drvStorageFltIMedia_IsReadOnly(PPDMIMEDIA pInterface)
191{
192 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
193 bool fRc = pThis->pIMediaBelow->pfnIsReadOnly(pThis->pIMediaBelow);
194 return fRc;
195}
196
197/** @interface_method_impl{PDMIMEDIA,pfnBiosGetPCHSGeometry} */
198static DECLCALLBACK(int) drvStorageFltIMedia_BiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
199{
200 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
201 int rc = pThis->pIMediaBelow->pfnBiosGetPCHSGeometry(pThis->pIMediaBelow, pPCHSGeometry);
202 return rc;
203}
204
205/** @interface_method_impl{PDMIMEDIA,pfnBiosSetPCHSGeometry} */
206static DECLCALLBACK(int) drvStorageFltIMedia_BiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
207{
208 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
209 int rc = pThis->pIMediaBelow->pfnBiosSetPCHSGeometry(pThis->pIMediaBelow, pPCHSGeometry);
210 return rc;
211}
212
213/** @interface_method_impl{PDMIMEDIA,pfnBiosGetLCHSGeometry} */
214static DECLCALLBACK(int) drvStorageFltIMedia_BiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
215{
216 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
217 int rc = pThis->pIMediaBelow->pfnBiosGetLCHSGeometry(pThis->pIMediaBelow, pLCHSGeometry);
218 return rc;
219}
220
221/** @interface_method_impl{PDMIMEDIA,pfnBiosSetLCHSGeometry} */
222static DECLCALLBACK(int) drvStorageFltIMedia_BiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
223{
224 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
225 int rc = pThis->pIMediaBelow->pfnBiosSetLCHSGeometry(pThis->pIMediaBelow, pLCHSGeometry);
226 return rc;
227}
228
229/** @interface_method_impl{PDMIMEDIA,pfnGetUuid} */
230static DECLCALLBACK(int) drvStorageFltIMedia_GetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
231{
232 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
233 int rc = pThis->pIMediaBelow->pfnGetUuid(pThis->pIMediaBelow, pUuid);
234 return rc;
235}
236
237/** @interface_method_impl{PDMIMEDIA,pfnDiscard} */
238static DECLCALLBACK(int) drvStorageFltIMedia_Discard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)
239{
240 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
241 int rc = pThis->pIMediaBelow->pfnDiscard(pThis->pIMediaBelow, paRanges, cRanges);
242 return rc;
243}
244
245
246/*
247 *
248 * IBase Implementation.
249 *
250 */
251
252
253static DECLCALLBACK(void *) drvStorageFltIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
254{
255 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
256 PDRVSTORAGEFILTER pThis = PDMINS_2_DATA(pDrvIns, PDRVSTORAGEFILTER);
257
258 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
259 if (pThis->pIMediaBelow)
260 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
261 if (pThis->pIMediaPortAbove)
262 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IMediaPort);
263
264 if (pThis->fAsyncIOSupported && pThis->pIMediaAsyncBelow)
265 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, &pThis->IMediaAsync);
266 if (pThis->fAsyncIOSupported && pThis->pIMediaAsyncPortAbove)
267 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pThis->IMediaAsyncPort);
268 return NULL;
269}
270
271
272/*
273 *
274 * PDMDRVREG Methods
275 *
276 */
277
278
279/**
280 * Construct a storage filter driver.
281 *
282 * @copydoc FNPDMDRVCONSTRUCT
283 */
284static DECLCALLBACK(int) drvStorageFlt_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
285{
286 PDRVSTORAGEFILTER pThis = PDMINS_2_DATA(pDrvIns, PDRVSTORAGEFILTER);
287
288 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
289
290 /*
291 * Initialize the instance data.
292 */
293 pDrvIns->IBase.pfnQueryInterface = drvStorageFltIBase_QueryInterface;
294
295 pThis->IMedia.pfnRead = drvStorageFltIMedia_Read;
296 pThis->IMedia.pfnWrite = drvStorageFltIMedia_Write;
297 pThis->IMedia.pfnFlush = drvStorageFltIMedia_Flush;
298 pThis->IMedia.pfnMerge = drvStorageFltIMedia_Merge;
299 pThis->IMedia.pfnGetSize = drvStorageFltIMedia_GetSize;
300 pThis->IMedia.pfnIsReadOnly = drvStorageFltIMedia_IsReadOnly;
301 pThis->IMedia.pfnBiosGetPCHSGeometry = drvStorageFltIMedia_BiosGetPCHSGeometry;
302 pThis->IMedia.pfnBiosSetPCHSGeometry = drvStorageFltIMedia_BiosSetPCHSGeometry;
303 pThis->IMedia.pfnBiosGetLCHSGeometry = drvStorageFltIMedia_BiosGetLCHSGeometry;
304 pThis->IMedia.pfnBiosSetLCHSGeometry = drvStorageFltIMedia_BiosSetLCHSGeometry;
305 pThis->IMedia.pfnGetUuid = drvStorageFltIMedia_GetUuid;
306 pThis->IMedia.pfnDiscard = drvStorageFltIMedia_Discard;
307
308 pThis->IMediaPort.pfnQueryDeviceLocation = drvStorageFltIMediaPort_QueryDeviceLocation;
309
310 pThis->IMediaAsync.pfnStartRead = drvStorageFltIMediaAsync_StartRead;
311 pThis->IMediaAsync.pfnStartWrite = drvStorageFltIMediaAsync_StartWrite;
312 pThis->IMediaAsync.pfnStartFlush = drvStorageFltIMediaAsync_StartFlush;
313 pThis->IMediaAsync.pfnStartDiscard = drvStorageFltIMediaAsync_StartDiscard;
314
315 pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvStorageFltIMediaAsyncPort_TransferCompleteNotify;
316
317 /*
318 * Validate and read config.
319 */
320 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "AsyncIOSupported|", "");
321
322 int rc = CFGMR3QueryBoolDef(pCfg, "AsyncIOSupported", &pThis->fAsyncIOSupported, true);
323 AssertLogRelRCReturn(rc, rc);
324
325 /*
326 * Query interfaces from the driver/device above us.
327 */
328 pThis->pIMediaPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
329 pThis->pIMediaAsyncPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
330
331 /*
332 * Attach driver below us.
333 */
334 PPDMIBASE pIBaseBelow;
335 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pIBaseBelow);
336 AssertLogRelRCReturn(rc, rc);
337
338 pThis->pIMediaBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMIMEDIA);
339 pThis->pIMediaAsyncBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMIMEDIAASYNC);
340
341 AssertLogRelReturn(pThis->pIMediaBelow, VERR_PDM_MISSING_INTERFACE_BELOW);
342
343 if (!pThis->pIMediaBelow->pfnDiscard)
344 pThis->IMedia.pfnDiscard = NULL;
345 if (!pThis->pIMediaAsyncBelow || !pThis->pIMediaAsyncBelow->pfnStartDiscard)
346 pThis->IMediaAsync.pfnStartDiscard = NULL;
347
348 return VINF_SUCCESS;
349}
350
351
352/**
353 * Storage filter driver registration record.
354 */
355static const PDMDRVREG g_DrvStorageFilter =
356{
357 /* u32Version */
358 PDM_DRVREG_VERSION,
359 /* szName */
360 "StorageFilter",
361 /* szRCMod */
362 "",
363 /* szR0Mod */
364 "",
365 /* pszDescription */
366 "Storage Filter Driver Sample",
367 /* fFlags */
368 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
369 /* fClass. */
370 PDM_DRVREG_CLASS_MEDIA,
371 /* cMaxInstances */
372 ~0U,
373 /* cbInstance */
374 sizeof(DRVSTORAGEFILTER),
375 /* pfnConstruct */
376 drvStorageFlt_Construct,
377 /* pfnDestruct */
378 NULL,
379 /* pfnRelocate */
380 NULL,
381 /* pfnIOCtl */
382 NULL,
383 /* pfnPowerOn */
384 NULL,
385 /* pfnReset */
386 NULL,
387 /* pfnSuspend */
388 NULL,
389 /* pfnResume */
390 NULL,
391 /* pfnAttach */
392 NULL,
393 /* pfnDetach */
394 NULL,
395 /* pfnPowerOff */
396 NULL,
397 /* pfnSoftReset */
398 NULL,
399 /* u32EndVersion */
400 PDM_DRVREG_VERSION
401};
402
403
404/**
405 * Register builtin devices.
406 *
407 * @returns VBox status code.
408 * @param pCallbacks Pointer to the callback table.
409 * @param u32Version VBox version number.
410 */
411extern "C" DECLEXPORT(int) VBoxDriversRegister(PPDMDRVREGCB pCallbacks, uint32_t u32Version)
412{
413 LogFlow(("VBoxSampleDriver::VBoxDriversRegister: u32Version=%#x pCallbacks->u32Version=%#x\n",
414 u32Version, pCallbacks->u32Version));
415
416 AssertLogRelMsgReturn(pCallbacks->u32Version == PDM_DRVREG_CB_VERSION,
417 ("%#x, expected %#x\n", pCallbacks->u32Version, PDM_DRVREG_CB_VERSION),
418 VERR_VERSION_MISMATCH);
419
420 return pCallbacks->pfnRegister(pCallbacks, &g_DrvStorageFilter);
421}
422
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use