VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp@ 79929

Last change on this file since 79929 was 79929, checked in by vboxsync, 6 years ago

Attempt to fix burn related to bad doxygen doc field

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.2 KB
Line 
1/* $Id: DevVirtioSCSI.cpp 79929 2019-07-23 12:03:59Z vboxsync $ $Revision: 79929 $ $Date: 2019-07-23 12:03:59 +0000 (Tue, 23 Jul 2019) $ $Author: vboxsync $ */
2/** @file
3 * VBox storage devices - Virtio SCSI Driver
4 *
5 */
6
7/*
8 * Copyright (C) 2006-2019 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23#define LOG_GROUP LOG_GROUP_DRV_SCSI
24
25#include <VBox/vmm/pdmdev.h>
26#include <VBox/vmm/pdmstorageifs.h>
27#include <VBox/vmm/pdmcritsect.h>
28#include <VBox/version.h>
29#include <iprt/errcore.h>
30#include <VBox/log.h>
31#include <iprt/assert.h>
32#include <iprt/string.h>
33#include "../build/VBoxDD.h"
34#include <VBox/scsi.h>
35#ifdef IN_RING3
36# include <iprt/alloc.h>
37# include <iprt/memcache.h>
38# include <iprt/param.h>
39# include <iprt/uuid.h>
40#endif
41#include "../VirtIO/Virtio_1_0.h"
42
43#include "VBoxSCSI.h"
44#include "VBoxDD.h"
45
46
47/*********************************************************************************************************************************
48* Structures and Typedefs *
49*********************************************************************************************************************************/
50#define VIRTIOSCSI_MAX_TARGETS 1
51
52/**
53 * Device Instance Data.
54 */
55typedef struct VIRTIOSCSITARGET
56{
57
58
59 /** Pointer to the owning virtioScsi device instance. - R3 pointer */
60 R3PTRTYPE(struct VIRTIOSCSI *) pVirtioScsiR3;
61 /** Pointer to the owning virtioScsi device instance. - R0 pointer */
62 R3PTRTYPE(struct VIRTIOSCSI *) pVirtioScsiR0;
63 /** Pointer to the owning virtioScsi device instance. - RC pointer */
64 R3PTRTYPE(struct VIRTIOSCSI *) pVirtioScsiRC;
65
66 /** Pointer to attached driver's base interface. */
67 R3PTRTYPE(PPDMIBASE) pUpstreamDrvBase;
68
69 /** LUN of the device. */
70 RTUINT iLUN;
71
72 /** Our base interface. */
73 PDMIBASE IBase;
74
75 /** Flag whether device is present. */
76 bool fPresent;
77
78 /** Media port interface. */
79 PDMIMEDIAPORT IMediaPort;
80
81 /** Extended media port interface. */
82 PDMIMEDIAEXPORT IMediaExPort;
83
84 /** Number of outstanding tasks on the port. */
85 volatile uint32_t cOutstandingRequests;
86
87 /** LUN Description */
88 char * pszLunName;
89
90 /** Pointer to the attached driver's media interface. */
91 R3PTRTYPE(PPDMIMEDIA) pDrvMedia;
92
93 /** Pointer to the attached driver's extended media interface. */
94 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx;
95
96 R3PTRTYPE(PVQUEUE) pCtlQueue; // ? TBD
97 R3PTRTYPE(PVQUEUE) pEvtQueue; // ? TBD
98 R3PTRTYPE(PVQUEUE) pReqQueue; // ? TBD
99
100} VIRTIOSCSITARGET, *PVIRTIOSCSITARGET;
101
102
103/**
104 * Main VirtIO SCSI device state.
105 *
106 * @extends PDMPCIDEV
107 */
108typedef struct VIRTIOSCSI
109{
110
111 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */
112 PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */
113 PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */
114
115 /* virtioState must be first member */
116 VIRTIOSTATE virtioState;
117
118 /* SCSI target instances data */
119 VIRTIOSCSITARGET aTargetInstances[VIRTIOSCSI_MAX_TARGETS];
120
121 /** Base address of the I/O ports. */
122 RTIOPORT IOPortBase;
123
124 /** Base address of the memory mapping. */
125 RTGCPHYS GCPhysMMIOBase;
126
127 /** IMediaExPort: Media ejection notification */
128 R3PTRTYPE(PPDMIMEDIANOTIFY) pMediaNotify;
129
130 /** Queue to send tasks to R3. - HC ptr */
131 R3PTRTYPE(PPDMQUEUE) pNotifierQueueR3;
132
133 /** The support driver session handle. */
134 R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession;
135
136 /** Worker thread. */
137 R3PTRTYPE(PPDMTHREAD) pThreadWrk;
138
139 /** The event semaphore the processing thread waits on. */
140 SUPSEMEVENT hEvtProcess;
141
142 /** Number of ports detected */
143 uint64_t cTargets;
144
145 /** True if PDMDevHlpAsyncNotificationCompleted should be called when port goes idle */
146 bool volatile fSignalIdle;
147
148} VIRTIOSCSI, *PVIRTIOSCSI;
149
150
151
152//pk: Needed for virtioIO (e.g. to talk to devSCSI? TBD ??
153/**
154 * Task state for a CCB request.
155 */
156typedef struct VIRTIOSCSIREQ
157{
158 /** Device this task is assigned to. */
159 PVIRTIOSCSITARGET pTargetDevice;
160 /** The command control block from the guest. */
161// CCBU CCBGuest;
162 /** Guest physical address of th CCB. */
163 RTGCPHYS GCPhysAddrCCB;
164 /** Pointer to the R3 sense buffer. */
165 uint8_t *pbSenseBuffer;
166 /** Flag whether this is a request from the BIOS. */
167 bool fBIOS;
168 /** 24-bit request flag (default is 32-bit). */
169 bool fIs24Bit;
170 /** SCSI status code. */
171 uint8_t u8ScsiSts;
172} VIRTIOSCSIREQ;
173typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
174
175
176#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION 0x01
177
178#define PCI_VENDOR_ID_VIRTIO 0x1AF4
179#define PCI_DEVICE_ID_VIRTIO_SCSI_HOST 0x1048
180#define PCI_CLASS_BASE_MASS_STORAGE 0x01
181#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER 0x00
182#define PCI_CLASS_PROG_UNSPECIFIED 0x00
183#define VIRTIO_SCSI_NAME_FMT "VIRTIOSCSI%d" /* "VSCSI" *might* be ambiguous with VBoxSCSI? */
184#define VIRTIO_SCSI_PCI_CLASS 0x01 /* Base class Mass Storage? */
185#define VIRTIO_SCSI_N_QUEUES 3 /* Control, Event, Request */
186#define VIRTIO_SCSI_REGION_MEM_IO 0
187#define VIRTIO_SCSI_REGION_PORT_IO 1
188#define VIRTIO_SCSI_REGION_PCI_CAP 2
189
190/**
191 * Definitions that follow are based on the VirtIO 1.0 specification.
192 * Struct names are the same. The field names have been adapted to VirtualBox
193 * data type + camel case annotation, with the original field name from the
194 * VirtIO specification in the field's comment.
195 */
196
197/** @name VirtIO 1.0 SCSI Host feature bits
198 * @{ */
199#define VIRTIO_SCSI_F_INOUT 0 /** Request is device readable AND writeable */
200#define VIRTIO_SCSI_F_HOTPLUG 1 /** Host SHOULD allow hotplugging SCSI LUNs & targets */
201#define VIRTIO_SCSI_F_CHANGE 2 /** Host reports LUN changes via VIRTIO_SCSI_T_PARAM_CHANGE event */
202/** @} */
203
204#define CDB_SIZE 1 /* logic tbd */
205#define SENSE_SIZE 1 /* logic tbd */
206#define PI_BYTES_OUT 1 /* logic tbd */
207#define PI_BYTES_IN 1 /* logic tbd */
208#define DATA_OUT 1 /* logic tbd */
209typedef struct virtio_scsi_req_cmd
210{
211 /* Device-readable part */
212 uint8_t uLUN[8]; /** lun */
213 uint64_t uId; /** id */
214 uint8_t uTaskAttr; /** task_attr */
215 uint8_t uPrio; /** prio */
216 uint8_t uCrn; /** crn */
217 uint8_t uCdb[CDB_SIZE]; /** cdb */
218
219 /** Following three fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
220
221 uint32_t uPiBytesOut; /** pi_bytesout */
222 uint32_t uPiBytesIn; /** pi_bytesin */
223 uint8_t uPiOut[PI_BYTES_OUT]; /** pi_out[] */
224
225 uint8_t uDataOut[DATA_OUT]; /** dataout */
226
227 /* Device-writable part */
228 uint32_t uSenseLen; /** sense_len */
229 uint32_t uResidual; /** residual */
230 uint16_t uStatusQualifier; /** status_qualifier */
231 uint8_t uStatus; /** status */
232 uint8_t uResponse; /** response */
233 uint8_t uSense[SENSE_SIZE]; /** sense */
234
235 /** Following two fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
236 uint8_t uPiIn[PI_BYTES_IN]; /** pi_in[] */
237 uint8_t uDataIn[]; /** detain; */
238} VIRTIOSCSIREQCMD, *PVIRTIOSCSIREQCMD;
239
240/** Command-specific response values */
241#define VIRTIO_SCSI_S_OK 0 /* control, command */
242#define VIRTIO_SCSI_S_OVERRUN 1 /* control */
243#define VIRTIO_SCSI_S_ABORTED 2 /* control */
244#define VIRTIO_SCSI_S_BAD_TARGET 3 /* control, command */
245#define VIRTIO_SCSI_S_RESET 4 /* control */
246#define VIRTIO_SCSI_S_BUSY 5 /* control, command */
247#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 /* control, command */
248#define VIRTIO_SCSI_S_TARGET_FAILURE 7 /* control, command */
249#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 /* control, command */
250#define VIRTIO_SCSI_S_FAILURE 9 /* control, command */
251#define VIRTIO_SCSI_S_INCORRECT_LUN 12 /* command */
252
253
254/** task_attr */
255#define VIRTIO_SCSI_S_SIMPLE 0
256#define VIRTIO_SCSI_S_ORDERED 1
257#define VIRTIO_SCSI_S_HEAD 2
258#define VIRTIO_SCSI_S_ACA 3
259
260#define VIRTIO_SCSI_T_TMF 0
261#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
262#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
263#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
264#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
265#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
266#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
267#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
268#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
269
270typedef struct virtio_scsi_ctrl_tmf
271{
272 // Device-readable part
273 uint32_t uType; /** type */
274 uint32_t uSubtype; /** subtype */
275 uint8_t uLUN[8]; /** lun */
276 uint64_t uId; /** id */
277 // Device-writable part
278 uint8_t uResponse; /** response */
279} VIRTIOSCSICTRLBUF, *PVIRTIOSCSICTRLBUF;
280
281/* command-specific response values */
282
283#define VIRTIO_SCSI_S_FUNCTION_COMPLETE 0
284#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
285#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
286
287#define VIRTIO_SCSI_T_AN_QUERY 1 /** Asynchronous notification query */
288#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 /** Asynchronous notification subscription */
289
290typedef struct virtio_scsi_ctrl_an
291{
292 // Device-readable part
293 uint32_t uType; /** type */
294 uint8_t uLUN[8]; /** lun */
295 uint32_t uEventRequested; /** event_requested */
296 // Device-writable part
297 uint32_t uEventActual; /** event_actual */
298 uint8_t uResponse; /** response */
299} VIRTIOSCSICTRLAN, *PVIRTIOSCSICTRLAN;
300
301#define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2
302#define VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT 4
303#define VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST 8
304#define VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE 16
305#define VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST 32
306#define VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY 64
307
308/** Device operation: controlq */
309
310typedef struct virtio_scsi_ctrl
311{
312 uint32_t type; /** type */
313 uint8_t response; /** response */
314} VIRTIOSCSICTRL, *PVIRTIOSCSICTRL;
315
316#define VIRTIO_SCSI_T_NO_EVENT 0
317
318#define VIRTIO_SCSI_T_TRANSPORT_RESET 1
319#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 /** Asynchronous notification */
320#define VIRTIO_SCSI_T_PARAM_CHANGE 3
321
322#define VIRTIO_SCSI_EVT_RESET_HARD 0
323#define VIRTIO_SCSI_EVT_RESET_RESCAN 1
324#define VIRTIO_SCSI_EVT_RESET_REMOVED 2
325
326/** Device operation: eventq */
327
328#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
329typedef struct virtio_scsi_event {
330 // Device-writable part
331 uint32_t uEvent; /** event: */
332 uint8_t uLUN[8]; /** lun */
333 uint32_t uReason; /** reason */
334} VIRTIOSCSIEVENT, *PVIRTIOSCSIEVENT;
335
336
337/*********************************************************************************************************************************/
338
339#ifdef BOOTABLE_SUPPORT_TBD
340/** @callback_method_impl{FNIOMIOPORTIN} */
341static DECLCALLBACK(int) virtioScsiR3BiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
342 uint32_t *pcTransfers, unsigned cb);
343{
344}
345/** @callback_method_impl{FNIOMIOPORTOUT} */
346static DECLCALLBACK(int) virtioScsiR3BiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb);
347{
348}
349/** @callback_method_impl{FNIOMIOPORTOUTSTRING} */
350static DECLCALLBACK(int) virtioScsiR3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,
351 uint32_t *pcTransfers, unsigned cb);
352{
353}
354/** @callback_method_impl{FNIOMIOPORTINSTRING} */
355static DECLCALLBACK(int) virtioScsiR3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
356 uint32_t *pcTransfers, unsigned cb);
357{
358}
359#endif
360
361/**
362 * virtio-scsi debugger info callback.
363 *
364 * @param pDevIns The device instance.
365 * @param pHlp The output helpers.
366 * @param pszArgs The arguments.
367 */
368static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
369{
370 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
371 bool fVerbose = false;
372
373 /* Parse arguments. */
374 if (pszArgs)
375 fVerbose = strstr(pszArgs, "verbose") != NULL;
376
377 /* Show basic information. */
378 pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",
379 pDevIns->pReg->szName,
380 pDevIns->iInstance);
381 pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets);
382}
383
384/** @callback_method_impl{FNSSMDEVLIVEEXEC} */
385static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
386{
387 LogFunc(("callback"));
388 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
389 RT_NOREF(pThis);
390 RT_NOREF(uPass);
391 RT_NOREF(pSSM);
392 return VINF_SSM_DONT_CALL_AGAIN;
393}
394
395/** @callback_method_impl{FNSSMDEVLOADEXEC} */
396static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
397{
398 LogFunc(("callback"));
399 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
400 RT_NOREF(pThis);
401 RT_NOREF(uPass);
402 RT_NOREF(pSSM);
403 RT_NOREF(uVersion);
404 return VINF_SSM_DONT_CALL_AGAIN;
405}
406
407/** @callback_method_impl{FNSSMDEVSAVEEXEC} */
408static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
409{
410 LogFunc(("callback"));
411 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
412 RT_NOREF(pThis);
413 RT_NOREF(pSSM);
414 return VINF_SUCCESS;
415}
416
417/** @callback_method_impl{FNSSMDEVLOADDONE} */
418static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
419{
420 LogFunc(("callback"));
421 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
422 RT_NOREF(pThis);
423 RT_NOREF(pSSM);
424 return VINF_SUCCESS;
425}
426
427/**
428 * Memory mapped I/O Handler for read operations.
429 *
430 * @returns VBox status code.
431 *
432 * @param pDevIns The device instance.
433 * @param pvUser User argument.
434 * @param GCPhysAddr Physical address (in GC) where the read starts.
435 * @param pv Where to store the result.
436 * @param cb Number of bytes read.
437 */
438PDMBOTHCBDECL(int) virtioScsiMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
439{
440 RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
441 LogFunc(("Read from MMIO area\n"));
442 return VINF_SUCCESS;
443}
444
445/**
446 * Memory mapped I/O Handler for write operations.
447 *
448 * @returns VBox status code.
449 *
450 * @param pDevIns The device instance.
451 * @param pvUser User argument.
452 * @param GCPhysAddr Physical address (in GC) where the read starts.
453 * @param pv Where to fetch the result.
454 * @param cb Number of bytes to write.
455 */
456PDMBOTHCBDECL(int) virtioScsiMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
457{
458 RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
459 LogFunc(("Write to MMIO area\n"));
460 return VINF_SUCCESS;
461}
462
463/**
464 * @callback_method_impl{FNPCIIOREGIONMAP}
465 */
466static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
467 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
468{
469 RT_NOREF(pPciDev, iRegion);
470 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
471 int rc = VINF_SUCCESS;
472
473 Assert(cb >= 32);
474
475 switch (iRegion)
476 {
477 case 0:
478 LogFunc(("virtio-scsi controller MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
479
480 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
481 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
482 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
483 virtioScsiMMIOWrite, virtioScsiMMIORead,
484 "virtio-scsi MMIO");
485 pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
486 return rc;
487 case 1:
488 /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */
489 AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));
490 default:
491 AssertMsgFailed(("Invalid enmType=%d\n", enmType));
492 }
493 return VERR_GENERAL_FAILURE; /* Should never get here */
494}
495
496
497/**
498 * @copydoc FNPDMDEVRESET
499 */
500static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
501{
502 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
503 NOREF(pThis);
504
505// ASMAtomicWriteBool(&pThis->fSignalIdle, true);
506// if (!virtioScsiR3AllAsyncIOIsFinished(pDevIns))
507// PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3IsAsyncResetDone);
508// else
509// {
510// ASMAtomicWriteBool(&pThis->fSignalIdle, false);
511// }
512}
513
514static DECLCALLBACK(void) virtioScsiR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
515{
516 LogFunc(("Relocating virtio-scsi"));
517 RT_NOREF(offDelta);
518 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
519
520 pThis->pDevInsR3 = pDevIns;
521
522 for (uint32_t i = 0; i < VIRTIOSCSI_MAX_TARGETS; i++)
523 {
524 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
525 pTarget->pVirtioScsiR3 = pThis;;
526 }
527
528}
529
530static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
531 uint32_t *piInstance, uint32_t *piLUN)
532{
533 PVIRTIOSCSITARGET pVirtioScsiTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
534 PPDMDEVINS pDevIns = pVirtioScsiTarget->CTX_SUFF(pVirtioScsi)->CTX_SUFF(pDevIns);
535
536 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
537 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
538 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
539
540 *ppcszController = pDevIns->pReg->szName;
541 *piInstance = pDevIns->iInstance;
542 *piLUN = pVirtioScsiTarget->iLUN;
543
544 return VINF_SUCCESS;
545}
546
547/**
548 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
549 */
550static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
551 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
552 size_t cbCopy)
553{
554 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
555 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
556 size_t cbCopied = 0;
557 RT_NOREF(pTarget);
558 RT_NOREF(pReq);
559 RT_NOREF(pInterface);
560 RT_NOREF(pvIoReqAlloc);
561 RT_NOREF(offDst);
562 RT_NOREF(pSgBuf);
563 RT_NOREF(hIoReq);
564 RT_NOREF(cbCopy);
565 RT_NOREF(cbCopied);
566
567/*
568 if (RT_UNLIKELY(pReq->fBIOS))
569 cbCopied = vboxscsiCopyToBuf(&pTarget->CTX_SUFF(pVirtioScsi)->VBoxSCSI, pSgBuf, offDst, cbCopy);
570 else
571 cbCopied = virtioScsiR3CopySgBufToGuest(pTarget->CTX_SUFF(pVirtioScsi), pReq, pSgBuf, offDst, cbCopy);
572 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
573*/
574 return 0; /* placeholder */
575}
576
577/**
578 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
579 */
580static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
581 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
582 size_t cbCopy)
583{
584 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
585 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
586 size_t cbCopied = 0;
587 RT_NOREF(pTarget);
588 RT_NOREF(pReq);
589 RT_NOREF(pInterface);
590 RT_NOREF(pvIoReqAlloc);
591 RT_NOREF(offSrc);
592 RT_NOREF(pSgBuf);
593 RT_NOREF(hIoReq);
594 RT_NOREF(cbCopy);
595 RT_NOREF(cbCopied);
596
597/*
598 if (RT_UNLIKELY(pReq->fBIOS))
599 cbCopied = vboxscsiCopyFromBuf(&pTarget->CTX_SUFF(pVirtioScsi)->VBoxSCSI, pSgBuf, offSrc, cbCopy);
600 else
601 cbCopied = vboxscsiR3CopySgBufFromGuest(pTarget->CTX_SUFF(pVirtioScsi), pReq, pSgBuf, offSrc, cbCopy);
602 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
603*/
604 return 0; /* placeholder */
605
606}
607
608/**
609 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
610 */
611static DECLCALLBACK(int) virtioScsiR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
612 void *pvIoReqAlloc, int rcReq)
613{
614 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
615 RT_NOREF(pTarget);
616 RT_NOREF(pInterface);
617 RT_NOREF(pvIoReqAlloc);
618 RT_NOREF(rcReq);
619 RT_NOREF(hIoReq);
620// virtioScsiR3ReqComplete(pTarget->CTX_SUFF(pVirtioScsi), (VIRTIOSCSIREQ)pvIoReqAlloc, rcReq);
621 return VINF_SUCCESS;
622}
623
624/**
625 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
626 */
627static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
628 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
629{
630
631 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
632 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
633
634 switch (enmState)
635 {
636 case PDMMEDIAEXIOREQSTATE_SUSPENDED:
637 {
638 /* Make sure the request is not accounted for so the VM can suspend successfully. */
639 uint32_t cTasksActive = ASMAtomicDecU32(&pTarget->cOutstandingRequests);
640 if (!cTasksActive && pTarget->CTX_SUFF(pVirtioScsi)->fSignalIdle)
641 PDMDevHlpAsyncNotificationCompleted(pTarget->CTX_SUFF(pVirtioScsi)->pDevInsR3);
642 break;
643 }
644 case PDMMEDIAEXIOREQSTATE_ACTIVE:
645 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
646 ASMAtomicIncU32(&pTarget->cOutstandingRequests);
647 break;
648 default:
649 AssertMsgFailed(("Invalid request state given %u\n", enmState));
650 }
651}
652
653/**
654 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
655 */
656static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
657{
658 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
659 PVIRTIOSCSI pThis = pTarget->CTX_SUFF(pVirtioScsi);
660
661 if (pThis->pMediaNotify)
662 virtioSetWriteLed(&(pThis->virtioState), false);
663}
664
665
666/**
667 * Transmit queue consumer
668 * Queue a new async task.
669 *
670 * @returns Success indicator.
671 * If false the item will not be removed and the flushing will stop.
672 * @param pDevIns The device instance.
673 * @param pItem The item to consume. Upon return this item will be freed.
674 */
675static DECLCALLBACK(bool) virtioScsiR3NotifyQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
676{
677 RT_NOREF(pItem);
678 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
679
680 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess);
681 AssertRC(rc);
682
683 return true;
684}
685
686
687/**
688 * virtio-scsi VirtIO Device-specific capabilities read callback
689 * (other VirtIO capabilities and features are handled in VirtIO implementation)
690 *
691 * @param pDevIns The device instance.
692 * @param GCPhysAddr Guest driver physical address to read
693 * @param pvBuf Buffer in which to save read data
694 * @param cbRead Number of bytes to read
695 */
696static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbRead)
697{
698/*TBD*/
699 LogFlowFunc(("Read from Device-Specific capabilities, callback to VirtIO client\n"));
700 RT_NOREF(pDevIns);
701 RT_NOREF(GCPhysAddr);
702 RT_NOREF(pvBuf);
703 RT_NOREF(cbRead);
704 int rv = VINF_SUCCESS;
705 return rv;
706}
707
708/**
709 * virtio-scsi VirtIO Device-specific capabilities read callback
710 * (other VirtIO capabilities and features are handled in VirtIO implementation)
711 *
712 * @param pDevIns The device instance.
713 * @param GCPhysAddr Guest driver physical address to write
714 * @param pvBuf Buffer in which to save read data
715 * @param cbWrite Number of bytes to write
716 */
717static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbWrite)
718{
719/*TBD*/
720 LogFlowFunc(("Write to Device-Specific capabilities, callback to VirtIO client\n"));
721 RT_NOREF(pDevIns);
722 RT_NOREF(GCPhysAddr);
723 RT_NOREF(pvBuf);
724 RT_NOREF(cbWrite);
725 int rv = VINF_SUCCESS;
726 return rv;
727}
728
729/**
730 * Detach notification.
731 *
732 * One harddisk at one port has been unplugged.
733 * The VM is suspended at this point.
734 *
735 * @param pDevIns The device instance.
736 * @param iLUN The logical unit which is being detached.
737 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
738 */
739static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
740{
741 RT_NOREF(fFlags);
742 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
743 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
744
745 Log(("%s:\n", __FUNCTION__));
746
747 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
748 ("virtio-scsi: Device does not support hotplugging\n"));
749
750 /*
751 * Zero some important members.
752 */
753 pTarget->fPresent = false;
754 pTarget->pUpstreamDrvBase = NULL;
755}
756
757
758/**
759 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
760 */
761static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
762{
763 PPDMDRVINS pDevIns = PDMIBASE_2_PDMDRV(pInterface);
764 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
765 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
766 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);
767 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
768 return NULL;
769}
770
771/**
772 * Attach command.
773 *
774 * This is called when we change block driver.
775 *
776 * @returns VBox status code.
777 * @param pDevIns The device instance.
778 * @param iLUN The logical unit which is being detached.
779 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
780 */
781static DECLCALLBACK(int) virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
782{
783 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
784 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
785 int rc;
786
787 pThis->pDevInsR3 = pDevIns;
788 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
789 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
790
791 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
792 ("virtio-scsi: Device does not support hotplugging\n"),
793 VERR_INVALID_PARAMETER);
794
795 /* the usual paranoia */
796 AssertRelease(!pTarget->pUpstreamDrvBase);
797 Assert(pTarget->iLUN == iLUN);
798
799 /*
800 * Try attach the SCSI driver and get the interfaces,
801 * required as well as optional.
802 */
803 rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pDevIns->IBase,
804 &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
805 if (RT_SUCCESS(rc))
806 pTarget->fPresent = true;
807 else
808 AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->pszLunName, rc));
809
810 if (RT_FAILURE(rc))
811 {
812 pTarget->fPresent = false;
813 pTarget->pUpstreamDrvBase = NULL;
814 }
815 return rc;
816}
817
818static DECLCALLBACK(int) virtioScsiDestruct(PPDMDEVINS pDevIns)
819{
820 /*
821 * Check the versions here as well since the destructor is *always* called.
822 */
823 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
824 return VINF_SUCCESS;
825}
826
827static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
828{
829
830 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
831 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
832 int rc = VINF_SUCCESS;
833 bool fBootable = true;
834
835 LogFunc(("PDM device instance: %d\n", iInstance));
836
837 /*
838 * Validate and read configuration.
839 */
840 if (!CFGMR3AreValuesValid(pCfg,"NumTargets\0"
841 "Bootable\0"
842 /* "GCEnabled\0" TBD */
843 /* "R0Enabled\0" TBD */
844 ))
845 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
846 N_("virtio-scsi configuration error: unknown option specified"));
847
848 rc = CFGMR3QueryIntegerDef(pCfg, "NumTargets", &pThis->cTargets, true);
849 if (RT_FAILURE(rc))
850 return PDMDEV_SET_ERROR(pDevIns, rc,
851 N_("virtio-scsi configuration error: failed to read NumTargets as integer"));
852 LogFunc(("NumTargets=%d\n", pThis->cTargets));
853
854 rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &fBootable, true);
855 if (RT_FAILURE(rc))
856 return PDMDEV_SET_ERROR(pDevIns, rc,
857 N_("virtio-scsi configuration error: failed to read Bootable as boolean"));
858 LogFunc(("Bootable=%RTbool (unimplemented)\n", fBootable));
859
860 VIRTIOPCIPARAMS virtioPciParams, *pVirtioPciParams = &virtioPciParams;
861 pVirtioPciParams->uDeviceId = PCI_DEVICE_ID_VIRTIO_SCSI_HOST;
862 pVirtioPciParams->uClassBase = PCI_CLASS_BASE_MASS_STORAGE;
863 pVirtioPciParams->uClassSub = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;
864 pVirtioPciParams->uClassProg = PCI_CLASS_PROG_UNSPECIFIED;
865 pVirtioPciParams->uSubsystemId = PCI_DEVICE_ID_VIRTIO_SCSI_HOST; /* Virtio 1.0 spec allows PCI Device ID here */
866 pVirtioPciParams->uInterruptLine = 0x00;
867 pVirtioPciParams->uInterruptPin = 0x01;
868
869
870 PVIRTIOSTATE pVirtioScsi = &(pThis->virtioState);
871 rc = virtioConstruct(pDevIns, pVirtioScsi, iInstance, pVirtioPciParams,
872 VIRTIO_SCSI_NAME_FMT, VIRTIO_SCSI_N_QUEUES, VIRTIO_SCSI_REGION_PCI_CAP,
873 virtioScsiR3DevCapRead, virtioScsiR3DevCapWrite, sizeof(VIRTIODEVCFG));
874 if (RT_FAILURE(rc))
875 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
876
877 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO_SCSI_REGION_PORT_IO, 32,
878 PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map);
879 if (RT_FAILURE(rc))
880 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: cannot register PCI mmio address space"));
881
882#ifdef BOOTABLE_SUPPORT_TBD
883 if (fBootable)
884 {
885 /* Register I/O port space for BIOS access. */
886 rc = PDMDevHlpIOPortRegister(pDevIns, VIRTIOSCSI_BIOS_IO_PORT, 4, NULL,
887 virtioScsiR3BiosIoPortWrite, virtioScsiR3BiosIoPortRead,
888 virtioScsiR3BiosIoPortWriteStr, virtioScsiR3BiosIoPortReadStr,
889 "virtio-scsi BIOS");
890 if (RT_FAILURE(rc))
891 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register BIOS I/O handlers"));
892 }
893#endif
894
895 /* Initialize task queue. */
896 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 5, 0,
897 virtioScsiR3NotifyQueueConsumer, true, "VirtioTask", &pThis->pNotifierQueueR3);
898 if (RT_FAILURE(rc))
899 return rc;
900
901 /* Initialize per device instance. */
902 for (RTUINT iLUN = 0; iLUN < VIRTIOSCSI_MAX_TARGETS; iLUN++)
903 {
904 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
905
906 if (RTStrAPrintf(&pTarget->pszLunName, "VSCSI%u", iLUN) < 0)
907 AssertLogRelFailedReturn(VERR_NO_MEMORY);
908
909 /* Initialize static parts of the device. */
910 pTarget->iLUN = iLUN;
911 pTarget->pVirtioScsiR3 = pThis;
912 /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
913 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsiR3QueryDeviceLocation;
914 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsiR3IoReqCompleteNotify;
915 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsiR3IoReqCopyFromBuf;
916 pTarget->IMediaExPort.pfnIoReqCopyToBuf = virtioScsiR3IoReqCopyToBuf;
917 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsiR3IoReqStateChanged;
918 pTarget->IMediaExPort.pfnMediumEjected = virtioScsiR3MediumEjected;
919 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL;
920 pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
921 pDevIns->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
922
923 LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName));
924
925 /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */
926 AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
927 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pDevIns->IBase, &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
928 if (RT_SUCCESS(rc))
929 {
930 pTarget->fPresent = true;
931
932 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIA);
933 AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
934 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iLUN),
935 VERR_PDM_MISSING_INTERFACE);
936
937 /* Get the extended media interface. */
938 pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIAEX);
939 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
940 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iLUN),
941 VERR_PDM_MISSING_INTERFACE);
942
943// pk: Not sure if this is needed here yet with VirtIO or DrvScsi, will investigate after basic VirtIO working.
944// rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(BUSLOGICREQ));
945// AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!", pTarget->iLUN),
946
947 }
948 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
949 {
950 pTarget->fPresent = false;
951 pTarget->pUpstreamDrvBase = NULL;
952 rc = VINF_SUCCESS;
953 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszLunName));
954 }
955 else
956 {
957 AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s\n", pTarget->pszLunName));
958 return rc;
959 }
960 }
961
962 rc = PDMDevHlpSSMRegisterEx(pDevIns, VIRTIOSCSI_SAVED_STATE_MINOR_VERSION, sizeof(*pThis), NULL,
963 NULL, virtioScsiR3LiveExec, NULL,
964 NULL, virtioScsiR3SaveExec, NULL,
965 NULL, virtioScsiR3LoadExec, virtioScsiR3LoadDone);
966 if (RT_FAILURE(rc))
967 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register save state handlers"));
968 /*
969 * Register the debugger info callback.
970 */
971 char szTmp[128];
972 RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
973 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info);
974
975 return rc;
976}
977
978/**
979 * The device registration structure.
980 */
981const PDMDEVREG g_DeviceVirtioSCSI =
982{
983 /* u32Version */
984 PDM_DEVREG_VERSION,
985 /* szName */
986 "virtio-scsi",
987 /* szRCMod */
988 "",
989 /* szR0Mod */
990 "",
991 /* pszDescription */
992 "Virtio SCSI.\n",
993 /* fFlags */
994#ifdef VIRTIOSCSI_GC_SUPPORT
995 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
996#else
997 PDM_DEVREG_FLAGS_DEFAULT_BITS,
998#endif
999 /* fClass */
1000 PDM_DEVREG_CLASS_MISC,
1001 /* cMaxInstances */
1002 ~0U,
1003 /* cbInstance */
1004 sizeof(VIRTIOSCSI),
1005 /* pfnConstruct */
1006 virtioScsiConstruct,
1007 /* pfnDestruct */
1008 virtioScsiDestruct,
1009 /* pfnRelocate */
1010 virtioScsiR3Relocate,
1011 /* pfnMemSetup */
1012 NULL,
1013 /* pfnPowerOn */
1014 NULL,
1015 /* pfnReset */
1016 virtioScsiR3Reset,
1017 /* pfnSuspend */
1018 NULL,
1019 /* pfnResume */
1020 NULL,
1021 /* pfnAttach */
1022 virtioScsiR3Attach,
1023 /* pfnDetach */
1024 virtioScsiR3Detach,
1025 /* pfnQueryInterface */
1026 NULL,
1027 /* pfnInitComplete */
1028 NULL,
1029 /* pfnPowerOff */
1030 NULL,
1031 /* pfnSoftReset */
1032 NULL,
1033 /* u32VersionEnd */
1034 PDM_DEVREG_VERSION
1035};
1036
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette