VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 2 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.8 KB
Line 
1/* $Id: DrvStorageFilter.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBox storage filter driver sample.
4 */
5
6/*
7 * Copyright (C) 2012-2022 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/pdmdrv.h>
24#include <VBox/vmm/pdmstorageifs.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <VBox/version.h>
28
29#include <iprt/uuid.h>
30
31
32/*********************************************************************************************************************************
33* Structures and Typedefs *
34*********************************************************************************************************************************/
35/**
36 * Storage Filter Driver Instance Data.
37 */
38typedef struct DRVSTORAGEFILTER
39{
40 /** @name Interfaces exposed by this driver.
41 * @{ */
42 PDMIMEDIA IMedia;
43 PDMIMEDIAPORT IMediaPort;
44 PDMIMEDIAEX IMediaEx;
45 PDMIMEDIAEXPORT IMediaExPort;
46 /** @} */
47
48 /** @name Interfaces exposed by the driver below us.
49 * @{ */
50 PPDMIMEDIA pIMediaBelow;
51 PPDMIMEDIAEX pIMediaExBelow;
52 /** @} */
53
54 /** @name Interfaces exposed by the driver/device above us.
55 * @{ */
56 PPDMIMEDIAPORT pIMediaPortAbove;
57 PPDMIMEDIAEXPORT pIMediaExPortAbove;
58 /** @} */
59
60 /** If clear, then suppress Async support. */
61 bool fAsyncIOSupported;
62
63 /** @todo implement memfrob. */
64} DRVSTORAGEFILTER;
65/** Pointer to a storage filter driver instance. */
66typedef DRVSTORAGEFILTER *PDRVSTORAGEFILTER;
67
68
69
70/*
71 *
72 * IMediaPort Implementation.
73 *
74 */
75
76/** @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation} */
77static DECLCALLBACK(int) drvStorageFltIMediaPort_QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
78 uint32_t *piInstance, uint32_t *piLUN)
79{
80 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaPort);
81 int rc = pThis->pIMediaPortAbove->pfnQueryDeviceLocation(pThis->pIMediaPortAbove, ppcszController, piInstance, piLUN);
82 return rc;
83}
84
85
86/*
87 *
88 * IMedia Implementation.
89 *
90 */
91
92/** @interface_method_impl{PDMIMEDIA,pfnRead} */
93static DECLCALLBACK(int) drvStorageFltIMedia_Read(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
94{
95 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
96 int rc = pThis->pIMediaBelow->pfnRead(pThis->pIMediaBelow, off, pvBuf, cbRead);
97 return rc;
98}
99
100/** @interface_method_impl{PDMIMEDIA,pfnWrite} */
101static DECLCALLBACK(int) drvStorageFltIMedia_Write(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
102{
103 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
104 int rc = pThis->pIMediaBelow->pfnWrite(pThis->pIMediaBelow, off, pvBuf, cbWrite);
105 return rc;
106}
107
108/** @interface_method_impl{PDMIMEDIA,pfnFlush} */
109static DECLCALLBACK(int) drvStorageFltIMedia_Flush(PPDMIMEDIA pInterface)
110{
111 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
112 int rc = pThis->pIMediaBelow->pfnFlush(pThis->pIMediaBelow);
113 return rc;
114}
115
116/** @interface_method_impl{PDMIMEDIA,pfnMerge} */
117static DECLCALLBACK(int) drvStorageFltIMedia_Merge(PPDMIMEDIA pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser)
118{
119 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
120 int rc = pThis->pIMediaBelow->pfnMerge(pThis->pIMediaBelow, pfnProgress, pvUser);
121 return rc;
122}
123
124/** @interface_method_impl{PDMIMEDIA,pfnGetSize} */
125static DECLCALLBACK(uint64_t) drvStorageFltIMedia_GetSize(PPDMIMEDIA pInterface)
126{
127 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
128 uint64_t cb = pThis->pIMediaBelow->pfnGetSize(pThis->pIMediaBelow);
129 return cb;
130}
131
132/** @interface_method_impl{PDMIMEDIA,pfnIsReadOnly} */
133static DECLCALLBACK(bool) drvStorageFltIMedia_IsReadOnly(PPDMIMEDIA pInterface)
134{
135 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
136 bool fRc = pThis->pIMediaBelow->pfnIsReadOnly(pThis->pIMediaBelow);
137 return fRc;
138}
139
140/** @interface_method_impl{PDMIMEDIA,pfnBiosGetPCHSGeometry} */
141static DECLCALLBACK(int) drvStorageFltIMedia_BiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
142{
143 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
144 int rc = pThis->pIMediaBelow->pfnBiosGetPCHSGeometry(pThis->pIMediaBelow, pPCHSGeometry);
145 return rc;
146}
147
148/** @interface_method_impl{PDMIMEDIA,pfnBiosSetPCHSGeometry} */
149static DECLCALLBACK(int) drvStorageFltIMedia_BiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
150{
151 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
152 int rc = pThis->pIMediaBelow->pfnBiosSetPCHSGeometry(pThis->pIMediaBelow, pPCHSGeometry);
153 return rc;
154}
155
156/** @interface_method_impl{PDMIMEDIA,pfnBiosGetLCHSGeometry} */
157static DECLCALLBACK(int) drvStorageFltIMedia_BiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
158{
159 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
160 int rc = pThis->pIMediaBelow->pfnBiosGetLCHSGeometry(pThis->pIMediaBelow, pLCHSGeometry);
161 return rc;
162}
163
164/** @interface_method_impl{PDMIMEDIA,pfnBiosSetLCHSGeometry} */
165static DECLCALLBACK(int) drvStorageFltIMedia_BiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
166{
167 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
168 int rc = pThis->pIMediaBelow->pfnBiosSetLCHSGeometry(pThis->pIMediaBelow, pLCHSGeometry);
169 return rc;
170}
171
172/** @interface_method_impl{PDMIMEDIA,pfnGetUuid} */
173static DECLCALLBACK(int) drvStorageFltIMedia_GetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
174{
175 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
176 int rc = pThis->pIMediaBelow->pfnGetUuid(pThis->pIMediaBelow, pUuid);
177 return rc;
178}
179
180/** @interface_method_impl{PDMIMEDIA,pfnDiscard} */
181static DECLCALLBACK(int) drvStorageFltIMedia_Discard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)
182{
183 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMedia);
184 int rc = pThis->pIMediaBelow->pfnDiscard(pThis->pIMediaBelow, paRanges, cRanges);
185 return rc;
186}
187
188
189/*
190 *
191 * IMediaExPort Implementation.
192 *
193 */
194
195/** @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} */
196static DECLCALLBACK(int) drvStorageFltIMedia_IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
197 void *pvIoReqAlloc, int rcReq)
198{
199 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaExPort);
200 return pThis->pIMediaExPortAbove->pfnIoReqCompleteNotify(pThis->pIMediaExPortAbove, hIoReq, pvIoReqAlloc, rcReq);
201}
202
203
204/** @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} */
205static DECLCALLBACK(int) drvStorageFltIMedia_IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
206 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
207 size_t cbCopy)
208{
209 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaExPort);
210 return pThis->pIMediaExPortAbove->pfnIoReqCopyFromBuf(pThis->pIMediaExPortAbove, hIoReq, pvIoReqAlloc,
211 offDst, pSgBuf, cbCopy);
212}
213
214/** @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} */
215static DECLCALLBACK(int) drvStorageFltIMedia_IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
216 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
217 size_t cbCopy)
218{
219 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaExPort);
220 return pThis->pIMediaExPortAbove->pfnIoReqCopyToBuf(pThis->pIMediaExPortAbove, hIoReq, pvIoReqAlloc,
221 offSrc, pSgBuf, cbCopy);
222}
223
224/** @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqQueryDiscardRanges} */
225static DECLCALLBACK(int) drvStorageFltIMedia_IoReqQueryDiscardRanges(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
226 void *pvIoReqAlloc, uint32_t idxRangeStart,
227 uint32_t cRanges, PRTRANGE paRanges,
228 uint32_t *pcRanges)
229{
230 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaExPort);
231 return pThis->pIMediaExPortAbove->pfnIoReqQueryDiscardRanges(pThis->pIMediaExPortAbove, hIoReq, pvIoReqAlloc,
232 idxRangeStart, cRanges, paRanges, pcRanges);
233}
234
235/** @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} */
236static DECLCALLBACK(void) drvStorageFltIMedia_IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
237 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
238{
239 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaExPort);
240 return pThis->pIMediaExPortAbove->pfnIoReqStateChanged(pThis->pIMediaExPortAbove, hIoReq, pvIoReqAlloc, enmState);
241}
242
243
244/*
245 *
246 * IMediaEx Implementation.
247 *
248 */
249
250/** @interface_method_impl{PDMIMEDIAEX,pfnQueryFeatures} */
251static DECLCALLBACK(int) drvStorageFltIMedia_QueryFeatures(PPDMIMEDIAEX pInterface, uint32_t *pfFeatures)
252{
253 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
254
255 int rc = pThis->pIMediaExBelow->pfnQueryFeatures(pThis->pIMediaExBelow, pfFeatures);
256 if (RT_SUCCESS(rc) && !pThis->fAsyncIOSupported)
257 *pfFeatures &= ~PDMIMEDIAEX_FEATURE_F_ASYNC;
258
259 return rc;
260}
261
262/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet} */
263static DECLCALLBACK(int) drvStorageFltIMedia_IoReqAllocSizeSet(PPDMIMEDIAEX pInterface, size_t cbIoReqAlloc)
264{
265 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
266 return pThis->pIMediaExBelow->pfnIoReqAllocSizeSet(pThis->pIMediaExBelow, cbIoReqAlloc);
267}
268
269/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAlloc} */
270static DECLCALLBACK(int) drvStorageFltIMedia_IoReqAlloc(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc,
271 PDMMEDIAEXIOREQID uIoReqId, uint32_t fFlags)
272{
273 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
274
275 if (!pThis->fAsyncIOSupported)
276 fFlags |= PDMIMEDIAEX_F_SYNC;
277 return pThis->pIMediaExBelow->pfnIoReqAlloc(pThis->pIMediaExBelow, phIoReq, ppvIoReqAlloc, uIoReqId, fFlags);
278}
279
280/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFree} */
281static DECLCALLBACK(int) drvStorageFltIMedia_IoReqFree(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
282{
283 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
284 return pThis->pIMediaExBelow->pfnIoReqFree(pThis->pIMediaExBelow, hIoReq);
285}
286
287/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQueryResidual} */
288static DECLCALLBACK(int) drvStorageFltIMedia_IoReqQueryResidual(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbResidual)
289{
290 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
291 return pThis->pIMediaExBelow->pfnIoReqQueryResidual(pThis->pIMediaExBelow, hIoReq, pcbResidual);
292}
293
294/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancelAll} */
295static DECLCALLBACK(int) drvStorageFltIMedia_IoReqCancelAll(PPDMIMEDIAEX pInterface)
296{
297 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
298 return pThis->pIMediaExBelow->pfnIoReqCancelAll(pThis->pIMediaExBelow);
299}
300
301/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancel} */
302static DECLCALLBACK(int) drvStorageFltIMedia_IoReqCancel(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQID uIoReqId)
303{
304 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
305 return pThis->pIMediaExBelow->pfnIoReqCancel(pThis->pIMediaExBelow, uIoReqId);
306}
307
308/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqRead} */
309static DECLCALLBACK(int) drvStorageFltIMedia_IoReqRead(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbRead)
310{
311 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
312 return pThis->pIMediaExBelow->pfnIoReqRead(pThis->pIMediaExBelow, hIoReq, off, cbRead);
313}
314
315/**
316 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqWrite}
317 */
318static DECLCALLBACK(int) drvStorageFltIMedia_IoReqWrite(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbWrite)
319{
320 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
321 return pThis->pIMediaExBelow->pfnIoReqWrite(pThis->pIMediaExBelow, hIoReq, off, cbWrite);
322}
323
324/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFlush} */
325static DECLCALLBACK(int) drvStorageFltIMedia_IoReqFlush(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
326{
327 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
328 return pThis->pIMediaExBelow->pfnIoReqFlush(pThis->pIMediaExBelow, hIoReq);
329}
330
331/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqDiscard} */
332static DECLCALLBACK(int) drvStorageFltIMedia_IoReqDiscard(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, unsigned cRangesMax)
333{
334 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
335 return pThis->pIMediaExBelow->pfnIoReqDiscard(pThis->pIMediaExBelow, hIoReq, cRangesMax);
336}
337
338/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSendScsiCmd} */
339static DECLCALLBACK(int) drvStorageFltIMedia_IoReqSendScsiCmd(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
340 uint32_t uLun, const uint8_t *pbCdb, size_t cbCdb,
341 PDMMEDIAEXIOREQSCSITXDIR enmTxDir, PDMMEDIAEXIOREQSCSITXDIR *penmTxDirRet,
342 size_t cbBuf, uint8_t *pabSense, size_t cbSense, size_t *pcbSenseRet,
343 uint8_t *pu8ScsiSts, uint32_t cTimeoutMillies)
344{
345 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
346 return pThis->pIMediaExBelow->pfnIoReqSendScsiCmd(pThis->pIMediaExBelow, hIoReq, uLun, pbCdb, cbCdb,
347 enmTxDir, penmTxDirRet, cbBuf, pabSense, cbSense, pcbSenseRet,
348 pu8ScsiSts, cTimeoutMillies);
349}
350
351/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetActiveCount} */
352static DECLCALLBACK(uint32_t) drvStorageFltIMedia_IoReqGetActiveCount(PPDMIMEDIAEX pInterface)
353{
354 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
355 return pThis->pIMediaExBelow->pfnIoReqGetActiveCount(pThis->pIMediaExBelow);
356}
357
358/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetSuspendedCount} */
359static DECLCALLBACK(uint32_t) drvStorageFltIMedia_IoReqGetSuspendedCount(PPDMIMEDIAEX pInterface)
360{
361 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
362 return pThis->pIMediaExBelow->pfnIoReqGetSuspendedCount(pThis->pIMediaExBelow);
363}
364
365/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedFirst} */
366static DECLCALLBACK(int) drvStorageFltIMedia_IoReqQuerySuspendedStart(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq,
367 void **ppvIoReqAlloc)
368{
369 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
370 return pThis->pIMediaExBelow->pfnIoReqQuerySuspendedStart(pThis->pIMediaExBelow, phIoReq, ppvIoReqAlloc);
371}
372
373/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedNext} */
374static DECLCALLBACK(int) drvStorageFltIMedia_IoReqQuerySuspendedNext(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
375 PPDMMEDIAEXIOREQ phIoReqNext, void **ppvIoReqAllocNext)
376{
377 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
378 return pThis->pIMediaExBelow->pfnIoReqQuerySuspendedNext(pThis->pIMediaExBelow, hIoReq, phIoReqNext, ppvIoReqAllocNext);
379}
380
381/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedSave} */
382static DECLCALLBACK(int) drvStorageFltIMedia_IoReqSuspendedSave(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
383{
384 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
385 return pThis->pIMediaExBelow->pfnIoReqSuspendedSave(pThis->pIMediaExBelow, pSSM, hIoReq);
386}
387
388/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedLoad} */
389static DECLCALLBACK(int) drvStorageFltIMedia_IoReqSuspendedLoad(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
390{
391 PDRVSTORAGEFILTER pThis = RT_FROM_MEMBER(pInterface, DRVSTORAGEFILTER, IMediaEx);
392 return pThis->pIMediaExBelow->pfnIoReqSuspendedLoad(pThis->pIMediaExBelow, pSSM, hIoReq);
393}
394
395
396/*
397 *
398 * IBase Implementation.
399 *
400 */
401
402
403static DECLCALLBACK(void *) drvStorageFltIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
404{
405 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
406 PDRVSTORAGEFILTER pThis = PDMINS_2_DATA(pDrvIns, PDRVSTORAGEFILTER);
407
408 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
409 if (pThis->pIMediaBelow)
410 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
411 if (pThis->pIMediaPortAbove)
412 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IMediaPort);
413 if (pThis->pIMediaExBelow)
414 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEX, &pThis->IMediaEx);
415 if (pThis->pIMediaExPortAbove)
416 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pThis->IMediaExPort);
417
418 return NULL;
419}
420
421
422/*
423 *
424 * PDMDRVREG Methods
425 *
426 */
427
428
429/**
430 * Construct a storage filter driver.
431 *
432 * @copydoc FNPDMDRVCONSTRUCT
433 */
434static DECLCALLBACK(int) drvStorageFlt_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
435{
436 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
437 PDRVSTORAGEFILTER pThis = PDMINS_2_DATA(pDrvIns, PDRVSTORAGEFILTER);
438 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
439
440 /*
441 * Initialize the instance data.
442 */
443 pDrvIns->IBase.pfnQueryInterface = drvStorageFltIBase_QueryInterface;
444
445 pThis->IMedia.pfnRead = drvStorageFltIMedia_Read;
446 pThis->IMedia.pfnWrite = drvStorageFltIMedia_Write;
447 pThis->IMedia.pfnFlush = drvStorageFltIMedia_Flush;
448 pThis->IMedia.pfnMerge = drvStorageFltIMedia_Merge;
449 pThis->IMedia.pfnGetSize = drvStorageFltIMedia_GetSize;
450 pThis->IMedia.pfnIsReadOnly = drvStorageFltIMedia_IsReadOnly;
451 pThis->IMedia.pfnBiosGetPCHSGeometry = drvStorageFltIMedia_BiosGetPCHSGeometry;
452 pThis->IMedia.pfnBiosSetPCHSGeometry = drvStorageFltIMedia_BiosSetPCHSGeometry;
453 pThis->IMedia.pfnBiosGetLCHSGeometry = drvStorageFltIMedia_BiosGetLCHSGeometry;
454 pThis->IMedia.pfnBiosSetLCHSGeometry = drvStorageFltIMedia_BiosSetLCHSGeometry;
455 pThis->IMedia.pfnGetUuid = drvStorageFltIMedia_GetUuid;
456 pThis->IMedia.pfnDiscard = drvStorageFltIMedia_Discard;
457
458 pThis->IMediaEx.pfnQueryFeatures = drvStorageFltIMedia_QueryFeatures;
459 pThis->IMediaEx.pfnIoReqAllocSizeSet = drvStorageFltIMedia_IoReqAllocSizeSet;
460 pThis->IMediaEx.pfnIoReqAlloc = drvStorageFltIMedia_IoReqAlloc;
461 pThis->IMediaEx.pfnIoReqFree = drvStorageFltIMedia_IoReqFree;
462 pThis->IMediaEx.pfnIoReqQueryResidual = drvStorageFltIMedia_IoReqQueryResidual;
463 pThis->IMediaEx.pfnIoReqCancelAll = drvStorageFltIMedia_IoReqCancelAll;
464 pThis->IMediaEx.pfnIoReqCancel = drvStorageFltIMedia_IoReqCancel;
465 pThis->IMediaEx.pfnIoReqRead = drvStorageFltIMedia_IoReqRead;
466 pThis->IMediaEx.pfnIoReqWrite = drvStorageFltIMedia_IoReqWrite;
467 pThis->IMediaEx.pfnIoReqFlush = drvStorageFltIMedia_IoReqFlush;
468 pThis->IMediaEx.pfnIoReqDiscard = drvStorageFltIMedia_IoReqDiscard;
469 pThis->IMediaEx.pfnIoReqSendScsiCmd = drvStorageFltIMedia_IoReqSendScsiCmd;
470 pThis->IMediaEx.pfnIoReqGetActiveCount = drvStorageFltIMedia_IoReqGetActiveCount;
471 pThis->IMediaEx.pfnIoReqGetSuspendedCount = drvStorageFltIMedia_IoReqGetSuspendedCount;
472 pThis->IMediaEx.pfnIoReqQuerySuspendedStart = drvStorageFltIMedia_IoReqQuerySuspendedStart;
473 pThis->IMediaEx.pfnIoReqQuerySuspendedNext = drvStorageFltIMedia_IoReqQuerySuspendedNext;
474 pThis->IMediaEx.pfnIoReqSuspendedSave = drvStorageFltIMedia_IoReqSuspendedSave;
475 pThis->IMediaEx.pfnIoReqSuspendedLoad = drvStorageFltIMedia_IoReqSuspendedLoad;
476
477 pThis->IMediaPort.pfnQueryDeviceLocation = drvStorageFltIMediaPort_QueryDeviceLocation;
478
479 pThis->IMediaExPort.pfnIoReqCompleteNotify = drvStorageFltIMedia_IoReqCompleteNotify;
480 pThis->IMediaExPort.pfnIoReqCopyFromBuf = drvStorageFltIMedia_IoReqCopyFromBuf;
481 pThis->IMediaExPort.pfnIoReqCopyToBuf = drvStorageFltIMedia_IoReqCopyToBuf;
482 pThis->IMediaExPort.pfnIoReqQueryDiscardRanges = drvStorageFltIMedia_IoReqQueryDiscardRanges;
483 pThis->IMediaExPort.pfnIoReqStateChanged = drvStorageFltIMedia_IoReqStateChanged;
484
485 /*
486 * Validate and read config.
487 */
488 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "AsyncIOSupported|", "");
489
490 int rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "AsyncIOSupported", &pThis->fAsyncIOSupported, true);
491 AssertLogRelRCReturn(rc, rc);
492
493 /*
494 * Query interfaces from the driver/device above us.
495 */
496 pThis->pIMediaPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
497 pThis->pIMediaExPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT);
498
499 /*
500 * Attach driver below us.
501 */
502 PPDMIBASE pIBaseBelow;
503 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pIBaseBelow);
504 AssertLogRelRCReturn(rc, rc);
505
506 pThis->pIMediaBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMIMEDIA);
507 pThis->pIMediaExBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMIMEDIAEX);
508
509 AssertLogRelReturn(pThis->pIMediaBelow, VERR_PDM_MISSING_INTERFACE_BELOW);
510
511 if (!pThis->pIMediaBelow->pfnDiscard)
512 pThis->IMedia.pfnDiscard = NULL;
513
514 return VINF_SUCCESS;
515}
516
517
518/**
519 * Storage filter driver registration record.
520 */
521static const PDMDRVREG g_DrvStorageFilter =
522{
523 /* u32Version */
524 PDM_DRVREG_VERSION,
525 /* szName */
526 "StorageFilter",
527 /* szRCMod */
528 "",
529 /* szR0Mod */
530 "",
531 /* pszDescription */
532 "Storage Filter Driver Sample",
533 /* fFlags */
534 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
535 /* fClass. */
536 PDM_DRVREG_CLASS_MEDIA,
537 /* cMaxInstances */
538 ~0U,
539 /* cbInstance */
540 sizeof(DRVSTORAGEFILTER),
541 /* pfnConstruct */
542 drvStorageFlt_Construct,
543 /* pfnDestruct */
544 NULL,
545 /* pfnRelocate */
546 NULL,
547 /* pfnIOCtl */
548 NULL,
549 /* pfnPowerOn */
550 NULL,
551 /* pfnReset */
552 NULL,
553 /* pfnSuspend */
554 NULL,
555 /* pfnResume */
556 NULL,
557 /* pfnAttach */
558 NULL,
559 /* pfnDetach */
560 NULL,
561 /* pfnPowerOff */
562 NULL,
563 /* pfnSoftReset */
564 NULL,
565 /* u32EndVersion */
566 PDM_DRVREG_VERSION
567};
568
569
570/**
571 * Register builtin devices.
572 *
573 * @returns VBox status code.
574 * @param pCallbacks Pointer to the callback table.
575 * @param u32Version VBox version number.
576 */
577extern "C" DECLEXPORT(int) VBoxDriversRegister(PPDMDRVREGCB pCallbacks, uint32_t u32Version)
578{
579 LogFlow(("VBoxSampleDriver::VBoxDriversRegister: u32Version=%#x pCallbacks->u32Version=%#x\n",
580 u32Version, pCallbacks->u32Version));
581
582 AssertLogRelMsgReturn(u32Version >= VBOX_VERSION,
583 ("VirtualBox version %#x, expected %#x or higher\n", u32Version, VBOX_VERSION),
584 VERR_VERSION_MISMATCH);
585 AssertLogRelMsgReturn(pCallbacks->u32Version == PDM_DRVREG_CB_VERSION,
586 ("callback version %#x, expected %#x\n", pCallbacks->u32Version, PDM_DRVREG_CB_VERSION),
587 VERR_VERSION_MISMATCH);
588
589 return pCallbacks->pfnRegister(pCallbacks, &g_DrvStorageFilter);
590}
591
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use