VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use