VirtualBox

Changeset 81634 in vbox


Ignore:
Timestamp:
Nov 4, 2019 1:58:52 AM (5 years ago)
Author:
vboxsync
Message:

DevVirtioScsi,Virtio_1_0: A quick and superficial review of DevVirtioScsi. bugref:9218 bugref:9440

DevVirtioScsi.cpp:

  • Changed a bunch of 'virtioScsi' prefixes to 'virtioScsiR3' to prepare for ring-0 enabling of the code.
  • VIRTIO_IN_DIRECTION -> VIRTIO_IS_IN_DIRECTION because predicates should have a verb in them. Ditto for VIRTIO_OUT_DIRECTION.
  • Avoid the 'u' prefix when possible, e.g. s/uOffset/offConfig/, s/uIntraOffset/offIntra/, s/uSenseLen/cbSenseLen/, s/uAsyncTypesMask/fAsyncTypesMask/, ++.
  • The macros MATCH_SCSI_CONFIG, LOG_ACCESSOR, SCSI_CONFIG_ACCESSOR and SCSI_CONFIG_ACCESSOR_READONLY are local to virtioScsiCfgAccessed() and should be defined inside given the amount of non-parameters they access.
  • The unnecessary/compulsory initialization of variables, like 'rc' in virtioScsiDevCapRead and virtioScsiDevCapWrite, drives me nuts. It looks like there is code missing that would require 'rc' to be initialized.
  • Better if the 'pv' parameter to virtioScsiCfgAccessed is 'void *' rather than 'const void *'. Saves a lot of confusing casting inside the function.
  • virtioScsiDevCapRead/FNVIRTIODEVCAPREAD should not take a 'const' 'pv' parameter, that's just wrong.
  • Marking VIRTIOSCSI::szInstance and szQueueNames as 'const' doesn't buy us anything other than some confusing casts in the constructor. (szQueueNames should actually be aszQueueNames as it's an array of strings.)
  • SUBSCRIBABLE_EVENTS is missing vital parentheses, messing up the test in VIRTIOSCSI_T_AN_SUBSCRIBE (harmless, as logging only). See also MATCH_SCSI_CONFIG (also harmless). Parentheses around expression like that should be an automatic habit.
  • SUBSCRIBABLE_EVENTS is using '&' instead of '|', making the value zero.
  • The VIRTIOSCSIREQ::pbSense allocation must be zeroed (use the 'Z' allocator variant) to make sure the guest never see any old heap data. (The whole sense buffer is returned in virtioScsiR3IoReqFinish, rather than just the valid length.)
  • In case of VIRTIOSCSIREQ::pbSense allocation failure, pReq and pVirtqReq must be freed too.
  • Inconsistent parameter indention (when parameter list spills onto a new line). My preference is aligning to opening parenthesis. (E.g. 2nd RTStrPrintf in virtioScsiConstruct().)
  • Inconsistent identation of multiline macros (VIRTIOSCSI_HOST_SCSI_FEATURES_ALL vs VIRTIO_[IS_]IN_DIRECTION).
  • A couple of missing/incorrect indentations.
  • No need to split lines for VIRTIOCALLBACKS (just get used to about 130 columns wide sources).
  • Some unnecessary casts (RTStrPrintf((char *)pThis->szInstance,...), SCSI_CONFIG_ACCESSOR*, (size_t)pReq->cbSense[Alloc], ++).
  • Some unnecessary parentheses (SCSI_CONFIG_ACCESSOR*, ++).
  • VIRTIOSCSI_T_EVENTS_MISSED should use UINT32_C to be on the safe side.
  • There are three uses of LogIs2Enabled() that seem to need RT_NOREF, and the latter including several unnecessary variables. Put the whole block inside #ifdef LOG_ENABLED and dropping the expansive RT_NOREF.
  • Five 'sizeof(aReqSegs) / sizeof(RTSGSEG)' that would more easily be written 'RT_ELEMENTS(aReqSegs)'.
  • There shall be a space between 'switch' and the parenthesis.
  • VIRTIOSCSI_EVENT_T::uVirtioLun is a byte array and should be called 'abVirtioLun'. Ditto REQ_CMD_HDR_T::uVirtioLun, VIRTIOSCSI_CTRL_TMF_T::uScsiLun, VIRTIOSCSI_CTRL_AN_T::uScsiLun.
  • VIRTIOSCSIREQ::uSenseLen is easily confused with the 'cbSense' member, best to change the latter to 'cbSenseAlloc' (done) and then the former to 'cbSense' (not done).
  • REQ_CMD_HDR should be typedef 'REQ_CMD_HDR_T', as you're not consequentially using 'struct ...'). Ditto REQ_CMD_PI
  • pragma pack(1) is not needed on REQ_CMD_PI_T and REQ_RESP_HDR_T, so keep them out of it. Recomment using AssertCompileSize on structures like this.
  • struct, union and enum tags are either omitted or the same as the typedef name.
  • A few same-line doxygen comments missing the '<' markers and a couple the 2nd '*'.
  • Try keep the same-line doxygen comments aligned at a tab (4+) and avoid having them slide sideways in the next strcture or define block.
  • The WORKER structure is a bit too generic, renamed it VIRTIOSCSIWORKER. Arrays are plural, so s/aWorker/aWorkers/ too.
  • When casting an integer to a pointer you must go thru uintptr_t or intptr_t, not uint64_t like in the PDMDevHlpThreadCreate call, as type size matters some compilers.
  • Try avoid having Log statement gobble up unnecessary virtual space (a few lines as possible), as they are just noise making it hard to get an idea what's going on.
  • Always scope switch cases with variables in them (e.g virtioScsiSendEvent).
  • ++

Virtio_1_0*: A few preliminary changes.

Location:
trunk/src/VBox/Devices
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r81628 r81634  
    33 * VBox storage devices - Virtio SCSI Driver
    44 *
     5 * Log-levels used:
     6 *    - Level 1:   The most important (but usually rare) things to note
     7 *    - Level 2:   SCSI command logging
     8 *    - Level 3:   Vector and I/O transfer summary (shows what client sent an expects and fulfillment)
     9 *    - Level 6:   Device ⟷ Guest Driver negotation, traffic, notifications and state handling
     10 *    - Level 12:  Brief formatted hex dumps of I/O data
    511 */
    612
     
    4955#include "VBoxDD.h"
    5056
    51 /*
    52  * RT log-levels used:
    53  *
    54  *    Level 1:   The most important (but usually rare) things to note
    55  *    Level 2:   SCSI command logging
    56  *    Level 3:   Vector and I/O transfer summary (shows what client sent an expects and fulfillment)
    57  *    Level 6:   Device ⟷ Guest Driver negotation, traffic, notifications and state handling
    58  *    Level 12:  Brief formatted hex dumps of I/O data
    59  */
    6057
    6158#define LUN0    0
    6259/** @name VirtIO 1.0 SCSI Host feature bits (See VirtIO 1.0 specification, Section 5.6.3)
    6360 * @{  */
    64 #define VIRTIO_SCSI_F_INOUT                RT_BIT_64(0)           /** Request is device readable AND writeable         */
    65 #define VIRTIO_SCSI_F_HOTPLUG              RT_BIT_64(1)           /** Host allows hotplugging SCSI LUNs & targets      */
    66 #define VIRTIO_SCSI_F_CHANGE               RT_BIT_64(2)           /** Host LUNs chgs via VIRTIOSCSI_T_PARAM_CHANGE evt */
    67 #define VIRTIO_SCSI_F_T10_PI               RT_BIT_64(3)           /** Add T10 port info (DIF/DIX) in SCSI req hdr      */
     61#define VIRTIO_SCSI_F_INOUT                RT_BIT_64(0)         /** Request is device readable AND writeable         */
     62#define VIRTIO_SCSI_F_HOTPLUG              RT_BIT_64(1)         /** Host allows hotplugging SCSI LUNs & targets      */
     63#define VIRTIO_SCSI_F_CHANGE               RT_BIT_64(2)         /** Host LUNs chgs via VIRTIOSCSI_T_PARAM_CHANGE evt */
     64#define VIRTIO_SCSI_F_T10_PI               RT_BIT_64(3)         /** Add T10 port info (DIF/DIX) in SCSI req hdr      */
    6865/** @} */
    6966
    7067
    7168#define VIRTIOSCSI_HOST_SCSI_FEATURES_ALL \
    72             (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG | VIRTIO_SCSI_F_CHANGE | VIRTIO_SCSI_F_T10_PI)
     69    (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG | VIRTIO_SCSI_F_CHANGE | VIRTIO_SCSI_F_T10_PI)
    7370
    7471#define VIRTIOSCSI_HOST_SCSI_FEATURES_NONE          0
    7572
    76 #define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED \
    77              VIRTIOSCSI_HOST_SCSI_FEATURES_NONE
    78 
    79 #define VIRTIOSCSI_REQ_QUEUE_CNT                    1            /**< T.B.D. Consider increasing                      */
     73#define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED       VIRTIOSCSI_HOST_SCSI_FEATURES_NONE
     74
     75#define VIRTIOSCSI_REQ_QUEUE_CNT                    1           /**< T.B.D. Consider increasing                      */
    8076#define VIRTIOSCSI_QUEUE_CNT                        VIRTIOSCSI_REQ_QUEUE_CNT + 2
    81 #define VIRTIOSCSI_MAX_LUN                          256          /* < VirtIO specification, section 5.6.4             */
    82 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             128          /* < T.B.D. What is a good value for this?           */
    83 #define VIRTIOSCSI_MAX_SEG_COUNT                    126          /* < T.B.D. What is a good value for this?           */
    84 #define VIRTIOSCSI_MAX_SECTORS_HINT                 0x10000      /* < VirtIO specification, section 5.6.4             */
    85 #define VIRTIOSCSI_MAX_CHANNEL_HINT                 0            /* < VirtIO specification, section 5.6.4 should be 0 */
    86 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01         /**< SSM version #                                   */
    87 
    88 #define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048       /**< Informs guest driver of type of VirtIO device   */
    89 #define PCI_CLASS_BASE_MASS_STORAGE                 0x01         /**< PCI Mass Storage device class                   */
    90 #define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00         /**< PCI SCSI Controller subclass                    */
    91 #define PCI_CLASS_PROG_UNSPECIFIED                  0x00         /**< Programming interface. N/A.                     */
    92 #define VIRTIOSCSI_PCI_CLASS                        0x01         /**< Base class Mass Storage?                        */
     77#define VIRTIOSCSI_MAX_LUN                          256         /**< VirtIO specification, section 5.6.4             */
     78#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             128         /**< T.B.D. What is a good value for this?           */
     79#define VIRTIOSCSI_MAX_SEG_COUNT                    126         /**< T.B.D. What is a good value for this?           */
     80#define VIRTIOSCSI_MAX_SECTORS_HINT                 0x10000     /**< VirtIO specification, section 5.6.4             */
     81#define VIRTIOSCSI_MAX_CHANNEL_HINT                 0           /**< VirtIO specification, section 5.6.4 should be 0 */
     82#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01        /**< SSM version #                                   */
     83
     84#define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048      /**< Informs guest driver of type of VirtIO device   */
     85#define PCI_CLASS_BASE_MASS_STORAGE                 0x01        /**< PCI Mass Storage device class                   */
     86#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00        /**< PCI SCSI Controller subclass                    */
     87#define PCI_CLASS_PROG_UNSPECIFIED                  0x00        /**< Programming interface. N/A.                     */
     88#define VIRTIOSCSI_PCI_CLASS                        0x01        /**< Base class Mass Storage?                        */
    9389
    9490#define VIRTIOSCSI_SENSE_SIZE_DEFAULT               96          /**< VirtIO 1.0: 96 on reset, guest can change       */
     
    10298 * (Note: # of request queues is determined by virtio_scsi_config.num_queues. VirtIO 1.0, 5.6.4)
    10399 */
    104 #define CONTROLQ_IDX                                0            /**< Spec-defined Index of control queue             */
    105 #define EVENTQ_IDX                                  1            /**< Spec-defined Index of event queue               */
    106 #define VIRTQ_REQ_BASE                              2            /**< Spec-defined base index of request queues       */
    107 
    108 #define QUEUENAME(qIdx) (pThis->szQueueNames[qIdx])              /**< Macro to get queue name from its index          */
     100#define CONTROLQ_IDX                                0           /**< Spec-defined Index of control queue             */
     101#define EVENTQ_IDX                                  1           /**< Spec-defined Index of event queue               */
     102#define VIRTQ_REQ_BASE                              2           /**< Spec-defined base index of request queues       */
     103
     104#define QUEUENAME(qIdx) (pThis->aszQueueNames[qIdx])            /**< Macro to get queue name from its index          */
    109105#define CBQUEUENAME(qIdx) RTStrNLen(QUEUENAME(qIdx), sizeof(QUEUENAME(qIdx)))
    110106
    111107#define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT)
    112108
    113 /**
    114  * Resolves to boolean true if uOffset matches a field offset and size exactly,
    115  * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
    116  * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
    117  * (Easily re-written to allow unaligned bounded access to a field).
    118  *
    119  * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
    120  * @result           - true or false
    121  */
    122 #define MATCH_SCSI_CONFIG(member) \
    123             (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
    124              && (   uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    125                  || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
    126              && cb == sizeof(uint32_t)) \
    127          || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    128                && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member))
    129 
    130 #define LOG_ACCESSOR(member) \
    131         virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
    132             pv, cb, uIntraOffset, fWrite, false, 0);
    133 
    134 #define SCSI_CONFIG_ACCESSOR(member) \
    135     do \
    136     { \
    137         uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    138         if (fWrite) \
    139             memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \
    140         else \
    141             memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
    142         LOG_ACCESSOR(member); \
    143     } while(0)
    144 
    145 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \
    146     do \
    147     { \
    148         uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    149         if (fWrite) \
    150             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    151         else \
    152         { \
    153             memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
    154             LOG_ACCESSOR(member); \
    155         } \
    156     } while(0)
    157 
    158 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \
    159             pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE
    160 
    161 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \
    162             pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE
     109#define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \
     110    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE)
     111
     112#define VIRTIO_IS_OUT_DIRECTION(pMediaExTxDirEnumValue) \
     113    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE)
     114
    163115/**
    164116 * VirtIO SCSI Host Device device-specific configuration (see VirtIO 1.0, section 5.6.4)
     
    168120typedef struct virtio_scsi_config
    169121{
    170     uint32_t uNumQueues;                                         /**< num_queues       # of req q's exposed by dev    */
    171     uint32_t uSegMax;                                            /**< seg_max          Max # of segs allowed in cmd   */
    172     uint32_t uMaxSectors;                                        /**< max_sectors      Hint to guest max xfer to use  */
    173     uint32_t uCmdPerLun;                                         /**< cmd_per_lun      Max # of link cmd sent per lun */
    174     uint32_t uEventInfoSize;                                     /**< event_info_size  Fill max, evtq bufs            */
    175     uint32_t uSenseSize;                                         /**< sense_size       Max sense data size dev writes */
    176     uint32_t uCdbSize;                                           /**< cdb_size         Max CDB size driver writes     */
    177     uint16_t uMaxChannel;                                        /**< max_channel      Hint to guest driver           */
    178     uint16_t uMaxTarget;                                         /**< max_target       Hint to guest driver           */
    179     uint32_t uMaxLun;                                            /**< max_lun          Hint to guest driver           */
     122    uint32_t uNumQueues;                                        /**< num_queues       \# of req q's exposed by dev   */
     123    uint32_t uSegMax;                                           /**< seg_max          Max \# of segs allowed in cmd  */
     124    uint32_t uMaxSectors;                                       /**< max_sectors      Hint to guest max xfer to use  */
     125    uint32_t uCmdPerLun;                                        /**< cmd_per_lun      Max \# of link cmd sent per lun */
     126    uint32_t uEventInfoSize;                                    /**< event_info_size  Fill max, evtq bufs            */
     127    uint32_t uSenseSize;                                        /**< sense_size       Max sense data size dev writes */
     128    uint32_t uCdbSize;                                          /**< cdb_size         Max CDB size driver writes     */
     129    uint16_t uMaxChannel;                                       /**< max_channel      Hint to guest driver           */
     130    uint16_t uMaxTarget;                                        /**< max_target       Hint to guest driver           */
     131    uint32_t uMaxLun;                                           /**< max_lun          Hint to guest driver           */
    180132} VIRTIOSCSI_CONFIG_T, PVIRTIOSCSI_CONFIG_T;
    181133
     
    191143 * Device operation: eventq
    192144 */
    193 #define VIRTIOSCSI_T_EVENTS_MISSED             0x80000000
    194 typedef struct virtio_scsi_event {
     145#define VIRTIOSCSI_T_EVENTS_MISSED                  UINT32_C(0x80000000)
     146typedef struct virtio_scsi_event
     147{
    195148    // Device-writable part
    196149    uint32_t uEvent;                                            /**< event:                                          */
    197     uint8_t  uVirtioLun[8];                                     /**< lun                                             */
     150    uint8_t  abVirtioLun[8];                                    /**< lun                                             */
    198151    uint32_t uReason;                                           /**< reason                                          */
    199152} VIRTIOSCSI_EVENT_T, *PVIRTIOSCSI_EVENT_T;
     
    207160
    208161
     162
     163/**
     164 * Device operation: reqestq
     165 */
    209166#pragma pack(1)
    210 
    211 /**
    212  * Device operation: reqestq
    213  */
    214 struct REQ_CMD_HDR
    215 {
    216     uint8_t  uVirtioLun[8];                                     /**< lun                                          */
     167typedef struct REQ_CMD_HDR_T
     168{
     169    uint8_t  abVirtioLun[8];                                    /**< lun                                          */
    217170    uint64_t uId;                                               /**< id                                           */
    218171    uint8_t  uTaskAttr;                                         /**< task_attr                                    */
    219172    uint8_t  uPrio;                                             /**< prio                                         */
    220173    uint8_t  uCrn;                                              /**< crn                                          */
    221 };
    222 
    223 struct REQ_CMD_PI
     174} REQ_CMD_HDR_T;
     175#pragma pack()
     176AssertCompileSize(REQ_CMD_HDR_T, 19);
     177
     178typedef struct REQ_CMD_PI_T
    224179{
    225180    uint32_t uPiBytesOut;                                       /**< pi_bytesout                                  */
    226181    uint32_t uPiBytesIn;                                        /**< pi_bytesin                                   */
    227 };
    228 
    229 struct REQ_RESP_HDR
    230 {
    231     uint32_t uSenseLen;                                         /**< sense_len                                    */
     182} REQ_CMD_PI_T;
     183AssertCompileSize(REQ_CMD_PI_T, 8);
     184
     185typedef struct REQ_RESP_HDR_T
     186{
     187    uint32_t cbSenseLen;                                        /**< sense_len                                    */
    232188    uint32_t uResidual;                                         /**< residual                                     */
    233189    uint16_t uStatusQualifier;                                  /**< status_qualifier                             */
    234190    uint8_t  uStatus;                                           /**< status            SCSI status code           */
    235191    uint8_t  uResponse;                                         /**< response                                     */
    236 };
    237 
    238 typedef struct virtio_scsi_req_cmd
    239 {
    240     /* Device-readable section */
    241 
    242     struct REQ_CMD_HDR  ReqHdr;
     192} REQ_RESP_HDR_T;
     193AssertCompileSize(REQ_RESP_HDR_T, 12);
     194
     195#pragma pack(1)
     196typedef struct VIRTIOSCSI_REQ_CMD_T
     197{
     198    /** Device-readable section
     199     * @{ */
     200    REQ_CMD_HDR_T  ReqHdr;
    243201    uint8_t  uCdb[1];                                           /**< cdb                                          */
    244202
    245     struct REQ_CMD_PI piHdr;                                    /** T10 Pi block integrity (optional feature)     */
     203    REQ_CMD_PI_T piHdr;                                         /** T10 Pi block integrity (optional feature)     */
    246204    uint8_t  uPiOut[1];                                         /**< pi_out[]          T10 pi block integrity     */
    247205    uint8_t  uDataOut[1];                                       /**< dataout                                      */
    248 
    249     /** Device writable section */
    250 
    251     struct REQ_RESP_HDR  respHdr;
     206    /** @} */
     207
     208    /** @name Device writable section
     209     * @{ */
     210    REQ_RESP_HDR_T respHdr;
    252211    uint8_t  uSense[1];                                         /**< sense                                        */
    253212    uint8_t  uPiIn[1];                                          /**< pi_in[]           T10 Pi block integrity     */
    254213    uint8_t  uDataIn[1];                                        /**< detain;                                      */
    255 
    256 }  VIRTIOSCSI_REQ_CMD_T, *PVIRTIOSCSI_REQ_CMD_T;
     214    /** @} */
     215} VIRTIOSCSI_REQ_CMD_T, *PVIRTIOSCSI_REQ_CMD_T;
    257216#pragma pack()
     217AssertCompileSize(VIRTIOSCSI_REQ_CMD_T, 19+8+12+6);
    258218
    259219/** @name VirtIO 1.0 SCSI Host Device Req command-specific response values
    260220 * @{  */
    261 #define VIRTIOSCSI_S_OK                             0          /**< control, command                                 */
    262 #define VIRTIOSCSI_S_OVERRUN                        1          /**< control                                          */
    263 #define VIRTIOSCSI_S_ABORTED                        2          /**< control                                          */
    264 #define VIRTIOSCSI_S_BAD_TARGET                     3          /**< control, command                                 */
    265 #define VIRTIOSCSI_S_RESET                          4          /**< control                                          */
    266 #define VIRTIOSCSI_S_BUSY                           5          /**< control, command                                 */
    267 #define VIRTIOSCSI_S_TRANSPORT_FAILURE              6          /**< control, command                                 */
    268 #define VIRTIOSCSI_S_TARGET_FAILURE                 7          /**< control, command                                 */
    269 #define VIRTIOSCSI_S_NEXUS_FAILURE                  8          /**< control, command                                 */
    270 #define VIRTIOSCSI_S_FAILURE                        9          /**< control, command                                 */
    271 #define VIRTIOSCSI_S_INCORRECT_LUN                  12         /**< command                                          */
     221#define VIRTIOSCSI_S_OK                             0           /**< control, command                                 */
     222#define VIRTIOSCSI_S_OVERRUN                        1           /**< control                                          */
     223#define VIRTIOSCSI_S_ABORTED                        2           /**< control                                          */
     224#define VIRTIOSCSI_S_BAD_TARGET                     3           /**< control, command                                 */
     225#define VIRTIOSCSI_S_RESET                          4           /**< control                                          */
     226#define VIRTIOSCSI_S_BUSY                           5           /**< control, command                                 */
     227#define VIRTIOSCSI_S_TRANSPORT_FAILURE              6           /**< control, command                                 */
     228#define VIRTIOSCSI_S_TARGET_FAILURE                 7           /**< control, command                                 */
     229#define VIRTIOSCSI_S_NEXUS_FAILURE                  8           /**< control, command                                 */
     230#define VIRTIOSCSI_S_FAILURE                        9           /**< control, command                                 */
     231#define VIRTIOSCSI_S_INCORRECT_LUN                  12          /**< command                                          */
    272232/** @} */
    273233
    274234/** @name VirtIO 1.0 SCSI Host Device command-specific task_attr values
    275235 * @{  */
    276 #define VIRTIOSCSI_S_SIMPLE                        0           /**<                                                  */
    277 #define VIRTIOSCSI_S_ORDERED                       1           /**<                                                  */
    278 #define VIRTIOSCSI_S_HEAD                          2           /**<                                                  */
    279 #define VIRTIOSCSI_S_ACA                           3           /**<                                                  */
     236#define VIRTIOSCSI_S_SIMPLE                         0           /**<                                                  */
     237#define VIRTIOSCSI_S_ORDERED                        1           /**<                                                  */
     238#define VIRTIOSCSI_S_HEAD                           2           /**<                                                  */
     239#define VIRTIOSCSI_S_ACA                            3           /**<                                                  */
    280240/** @} */
    281241
     
    283243 * VirtIO 1.0 SCSI Host Device Control command before we know type (5.6.6.2)
    284244 */
    285 typedef struct virtio_scsi_ctrl
     245typedef struct VIRTIOSCSI_CTRL_T
    286246{
    287247    uint32_t uType;
     
    290250/** @name VirtIO 1.0 SCSI Host Device command-specific TMF values
    291251 * @{  */
    292 #define VIRTIOSCSI_T_TMF                           0           /**<                                                  */
    293 #define VIRTIOSCSI_T_TMF_ABORT_TASK                0           /**<                                                  */
    294 #define VIRTIOSCSI_T_TMF_ABORT_TASK_SET            1           /**<                                                  */
    295 #define VIRTIOSCSI_T_TMF_CLEAR_ACA                 2           /**<                                                  */
    296 #define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET            3           /**<                                                  */
    297 #define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET           4           /**<                                                  */
    298 #define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET        5           /**<                                                  */
    299 #define VIRTIOSCSI_T_TMF_QUERY_TASK                6           /**<                                                  */
    300 #define VIRTIOSCSI_T_TMF_QUERY_TASK_SET            7           /**<                                                  */
     252#define VIRTIOSCSI_T_TMF                            0           /**<                                                  */
     253#define VIRTIOSCSI_T_TMF_ABORT_TASK                 0           /**<                                                  */
     254#define VIRTIOSCSI_T_TMF_ABORT_TASK_SET             1           /**<                                                  */
     255#define VIRTIOSCSI_T_TMF_CLEAR_ACA                  2           /**<                                                  */
     256#define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET             3           /**<                                                  */
     257#define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET            4           /**<                                                  */
     258#define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET         5           /**<                                                  */
     259#define VIRTIOSCSI_T_TMF_QUERY_TASK                 6           /**<                                                  */
     260#define VIRTIOSCSI_T_TMF_QUERY_TASK_SET             7           /**<                                                  */
    301261/** @} */
    302262
    303263#pragma pack(1)
    304 typedef struct virtio_scsi_ctrl_tmf
     264typedef struct VIRTIOSCSI_CTRL_TMF_T
    305265{
    306266     // Device-readable part
    307     uint32_t uType;                                            /** type                                              */
    308     uint32_t uSubtype;                                         /** subtype                                           */
    309     uint8_t  uScsiLun[8];                                      /** lun                                               */
    310     uint64_t uId;                                              /** id                                                */
     267    uint32_t uType;                                             /**< type                                             */
     268    uint32_t uSubtype;                                          /**< subtype                                          */
     269    uint8_t  abScsiLun[8];                                      /**< lun                                              */
     270    uint64_t uId;                                               /**< id                                               */
    311271    // Device-writable part
    312     uint8_t  uResponse;                                        /** response                                          */
     272    uint8_t  uResponse;                                         /**< response                                         */
    313273} VIRTIOSCSI_CTRL_TMF_T, *PVIRTIOSCSI_CTRL_TMF_T;
    314274#pragma pack()
     275AssertCompileSize(VIRTIOSCSI_CTRL_TMF_T, 25);
    315276
    316277/** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values
    317278 * @{  */
    318 #define VIRTIOSCSI_S_FUNCTION_COMPLETE            0           /**<                                                   */
    319 #define VIRTIOSCSI_S_FUNCTION_SUCCEEDED           10          /**<                                                   */
    320 #define VIRTIOSCSI_S_FUNCTION_REJECTED            11          /**<                                                   */
     279#define VIRTIOSCSI_S_FUNCTION_COMPLETE              0           /**<                                                   */
     280#define VIRTIOSCSI_S_FUNCTION_SUCCEEDED             10          /**<                                                   */
     281#define VIRTIOSCSI_S_FUNCTION_REJECTED              11          /**<                                                   */
    321282/** @} */
    322283
    323 #define VIRTIOSCSI_T_AN_QUERY                     1           /** Asynchronous notification query                    */
    324 #define VIRTIOSCSI_T_AN_SUBSCRIBE                 2           /** Asynchronous notification subscription             */
     284#define VIRTIOSCSI_T_AN_QUERY                       1           /**<Asynchronous notification query                    */
     285#define VIRTIOSCSI_T_AN_SUBSCRIBE                   2           /**<Asynchronous notification subscription             */
    325286
    326287#pragma pack(1)
    327 typedef struct virtio_scsi_ctrl_an
     288typedef struct VIRTIOSCSI_CTRL_AN_T
    328289{
    329290    // Device-readable part
    330     uint32_t  uType;                                          /** type                                               */
    331     uint8_t   uScsiLun[8];                                    /** lun                                                */
    332     uint32_t  uEventsRequested;                               /** event_requested                                    */
     291    uint32_t  uType;                                            /**< type                                              */
     292    uint8_t   abScsiLun[8];                                     /**< lun                                               */
     293    uint32_t  fEventsRequested;                                 /**< event_requested                                   */
    333294    // Device-writable part
    334     uint32_t  uEventActual;                                   /** event_actual                                       */
    335     uint8_t   uResponse;                                      /** response                                           */
     295    uint32_t  uEventActual;                                     /**< event_actual                                      */
     296    uint8_t   uResponse;                                        /**< response                                          */
    336297}  VIRTIOSCSI_CTRL_AN_T, *PVIRTIOSCSI_CTRL_AN_T;
    337298#pragma pack()
    338 
    339 typedef union virtio_scsi_ctrl_union
    340 {
    341     VIRTIOSCSI_CTRL_T      scsiCtrl;
    342     VIRTIOSCSI_CTRL_TMF_T  scsiCtrlTmf;
    343     VIRTIOSCSI_CTRL_AN_T   scsiCtrlAsyncNotify;
     299AssertCompileSize(VIRTIOSCSI_CTRL_AN_T, 21);
     300
     301typedef union VIRTIO_SCSI_CTRL_UNION_T
     302{
     303    VIRTIOSCSI_CTRL_T       scsiCtrl;
     304    VIRTIOSCSI_CTRL_TMF_T   scsiCtrlTmf;
     305    VIRTIOSCSI_CTRL_AN_T    scsiCtrlAsyncNotify;
     306    uint8_t                 ab[25];
    344307} VIRTIO_SCSI_CTRL_UNION_T, *PVIRTIO_SCSI_CTRL_UNION_T;
     308AssertCompile(sizeof(VIRTIO_SCSI_CTRL_UNION_T) == 28); /* VIRTIOSCSI_CTRL_T forces 4 byte alignment, the other two are byte packed. */
    345309
    346310/** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values
    347311 * @{  */
    348 #define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2           /**<                                                   */
    349 #define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT          4           /**<                                                   */
    350 #define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST    8           /**<                                                   */
    351 #define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE        16          /**<                                                   */
    352 #define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST          32          /**<                                                   */
    353 #define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY         64          /**<                                                   */
     312#define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2              /**<                                                   */
     313#define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT          4              /**<                                                   */
     314#define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST    8              /**<                                                   */
     315#define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE        16             /**<                                                   */
     316#define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST          32             /**<                                                   */
     317#define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY         64             /**<                                                   */
    354318/** @} */
    355319
    356320#define SUBSCRIBABLE_EVENTS \
    357               VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \
    358             & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \
    359             & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \
    360             & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \
    361             & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \
    362             & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY
     321    (  VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \
     322     | VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \
     323     | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \
     324     | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \
     325     | VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \
     326     | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY )
    363327
    364328/**
    365329 * Worker thread context
    366330 */
    367 typedef struct WORKER
    368 {
    369     R3PTRTYPE(PPDMTHREAD)           pThread;                  /**< pointer to worker thread's handle                 */
    370     SUPSEMEVENT                     hEvtProcess;              /**< handle of associated sleep/wake-up semaphore      */
    371     bool                            fSleeping;                /**< Flags whether worker thread is sleeping or not    */
    372     bool                            fNotified;                /**< Flags whether worker thread notified              */
    373 } WORKER, *PWORKER;
     331typedef struct VIRTIOSCSIWORKER
     332{
     333    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
     334    SUPSEMEVENT                     hEvtProcess;                /**< handle of associated sleep/wake-up semaphore      */
     335    bool                            fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
     336    bool                            fNotified;                  /**< Flags whether worker thread notified              */
     337} VIRTIOSCSIWORKER;
     338typedef VIRTIOSCSIWORKER *PVIRTIOSCSIWORKER;
    374339
    375340/**
     
    407372    PPDMIMEDIANOTIFY                pMediaNotify;
    408373
    409      /** Pointer to the attached driver's extended media interface. */
     374    /** Pointer to the attached driver's extended media interface. */
    410375    R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
    411376
     
    419384
    420385/**
    421  *  PDM instance data (state) for VirtIO Host SCSI device
     386 * PDM instance data (state) for VirtIO Host SCSI device
    422387 *
    423388 * @extends     PDMPCIDEV
     
    434399    R3PTRTYPE(PVIRTIOSCSITARGET)    paTargetInstances;
    435400#if HC_ARCH_BITS == 32
    436       RTR3PTR                 R3PtrPadding0;
     401    RTR3PTR                         R3PtrPadding0;
    437402#endif
    438403
    439404    /** Per device-bound virtq worker-thread contexts (eventq slot unused) */
    440     WORKER                          aWorker[VIRTIOSCSI_QUEUE_CNT];
     405    VIRTIOSCSIWORKER                aWorkers[VIRTIOSCSI_QUEUE_CNT];
    441406
    442407    bool                            fBootable;
     
    444409    bool                            fR0Enabled;
    445410    /** Instance name */
    446     const char                      szInstance[16];
     411    char                            szInstance[16];
    447412
    448413    /** Device-specific spec-based VirtIO queuenames */
    449     const char                      szQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];
     414    char                            aszQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];
    450415
    451416    /** Track which VirtIO queues we've attached to */
    452     bool                            fQueueAttached[VIRTIOSCSI_QUEUE_CNT];
     417    bool                            afQueueAttached[VIRTIOSCSI_QUEUE_CNT];
    453418
    454419    /** Device base interface. */
     
    480445
    481446    /** Mask of VirtIO Async Event types this device will deliver */
    482     uint32_t                        uAsyncEvtsEnabled;
     447    uint32_t                        fAsyncEvtsEnabled;
    483448
    484449    /** Total number of requests active across all targets */
     
    489454
    490455    /** Events the guest has subscribed to get notifications of */
    491     uint32_t                        uSubscribedEvents;
     456    uint32_t                        fSubscribedEvents;
    492457
    493458    /** Set if events missed due to lack of bufs avail on eventq */
    494     bool                           fEventsMissed;
     459    bool                            fEventsMissed;
    495460
    496461    /** VirtIO Host SCSI device runtime configuration parameters */
     
    522487/**
    523488 * Request structure for IMediaEx (Associated Interfaces implemented by DrvSCSI)
    524  * (NOTE: cbIn, cbOUt, cbDataOut mostly for debugging)
     489 * @note cbIn, cbOUt, cbDataOut mostly for debugging
    525490 */
    526491typedef struct VIRTIOSCSIREQ
    527492{
    528     PDMMEDIAEXIOREQ                hIoReq;                   /**< Handle of I/O request                             */
    529     PVIRTIOSCSITARGET              pTarget;                  /**< Target                                            */
    530     uint16_t                       qIdx;                     /**< Index of queue this request arrived on            */
    531     PVIRTIO_DESC_CHAIN_T           pDescChain;               /**< Prepared desc chain pulled from virtq avail ring  */
    532     uint32_t                       cbDataIn;                 /**< size of dataout buffer                            */
    533     uint32_t                       cbDataOut;                /**< size of dataout buffer                            */
    534     uint16_t                       uDataInOff;               /**< Fixed size of respHdr + sense (precede datain)    */
    535     uint16_t                       uDataOutOff;              /**< Fixed size of respHdr + sense (precede datain)    */
    536     uint32_t                       cbSense                /**< Size of sense buffer                              */
    537     size_t                         uSenseLen;                /**< Receives # bytes written into sense buffer        */
    538     uint8_t                       *pbSense;                  /**< Pointer to R3 sense buffer                        */
    539     PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                 /**< Receives transfer direction of I/O req            */
    540     uint8_t                        uStatus;                  /**< SCSI status code                                  */
     493    PDMMEDIAEXIOREQ                hIoReq;                      /**< Handle of I/O request                             */
     494    PVIRTIOSCSITARGET              pTarget;                     /**< Target                                            */
     495    uint16_t                       qIdx;                        /**< Index of queue this request arrived on            */
     496    PVIRTIO_DESC_CHAIN_T           pDescChain;                  /**< Prepared desc chain pulled from virtq avail ring  */
     497    uint32_t                       cbDataIn;                    /**< size of dataout buffer                            */
     498    uint32_t                       cbDataOut;                   /**< size of dataout buffer                            */
     499    uint16_t                       uDataInOff;                  /**< Fixed size of respHdr + sense (precede datain)    */
     500    uint16_t                       uDataOutOff;                 /**< Fixed size of respHdr + sense (precede datain)    */
     501    uint32_t                       cbSenseAlloc;                /**< Size of sense buffer                              */
     502    size_t                         cbSenseLen;                  /**< Receives \# bytes written into sense buffer       */
     503    uint8_t                       *pbSense;                     /**< Pointer to R3 sense buffer                        */
     504    PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                    /**< Receives transfer direction of I/O req            */
     505    uint8_t                        uStatus;                     /**< SCSI status code                                  */
    541506} VIRTIOSCSIREQ;
     507typedef VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
    542508
    543509DECLINLINE(const char *) virtioGetTxDirText(uint32_t enmTxDir)
     
    590556}
    591557
    592 DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t uAsyncTypesMask)
     558DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t fAsyncTypesMask)
    593559{
    594560    RTStrPrintf(pszOutput, cbOutput, "%s%s%s%s%s%s",
    595         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) ? "CHANGE_OPERATION  "   : "",
    596         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)         ? "POWER_MGMT  "         : "",
    597         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)   ? "EXTERNAL_REQ  "       : "",
    598         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)       ? "MEDIA_CHANGE  "       : "",
    599         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)         ? "MULTI_HOST  "         : "",
    600         (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)        ? "DEVICE_BUSY  "        : "");
    601 }
    602 
    603 uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax)
     561                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE ? "CHANGE_OPERATION  "   : "",
     562                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT         ? "POWER_MGMT  "         : "",
     563                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST   ? "EXTERNAL_REQ  "       : "",
     564                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE       ? "MEDIA_CHANGE  "       : "",
     565                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST         ? "MULTI_HOST  "         : "",
     566                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY        ? "DEVICE_BUSY  "        : "");
     567}
     568
     569#ifdef LOG_ENABLED
     570static uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax)
    604571{
    605572    if (uCmd < 0x1f)
    606573        return 6;
    607     else if (uCmd >= 0x20 && uCmd < 0x60)
     574    if (uCmd >= 0x20 && uCmd < 0x60)
    608575        return 10;
    609     else if (uCmd >= 0x60 && uCmd < 0x80)
     576    if (uCmd >= 0x60 && uCmd < 0x80)
    610577        return cbMax;
    611     else if (uCmd >= 0x80 && uCmd < 0xa0)
     578    if (uCmd >= 0x80 && uCmd < 0xa0)
    612579        return 16;
    613     else if (uCmd >= 0xa0 && uCmd < 0xC0)
     580    if (uCmd >= 0xa0 && uCmd < 0xc0)
    614581        return 12;
    615     else
    616         return cbMax;
    617 }
    618 
    619 typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
    620 
    621 static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
     582    return cbMax;
     583}
     584#endif /* LOG_ENABLED */
     585
     586
     587static int virtioScsiR3SendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
    622588{
    623589
     
    625591    event.uEvent = uEventType;
    626592    event.uReason = uReason;
    627     event.uVirtioLun[0] = 1;
    628     event.uVirtioLun[1] = uTarget;
    629     event.uVirtioLun[2] = (LUN0 >> 8) & 0x40;
    630     event.uVirtioLun[3] = LUN0 & 0xff;
    631     event.uVirtioLun[4] = event.uVirtioLun[5] = event.uVirtioLun[6] = event.uVirtioLun[7] = 0;
    632 
    633     switch(uEventType)
     593    event.abVirtioLun[0] = 1;
     594    event.abVirtioLun[1] = uTarget;
     595    event.abVirtioLun[2] = (LUN0 >> 8) & 0x40;
     596    event.abVirtioLun[3] = LUN0 & 0xff;
     597    event.abVirtioLun[4] = event.abVirtioLun[5] = event.abVirtioLun[6] = event.abVirtioLun[7] = 0;
     598
     599    /** @todo r=bird: This switch is missing some masking, right?  Because 'VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED'
     600     * will never end up here but be disregarded in the 'default' case.  Given that the only caller of this function
     601     * is virtioScsiR3ReportEventsMissed(), I find this a bit confusing.
     602     *
     603     * For the time being I've added a VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED case to make the code make sense,
     604     * but it migth not be what you had in mind.   I've also changed uEventType to fEventType since that's more appropriate. */
     605    switch (uEventType)
    634606    {
    635607        case VIRTIOSCSI_T_NO_EVENT:
    636             if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED)
    637                 Log6Func(("(target=%d, LUN=%d) Warning driver that events were missed\n", uTarget, LUN0));
    638             else
    639                 Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n",
    640                           uTarget, LUN0));
     608            Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n", uTarget, LUN0));
     609            break;
     610        case VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED:
     611            Log6Func(("(target=%d, LUN=%d): Warning driver that events were missed\n", uTarget, LUN0));
    641612            break;
    642613        case VIRTIOSCSI_T_TRANSPORT_RESET:
    643             switch(uReason)
     614            switch (uReason)
    644615            {
    645616                case VIRTIOSCSI_EVT_RESET_REMOVED:
     
    655626            break;
    656627        case VIRTIOSCSI_T_ASYNC_NOTIFY:
     628        {
     629#ifdef LOG_ENABLED
    657630            char szTypeText[128];
    658631            virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason);
    659             Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n",
    660                          uTarget, LUN0, szTypeText));
     632            Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, LUN0, szTypeText));
     633#endif
    661634            break;
     635        }
    662636        case VIRTIOSCSI_T_PARAM_CHANGE:
    663637            LogFunc(("(target=%d, LUN=%d): PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n",
    664                         uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff));
     638                     uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff));
    665639            break;
    666640        default:
    667             Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n",
    668                         uTarget, LUN0, uEventType));
     641            Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, LUN0, uEventType));
    669642            return VINF_SUCCESS;
    670643    }
     
    682655    RTSGBUF reqSegBuf;
    683656    RTSGSEG aReqSegs[] = { { &event, sizeof(event) } };
    684     RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    685 
    686     virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
     657    RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
     658
     659    virtioQueuePut( pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
    687660    virtioQueueSync(pThis->hVirtio, EVENTQ_IDX);
    688661
     
    690663}
    691664
    692 static void virtioScsiFreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq)
     665/** Internal worker. */
     666static void virtioScsiR3FreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq)
    693667{
    694668    RTMemFree(pReq->pbSense);
     669    pReq->pbSense = NULL;
    695670    pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
    696671}
     
    699674 * This is called to complete a request immediately
    700675 *
    701  * @param pThis      - PDM driver instance state
    702  * @param qIdx       - Queue index
    703  * @param pDescChain - Pointer to pre-processed descriptor chain pulled from virtq
    704  * @param pRespHdr   - Response header
    705  * @param pbSense    - Pointer to sense buffer or NULL if none.
     676 * @param   pThis      PDM driver instance state
     677 * @param   qIdx        Queue index
     678 * @param   pDescChain Pointer to pre-processed descriptor chain pulled from virtq
     679 * @param   pRespHdr    Response header
     680 * @param   pbSense    Pointer to sense buffer or NULL if none.
    706681 *
    707  * @returns virtual box status code
    708  */
    709 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain,
    710                             struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
    711 {
    712     uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
    713     AssertReturn(abSenseBuf, VERR_NO_MEMORY);
    714 
    715     const char *pszCtrlRespText = virtioGetReqRespText(pRespHdr->uResponse);
    716     Log2Func(("   status: %s    response: %s\n",
    717               SCSIStatusText(pRespHdr->uStatus),  pszCtrlRespText));
    718     RT_NOREF(pszCtrlRespText);
     682 * @returns VBox status code.
     683 */
     684static int virtioScsiR3ReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain,
     685                              REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense)
     686{
     687    uint8_t *pabSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
     688    AssertReturn(pabSenseBuf, VERR_NO_MEMORY);
     689
     690    Log2Func(("   status: %s    response: %s\n", SCSIStatusText(pRespHdr->uStatus), virtioGetReqRespText(pRespHdr->uResponse)));
    719691
    720692    RTSGSEG aReqSegs[2];
     
    722694    aReqSegs[0].pvSeg = pRespHdr;
    723695    aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize;
    724     aReqSegs[1].pvSeg = abSenseBuf;
    725 
    726     if (pbSense && pRespHdr->uSenseLen)
    727         memcpy(abSenseBuf, pbSense, pRespHdr->uSenseLen);
     696    aReqSegs[1].pvSeg = pabSenseBuf;
     697
     698    if (pbSense && pRespHdr->cbSenseLen)
     699        memcpy(pabSenseBuf, pbSense, pRespHdr->cbSenseLen);
    728700    else
    729         pRespHdr->uSenseLen = 0;
     701        pRespHdr->cbSenseLen = 0;
    730702
    731703    RTSGBUF reqSegBuf;
     
    738710    virtioQueueSync(pThis->hVirtio, qIdx);
    739711
    740     RTMemFree(abSenseBuf);
     712    RTMemFree(pabSenseBuf);
    741713
    742714    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     
    748720}
    749721
    750 static void virtioSenseKeyToVirtioResp(struct REQ_RESP_HDR *respHdr, uint8_t uSenseKey)
     722static void virtioScsiR3SenseKeyToVirtioResp(REQ_RESP_HDR_T *respHdr, uint8_t uSenseKey)
    751723{
    752724    switch (uSenseKey)
     
    772744    }
    773745}
     746
    774747/**
    775748 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
    776749 */
    777 static DECLCALLBACK(int) virtioScsiIoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    778                                                void *pvIoReqAlloc, int rcReq)
     750static DECLCALLBACK(int) virtioScsiR3IoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     751                                                 void *pvIoReqAlloc, int rcReq)
    779752{
    780753    RT_NOREF(pInterface);
     
    796769    Assert(!(cbXfer & 0xffffffff00000000));
    797770    uint32_t cbXfer32 = cbXfer & 0xffffffff;
    798     struct REQ_RESP_HDR respHdr = { 0 };
    799     respHdr.uSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->uSenseLen;
     771    REQ_RESP_HDR_T respHdr = { 0 };
     772    respHdr.cbSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->cbSenseLen;
    800773    AssertMsg(!(cbResidual & 0xffffffff00000000),
    801774            ("WARNING: Residual size larger than sizeof(uint32_t), truncating"));
     
    811784    else
    812785    {
    813         switch(rcReq)
     786        switch (rcReq)
    814787        {
    815788            case SCSI_STATUS_OK:
     
    818791                    respHdr.uResponse = VIRTIOSCSI_S_OK;
    819792                else
    820                     virtioSenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
     793                    virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
    821794                break;
    822795            }
    823796            case SCSI_STATUS_CHECK_CONDITION:
    824                 virtioSenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
     797                virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
    825798                break;
    826799
     
    847820        const char *pszTxDirText = virtioGetTxDirText(pReq->enmTxDir);
    848821        LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n",
    849              pszTxDirText, respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize));
     822                 pszTxDirText, respHdr.cbSenseLen, pThis->virtioScsiConfig.uSenseSize));
    850823        RT_NOREF(pszTxDirText);
    851824    }
    852825
    853     if (respHdr.uSenseLen && LogIs2Enabled())
     826    if (respHdr.cbSenseLen && LogIs2Enabled())
    854827    {
    855828        LogFunc(("Sense: %s\n", SCSISenseText(pReq->pbSense[2])));
     
    859832    int cSegs = 0;
    860833
    861     if (   (VIRTIO_IN_DIRECTION(pReq->enmTxDir)  && cbXfer32 > pReq->cbDataIn)
    862         || (VIRTIO_OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut))
     834    if (   (VIRTIO_IS_IN_DIRECTION(pReq->enmTxDir)  && cbXfer32 > pReq->cbDataIn)
     835        || (VIRTIO_IS_OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut))
    863836    {
    864837        Log2Func((" * * * * Data overrun, returning sense\n"));
    865838        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    866839                              0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
    867         respHdr.uSenseLen = sizeof(abSense);
    868         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    869         respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;
    870         respHdr.uResidual = pReq->cbDataIn;
    871 
    872         virtioScsiReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);
     840        respHdr.cbSenseLen = sizeof(abSense);
     841        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
     842        respHdr.uResponse  = VIRTIOSCSI_S_OVERRUN;
     843        respHdr.uResidual  = pReq->cbDataIn;
     844
     845        virtioScsiR3ReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);
    873846    }
    874847    else
     
    883856
    884857        aReqSegs[cSegs].pvSeg = pReq->pbSense;
    885         aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
     858        aReqSegs[cSegs++].cbSeg = pReq->cbSenseAlloc; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
    886859
    887860        RTSGBUF reqSegBuf;
     
    902875    }
    903876
    904     virtioScsiFreeReq(pTarget, pReq);
     877    virtioScsiR3FreeReq(pTarget, pReq);
    905878
    906879    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     
    915888 * Copy virtual memory from VSCSI layer to guest physical memory
    916889 */
    917 static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     890static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    918891                                                      void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
    919892{
     
    965938 * Copy guest physical memory to VSCSI layer virtual memory
    966939 */
    967 static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     940static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    968941                                                    void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
    969942{
     
    1003976}
    1004977
    1005 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     978/**
     979 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     980 */
     981static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
     982{
     983    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     984    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
     985    LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
     986    if (pThis->pMediaNotify)
     987    {
     988        int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
     989                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
     990                                   pThis->pMediaNotify, pTarget->iTarget);
     991        AssertRC(rc);
     992    }
     993}
     994
     995/**
     996 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     997 */
     998static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     999                                                        void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     1000{
     1001    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
     1002    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
     1003
     1004    switch (enmState)
     1005    {
     1006        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
     1007        {
     1008            /* Stop considering this request active */
     1009            if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     1010                PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
     1011            break;
     1012        }
     1013        case PDMMEDIAEXIOREQSTATE_ACTIVE:
     1014            ASMAtomicIncU32(&pThis->cActiveReqs);
     1015            break;
     1016        default:
     1017            AssertMsgFailed(("Invalid request state given %u\n", enmState));
     1018    }
     1019}
     1020
     1021
     1022/*********************************************************************************************************************************
     1023*   Worker Thread                                                                                                                *
     1024*********************************************************************************************************************************/
     1025
     1026/**
     1027 * Handles request queues for/on a worker thread.
     1028 *
     1029 * @returns VBox status code (logged by caller).
     1030 */
     1031static int virtioScsiR3ReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
    10061032{
    10071033    AssertReturn(pDescChain->cbPhysSend, VERR_INVALID_PARAMETER);
     
    10091035    ASMAtomicIncU32(&pThis->cActiveReqs);
    10101036
    1011     /* Extract command header and CDB from guest physical memory */
    1012 
    1013     size_t cbReqHdr = sizeof(struct REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize;
     1037    /*
     1038     * Extract command header and CDB from guest physical memory
     1039     */
     1040    size_t cbReqHdr = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize;
    10141041    PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbReqHdr);
    10151042    AssertReturn(pVirtqReq, VERR_NO_MEMORY);
     
    10241051    }
    10251052
    1026     uint8_t  uTarget  = pVirtqReq->ReqHdr.uVirtioLun[1];
    1027     uint32_t uScsiLun = (pVirtqReq->ReqHdr.uVirtioLun[2] << 8 | pVirtqReq->ReqHdr.uVirtioLun[3]) & 0x3fff;
     1053    uint8_t  uTarget  = pVirtqReq->ReqHdr.abVirtioLun[1];
     1054    uint32_t uScsiLun = (pVirtqReq->ReqHdr.abVirtioLun[2] << 8 | pVirtqReq->ReqHdr.abVirtioLun[3]) & 0x3fff;
    10281055    PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[uTarget];
    10291056
    10301057    LogFunc(("[%s] (Target: %d LUN: %d)  CDB: %.*Rhxs\n",
    1031         SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun,
    1032         virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0],
    1033         pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
     1058             SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun,
     1059             virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
    10341060
    10351061    Log3Func(("cmd id: %RX64, attr: %x, prio: %d, crn: %x\n",
    1036         pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));
     1062              pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));
    10371063
    10381064    /*
    10391065     * Calculate request offsets
    10401066     */
    1041     off_t uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize;
    1042     off_t uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize;
     1067    off_t uDataOutOff = sizeof(REQ_CMD_HDR_T)  + pThis->virtioScsiConfig.uCdbSize;
     1068    off_t uDataInOff  = sizeof(REQ_RESP_HDR_T) + pThis->virtioScsiConfig.uSenseSize;
    10431069    uint32_t cbDataOut = pDescChain->cbPhysSend - uDataOutOff;
    10441070    uint32_t cbDataIn  = pDescChain->cbPhysReturn - uDataInOff;
    1045     /**
     1071    /*
    10461072     * Handle submission errors
    10471073     */
     
    10501076    {
    10511077        Log2Func(("Aborting req submission because reset is in progress\n"));
    1052         struct REQ_RESP_HDR respHdr = { 0 };
    1053         respHdr.uSenseLen = 0;
    1054         respHdr.uStatus   = SCSI_STATUS_OK;
    1055         respHdr.uResponse = VIRTIOSCSI_S_RESET;
    1056         respHdr.uResidual = cbDataIn + cbDataOut;
    1057         virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, NULL);
     1078        REQ_RESP_HDR_T respHdr = { 0 };
     1079        respHdr.cbSenseLen = 0;
     1080        respHdr.uStatus    = SCSI_STATUS_OK;
     1081        respHdr.uResponse  = VIRTIOSCSI_S_RESET;
     1082        respHdr.uResidual  = cbDataIn + cbDataOut;
     1083        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, NULL);
    10581084        RTMemFree(pVirtqReq);
    10591085        return VINF_SUCCESS;
    10601086    }
    1061     else
    10621087    if (RT_UNLIKELY(uScsiLun != 0))
    10631088    {
     
    10661091                              0, SCSI_SENSE_ILLEGAL_REQUEST,
    10671092                              0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
    1068         struct REQ_RESP_HDR respHdr = { 0 };
    1069         respHdr.uSenseLen = sizeof(abSense);
    1070         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1071         respHdr.uResponse = VIRTIOSCSI_S_OK;
    1072         respHdr.uResidual = cbDataOut + cbDataIn;
    1073         virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
     1093        REQ_RESP_HDR_T respHdr = { 0 };
     1094        respHdr.cbSenseLen = sizeof(abSense);
     1095        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
     1096        respHdr.uResponse  = VIRTIOSCSI_S_OK;
     1097        respHdr.uResidual  = cbDataOut + cbDataIn;
     1098        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
    10741099        RTMemFree(pVirtqReq);
    10751100        return VINF_SUCCESS;
    10761101    }
    1077     else
    10781102    if (RT_UNLIKELY(uTarget >= pThis->cTargets || !pTarget->fPresent))
    10791103    {
     
    10811105        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    10821106                              0, SCSI_SENSE_NOT_READY, 0, 0, 0, 0, 10, 0, 0, 0 };
    1083         struct REQ_RESP_HDR respHdr = { 0 };
    1084         respHdr.uSenseLen = sizeof(abSense);
    1085         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1086         respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET;
    1087         respHdr.uResidual = cbDataIn + cbDataOut;
    1088         virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
     1107        REQ_RESP_HDR_T respHdr = { 0 };
     1108        respHdr.cbSenseLen = sizeof(abSense);
     1109        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
     1110        respHdr.uResponse  = VIRTIOSCSI_S_BAD_TARGET;
     1111        respHdr.uResidual  = cbDataIn + cbDataOut;
     1112        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
    10891113        RTMemFree(pVirtqReq);
    10901114        return VINF_SUCCESS;
    10911115    }
    1092     else
    10931116    if (RT_UNLIKELY(cbDataIn && cbDataOut && !pThis->fHasInOutBufs)) /* VirtIO 1.0, 5.6.6.1.1 */
    10941117    {
     
    10961119        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    10971120                              0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
    1098         struct REQ_RESP_HDR respHdr = { 0 };
    1099         respHdr.uSenseLen = sizeof(abSense);
    1100         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1101         respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    1102         respHdr.uResidual = cbDataIn + cbDataOut;
    1103         virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
     1121        REQ_RESP_HDR_T respHdr = { 0 };
     1122        respHdr.cbSenseLen = sizeof(abSense);
     1123        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
     1124        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
     1125        respHdr.uResidual  = cbDataIn + cbDataOut;
     1126        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
    11041127        RTMemFree(pVirtqReq);
    11051128        return VINF_SUCCESS;
     
    11141137
    11151138    int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
    1116                                   PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     1139                                      PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
    11171140
    11181141    if (RT_FAILURE(rc))
    11191142    {
    11201143        RTMemFree(pVirtqReq);
    1121         virtioScsiFreeReq(pTarget, NULL);
     1144        /** @todo r=bird: This *will* crash: virtioScsiR3FreeReq(pTarget, NULL); */
    11221145        AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
    11231146    }
     
    11321155    pReq->uDataOutOff = uDataOutOff;
    11331156
    1134     pReq->cbSense = pThis->virtioScsiConfig.uSenseSize;
    1135     pReq->pbSense = (uint8_t *)RTMemAlloc(pReq->cbSense);
    1136     AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
     1157    pReq->cbSenseAlloc = pThis->virtioScsiConfig.uSenseSize;
     1158    pReq->pbSense      = (uint8_t *)RTMemAllocZ(pReq->cbSenseAlloc);
     1159    AssertMsgReturnStmt(pReq->pbSense, ("Out of memory allocating sense buffer"),
     1160                        virtioScsiR3FreeReq(pTarget, pReq); RTMemFree(pVirtqReq), VERR_NO_MEMORY);
    11371161
    11381162    /* Note: DrvSCSI allocates one virtual memory buffer for input and output phases of the request */
     
    11401164                                        pVirtqReq->uCdb, (size_t)pThis->virtioScsiConfig.uCdbSize,
    11411165                                        PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir,
    1142                                         (size_t)RT_MAX(cbDataIn, cbDataOut),
    1143                                         pReq->pbSense, (size_t)pReq->cbSense, &pReq->uSenseLen,
    1144                                         &pReq->uStatus, 30 * RT_MS_1SEC);
     1166                                        RT_MAX(cbDataIn, cbDataOut),
     1167                                        pReq->pbSense, pReq->cbSenseAlloc, &pReq->cbSenseLen,
     1168                                        &pReq->uStatus, RT_MS_30SEC);
    11451169
    11461170    if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     
    11501174         * and there will be no callback to the finished/completion function for this request
    11511175         */
     1176        Assert(RT_FAILURE_NP(rc));
    11521177        Log2Func(("Request submission error from lower-level driver\n"));
    11531178        uint8_t uASC, uASCQ = 0;
     
    11641189                              0, SCSI_SENSE_VENDOR_SPECIFIC,
    11651190                              0, 0, 0, 0, 10, uASC, uASCQ, 0 };
    1166         struct REQ_RESP_HDR respHdr = { 0 };
    1167         respHdr.uSenseLen = sizeof(abSense);
    1168         respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
    1169         respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    1170         respHdr.uResidual = cbDataIn + cbDataOut;
    1171         virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
    1172         virtioScsiFreeReq(pTarget, pReq);
     1191        REQ_RESP_HDR_T respHdr = { 0 };
     1192        respHdr.cbSenseLen = sizeof(abSense);
     1193        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
     1194        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
     1195        respHdr.uResidual  = cbDataIn + cbDataOut;
     1196        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
     1197        virtioScsiR3FreeReq(pTarget, pReq);
    11731198    }
    11741199
     
    11771202}
    11781203
    1179 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
    1180 {
    1181     RT_NOREF2(pThis, qIdx);
    1182 
    1183     uint8_t uResponse = VIRTIOSCSI_S_OK;
    1184 
    1185     PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion =
    1186         (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAlloc(sizeof(VIRTIO_SCSI_CTRL_UNION_T));
    1187 
    1188     uint8_t *pb = (uint8_t *)pScsiCtrlUnion;
     1204/**
     1205 * Handles control transfers for/on a worker thread.
     1206 *
     1207 * @returns VBox status code (ignored by the caller).
     1208 * @param   pThis       The device instance data.
     1209 * @param   qIdx        CONTROLQ_IDX
     1210 * @param   pDescChain  Descriptor chain to process.
     1211 */
     1212static int virtioScsiR3Ctrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
     1213{
     1214    uint8_t bResponse = VIRTIOSCSI_S_OK;
     1215
     1216    /*
     1217     * Allocate buffer and read in the control request/whatever.
     1218     */
     1219    /** @todo r=bird: The following may misbehave if the guest is not feeding you
     1220     *        sufficient data.  There are no size checks below or with the caller
     1221     *        that I can see, and more importantly you're using RTMemAlloc rather
     1222     *        than RTMemAllocZ here, so you'll get random heap bytes.
     1223     *
     1224     *        I've changed it to RTMemAllocZ so the memory is all zeroed, but you
     1225     *        need to consider how to deal with incorrectly sized input.
     1226     */
     1227    PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion = (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAllocZ(sizeof(VIRTIO_SCSI_CTRL_UNION_T));
     1228    AssertPtrReturn(pScsiCtrlUnion, VERR_NO_MEMORY /*ignored*/);
     1229
     1230    uint8_t *pb = pScsiCtrlUnion->ab;
    11891231    for (size_t cb = RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T)); cb; )
    11901232    {
    11911233        size_t cbSeg = cb;
     1234        /** @todo r=bird: This is ABUSING the RTSgBuf, interchanging host context
     1235         * pointers with RTGCPHYS.  If we hadn't just dropped 32-bit host
     1236         * support, this would have been a serious problem.  Now it is just UGLY! */
     1237        AssertCompile(sizeof(RTGCPHYS) == sizeof(void *)); /* ASSUMING RTGCPHYS and host pointers are interchangable. (horrible!) */
    11921238        RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
    11931239        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pb, cbSeg);
     
    12001246     * See VirtIO 1.0 specification section 5.6.6.2
    12011247     */
    1202     uint32_t uSubscribedEvents  =
    1203                             VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
    1204                           | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST
    1205                           | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE
    1206                           | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY;
     1248    uint32_t fSubscribedEvents  = VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
     1249                                | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST
     1250                                | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE
     1251                                | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY;
    12071252
    12081253    RTSGBUF reqSegBuf;
    12091254
    12101255
    1211     switch(pScsiCtrlUnion->scsiCtrl.uType)
     1256    switch (pScsiCtrlUnion->scsiCtrl.uType)
    12121257    {
    12131258        case VIRTIOSCSI_T_TMF: /* Task Management Functions */
    12141259        {
    1215             uint8_t  uTarget  = pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[1];
    1216             uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[2] << 8
    1217                                | pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[3]) & 0x3fff;
    1218             if (LogIs2Enabled())
    1219             {
    1220                 const char *pszTmfTypeText = virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype);
    1221                 Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
    1222                     QUEUENAME(qIdx), uTarget, uScsiLun, pszTmfTypeText));
    1223                 RT_NOREF3(pszTmfTypeText, uTarget, uScsiLun);
    1224             }
     1260            uint8_t  uTarget  = pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[1];
     1261            uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[2] << 8
     1262                               | pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[3]) & 0x3fff;
     1263            Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
     1264                      QUEUENAME(qIdx), uTarget, uScsiLun, virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype)));
    12251265
    12261266            PVIRTIOSCSITARGET pTarget = NULL;
     
    12291269
    12301270            if (uTarget >= pThis->cTargets || !pTarget->fPresent)
    1231                 uResponse = VIRTIOSCSI_S_BAD_TARGET;
     1271                bResponse = VIRTIOSCSI_S_BAD_TARGET;
    12321272            else
    12331273            if (uScsiLun != 0)
    1234                 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
     1274                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
    12351275            else
    1236             switch(pScsiCtrlUnion->scsiCtrlTmf.uSubtype)
    1237             {
    1238                 case VIRTIOSCSI_T_TMF_ABORT_TASK:
    1239                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1240                     break;
    1241                 case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:
    1242                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1243                     break;
    1244                 case VIRTIOSCSI_T_TMF_CLEAR_ACA:
    1245                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1246                     break;
    1247                 case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:
    1248                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1249                     break;
    1250                 case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:
    1251                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1252                     break;
    1253                 case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:
    1254                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    1255                     break;
    1256                 case VIRTIOSCSI_T_TMF_QUERY_TASK:
    1257                     uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
    1258                     break;
    1259                 case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:
    1260                     uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
    1261                     break;
    1262                 default:
    1263                     LogFunc(("Unknown TMF type\n"));
    1264                     uResponse = VIRTIOSCSI_S_FAILURE;
    1265             }
    1266 
    1267             RTSGSEG aReqSegs[] = { { &uResponse,  sizeof(uResponse) } };
    1268             RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
     1276                switch (pScsiCtrlUnion->scsiCtrlTmf.uSubtype)
     1277                {
     1278                    case VIRTIOSCSI_T_TMF_ABORT_TASK:
     1279                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1280                        break;
     1281                    case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:
     1282                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1283                        break;
     1284                    case VIRTIOSCSI_T_TMF_CLEAR_ACA:
     1285                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1286                        break;
     1287                    case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:
     1288                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1289                        break;
     1290                    case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:
     1291                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1292                        break;
     1293                    case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:
     1294                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1295                        break;
     1296                    case VIRTIOSCSI_T_TMF_QUERY_TASK:
     1297                        bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
     1298                        break;
     1299                    case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:
     1300                        bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
     1301                        break;
     1302                    default:
     1303                        LogFunc(("Unknown TMF type\n"));
     1304                        bResponse = VIRTIOSCSI_S_FAILURE;
     1305                }
     1306
     1307            RTSGSEG aReqSegs[] = { { &bResponse,  sizeof(bResponse) } };
     1308            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    12691309
    12701310            break;
     
    12751315            PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnQuery = &pScsiCtrlUnion->scsiCtrlAsyncNotify;
    12761316
    1277             uSubscribedEvents &= pScsiCtrlAnQuery->uEventsRequested;
    1278 
    1279             uint8_t  uTarget  = pScsiCtrlAnQuery->uScsiLun[1];
    1280             uint32_t uScsiLun = (pScsiCtrlAnQuery->uScsiLun[2] << 8 | pScsiCtrlAnQuery->uScsiLun[3]) & 0x3fff;
     1317            fSubscribedEvents &= pScsiCtrlAnQuery->fEventsRequested;
     1318
     1319            uint8_t  uTarget  = pScsiCtrlAnQuery->abScsiLun[1];
     1320            uint32_t uScsiLun = (pScsiCtrlAnQuery->abScsiLun[2] << 8 | pScsiCtrlAnQuery->abScsiLun[3]) & 0x3fff;
    12811321
    12821322            PVIRTIOSCSITARGET pTarget = NULL;
     
    12851325
    12861326            if (uTarget >= pThis->cTargets || !pTarget->fPresent)
    1287                 uResponse = VIRTIOSCSI_S_BAD_TARGET;
     1327                bResponse = VIRTIOSCSI_S_BAD_TARGET;
    12881328            else
    12891329            if (uScsiLun != 0)
    1290                 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
     1330                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
    12911331            else
    1292                 uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
    1293 
     1332                bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
     1333
     1334#ifdef LOG_ENABLED
    12941335            if (LogIs2Enabled())
    12951336            {
    12961337                char szTypeText[128];
    1297                 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText),
    1298                     pScsiCtrlAnQuery->uEventsRequested);
     1338                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnQuery->fEventsRequested);
    12991339                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Query: %s\n",
    1300                     QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
    1301                 RT_NOREF3(szTypeText, uTarget, uScsiLun);
    1302 
     1340                          QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
    13031341            }
    1304             RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
    1305             RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
     1342#endif
     1343            RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) },  { &bResponse, sizeof(bResponse)  } };
     1344            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    13061345
    13071346            break;
     
    13121351            PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnSubscribe = &pScsiCtrlUnion->scsiCtrlAsyncNotify;
    13131352
    1314             if (pScsiCtrlAnSubscribe->uEventsRequested & ~SUBSCRIBABLE_EVENTS)
    1315                 LogFunc(("Unsupported bits in event subscription event mask: 0x%x\n",
    1316                     pScsiCtrlAnSubscribe->uEventsRequested));
    1317 
    1318             uSubscribedEvents &= pScsiCtrlAnSubscribe->uEventsRequested;
    1319             pThis->uAsyncEvtsEnabled = uSubscribedEvents;
    1320 
    1321             uint8_t  uTarget  = pScsiCtrlAnSubscribe->uScsiLun[1];
    1322             uint32_t uScsiLun = (pScsiCtrlAnSubscribe->uScsiLun[2] << 8
    1323                                | pScsiCtrlAnSubscribe->uScsiLun[3]) & 0x3fff;
    1324 
     1353            if (pScsiCtrlAnSubscribe->fEventsRequested & ~SUBSCRIBABLE_EVENTS)
     1354                LogFunc(("Unsupported bits in event subscription event mask: %#x\n", pScsiCtrlAnSubscribe->fEventsRequested));
     1355
     1356            fSubscribedEvents &= pScsiCtrlAnSubscribe->fEventsRequested;
     1357            pThis->fAsyncEvtsEnabled = fSubscribedEvents;
     1358
     1359            uint8_t  uTarget  = pScsiCtrlAnSubscribe->abScsiLun[1];
     1360            uint32_t uScsiLun = (pScsiCtrlAnSubscribe->abScsiLun[2] << 8
     1361                               | pScsiCtrlAnSubscribe->abScsiLun[3]) & 0x3fff;
     1362
     1363#ifdef LOG_ENABLED
    13251364            if (LogIs2Enabled())
    13261365            {
    13271366                char szTypeText[128];
    1328                 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->uEventsRequested);
     1367                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->fEventsRequested);
    13291368                Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Subscribe: %s\n",
    1330                     QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
    1331                 RT_NOREF3(szTypeText, uTarget, uScsiLun);
    1332 
     1369                          QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
    13331370            }
     1371#endif
    13341372
    13351373            PVIRTIOSCSITARGET pTarget = NULL;
     
    13381376
    13391377            if (uTarget >= pThis->cTargets || !pTarget->fPresent)
    1340                 uResponse = VIRTIOSCSI_S_BAD_TARGET;
     1378                bResponse = VIRTIOSCSI_S_BAD_TARGET;
    13411379            else
    13421380            if (uScsiLun != 0)
    1343                 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
     1381                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
    13441382            else
    13451383            {
     
    13481386                 *      and confirm when to use 'complete' vs. 'succeeded' See VirtIO 1.0 spec section 5.6.6.2
    13491387                 *      and read SAM docs*/
    1350                 if (uSubscribedEvents == pScsiCtrlAnSubscribe->uEventsRequested)
    1351                     uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
     1388                if (fSubscribedEvents == pScsiCtrlAnSubscribe->fEventsRequested)
     1389                    bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    13521390                else
    1353                     uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
     1391                    bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
    13541392            }
    1355             RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
    1356             RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
     1393            RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) },  { &bResponse, sizeof(bResponse)  } };
     1394            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    13571395
    13581396            break;
    13591397        }
    13601398        default:
    1361             LogFunc(("Unknown control type extracted from %s: %d\n",
    1362                 QUEUENAME(qIdx),  &pScsiCtrlUnion->scsiCtrl.uType));
    1363 
    1364             uResponse = VIRTIOSCSI_S_FAILURE;
    1365 
    1366             RTSGSEG aReqSegs[] = { { &uResponse,  sizeof(uResponse) } };
    1367             RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    1368     }
    1369 
    1370     const char *pszCtrlRespText = virtioGetReqRespText(uResponse);
    1371     LogFunc(("Response code: %s\n", pszCtrlRespText));
    1372     RT_NOREF(pszCtrlRespText);
    1373     virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true);
     1399        {
     1400            LogFunc(("Unknown control type extracted from %s: %u\n", QUEUENAME(qIdx), pScsiCtrlUnion->scsiCtrl.uType));
     1401
     1402            bResponse = VIRTIOSCSI_S_FAILURE;
     1403
     1404            RTSGSEG aReqSegs[] = { { &bResponse, sizeof(bResponse) } };
     1405            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
     1406        }
     1407    }
     1408
     1409    LogFunc(("Response code: %s\n", virtioGetReqRespText(bResponse)));
     1410    virtioQueuePut( pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true);
    13741411    virtioQueueSync(pThis->hVirtio, qIdx);
    13751412
     
    13771414}
    13781415
    1379 /*
    1380  * Unblock the worker thread so it can respond to a state change.
    1381  *
    1382  * @returns VBox status code.
    1383  * @param   pDevIns     The pcnet device instance.
    1384  * @param   pThread     The send thread.
    1385  */
    1386 static DECLCALLBACK(int) virtioScsiWorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1416/**
     1417 * @callback_method_impl{FNPDMTHREADWAKEUPDEV}
     1418 */
     1419static DECLCALLBACK(int) virtioScsiR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    13871420{
    13881421    RT_NOREF(pThread);
    13891422    uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff;
    13901423    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1391     return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorker[qIdx].hEvtProcess);
    1392 }
    1393 
    1394 static int virtioScsiWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    1395 {
    1396     int rc;
    1397     uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff;
     1424    return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorkers[qIdx].hEvtProcess);
     1425}
     1426
     1427/**
     1428 * @callback_method_impl{FNPDMTHREADDEV}
     1429 */
     1430static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1431{
     1432    uint16_t const qIdx = (uint16_t)(uintptr_t)pThread->pvUser;
    13981433    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1399     PWORKER pWorker = &pThis->aWorker[qIdx];
     1434    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
    14001435
    14011436    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     
    14131448                Log6Func(("%s worker sleeping...\n", QUEUENAME(qIdx)));
    14141449                Assert(ASMAtomicReadBool(&pWorker->fSleeping));
    1415                 rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
     1450                int rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
    14161451                AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
    14171452                if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     
    14231458        }
    14241459
    1425         if (!pThis->fQueueAttached[qIdx])
     1460        if (!pThis->afQueueAttached[qIdx])
    14261461        {
    14271462            LogFunc(("%s queue not attached, worker aborting...\n", QUEUENAME(qIdx)));
     
    14321467             Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx)));
    14331468             PVIRTIO_DESC_CHAIN_T pDescChain;
    1434              rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);
     1469             int rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);
    14351470             if (rc == VERR_NOT_AVAILABLE)
    14361471             {
     
    14411476             AssertRC(rc);
    14421477             if (qIdx == CONTROLQ_IDX)
    1443                  virtioScsiCtrl(pThis, qIdx, pDescChain);
     1478                 virtioScsiR3Ctrl(pThis, qIdx, pDescChain);
    14441479             else /* request queue index */
    14451480             {
    1446                   rc = virtioScsiReqSubmit(pThis, qIdx, pDescChain);
     1481                  rc = virtioScsiR3ReqSubmit(pThis, qIdx, pDescChain);
    14471482                  if (RT_FAILURE(rc))
    14481483                  {
     
    14561491
    14571492
    1458 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
    1459 {
    1460     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
     1493/*********************************************************************************************************************************
     1494*   Sending evnets
     1495*********************************************************************************************************************************/
     1496
     1497
     1498DECLINLINE(void) virtioScsiR3ReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
     1499{
     1500    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
    14611501}
    14621502
    14631503#if 0
    1464 /* Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
     1504
     1505/** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
    14651506 * This effectively removes the SCSI Target/LUN on the guest side
    14661507 */
    1467 DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
     1508DECLINLINE(void) virtioScsiR3ReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
    14681509{
    14691510    if (pThis->fHasHotplug)
    1470         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1471                 VIRTIOSCSI_EVT_RESET_REMOVED);
    1472 }
    1473 
    1474 /* Only invoke thi if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
     1511        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_REMOVED);
     1512}
     1513
     1514/** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
    14751515 * This effectively adds the SCSI Target/LUN on the guest side
    14761516 */
    1477 DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
     1517DECLINLINE(void) virtioScsiR3ReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
    14781518{
    14791519    if (pThis->fHasHotplug)
    1480         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1481                 VIRTIOSCSI_EVT_RESET_RESCAN);
    1482 }
    1483 
    1484 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
    1485 {
    1486     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1487             VIRTIOSCSI_EVT_RESET_HARD);
    1488 }
    1489 
    1490 DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
    1491 {
    1492     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
    1493         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1494                 VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
    1495 }
    1496 
    1497 DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
    1498 {
    1499     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
    1500         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1501                 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
    1502 }
    1503 
    1504 DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
    1505 {
    1506     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
    1507         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1508                 VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
    1509 }
    1510 
    1511 DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
    1512 {
    1513     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
    1514         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1515                 VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
    1516 }
    1517 
    1518 DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
    1519 {
    1520     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
    1521         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1522                 VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
    1523 }
    1524 
    1525 DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
    1526 {
    1527     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
    1528         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1529                 VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
    1530 }
    1531 
    1532 DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
     1520        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_RESCAN);
     1521}
     1522
     1523DECLINLINE(void) virtioScsiR3ReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
     1524{
     1525    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_HARD);
     1526}
     1527
     1528DECLINLINE(void) virtioScsiR3ReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1529{
     1530    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
     1531        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
     1532}
     1533
     1534DECLINLINE(void) virtioScsiR3ReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
     1535{
     1536    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
     1537        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
     1538}
     1539
     1540DECLINLINE(void) virtioScsiR3ReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
     1541{
     1542    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
     1543        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
     1544}
     1545
     1546DECLINLINE(void) virtioScsiR3ReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1547{
     1548    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
     1549        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
     1550}
     1551
     1552DECLINLINE(void) virtioScsiR3ReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
     1553{
     1554    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
     1555        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
     1556}
     1557
     1558DECLINLINE(void) virtioScsiR3ReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
     1559{
     1560    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
     1561        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
     1562}
     1563
     1564DECLINLINE(void) virtioScsiR3ReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
    15331565{
    15341566    uint32_t uReason = uSenseQualifier << 8 | uSenseCode;
    1535     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
     1567    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
    15361568
    15371569}
     
    15391571#endif
    15401572
    1541 static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
     1573/**
     1574 * @callback_method_impl{FNVIRTIOQUEUENOTIFIED}
     1575 */
     1576static DECLCALLBACK(void) virtioScsiR3Notified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
    15421577{
    15431578    RT_NOREF(hVirtio);
     
    15451580    AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
    15461581    PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
    1547     PWORKER pWorker = &pThis->aWorker[qIdx];
     1582    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
    15481583
    15491584    RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));
     
    15671602        Log3Func(("Driver queued buffer(s) to %s\n", QUEUENAME(qIdx)));
    15681603        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
    1569             virtioScsiReportEventsMissed(pThis, 0);
     1604            virtioScsiR3ReportEventsMissed(pThis, 0);
    15701605    }
    15711606    else
     
    15731608}
    15741609
    1575 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  uint32_t fVirtioReady)
     1610/**
     1611 * @callback_method_impl{FNVIRTIOSTATUSCHANGED}
     1612 */
     1613static DECLCALLBACK(void) virtioScsiR3StatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  uint32_t fVirtioReady)
    15761614{
    15771615    RT_NOREF(hVirtio);
     
    15921630
    15931631        for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
    1594             pThis->fQueueAttached[i] = true;
     1632            pThis->afQueueAttached[i] = true;
    15951633    }
    15961634    else
     
    15981636        LogFunc(("VirtIO is resetting\n"));
    15991637        for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
    1600             pThis->fQueueAttached[i] = false;
    1601     }
    1602 }
    1603 
    1604 /**
    1605  * virtio-scsi debugger info callback.
    1606  *
    1607  * @param   pDevIns     The device instance.
    1608  * @param   pHlp        The output helpers.
    1609  * @param   pszArgs     The arguments.
    1610  */
    1611 static DECLCALLBACK(void) virtioScsiInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     1638            pThis->afQueueAttached[i] = false;
     1639    }
     1640}
     1641
     1642
     1643/*********************************************************************************************************************************
     1644*   Misc                                                                                                                         *
     1645*********************************************************************************************************************************/
     1646
     1647/**
     1648 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-scsi debugger info callback.}
     1649 */
     1650static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    16121651{
    16131652    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1614     bool fVerbose = false;
    16151653
    16161654    /* Parse arguments. */
    1617     if (pszArgs)
    1618         fVerbose = strstr(pszArgs, "verbose") != NULL;
     1655    RT_NOREF(pszArgs); //bool fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL;
    16191656
    16201657    /* Show basic information. */
     
    16251662}
    16261663
    1627 /**
    1628  * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
    1629  */
    1630 static DECLCALLBACK(void) virtioScsiMediumEjected(PPDMIMEDIAEXPORT pInterface)
    1631 {
    1632     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    1633     PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
    1634     LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
    1635     if (pThis->pMediaNotify)
    1636     {
    1637          int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
    1638                                    (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
    1639                                     pThis->pMediaNotify, pTarget->iTarget);
    1640          AssertRC(rc);
    1641     }
    1642 }
    1643 
    1644 /** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
    1645 static DECLCALLBACK(int) virtioScsiLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    1646 {
    1647 LogFunc(("LIVE EXEC!!\n"));
     1664
     1665/*********************************************************************************************************************************
     1666*   Saved state                                                                                                                  *
     1667*********************************************************************************************************************************/
     1668
     1669/**
     1670 * @callback_method_impl{FNSSMDEVLIVEEXEC}
     1671 */
     1672static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
     1673{
     1674    LogFunc(("LIVE EXEC!!\n"));
    16481675    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    16491676    RT_NOREF(pThis);
     
    16531680}
    16541681
    1655 /** @callback_method_impl{FNSSMDEVLOADEXEC}  */
    1656 static DECLCALLBACK(int) virtioScsiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    1657 {
    1658 LogFunc(("LOAD EXEC!!\n"));
     1682/**
     1683 * @callback_method_impl{FNSSMDEVLOADEXEC}
     1684 */
     1685static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     1686{
     1687    LogFunc(("LOAD EXEC!!\n"));
    16591688    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    16601689    SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uNumQueues);
     
    16681697    SSMR3GetU16(pSSM, &pThis->virtioScsiConfig.uMaxTarget);
    16691698    SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uMaxLun);
    1670     SSMR3GetU32(pSSM, &pThis->uAsyncEvtsEnabled);
     1699    SSMR3GetU32(pSSM, &pThis->fAsyncEvtsEnabled);
    16711700    SSMR3GetU32(pSSM, (uint32_t *)&pThis->cActiveReqs);
    16721701    SSMR3GetBool(pSSM, &pThis->fEventsMissed);
     
    16801709    RT_NOREF(uPass);
    16811710    RT_NOREF(uVersion);
    1682     return VINF_SSM_DONT_CALL_AGAIN;
    1683 }
    1684 
    1685 /** @callback_method_impl{FNSSMDEVSAVEEXEC}  */
    1686 static DECLCALLBACK(int) virtioScsiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    1687 {
    1688 LogFunc(("SAVE EXEC!!\n"));
     1711    return VINF_SUCCESS;
     1712}
     1713
     1714/**
     1715 * @callback_method_impl{FNSSMDEVSAVEEXEC}
     1716 */
     1717static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     1718{
     1719    LogFunc(("SAVE EXEC!!\n"));
    16891720    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    16901721
     
    16991730    SSMR3PutU16(pSSM, pThis->virtioScsiConfig.uMaxTarget);
    17001731    SSMR3PutU32(pSSM, pThis->virtioScsiConfig.uMaxLun);
    1701     SSMR3PutU32(pSSM, pThis->uAsyncEvtsEnabled);
    1702     SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs);
     1732    SSMR3PutU32(pSSM, pThis->fAsyncEvtsEnabled);
     1733    SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs); /** @todo r=bird: Shouldn't this be zero?  I don't think we can have
     1734                                                      * outstanding requests when the VM is suspended (which we are when this
     1735                                                      * function is called), and more importantely, I don't understand how they
     1736                                                      * would be restored by virtioScsiR3LoadExec. */
    17031737    SSMR3PutBool(pSSM, pThis->fEventsMissed);
    17041738    SSMR3PutU32(pSSM, pThis->fVirtioReady);
     
    17081742    SSMR3PutU32(pSSM, pThis->fHasLunChange);
    17091743    SSMR3PutU32(pSSM, pThis->fResetting);
    1710     SSMR3PutU32(pSSM, pThis->fQuiescing);
     1744    SSMR3PutU32(pSSM, pThis->fQuiescing); /** @todo r=bird: This shall always be false, as the VM is suspended when saving, so no need to save this */
    17111745
    17121746    return VINF_SUCCESS;
    17131747}
    17141748
    1715 /** @callback_method_impl{FNSSMDEVLOADDONE}  */
    1716 static DECLCALLBACK(int) virtioScsiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     1749/**
     1750 * @callback_method_impl{FNSSMDEVLOADDONE}
     1751 */
     1752static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    17171753{
    17181754    LogFunc(("callback"));
     
    17231759}
    17241760
    1725 /**
    1726  * Is asynchronous handling of suspend or power off notification completed?
    1727  *
    1728  * This is called to check whether the device has quiesced.  Don't deadlock.
    1729  * Avoid blocking.  Do NOT wait for anything.
    1730  *
    1731  * @returns true if done, false if more work to be done.
    1732  *
    1733  * @param   pDevIns             The device instance.
    1734  * @remarks The caller will enter the device critical section.
    1735  * @thread  EMT(0)
    1736  */
    1737 static DECLCALLBACK(bool) virtioScsiDeviceQuiesced(PPDMDEVINS pDevIns)
     1761
     1762/*********************************************************************************************************************************
     1763*   Device Interface - Misplaced.                                                                                                             *
     1764*********************************************************************************************************************************/
     1765
     1766/**
     1767 * @callback_method_impl{FNPDMDEVASYNCNOTIFY}
     1768 */
     1769static DECLCALLBACK(bool) virtioScsiR3DeviceQuiesced(PPDMDEVINS pDevIns)
    17381770{
    17391771    LogFunc(("Device I/O activity quiesced.\n"));
     
    17451777}
    17461778
    1747 static void virtioScsiQuiesceDevice(PPDMDEVINS pDevIns)
     1779/**
     1780 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff().
     1781 */
     1782static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns)
    17481783{
    17491784    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     
    17521787    pThis->fQuiescing = true;
    17531788
    1754     PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiDeviceQuiesced);
     1789    PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3DeviceQuiesced);
    17551790
    17561791    /* If already quiesced invoke async callback.  */
     
    17601795
    17611796/**
    1762  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
    1763  */
    1764 static DECLCALLBACK(void) virtioScsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    1765                                                       void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
    1766 {
    1767     RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
    1768     PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
    1769 
    1770     switch (enmState)
    1771     {
    1772         case PDMMEDIAEXIOREQSTATE_SUSPENDED:
    1773         {
    1774             /* Stop considering this request active */
    1775             if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
    1776                 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
    1777             break;
    1778         }
    1779         case PDMMEDIAEXIOREQSTATE_ACTIVE:
    1780             ASMAtomicIncU32(&pThis->cActiveReqs);
    1781             break;
    1782         default:
    1783             AssertMsgFailed(("Invalid request state given %u\n", enmState));
    1784     }
    1785 }
    1786 
    1787 /**
    1788  * @copydoc FNPDMDEVRESET
    1789  */
    1790 static DECLCALLBACK(void) virtioScsiReset(PPDMDEVINS pDevIns)
     1797 * @inter FNPDMDEVRESET
     1798 */
     1799static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
    17911800{
    17921801    LogFunc(("\n"));
    17931802    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    17941803    pThis->fResetting = true;
    1795     virtioScsiQuiesceDevice(pDevIns);
     1804    virtioScsiR3QuiesceDevice(pDevIns);
    17961805}
    17971806
     
    17991808 * @interface_method_impl{PDMDEVREG,pfnResume}
    18001809 */
    1801 static DECLCALLBACK(void) virtioScsiResume(PPDMDEVINS pDevIns)
     1810static DECLCALLBACK(void) virtioScsiR3Resume(PPDMDEVINS pDevIns)
    18021811{
    18031812    LogFunc(("\n"));
     
    18111820     * be awake due to new reqs coming in.
    18121821     */
    1813      for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
    1814     {
    1815         PWORKER pWorker = &pThis->aWorker[qIdx];
     1822    for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
     1823    {
     1824        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
    18161825
    18171826        if (ASMAtomicReadBool(&pWorker->fSleeping))
     
    18301839 * @interface_method_impl{PDMDEVREG,pfnSuspend}
    18311840 */
    1832 static DECLCALLBACK(void) virtioScsiSuspendOrPoweroff(PPDMDEVINS pDevIns)
     1841static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
    18331842{
    18341843    LogFunc(("\n"));
    18351844
    1836     virtioScsiQuiesceDevice(pDevIns);
     1845    virtioScsiR3QuiesceDevice(pDevIns);
    18371846
    18381847    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     
    18531862}
    18541863
     1864
     1865/*********************************************************************************************************************************
     1866*   LEDs                                                                                                                         *
     1867*********************************************************************************************************************************/
     1868
     1869#if 0 /** @todo r=bird: LEDs are not being set it seems. */
     1870
    18551871/**
    18561872 * Turns on/off the write status LED.
     
    18591875 * @param   fOn             New LED state.
    18601876 */
    1861 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     1877static void virtioScsiR3SetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    18621878{
    18631879    LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
     
    18651881        pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
    18661882    else
    1867         pTarget->led.Actual.s.fWriting = fOn;
     1883        pTarget->led.Actual.s.fWriting = 0;
    18681884}
    18691885
     
    18741890 * @param   fOn             New LED state.
    18751891 */
    1876 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     1892static void virtioScsiR3SetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    18771893{
    18781894    LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
     
    18801896        pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
    18811897    else
    1882         pTarget->led.Actual.s.fReading = fOn;
    1883 }
    1884 
    1885 /**
    1886  * Gets the pointer to the status LED of a unit.
    1887  *
    1888  * @returns VBox status code.
    1889  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1890  * @param   iTarget         The unit which status LED we desire.
    1891  * @param   ppLed           Where to store the LED pointer.
    1892  */
    1893 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
    1894 {
    1895   PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
     1898        pTarget->led.Actual.s.fReading = 0;
     1899}
     1900
     1901#endif /* unused*/
     1902
     1903/**
     1904 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Target level.}
     1905 */
     1906static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
     1907{
     1908    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
    18961909    if (iTarget == 0)
    18971910    {
     
    19041917
    19051918/**
    1906  * Gets the pointer to the status LED of a unit.
    1907  *
    1908  * @returns VBox status code.
    1909  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1910  * @param   iTarget         The unit which status LED we desire.
    1911  * @param   ppLed           Where to store the LED pointer.
    1912  */
    1913 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
     1919 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Device level.}
     1920 */
     1921static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
    19141922{
    19151923    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
     
    19211929    }
    19221930    return VERR_PDM_LUN_NOT_FOUND;
    1923  }
    1924 
    1925 static int virtioScsiCfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
    1926                                     const void *pv, uint32_t cb, bool fWrite)
    1927 {
    1928 
     1931}
     1932
     1933
     1934/*********************************************************************************************************************************
     1935*   Virtio config.                                                                                                               *
     1936*********************************************************************************************************************************/
     1937
     1938/**
     1939 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead.
     1940 */
     1941static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)
     1942{
    19291943    AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);
    19301944
    1931     if (MATCH_SCSI_CONFIG(uNumQueues))
     1945/**
     1946 * Resolves to boolean true if uOffset matches a field offset and size exactly,
     1947 * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
     1948 * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
     1949 * (Easily re-written to allow unaligned bounded access to a field).
     1950 *
     1951 * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
     1952 * @result           - true or false
     1953 */
     1954#define MATCH_SCSI_CONFIG(member) \
     1955        (   (   RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
     1956             && (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
     1957                 || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
     1958             && cb == sizeof(uint32_t)) \
     1959         || (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
     1960             && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) )
     1961
     1962#define LOG_SCSI_CONFIG_ACCESSOR(member) \
     1963        virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
     1964                               pv, cb, offIntra, fWrite, false, 0);
     1965
     1966#define SCSI_CONFIG_ACCESSOR(member) \
     1967    do \
     1968    { \
     1969        uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
     1970        if (fWrite) \
     1971            memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \
     1972        else \
     1973            memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
     1974        LOG_SCSI_CONFIG_ACCESSOR(member); \
     1975    } while(0)
     1976
     1977#define SCSI_CONFIG_ACCESSOR_READONLY(member) \
     1978    do \
     1979    { \
     1980        uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
     1981        if (fWrite) \
     1982            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
     1983        else \
     1984        { \
     1985            memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
     1986            LOG_SCSI_CONFIG_ACCESSOR(member); \
     1987        } \
     1988    } while(0)
     1989
     1990    if (MATCH_SCSI_CONFIG(            uNumQueues))
    19321991        SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
    1933     else
    1934     if (MATCH_SCSI_CONFIG(uSegMax))
     1992    else if (MATCH_SCSI_CONFIG(       uSegMax))
    19351993        SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
    1936     else
    1937     if (MATCH_SCSI_CONFIG(uMaxSectors))
     1994    else if (MATCH_SCSI_CONFIG(       uMaxSectors))
    19381995        SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
    1939     else
    1940     if (MATCH_SCSI_CONFIG(uCmdPerLun))
     1996    else if (MATCH_SCSI_CONFIG(       uCmdPerLun))
    19411997        SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
    1942     else
    1943     if (MATCH_SCSI_CONFIG(uEventInfoSize))
     1998    else if (MATCH_SCSI_CONFIG(       uEventInfoSize))
    19441999        SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
    1945     else
    1946     if (MATCH_SCSI_CONFIG(uSenseSize))
    1947         SCSI_CONFIG_ACCESSOR(uSenseSize);
    1948     else
    1949     if (MATCH_SCSI_CONFIG(uCdbSize))
    1950         SCSI_CONFIG_ACCESSOR(uCdbSize);
    1951     else
    1952     if (MATCH_SCSI_CONFIG(uMaxChannel))
     2000    else if (MATCH_SCSI_CONFIG(       uSenseSize))
     2001        SCSI_CONFIG_ACCESSOR(         uSenseSize);
     2002    else if (MATCH_SCSI_CONFIG(       uCdbSize))
     2003        SCSI_CONFIG_ACCESSOR(         uCdbSize);
     2004    else if (MATCH_SCSI_CONFIG(       uMaxChannel))
    19532005        SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
    1954     else
    1955     if (MATCH_SCSI_CONFIG(uMaxTarget))
     2006    else if (MATCH_SCSI_CONFIG(       uMaxTarget))
    19562007        SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
    1957     else
    1958     if (MATCH_SCSI_CONFIG(uMaxLun))
     2008    else if (MATCH_SCSI_CONFIG(       uMaxLun))
    19592009        SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
    19602010    else
    19612011    {
    1962         LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
     2012        LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb));
    19632013        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    19642014    }
    19652015    return VINF_SUCCESS;
    1966 }
    1967 
    1968 /**
    1969  * virtio-scsi VirtIO Device-specific capabilities read callback
    1970  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    1971  *
    1972  * @param   pDevIns     The device instance.
    1973  * @param   uOffset     Offset within device specific capabilities struct
    1974  * @param   pv          Buffer in which to save read data
    1975  * @param   cb          Number of bytes to read
    1976  */
    1977 static DECLCALLBACK(int) virtioScsiDevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
    1978 {
    1979     int rc = VINF_SUCCESS;
    1980     PVIRTIOSCSI  pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1981 
    1982     rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, false);
    1983 
    1984     return rc;
    1985 }
    1986 
    1987 /**
    1988  * virtio-scsi VirtIO Device-specific capabilities read callback
    1989  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    1990  *
    1991  * @param   pDevIns     The device instance.
    1992  * @param   uOffset     Offset within device specific capabilities struct
    1993  * @param   pv          Buffer in which to save read data
    1994  * @param   cb          Number of bytes to write
    1995  */
    1996 static DECLCALLBACK(int) virtioScsiDevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
    1997 {
    1998     int rc = VINF_SUCCESS;
    1999     PVIRTIOSCSI  pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2000 
    2001     rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, true);
    2002 
    2003     return rc;
    2004 }
    2005 
    2006 /**
    2007  * Device relocation callback.
    2008  *
    2009  * When this callback is called the device instance data, and if the
    2010  * device have a GC component, is being relocated, or/and the selectors
    2011  * have been changed. The device must use the chance to perform the
    2012  * necessary pointer relocations and data updates.
    2013  *
    2014  * Before the GC code is executed the first time, this function will be
    2015  * called with a 0 delta so GC pointer calculations can be one in one place.
    2016  *
    2017  * @param   pDevIns     Pointer to the device instance.
    2018  * @param   offDelta    The relocation delta relative to the old location.
    2019  *
    2020  * @remark  A relocation CANNOT fail.
    2021  */
    2022 static DECLCALLBACK(void) virtioScsiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    2023 {
    2024     LogFunc(("Relocating virtio-scsi"));
    2025     RT_NOREF(offDelta);
    2026     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    2027 
    2028     pThis->pDevInsR3 = pDevIns;
    2029 
    2030     for (uint32_t i = 0; i < pThis->cTargets; i++)
    2031     {
    2032         PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[i];
    2033         pTarget->pVirtioScsi = pThis;
    2034     }
    2035 
    2036     /*
    2037      * Important: Forward to virtio framework!
    2038      */
    2039     virtioRelocate(pDevIns, offDelta);
    2040 
    2041 }
    2042 
    2043 static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    2044                                                        uint32_t *piInstance, uint32_t *piTarget)
     2016#undef SCSI_CONFIG_ACCESSOR_READONLY
     2017#undef SCSI_CONFIG_ACCESSOR
     2018#undef LOG_ACCESSOR
     2019#undef MATCH_SCSI_CONFIG
     2020}
     2021
     2022/**
     2023 * @callback_method_impl{FNVIRTIODEVCAPREAD}
     2024 */
     2025static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, void *pv, uint32_t cb)
     2026{
     2027    return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, pv, cb, false /*fRead*/);
     2028}
     2029
     2030/**
     2031 * @callback_method_impl{FNVIRTIODEVCAPWRITE}
     2032 */
     2033static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
     2034{
     2035    return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, (void *)pv, cb, true /*fWrite*/);
     2036}
     2037
     2038
     2039/*********************************************************************************************************************************
     2040*   Will move tomorrow.                                                                                                          *
     2041*********************************************************************************************************************************/
     2042
     2043/**
     2044 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation, Target level.}
     2045 */
     2046static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
     2047                                                         uint32_t *piInstance, uint32_t *piTarget)
    20452048{
    20462049    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
     
    20592062
    20602063/**
    2061  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    2062  */
    2063 static DECLCALLBACK(void *) virtioScsiTargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     2064 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Target level.}
     2065 */
     2066static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    20642067{
    20652068     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
     
    20722075
    20732076/**
    2074  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    2075  */
    2076 static DECLCALLBACK(void *) virtioScsiDeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     2077 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Device level.}
     2078 */
     2079static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    20772080{
    20782081    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
     
    20842087}
    20852088
    2086 /**
    2087  * Detach notification.
     2089
     2090/*********************************************************************************************************************************
     2091*   Device interface.                                                                                                            *
     2092*********************************************************************************************************************************/
     2093
     2094/**
     2095 * @interface_method_impl{PDMDEVREGR3,pfnDetach}
    20882096 *
    20892097 * One harddisk at one port has been unplugged.
    20902098 * The VM is suspended at this point.
    2091  *
    2092  * @param   pDevIns     The device instance.
    2093  * @param   iTarget        The logical unit which is being detached.
    2094  * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    2095  */
    2096 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
    2097 {
    2098     RT_NOREF(fFlags);
     2099 */
     2100static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
     2101{
    20992102    PVIRTIOSCSI       pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
    21002103    PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[iTarget];
     
    21042107    AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
    21052108              ("virtio-scsi: Device does not support hotplugging\n"));
     2109    RT_NOREF(fFlags);
    21062110
    21072111    /*
     
    21132117
    21142118/**
    2115  * Attach command.
     2119 * @interface_method_impl{PDMDEVREGR3,pfnAttach}
    21162120 *
    21172121 * This is called when we change block driver.
    2118  *
    2119  * @returns VBox status code.
    2120  * @param   pDevIns     The device instance.
    2121  * @param   iTarget        The logical unit which is being detached.
    2122  * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    2123  */
    2124 static DECLCALLBACK(int)  virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
     2122 */
     2123static DECLCALLBACK(int) virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
    21252124{
    21262125    PVIRTIOSCSI       pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     
    21592158}
    21602159
    2161 static DECLCALLBACK(int) virtioScsiDestruct(PPDMDEVINS pDevIns)
     2160/**
     2161 * @interface_method_impl{PDMDEVREGR3,pfnDestruct}
     2162 */
     2163static DECLCALLBACK(int) virtioScsiR3Destruct(PPDMDEVINS pDevIns)
    21622164{
    21632165    /*
     
    21712173    RTMemFree(pThis->paTargetInstances);
    21722174    pThis->paTargetInstances = NULL;
    2173     for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    2174     {
    2175         PWORKER pWorker = &pThis->aWorker[qIdx];
     2175    for (unsigned qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     2176    {
     2177        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
    21762178        if (pWorker->hEvtProcess != NIL_SUPSEMEVENT)
    21772179        {
     
    21832185}
    21842186
    2185 static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg){
    2186 
     2187/**
     2188 * @interface_method_impl{PDMDEVREGR3,pfnConstruct}
     2189 */
     2190static DECLCALLBACK(int) virtioScsiR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
     2191{
    21872192    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    21882193
     
    22432248    pVirtioPciParams->uInterruptPin  = 0x01;
    22442249
    2245     pThis->IBase.pfnQueryInterface = virtioScsiDeviceQueryInterface;
     2250    pThis->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
    22462251
    22472252    /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */
     
    22592264    rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
    22602265                         VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED,
    2261                          virtioScsiDevCapRead,
    2262                          virtioScsiDevCapWrite,
    2263                          virtioScsiStatusChanged,
    2264                          virtioScsiNotified,
    2265                          virtioScsiLiveExec,
    2266                          virtioScsiSaveExec,
    2267                          virtioScsiLoadExec,
    2268                          virtioScsiLoadDone,
     2266                         virtioScsiR3DevCapRead,
     2267                         virtioScsiR3DevCapWrite,
     2268                         virtioScsiR3StatusChanged,
     2269                         virtioScsiR3Notified,
     2270                         virtioScsiR3LiveExec,
     2271                         virtioScsiR3SaveExec,
     2272                         virtioScsiR3LoadExec,
     2273                         virtioScsiR3LoadDone,
    22692274                         sizeof(VIRTIOSCSI_CONFIG_T) /* cbDevSpecificCap */,
    22702275                         (void *)&pThis->virtioScsiConfig /* pDevSpecificCap */);
     
    22732278        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
    22742279
    2275     RTStrCopy((char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
    2276     RTStrCopy((char *)pThis->szQueueNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
     2280    RTStrCopy(pThis->aszQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
     2281    RTStrCopy(pThis->aszQueueNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
    22772282    for (uint16_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
    2278         RTStrPrintf((char *)pThis->szQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,
    2279             "requestq<%d>", qIdx - VIRTQ_REQ_BASE);
     2283        RTStrPrintf(pThis->aszQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,
     2284                    "requestq<%d>", qIdx - VIRTQ_REQ_BASE);
    22802285
    22812286    for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
    22822287    {
    22832288        rc = virtioQueueAttach(pThis->hVirtio, qIdx, QUEUENAME(qIdx));
    2284         pThis->fQueueAttached[qIdx] = (rc == VINF_SUCCESS);
     2289        pThis->afQueueAttached[qIdx] = (rc == VINF_SUCCESS);
    22852290
    22862291        if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
    22872292        {
    2288             rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorker[qIdx].pThread,
    2289                                        (void *)(uint64_t)qIdx, virtioScsiWorker,
    2290                                        virtioScsiWorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
     2293            rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorkers[qIdx].pThread,
     2294                                       (void *)(uintptr_t)qIdx, virtioScsiR3WorkerThread,
     2295                                       virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
    22912296            if (rc != VINF_SUCCESS)
    22922297            {
    2293                 LogRel(("Error creating thread for Virtual Queue %s\n", QUEUENAME(qIdx)));
     2298                LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", QUEUENAME(qIdx), rc));
    22942299                return rc;
    22952300            }
    22962301
    2297             rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorker[qIdx].hEvtProcess);
     2302            rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorkers[qIdx].hEvtProcess);
    22982303            if (RT_FAILURE(rc))
    22992304                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
    2300                                      N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
     2305                                           N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
    23012306         }
    23022307    }
     
    23062311    Log2Func(("Found %d targets attached to controller\n", pThis->cTargets));
    23072312
    2308      pThis->paTargetInstances = (PVIRTIOSCSITARGET)RTMemAllocZ(sizeof(VIRTIOSCSITARGET) * pThis->cTargets);
    2309      if (!pThis->paTargetInstances)
    2310           return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate memory for target states"));
     2313    pThis->paTargetInstances = (PVIRTIOSCSITARGET)RTMemAllocZ(sizeof(VIRTIOSCSITARGET) * pThis->cTargets);
     2314    if (!pThis->paTargetInstances)
     2315        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate memory for target states"));
    23112316
    23122317    for (RTUINT iTarget = 0; iTarget < pThis->cTargets; iTarget++)
     
    23222327        pTarget->led.u32Magic = PDMLED_MAGIC;
    23232328
    2324         pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
     2329        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
    23252330
    23262331        /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
    2327         pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiQueryDeviceLocation;
    2328         pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiIoReqFinish;
    2329         pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiIoReqCopyFromBuf;
    2330         pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiIoReqCopyToBuf;
    2331         pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiIoReqStateChanged;
    2332         pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiMediumEjected;
     2332        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
     2333        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiR3IoReqFinish;
     2334        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiR3IoReqCopyFromBuf;
     2335        pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiR3IoReqCopyToBuf;
     2336        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
     2337        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
    23332338        pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL; /* When used avoids copyFromBuf CopyToBuf*/
    23342339        pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
    23352340
    23362341
    2337         pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
    2338         pTarget->ILed.pfnQueryStatusLed                  = virtioScsiTargetQueryStatusLed;
    2339         pThis->ILeds.pfnQueryStatusLed                   = virtioScsiDeviceQueryStatusLed;
     2342        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
     2343        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3TargetQueryStatusLed;
     2344        pThis->ILeds.pfnQueryStatusLed                   = virtioScsiR3DeviceQueryStatusLed;
    23402345        pTarget->led.u32Magic                            = PDMLED_MAGIC;
    23412346
     
    23502355            pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA);
    23512356            AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
    2352                          ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget),
    2353                          VERR_PDM_MISSING_INTERFACE);
     2357                            ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget),
     2358                            VERR_PDM_MISSING_INTERFACE);
    23542359
    23552360            /* Get the extended media interface. */
    23562361            pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX);
    23572362            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    2358                          ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget),
    2359                          VERR_PDM_MISSING_INTERFACE);
     2363                            ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget),
     2364                            VERR_PDM_MISSING_INTERFACE);
    23602365
    23612366            rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(VIRTIOSCSIREQ));
    23622367            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    2363                          ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget),
    2364                          rc);
     2368                            ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget),
     2369                            rc);
    23652370
    23662371            pTarget->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIANOTIFY);
    23672372            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    2368                          ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n",
    2369                           iTarget), rc);
     2373                            ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n", iTarget),
     2374                            VERR_PDM_MISSING_INTERFACE);
    23702375
    23712376        }
     
    23742379            pTarget->fPresent = false;
    23752380            pTarget->pDrvBase = NULL;
     2381            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));
    23762382            rc = VINF_SUCCESS;
    2377             Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));
    23782383        }
    23792384        else
     
    23952400    char szTmp[128];
    23962401    RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
    2397     PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiInfo);
     2402    PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info);
    23982403
    23992404    return rc;
     
    24302435    /* .pszRCMod = */               "VBoxDDRC.rc",
    24312436    /* .pszR0Mod = */               "VBoxDDR0.r0",
    2432     /* .pfnConstruct = */           virtioScsiConstruct,
    2433     /* .pfnDestruct = */            virtioScsiDestruct,
    2434     /* .pfnRelocate = */            virtioScsiRelocate,
     2437    /* .pfnConstruct = */           virtioScsiR3Construct,
     2438    /* .pfnDestruct = */            virtioScsiR3Destruct,
     2439    /* .pfnRelocate = */            NULL,
    24352440    /* .pfnMemSetup = */            NULL,
    24362441    /* .pfnPowerOn = */             NULL,
    2437     /* .pfnReset = */               virtioScsiReset,
    2438     /* .pfnSuspend = */             virtioScsiSuspendOrPoweroff,
    2439     /* .pfnResume = */              virtioScsiResume,
    2440     /* .pfnAttach = */              virtioScsiAttach,
    2441     /* .pfnDetach = */              virtioScsiDetach,
     2442    /* .pfnReset = */               virtioScsiR3Reset,
     2443    /* .pfnSuspend = */             virtioScsiR3SuspendOrPowerOff,
     2444    /* .pfnResume = */              virtioScsiR3Resume,
     2445    /* .pfnAttach = */              virtioScsiR3Attach,
     2446    /* .pfnDetach = */              virtioScsiR3Detach,
    24422447    /* .pfnQueryInterface = */      NULL,
    24432448    /* .pfnInitComplete = */        NULL,
    2444     /* .pfnPowerOff = */            virtioScsiSuspendOrPoweroff,
     2449    /* .pfnPowerOff = */            virtioScsiR3SuspendOrPowerOff,
    24452450    /* .pfnSoftReset = */           NULL,
    24462451    /* .pfnReserved0 = */           NULL,
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r81630 r81634  
    385385    }
    386386}
    387 
    388 /**
    389  * NOTE: The consumer (PDM device) must call this function to 'forward' a relocation call.
    390  *
    391  * Device relocation callback.
    392  *
    393  * When this callback is called the device instance data, and if the
    394  * device have a GC component, is being relocated, or/and the selectors
    395  * have been changed. The device must use the chance to perform the
    396  * necessary pointer relocations and data updates.
    397  *
    398  * Before the GC code is executed the first time, this function will be
    399  * called with a 0 delta so GC pointer calculations can be one in one place.
    400  *
    401  * @param   pDevIns     Pointer to the device instance.
    402  * @param   offDelta    The relocation delta relative to the old location.
    403  *
    404  * @remark  A relocation CANNOT fail.
    405  */
    406 void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    407 {
    408     RT_NOREF(offDelta);
    409     PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
    410     LogFunc(("\n"));
    411 
    412     pVirtio->pDevInsR3 = pDevIns;
    413     pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    414     pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    415 }
    416 
    417387
    418388/**
     
    10581028
    10591029    pVirtio->pDevInsR3 = pDevIns;
    1060     pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    1061     pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    10621030    pVirtio->uDeviceStatus = 0;
    10631031    pVirtio->cbDevSpecificCfg = cbDevSpecificCfg;
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r81630 r81634  
    132132 * @param   cbRead      Number of bytes to read
    133133 */
    134 typedef DECLCALLBACK(int)   FNVIRTIODEVCAPREAD(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbRead);
     134typedef DECLCALLBACK(int)   FNVIRTIODEVCAPREAD(PPDMDEVINS pDevIns, uint32_t uOffset, void *pvBuf, uint32_t cbRead);
    135135typedef FNVIRTIODEVCAPREAD *PFNVIRTIODEVCAPREAD;
    136136
     
    140140typedef struct VIRTIOCALLBACKS
    141141{
    142      DECLCALLBACKMEMBER(void, pfnVirtioStatusChanged)
    143                                   (VIRTIOHANDLE hVirtio, void *pClient, uint32_t fDriverOk);
    144      DECLCALLBACKMEMBER(void, pfnVirtioQueueNotified)
    145                                   (VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx);
    146      DECLCALLBACKMEMBER(int,  pfnVirtioDevCapRead)
    147                                   (PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbRead);
    148      DECLCALLBACKMEMBER(int,  pfnVirtioDevCapWrite)
    149                                   (PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbWrite);
    150      DECLCALLBACKMEMBER(int,  pfnSSMDevLiveExec)
    151                                   (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
    152      DECLCALLBACKMEMBER(int,  pfnSSMDevSaveExec)
    153                                   (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
    154      DECLCALLBACKMEMBER(int,  pfnSSMDevLoadExec)
    155                                   (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
    156      DECLCALLBACKMEMBER(int,  pfnSSMDevLoadDone)
    157                                   (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
    158 
     142     DECLCALLBACKMEMBER(void, pfnVirtioStatusChanged)(VIRTIOHANDLE hVirtio, void *pClient, uint32_t fDriverOk);
     143     DECLCALLBACKMEMBER(void, pfnVirtioQueueNotified)(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx);
     144     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapRead)(PPDMDEVINS pDevIns, uint32_t uOffset, void *pvBuf, uint32_t cbRead);
     145     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapWrite)(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbWrite);
     146     DECLCALLBACKMEMBER(int,  pfnSSMDevLiveExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
     147     DECLCALLBACKMEMBER(int,  pfnSSMDevSaveExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
     148     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
     149     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadDone)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
    159150} VIRTIOCALLBACKS, *PVIRTIOCALLBACKS;
    160151/** @} */
     
    319310 */
    320311uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);
    321 
    322 /** CLIENT MUST CALL ON RELOCATE CALLBACK! */
    323 void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
    324312
    325313/**
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h

    r81630 r81634  
    127127    struct virtio_pci_cap pciCap;                                /**< Notification MMIO mapping capability      */
    128128    uint32_t uNotifyOffMultiplier;                               /**< notify_off_multiplier                     */
    129 }  VIRTIO_PCI_NOTIFY_CAP_T,  *PVIRTIO_PCI_NOTIFY_CAP_T;
     129} VIRTIO_PCI_NOTIFY_CAP_T, *PVIRTIO_PCI_NOTIFY_CAP_T;
    130130
    131131typedef struct virtio_pci_cfg_cap
     
    133133    struct virtio_pci_cap pciCap;                                /**< Cap. defines the BAR/off/len to access    */
    134134    uint8_t uPciCfgData[4];                                      /**< I/O buf for above cap.                    */
    135 } VIRTIO_PCI_CFG_CAP_T,   *PVIRTIO_PCI_CFG_CAP_T;
     135} VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T;
    136136
    137137/**
     
    142142typedef struct VIRTIOSTATE
    143143{
    144     char                      szInstance[16];                    /**< Instance name, e.g. "VIRTIOSCSI0"         */
    145     void *                    pClientContext;                    /**< Client callback returned on callbacks     */
    146 
    147     PPDMDEVINSR3              pDevInsR3;                         /**< Device instance - R3                      */
    148     PPDMDEVINSR0              pDevInsR0;                         /**< Device instance - R0                      */
    149     PPDMDEVINSRC              pDevInsRC;                         /**< Device instance - RC                      */
    150 
    151     RTGCPHYS                  pGcPhysPciCapBase;                 /**< Pointer to MMIO mapped capability data    */
    152     RTGCPHYS                  pGcPhysCommonCfg;                  /**< Pointer to MMIO mapped capability data    */
    153     RTGCPHYS                  pGcPhysNotifyCap;                  /**< Pointer to MMIO mapped capability data    */
    154     RTGCPHYS                  pGcPhysIsrCap;                     /**< Pointer to MMIO mapped capability data    */
    155     RTGCPHYS                  pGcPhysDeviceCap;                  /**< Pointer to MMIO mapped capability data    */
    156 
    157     RTGCPHYS                  pGcPhysQueueDesc[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
    158     RTGCPHYS                  pGcPhysQueueAvail[VIRTQ_MAX_CNT];  /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
    159     RTGCPHYS                  pGcPhysQueueUsed[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q used structs   GUEST */
    160     uint16_t                  uQueueNotifyOff[VIRTQ_MAX_CNT];    /**< (MMIO) per-Q notify offset           HOST */
    161     uint16_t                  uQueueMsixVector[VIRTQ_MAX_CNT];   /**< (MMIO) Per-queue vector for MSI-X   GUEST */
    162     uint16_t                  uQueueEnable[VIRTQ_MAX_CNT];       /**< (MMIO) Per-queue enable             GUEST */
    163     uint16_t                  uQueueSize[VIRTQ_MAX_CNT];         /**< (MMIO) Per-queue size          HOST/GUEST */
    164     uint16_t                  uQueueSelect;                      /**< (MMIO) queue selector               GUEST */
    165     uint16_t                  padding;
    166     uint64_t                  uDeviceFeatures;                   /**< (MMIO) Host features offered         HOST */
    167     uint64_t                  uDriverFeatures;                   /**< (MMIO) Host features accepted       GUEST */
    168     uint32_t                  uDeviceFeaturesSelect;             /**< (MMIO) hi/lo select uDeviceFeatures GUEST */
    169     uint32_t                  uDriverFeaturesSelect;             /**< (MMIO) hi/lo select uDriverFeatures GUEST */
    170     uint32_t                  uMsixConfig;                       /**< (MMIO) MSI-X vector                 GUEST */
    171     uint32_t                  uNumQueues;                        /**< (MMIO) Actual number of queues      GUEST */
    172     uint8_t                   uDeviceStatus;                     /**< (MMIO) Device Status                GUEST */
    173     uint8_t                   uPrevDeviceStatus;                 /**< (MMIO) Prev Device Status           GUEST */
    174     uint8_t                   uConfigGeneration;                 /**< (MMIO) Device config sequencer       HOST */
    175 
    176     VIRTQSTATE                virtqState[VIRTQ_MAX_CNT];         /**< Local impl-specific queue context         */
    177     VIRTIOCALLBACKS           virtioCallbacks;                   /**< Callback vectors to client                */
    178 
    179     PVIRTIO_PCI_CFG_CAP_T     pPciCfgCap;                        /**< Pointer to struct in configuration area   */
    180     PVIRTIO_PCI_NOTIFY_CAP_T  pNotifyCap;                        /**< Pointer to struct in configuration area   */
    181     PVIRTIO_PCI_CAP_T         pCommonCfgCap;                     /**< Pointer to struct in configuration area   */
    182     PVIRTIO_PCI_CAP_T         pIsrCap;                           /**< Pointer to struct in configuration area   */
    183     PVIRTIO_PCI_CAP_T         pDeviceCap;                        /**< Pointer to struct in configuration area   */
    184 
    185     uint32_t                  cbDevSpecificCfg;                  /**< Size of client's dev-specific config data */
    186     void                     *pDevSpecificCfg;                   /**< Pointer to client's struct                */
    187     void                     *pPrevDevSpecificCfg;               /**< Previous read dev-specific cfg of client  */
    188     bool                      fGenUpdatePending;                 /**< If set, update cfg gen after driver reads */
    189     uint8_t                   uPciCfgDataOff;
    190     uint8_t                   uISR;                              /**< Interrupt Status Register.                */
    191     uint8_t                   fMsiSupport;
     144    char                        szInstance[16];                     /**< Instance name, e.g. "VIRTIOSCSI0"         */
     145    R3PTRTYPE(void *)           pClientContext;                     /**< Client callback returned on callbacks     */
     146
     147    PPDMDEVINSR3                pDevInsR3;                          /**< Device instance - R3                      */
     148
     149    RTGCPHYS                    pGcPhysPciCapBase;                  /**< Pointer to MMIO mapped capability data    */
     150    RTGCPHYS                    pGcPhysCommonCfg;                   /**< Pointer to MMIO mapped capability data    */
     151    RTGCPHYS                    pGcPhysNotifyCap;                   /**< Pointer to MMIO mapped capability data    */
     152    RTGCPHYS                    pGcPhysIsrCap;                      /**< Pointer to MMIO mapped capability data    */
     153    RTGCPHYS                    pGcPhysDeviceCap;                   /**< Pointer to MMIO mapped capability data    */
     154
     155    RTGCPHYS                    pGcPhysQueueDesc[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
     156    RTGCPHYS                    pGcPhysQueueAvail[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
     157    RTGCPHYS                    pGcPhysQueueUsed[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q used structs   GUEST */
     158    uint16_t                    uQueueNotifyOff[VIRTQ_MAX_CNT];     /**< (MMIO) per-Q notify offset           HOST */
     159    uint16_t                    uQueueMsixVector[VIRTQ_MAX_CNT];    /**< (MMIO) Per-queue vector for MSI-X   GUEST */
     160    uint16_t                    uQueueEnable[VIRTQ_MAX_CNT];        /**< (MMIO) Per-queue enable             GUEST */
     161    uint16_t                    uQueueSize[VIRTQ_MAX_CNT];          /**< (MMIO) Per-queue size          HOST/GUEST */
     162    uint16_t                    uQueueSelect;                       /**< (MMIO) queue selector               GUEST */
     163    uint16_t                    padding;
     164    uint64_t                    uDeviceFeatures;                    /**< (MMIO) Host features offered         HOST */
     165    uint64_t                    uDriverFeatures;                    /**< (MMIO) Host features accepted       GUEST */
     166    uint32_t                    uDeviceFeaturesSelect;              /**< (MMIO) hi/lo select uDeviceFeatures GUEST */
     167    uint32_t                    uDriverFeaturesSelect;              /**< (MMIO) hi/lo select uDriverFeatures GUEST */
     168    uint32_t                    uMsixConfig;                        /**< (MMIO) MSI-X vector                 GUEST */
     169    uint32_t                    uNumQueues;                         /**< (MMIO) Actual number of queues      GUEST */
     170    uint8_t                     uDeviceStatus;                      /**< (MMIO) Device Status                GUEST */
     171    uint8_t                     uPrevDeviceStatus;                  /**< (MMIO) Prev Device Status           GUEST */
     172    uint8_t                     uConfigGeneration;                  /**< (MMIO) Device config sequencer       HOST */
     173
     174    VIRTQSTATE                  virtqState[VIRTQ_MAX_CNT];          /**< Local impl-specific queue context         */
     175    VIRTIOCALLBACKS             virtioCallbacks;                    /**< Callback vectors to client                */
     176
     177    PVIRTIO_PCI_CFG_CAP_T       pPciCfgCap;                         /**< Pointer to struct in configuration area   */
     178    PVIRTIO_PCI_NOTIFY_CAP_T    pNotifyCap;                         /**< Pointer to struct in configuration area   */
     179    PVIRTIO_PCI_CAP_T           pCommonCfgCap;                      /**< Pointer to struct in configuration area   */
     180    PVIRTIO_PCI_CAP_T           pIsrCap;                            /**< Pointer to struct in configuration area   */
     181    PVIRTIO_PCI_CAP_T           pDeviceCap;                         /**< Pointer to struct in configuration area   */
     182
     183    uint32_t                    cbDevSpecificCfg;                   /**< Size of client's dev-specific config data */
     184    void                       *pDevSpecificCfg;                    /**< Pointer to client's struct                */
     185    void                       *pPrevDevSpecificCfg;                /**< Previous read dev-specific cfg of client  */
     186    bool                        fGenUpdatePending;                  /**< If set, update cfg gen after driver reads */
     187    uint8_t                     uPciCfgDataOff;
     188    uint8_t                     uISR;                               /**< Interrupt Status Register.                */
     189    uint8_t                     fMsiSupport;
    192190
    193191} VIRTIOSTATE, *PVIRTIOSTATE;
Note: See TracChangeset for help on using the changeset viewer.

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