Index: /trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp	(revision 81633)
+++ /trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp	(revision 81634)
@@ -3,4 +3,10 @@
  * VBox storage devices - Virtio SCSI Driver
  *
+ * Log-levels used:
+ *    - Level 1:   The most important (but usually rare) things to note
+ *    - Level 2:   SCSI command logging
+ *    - Level 3:   Vector and I/O transfer summary (shows what client sent an expects and fulfillment)
+ *    - Level 6:   Device ⟷ Guest Driver negotation, traffic, notifications and state handling
+ *    - Level 12:  Brief formatted hex dumps of I/O data
  */
 
@@ -49,46 +55,36 @@
 #include "VBoxDD.h"
 
-/*
- * RT log-levels used:
- *
- *    Level 1:   The most important (but usually rare) things to note
- *    Level 2:   SCSI command logging
- *    Level 3:   Vector and I/O transfer summary (shows what client sent an expects and fulfillment)
- *    Level 6:   Device ⟷ Guest Driver negotation, traffic, notifications and state handling
- *    Level 12:  Brief formatted hex dumps of I/O data
- */
 
 #define LUN0    0
 /** @name VirtIO 1.0 SCSI Host feature bits (See VirtIO 1.0 specification, Section 5.6.3)
  * @{  */
-#define VIRTIO_SCSI_F_INOUT                RT_BIT_64(0)           /** Request is device readable AND writeable         */
-#define VIRTIO_SCSI_F_HOTPLUG              RT_BIT_64(1)           /** Host allows hotplugging SCSI LUNs & targets      */
-#define VIRTIO_SCSI_F_CHANGE               RT_BIT_64(2)           /** Host LUNs chgs via VIRTIOSCSI_T_PARAM_CHANGE evt */
-#define VIRTIO_SCSI_F_T10_PI               RT_BIT_64(3)           /** Add T10 port info (DIF/DIX) in SCSI req hdr      */
+#define VIRTIO_SCSI_F_INOUT                RT_BIT_64(0)         /** Request is device readable AND writeable         */
+#define VIRTIO_SCSI_F_HOTPLUG              RT_BIT_64(1)         /** Host allows hotplugging SCSI LUNs & targets      */
+#define VIRTIO_SCSI_F_CHANGE               RT_BIT_64(2)         /** Host LUNs chgs via VIRTIOSCSI_T_PARAM_CHANGE evt */
+#define VIRTIO_SCSI_F_T10_PI               RT_BIT_64(3)         /** Add T10 port info (DIF/DIX) in SCSI req hdr      */
 /** @} */
 
 
 #define VIRTIOSCSI_HOST_SCSI_FEATURES_ALL \
-            (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG | VIRTIO_SCSI_F_CHANGE | VIRTIO_SCSI_F_T10_PI)
+    (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG | VIRTIO_SCSI_F_CHANGE | VIRTIO_SCSI_F_T10_PI)
 
 #define VIRTIOSCSI_HOST_SCSI_FEATURES_NONE          0
 
-#define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED \
-             VIRTIOSCSI_HOST_SCSI_FEATURES_NONE
-
-#define VIRTIOSCSI_REQ_QUEUE_CNT                    1            /**< T.B.D. Consider increasing                      */
+#define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED       VIRTIOSCSI_HOST_SCSI_FEATURES_NONE
+
+#define VIRTIOSCSI_REQ_QUEUE_CNT                    1           /**< T.B.D. Consider increasing                      */
 #define VIRTIOSCSI_QUEUE_CNT                        VIRTIOSCSI_REQ_QUEUE_CNT + 2
-#define VIRTIOSCSI_MAX_LUN                          256          /* < VirtIO specification, section 5.6.4             */
-#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             128          /* < T.B.D. What is a good value for this?           */
-#define VIRTIOSCSI_MAX_SEG_COUNT                    126          /* < T.B.D. What is a good value for this?           */
-#define VIRTIOSCSI_MAX_SECTORS_HINT                 0x10000      /* < VirtIO specification, section 5.6.4             */
-#define VIRTIOSCSI_MAX_CHANNEL_HINT                 0            /* < VirtIO specification, section 5.6.4 should be 0 */
-#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01         /**< SSM version #                                   */
-
-#define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048       /**< Informs guest driver of type of VirtIO device   */
-#define PCI_CLASS_BASE_MASS_STORAGE                 0x01         /**< PCI Mass Storage device class                   */
-#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00         /**< PCI SCSI Controller subclass                    */
-#define PCI_CLASS_PROG_UNSPECIFIED                  0x00         /**< Programming interface. N/A.                     */
-#define VIRTIOSCSI_PCI_CLASS                        0x01         /**< Base class Mass Storage?                        */
+#define VIRTIOSCSI_MAX_LUN                          256         /**< VirtIO specification, section 5.6.4             */
+#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             128         /**< T.B.D. What is a good value for this?           */
+#define VIRTIOSCSI_MAX_SEG_COUNT                    126         /**< T.B.D. What is a good value for this?           */
+#define VIRTIOSCSI_MAX_SECTORS_HINT                 0x10000     /**< VirtIO specification, section 5.6.4             */
+#define VIRTIOSCSI_MAX_CHANNEL_HINT                 0           /**< VirtIO specification, section 5.6.4 should be 0 */
+#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01        /**< SSM version #                                   */
+
+#define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048      /**< Informs guest driver of type of VirtIO device   */
+#define PCI_CLASS_BASE_MASS_STORAGE                 0x01        /**< PCI Mass Storage device class                   */
+#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00        /**< PCI SCSI Controller subclass                    */
+#define PCI_CLASS_PROG_UNSPECIFIED                  0x00        /**< Programming interface. N/A.                     */
+#define VIRTIOSCSI_PCI_CLASS                        0x01        /**< Base class Mass Storage?                        */
 
 #define VIRTIOSCSI_SENSE_SIZE_DEFAULT               96          /**< VirtIO 1.0: 96 on reset, guest can change       */
@@ -102,63 +98,19 @@
  * (Note: # of request queues is determined by virtio_scsi_config.num_queues. VirtIO 1.0, 5.6.4)
  */
-#define CONTROLQ_IDX                                0            /**< Spec-defined Index of control queue             */
-#define EVENTQ_IDX                                  1            /**< Spec-defined Index of event queue               */
-#define VIRTQ_REQ_BASE                              2            /**< Spec-defined base index of request queues       */
-
-#define QUEUENAME(qIdx) (pThis->szQueueNames[qIdx])              /**< Macro to get queue name from its index          */
+#define CONTROLQ_IDX                                0           /**< Spec-defined Index of control queue             */
+#define EVENTQ_IDX                                  1           /**< Spec-defined Index of event queue               */
+#define VIRTQ_REQ_BASE                              2           /**< Spec-defined base index of request queues       */
+
+#define QUEUENAME(qIdx) (pThis->aszQueueNames[qIdx])            /**< Macro to get queue name from its index          */
 #define CBQUEUENAME(qIdx) RTStrNLen(QUEUENAME(qIdx), sizeof(QUEUENAME(qIdx)))
 
 #define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT)
 
-/**
- * Resolves to boolean true if uOffset matches a field offset and size exactly,
- * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
- * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
- * (Easily re-written to allow unaligned bounded access to a field).
- *
- * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
- * @result           - true or false
- */
-#define MATCH_SCSI_CONFIG(member) \
-            (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
-             && (   uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
-                 || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
-             && cb == sizeof(uint32_t)) \
-         || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
-               && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member))
-
-#define LOG_ACCESSOR(member) \
-        virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
-            pv, cb, uIntraOffset, fWrite, false, 0);
-
-#define SCSI_CONFIG_ACCESSOR(member) \
-    do \
-    { \
-        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
-        if (fWrite) \
-            memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \
-        else \
-            memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
-        LOG_ACCESSOR(member); \
-    } while(0)
-
-#define SCSI_CONFIG_ACCESSOR_READONLY(member) \
-    do \
-    { \
-        uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
-        if (fWrite) \
-            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
-        else \
-        { \
-            memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \
-            LOG_ACCESSOR(member); \
-        } \
-    } while(0)
-
-#define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \
-            pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE
-
-#define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \
-            pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE
+#define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \
+    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE)
+
+#define VIRTIO_IS_OUT_DIRECTION(pMediaExTxDirEnumValue) \
+    ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE)
+
 /**
  * VirtIO SCSI Host Device device-specific configuration (see VirtIO 1.0, section 5.6.4)
@@ -168,14 +120,14 @@
 typedef struct virtio_scsi_config
 {
-    uint32_t uNumQueues;                                         /**< num_queues       # of req q's exposed by dev    */
-    uint32_t uSegMax;                                            /**< seg_max          Max # of segs allowed in cmd   */
-    uint32_t uMaxSectors;                                        /**< max_sectors      Hint to guest max xfer to use  */
-    uint32_t uCmdPerLun;                                         /**< cmd_per_lun      Max # of link cmd sent per lun */
-    uint32_t uEventInfoSize;                                     /**< event_info_size  Fill max, evtq bufs            */
-    uint32_t uSenseSize;                                         /**< sense_size       Max sense data size dev writes */
-    uint32_t uCdbSize;                                           /**< cdb_size         Max CDB size driver writes     */
-    uint16_t uMaxChannel;                                        /**< max_channel      Hint to guest driver           */
-    uint16_t uMaxTarget;                                         /**< max_target       Hint to guest driver           */
-    uint32_t uMaxLun;                                            /**< max_lun          Hint to guest driver           */
+    uint32_t uNumQueues;                                        /**< num_queues       \# of req q's exposed by dev   */
+    uint32_t uSegMax;                                           /**< seg_max          Max \# of segs allowed in cmd  */
+    uint32_t uMaxSectors;                                       /**< max_sectors      Hint to guest max xfer to use  */
+    uint32_t uCmdPerLun;                                        /**< cmd_per_lun      Max \# of link cmd sent per lun */
+    uint32_t uEventInfoSize;                                    /**< event_info_size  Fill max, evtq bufs            */
+    uint32_t uSenseSize;                                        /**< sense_size       Max sense data size dev writes */
+    uint32_t uCdbSize;                                          /**< cdb_size         Max CDB size driver writes     */
+    uint16_t uMaxChannel;                                       /**< max_channel      Hint to guest driver           */
+    uint16_t uMaxTarget;                                        /**< max_target       Hint to guest driver           */
+    uint32_t uMaxLun;                                           /**< max_lun          Hint to guest driver           */
 } VIRTIOSCSI_CONFIG_T, PVIRTIOSCSI_CONFIG_T;
 
@@ -191,9 +143,10 @@
  * Device operation: eventq
  */
-#define VIRTIOSCSI_T_EVENTS_MISSED             0x80000000
-typedef struct virtio_scsi_event {
+#define VIRTIOSCSI_T_EVENTS_MISSED                  UINT32_C(0x80000000)
+typedef struct virtio_scsi_event
+{
     // Device-writable part
     uint32_t uEvent;                                            /**< event:                                          */
-    uint8_t  uVirtioLun[8];                                     /**< lun                                             */
+    uint8_t  abVirtioLun[8];                                    /**< lun                                             */
     uint32_t uReason;                                           /**< reason                                          */
 } VIRTIOSCSI_EVENT_T, *PVIRTIOSCSI_EVENT_T;
@@ -207,75 +160,82 @@
 
 
+
+/**
+ * Device operation: reqestq
+ */
 #pragma pack(1)
-
-/**
- * Device operation: reqestq
- */
-struct REQ_CMD_HDR
-{
-    uint8_t  uVirtioLun[8];                                     /**< lun                                          */
+typedef struct REQ_CMD_HDR_T
+{
+    uint8_t  abVirtioLun[8];                                    /**< lun                                          */
     uint64_t uId;                                               /**< id                                           */
     uint8_t  uTaskAttr;                                         /**< task_attr                                    */
     uint8_t  uPrio;                                             /**< prio                                         */
     uint8_t  uCrn;                                              /**< crn                                          */
-};
-
-struct REQ_CMD_PI
+} REQ_CMD_HDR_T;
+#pragma pack()
+AssertCompileSize(REQ_CMD_HDR_T, 19);
+
+typedef struct REQ_CMD_PI_T
 {
     uint32_t uPiBytesOut;                                       /**< pi_bytesout                                  */
     uint32_t uPiBytesIn;                                        /**< pi_bytesin                                   */
-};
-
-struct REQ_RESP_HDR
-{
-    uint32_t uSenseLen;                                         /**< sense_len                                    */
+} REQ_CMD_PI_T;
+AssertCompileSize(REQ_CMD_PI_T, 8);
+
+typedef struct REQ_RESP_HDR_T
+{
+    uint32_t cbSenseLen;                                        /**< sense_len                                    */
     uint32_t uResidual;                                         /**< residual                                     */
     uint16_t uStatusQualifier;                                  /**< status_qualifier                             */
     uint8_t  uStatus;                                           /**< status            SCSI status code           */
     uint8_t  uResponse;                                         /**< response                                     */
-};
-
-typedef struct virtio_scsi_req_cmd
-{
-    /* Device-readable section */
-
-    struct REQ_CMD_HDR  ReqHdr;
+} REQ_RESP_HDR_T;
+AssertCompileSize(REQ_RESP_HDR_T, 12);
+
+#pragma pack(1)
+typedef struct VIRTIOSCSI_REQ_CMD_T
+{
+    /** Device-readable section
+     * @{ */
+    REQ_CMD_HDR_T  ReqHdr;
     uint8_t  uCdb[1];                                           /**< cdb                                          */
 
-    struct REQ_CMD_PI piHdr;                                    /** T10 Pi block integrity (optional feature)     */
+    REQ_CMD_PI_T piHdr;                                         /** T10 Pi block integrity (optional feature)     */
     uint8_t  uPiOut[1];                                         /**< pi_out[]          T10 pi block integrity     */
     uint8_t  uDataOut[1];                                       /**< dataout                                      */
-
-    /** Device writable section */
-
-    struct REQ_RESP_HDR  respHdr;
+    /** @} */
+
+    /** @name Device writable section
+     * @{ */
+    REQ_RESP_HDR_T respHdr;
     uint8_t  uSense[1];                                         /**< sense                                        */
     uint8_t  uPiIn[1];                                          /**< pi_in[]           T10 Pi block integrity     */
     uint8_t  uDataIn[1];                                        /**< detain;                                      */
-
-}  VIRTIOSCSI_REQ_CMD_T, *PVIRTIOSCSI_REQ_CMD_T;
+    /** @} */
+} VIRTIOSCSI_REQ_CMD_T, *PVIRTIOSCSI_REQ_CMD_T;
 #pragma pack()
+AssertCompileSize(VIRTIOSCSI_REQ_CMD_T, 19+8+12+6);
 
 /** @name VirtIO 1.0 SCSI Host Device Req command-specific response values
  * @{  */
-#define VIRTIOSCSI_S_OK                             0          /**< control, command                                 */
-#define VIRTIOSCSI_S_OVERRUN                        1          /**< control                                          */
-#define VIRTIOSCSI_S_ABORTED                        2          /**< control                                          */
-#define VIRTIOSCSI_S_BAD_TARGET                     3          /**< control, command                                 */
-#define VIRTIOSCSI_S_RESET                          4          /**< control                                          */
-#define VIRTIOSCSI_S_BUSY                           5          /**< control, command                                 */
-#define VIRTIOSCSI_S_TRANSPORT_FAILURE              6          /**< control, command                                 */
-#define VIRTIOSCSI_S_TARGET_FAILURE                 7          /**< control, command                                 */
-#define VIRTIOSCSI_S_NEXUS_FAILURE                  8          /**< control, command                                 */
-#define VIRTIOSCSI_S_FAILURE                        9          /**< control, command                                 */
-#define VIRTIOSCSI_S_INCORRECT_LUN                  12         /**< command                                          */
+#define VIRTIOSCSI_S_OK                             0           /**< control, command                                 */
+#define VIRTIOSCSI_S_OVERRUN                        1           /**< control                                          */
+#define VIRTIOSCSI_S_ABORTED                        2           /**< control                                          */
+#define VIRTIOSCSI_S_BAD_TARGET                     3           /**< control, command                                 */
+#define VIRTIOSCSI_S_RESET                          4           /**< control                                          */
+#define VIRTIOSCSI_S_BUSY                           5           /**< control, command                                 */
+#define VIRTIOSCSI_S_TRANSPORT_FAILURE              6           /**< control, command                                 */
+#define VIRTIOSCSI_S_TARGET_FAILURE                 7           /**< control, command                                 */
+#define VIRTIOSCSI_S_NEXUS_FAILURE                  8           /**< control, command                                 */
+#define VIRTIOSCSI_S_FAILURE                        9           /**< control, command                                 */
+#define VIRTIOSCSI_S_INCORRECT_LUN                  12          /**< command                                          */
 /** @} */
 
 /** @name VirtIO 1.0 SCSI Host Device command-specific task_attr values
  * @{  */
-#define VIRTIOSCSI_S_SIMPLE                        0           /**<                                                  */
-#define VIRTIOSCSI_S_ORDERED                       1           /**<                                                  */
-#define VIRTIOSCSI_S_HEAD                          2           /**<                                                  */
-#define VIRTIOSCSI_S_ACA                           3           /**<                                                  */
+#define VIRTIOSCSI_S_SIMPLE                         0           /**<                                                  */
+#define VIRTIOSCSI_S_ORDERED                        1           /**<                                                  */
+#define VIRTIOSCSI_S_HEAD                           2           /**<                                                  */
+#define VIRTIOSCSI_S_ACA                            3           /**<                                                  */
 /** @} */
 
@@ -283,5 +243,5 @@
  * VirtIO 1.0 SCSI Host Device Control command before we know type (5.6.6.2)
  */
-typedef struct virtio_scsi_ctrl
+typedef struct VIRTIOSCSI_CTRL_T
 {
     uint32_t uType;
@@ -290,86 +250,91 @@
 /** @name VirtIO 1.0 SCSI Host Device command-specific TMF values
  * @{  */
-#define VIRTIOSCSI_T_TMF                           0           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_ABORT_TASK                0           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_ABORT_TASK_SET            1           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_CLEAR_ACA                 2           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET            3           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET           4           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET        5           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_QUERY_TASK                6           /**<                                                  */
-#define VIRTIOSCSI_T_TMF_QUERY_TASK_SET            7           /**<                                                  */
+#define VIRTIOSCSI_T_TMF                            0           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_ABORT_TASK                 0           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_ABORT_TASK_SET             1           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_CLEAR_ACA                  2           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET             3           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET            4           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET         5           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_QUERY_TASK                 6           /**<                                                  */
+#define VIRTIOSCSI_T_TMF_QUERY_TASK_SET             7           /**<                                                  */
 /** @} */
 
 #pragma pack(1)
-typedef struct virtio_scsi_ctrl_tmf
+typedef struct VIRTIOSCSI_CTRL_TMF_T
 {
      // Device-readable part
-    uint32_t uType;                                            /** type                                              */
-    uint32_t uSubtype;                                         /** subtype                                           */
-    uint8_t  uScsiLun[8];                                      /** lun                                               */
-    uint64_t uId;                                              /** id                                                */
+    uint32_t uType;                                             /**< type                                             */
+    uint32_t uSubtype;                                          /**< subtype                                          */
+    uint8_t  abScsiLun[8];                                      /**< lun                                              */
+    uint64_t uId;                                               /**< id                                               */
     // Device-writable part
-    uint8_t  uResponse;                                        /** response                                          */
+    uint8_t  uResponse;                                         /**< response                                         */
 } VIRTIOSCSI_CTRL_TMF_T, *PVIRTIOSCSI_CTRL_TMF_T;
 #pragma pack()
+AssertCompileSize(VIRTIOSCSI_CTRL_TMF_T, 25);
 
 /** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values
  * @{  */
-#define VIRTIOSCSI_S_FUNCTION_COMPLETE            0           /**<                                                   */
-#define VIRTIOSCSI_S_FUNCTION_SUCCEEDED           10          /**<                                                   */
-#define VIRTIOSCSI_S_FUNCTION_REJECTED            11          /**<                                                   */
+#define VIRTIOSCSI_S_FUNCTION_COMPLETE              0           /**<                                                   */
+#define VIRTIOSCSI_S_FUNCTION_SUCCEEDED             10          /**<                                                   */
+#define VIRTIOSCSI_S_FUNCTION_REJECTED              11          /**<                                                   */
 /** @} */
 
-#define VIRTIOSCSI_T_AN_QUERY                     1           /** Asynchronous notification query                    */
-#define VIRTIOSCSI_T_AN_SUBSCRIBE                 2           /** Asynchronous notification subscription             */
+#define VIRTIOSCSI_T_AN_QUERY                       1           /**<Asynchronous notification query                    */
+#define VIRTIOSCSI_T_AN_SUBSCRIBE                   2           /**<Asynchronous notification subscription             */
 
 #pragma pack(1)
-typedef struct virtio_scsi_ctrl_an
+typedef struct VIRTIOSCSI_CTRL_AN_T
 {
     // Device-readable part
-    uint32_t  uType;                                          /** type                                               */
-    uint8_t   uScsiLun[8];                                    /** lun                                                */
-    uint32_t  uEventsRequested;                               /** event_requested                                    */
+    uint32_t  uType;                                            /**< type                                              */
+    uint8_t   abScsiLun[8];                                     /**< lun                                               */
+    uint32_t  fEventsRequested;                                 /**< event_requested                                   */
     // Device-writable part
-    uint32_t  uEventActual;                                   /** event_actual                                       */
-    uint8_t   uResponse;                                      /** response                                           */
+    uint32_t  uEventActual;                                     /**< event_actual                                      */
+    uint8_t   uResponse;                                        /**< response                                          */
 }  VIRTIOSCSI_CTRL_AN_T, *PVIRTIOSCSI_CTRL_AN_T;
 #pragma pack()
-
-typedef union virtio_scsi_ctrl_union
-{
-    VIRTIOSCSI_CTRL_T      scsiCtrl;
-    VIRTIOSCSI_CTRL_TMF_T  scsiCtrlTmf;
-    VIRTIOSCSI_CTRL_AN_T   scsiCtrlAsyncNotify;
+AssertCompileSize(VIRTIOSCSI_CTRL_AN_T, 21);
+
+typedef union VIRTIO_SCSI_CTRL_UNION_T
+{
+    VIRTIOSCSI_CTRL_T       scsiCtrl;
+    VIRTIOSCSI_CTRL_TMF_T   scsiCtrlTmf;
+    VIRTIOSCSI_CTRL_AN_T    scsiCtrlAsyncNotify;
+    uint8_t                 ab[25];
 } VIRTIO_SCSI_CTRL_UNION_T, *PVIRTIO_SCSI_CTRL_UNION_T;
+AssertCompile(sizeof(VIRTIO_SCSI_CTRL_UNION_T) == 28); /* VIRTIOSCSI_CTRL_T forces 4 byte alignment, the other two are byte packed. */
 
 /** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values
  * @{  */
-#define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2           /**<                                                   */
-#define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT          4           /**<                                                   */
-#define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST    8           /**<                                                   */
-#define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE        16          /**<                                                   */
-#define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST          32          /**<                                                   */
-#define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY         64          /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2              /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT          4              /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST    8              /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE        16             /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST          32             /**<                                                   */
+#define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY         64             /**<                                                   */
 /** @} */
 
 #define SUBSCRIBABLE_EVENTS \
-              VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \
-            & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \
-            & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \
-            & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \
-            & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \
-            & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY
+    (  VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \
+     | VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \
+     | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \
+     | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \
+     | VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \
+     | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY )
 
 /**
  * Worker thread context
  */
-typedef struct WORKER
-{
-    R3PTRTYPE(PPDMTHREAD)           pThread;                  /**< pointer to worker thread's handle                 */
-    SUPSEMEVENT                     hEvtProcess;              /**< handle of associated sleep/wake-up semaphore      */
-    bool                            fSleeping;                /**< Flags whether worker thread is sleeping or not    */
-    bool                            fNotified;                /**< Flags whether worker thread notified              */
-} WORKER, *PWORKER;
+typedef struct VIRTIOSCSIWORKER
+{
+    R3PTRTYPE(PPDMTHREAD)           pThread;                    /**< pointer to worker thread's handle                 */
+    SUPSEMEVENT                     hEvtProcess;                /**< handle of associated sleep/wake-up semaphore      */
+    bool                            fSleeping;                  /**< Flags whether worker thread is sleeping or not    */
+    bool                            fNotified;                  /**< Flags whether worker thread notified              */
+} VIRTIOSCSIWORKER;
+typedef VIRTIOSCSIWORKER *PVIRTIOSCSIWORKER;
 
 /**
@@ -407,5 +372,5 @@
     PPDMIMEDIANOTIFY                pMediaNotify;
 
-     /** Pointer to the attached driver's extended media interface. */
+    /** Pointer to the attached driver's extended media interface. */
     R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
 
@@ -419,5 +384,5 @@
 
 /**
- *  PDM instance data (state) for VirtIO Host SCSI device
+ * PDM instance data (state) for VirtIO Host SCSI device
  *
  * @extends     PDMPCIDEV
@@ -434,9 +399,9 @@
     R3PTRTYPE(PVIRTIOSCSITARGET)    paTargetInstances;
 #if HC_ARCH_BITS == 32
-      RTR3PTR                 R3PtrPadding0;
+    RTR3PTR                         R3PtrPadding0;
 #endif
 
     /** Per device-bound virtq worker-thread contexts (eventq slot unused) */
-    WORKER                          aWorker[VIRTIOSCSI_QUEUE_CNT];
+    VIRTIOSCSIWORKER                aWorkers[VIRTIOSCSI_QUEUE_CNT];
 
     bool                            fBootable;
@@ -444,11 +409,11 @@
     bool                            fR0Enabled;
     /** Instance name */
-    const char                      szInstance[16];
+    char                            szInstance[16];
 
     /** Device-specific spec-based VirtIO queuenames */
-    const char                      szQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];
+    char                            aszQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];
 
     /** Track which VirtIO queues we've attached to */
-    bool                            fQueueAttached[VIRTIOSCSI_QUEUE_CNT];
+    bool                            afQueueAttached[VIRTIOSCSI_QUEUE_CNT];
 
     /** Device base interface. */
@@ -480,5 +445,5 @@
 
     /** Mask of VirtIO Async Event types this device will deliver */
-    uint32_t                        uAsyncEvtsEnabled;
+    uint32_t                        fAsyncEvtsEnabled;
 
     /** Total number of requests active across all targets */
@@ -489,8 +454,8 @@
 
     /** Events the guest has subscribed to get notifications of */
-    uint32_t                        uSubscribedEvents;
+    uint32_t                        fSubscribedEvents;
 
     /** Set if events missed due to lack of bufs avail on eventq */
-    bool                           fEventsMissed;
+    bool                            fEventsMissed;
 
     /** VirtIO Host SCSI device runtime configuration parameters */
@@ -522,22 +487,23 @@
 /**
  * Request structure for IMediaEx (Associated Interfaces implemented by DrvSCSI)
- * (NOTE: cbIn, cbOUt, cbDataOut mostly for debugging)
+ * @note cbIn, cbOUt, cbDataOut mostly for debugging
  */
 typedef struct VIRTIOSCSIREQ
 {
-    PDMMEDIAEXIOREQ                hIoReq;                   /**< Handle of I/O request                             */
-    PVIRTIOSCSITARGET              pTarget;                  /**< Target                                            */
-    uint16_t                       qIdx;                     /**< Index of queue this request arrived on            */
-    PVIRTIO_DESC_CHAIN_T           pDescChain;               /**< Prepared desc chain pulled from virtq avail ring  */
-    uint32_t                       cbDataIn;                 /**< size of dataout buffer                            */
-    uint32_t                       cbDataOut;                /**< size of dataout buffer                            */
-    uint16_t                       uDataInOff;               /**< Fixed size of respHdr + sense (precede datain)    */
-    uint16_t                       uDataOutOff;              /**< Fixed size of respHdr + sense (precede datain)    */
-    uint32_t                       cbSense;                  /**< Size of sense buffer                              */
-    size_t                         uSenseLen;                /**< Receives # bytes written into sense buffer        */
-    uint8_t                       *pbSense;                  /**< Pointer to R3 sense buffer                        */
-    PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                 /**< Receives transfer direction of I/O req            */
-    uint8_t                        uStatus;                  /**< SCSI status code                                  */
+    PDMMEDIAEXIOREQ                hIoReq;                      /**< Handle of I/O request                             */
+    PVIRTIOSCSITARGET              pTarget;                     /**< Target                                            */
+    uint16_t                       qIdx;                        /**< Index of queue this request arrived on            */
+    PVIRTIO_DESC_CHAIN_T           pDescChain;                  /**< Prepared desc chain pulled from virtq avail ring  */
+    uint32_t                       cbDataIn;                    /**< size of dataout buffer                            */
+    uint32_t                       cbDataOut;                   /**< size of dataout buffer                            */
+    uint16_t                       uDataInOff;                  /**< Fixed size of respHdr + sense (precede datain)    */
+    uint16_t                       uDataOutOff;                 /**< Fixed size of respHdr + sense (precede datain)    */
+    uint32_t                       cbSenseAlloc;                /**< Size of sense buffer                              */
+    size_t                         cbSenseLen;                  /**< Receives \# bytes written into sense buffer       */
+    uint8_t                       *pbSense;                     /**< Pointer to R3 sense buffer                        */
+    PDMMEDIAEXIOREQSCSITXDIR       enmTxDir;                    /**< Receives transfer direction of I/O req            */
+    uint8_t                        uStatus;                     /**< SCSI status code                                  */
 } VIRTIOSCSIREQ;
+typedef VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
 
 DECLINLINE(const char *) virtioGetTxDirText(uint32_t enmTxDir)
@@ -590,34 +556,34 @@
 }
 
-DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t uAsyncTypesMask)
+DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t fAsyncTypesMask)
 {
     RTStrPrintf(pszOutput, cbOutput, "%s%s%s%s%s%s",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) ? "CHANGE_OPERATION  "   : "",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)         ? "POWER_MGMT  "         : "",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)   ? "EXTERNAL_REQ  "       : "",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)       ? "MEDIA_CHANGE  "       : "",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)         ? "MULTI_HOST  "         : "",
-        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)        ? "DEVICE_BUSY  "        : "");
-}
-
-uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax)
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE ? "CHANGE_OPERATION  "   : "",
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT         ? "POWER_MGMT  "         : "",
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST   ? "EXTERNAL_REQ  "       : "",
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE       ? "MEDIA_CHANGE  "       : "",
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST         ? "MULTI_HOST  "         : "",
+                fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY        ? "DEVICE_BUSY  "        : "");
+}
+
+#ifdef LOG_ENABLED
+static uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax)
 {
     if (uCmd < 0x1f)
         return 6;
-    else if (uCmd >= 0x20 && uCmd < 0x60)
+    if (uCmd >= 0x20 && uCmd < 0x60)
         return 10;
-    else if (uCmd >= 0x60 && uCmd < 0x80)
+    if (uCmd >= 0x60 && uCmd < 0x80)
         return cbMax;
-    else if (uCmd >= 0x80 && uCmd < 0xa0)
+    if (uCmd >= 0x80 && uCmd < 0xa0)
         return 16;
-    else if (uCmd >= 0xa0 && uCmd < 0xC0)
+    if (uCmd >= 0xa0 && uCmd < 0xc0)
         return 12;
-    else
-        return cbMax;
-}
-
-typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
-
-static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
+    return cbMax;
+}
+#endif /* LOG_ENABLED */
+
+
+static int virtioScsiR3SendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
 {
 
@@ -625,21 +591,26 @@
     event.uEvent = uEventType;
     event.uReason = uReason;
-    event.uVirtioLun[0] = 1;
-    event.uVirtioLun[1] = uTarget;
-    event.uVirtioLun[2] = (LUN0 >> 8) & 0x40;
-    event.uVirtioLun[3] = LUN0 & 0xff;
-    event.uVirtioLun[4] = event.uVirtioLun[5] = event.uVirtioLun[6] = event.uVirtioLun[7] = 0;
-
-    switch(uEventType)
+    event.abVirtioLun[0] = 1;
+    event.abVirtioLun[1] = uTarget;
+    event.abVirtioLun[2] = (LUN0 >> 8) & 0x40;
+    event.abVirtioLun[3] = LUN0 & 0xff;
+    event.abVirtioLun[4] = event.abVirtioLun[5] = event.abVirtioLun[6] = event.abVirtioLun[7] = 0;
+
+    /** @todo r=bird: This switch is missing some masking, right?  Because 'VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED'
+     * will never end up here but be disregarded in the 'default' case.  Given that the only caller of this function
+     * is virtioScsiR3ReportEventsMissed(), I find this a bit confusing.
+     *
+     * For the time being I've added a VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED case to make the code make sense,
+     * but it migth not be what you had in mind.   I've also changed uEventType to fEventType since that's more appropriate. */
+    switch (uEventType)
     {
         case VIRTIOSCSI_T_NO_EVENT:
-            if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED)
-                Log6Func(("(target=%d, LUN=%d) Warning driver that events were missed\n", uTarget, LUN0));
-            else
-                Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n",
-                          uTarget, LUN0));
+            Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n", uTarget, LUN0));
+            break;
+        case VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED:
+            Log6Func(("(target=%d, LUN=%d): Warning driver that events were missed\n", uTarget, LUN0));
             break;
         case VIRTIOSCSI_T_TRANSPORT_RESET:
-            switch(uReason)
+            switch (uReason)
             {
                 case VIRTIOSCSI_EVT_RESET_REMOVED:
@@ -655,16 +626,18 @@
             break;
         case VIRTIOSCSI_T_ASYNC_NOTIFY:
+        {
+#ifdef LOG_ENABLED
             char szTypeText[128];
             virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason);
-            Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n",
-                         uTarget, LUN0, szTypeText));
+            Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, LUN0, szTypeText));
+#endif
             break;
+        }
         case VIRTIOSCSI_T_PARAM_CHANGE:
             LogFunc(("(target=%d, LUN=%d): PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n",
-                        uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff));
+                     uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff));
             break;
         default:
-            Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n",
-                        uTarget, LUN0, uEventType));
+            Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, LUN0, uEventType));
             return VINF_SUCCESS;
     }
@@ -682,7 +655,7 @@
     RTSGBUF reqSegBuf;
     RTSGSEG aReqSegs[] = { { &event, sizeof(event) } };
-    RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
-
-    virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
+    RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
+
+    virtioQueuePut( pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);
     virtioQueueSync(pThis->hVirtio, EVENTQ_IDX);
 
@@ -690,7 +663,9 @@
 }
 
-static void virtioScsiFreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq)
+/** Internal worker. */
+static void virtioScsiR3FreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq)
 {
     RTMemFree(pReq->pbSense);
+    pReq->pbSense = NULL;
     pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq);
 }
@@ -699,22 +674,19 @@
  * This is called to complete a request immediately
  *
- * @param pThis      - PDM driver instance state
- * @param qIdx       - Queue index
- * @param pDescChain - Pointer to pre-processed descriptor chain pulled from virtq
- * @param pRespHdr   - Response header
- * @param pbSense    - Pointer to sense buffer or NULL if none.
+ * @param   pThis       PDM driver instance state
+ * @param   qIdx        Queue index
+ * @param   pDescChain  Pointer to pre-processed descriptor chain pulled from virtq
+ * @param   pRespHdr    Response header
+ * @param   pbSense     Pointer to sense buffer or NULL if none.
  *
- * @returns virtual box status code
- */
-static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain,
-                            struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
-{
-    uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
-    AssertReturn(abSenseBuf, VERR_NO_MEMORY);
-
-    const char *pszCtrlRespText = virtioGetReqRespText(pRespHdr->uResponse);
-    Log2Func(("   status: %s    response: %s\n",
-              SCSIStatusText(pRespHdr->uStatus),  pszCtrlRespText));
-    RT_NOREF(pszCtrlRespText);
+ * @returns VBox status code.
+ */
+static int virtioScsiR3ReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain,
+                              REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense)
+{
+    uint8_t *pabSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
+    AssertReturn(pabSenseBuf, VERR_NO_MEMORY);
+
+    Log2Func(("   status: %s    response: %s\n", SCSIStatusText(pRespHdr->uStatus), virtioGetReqRespText(pRespHdr->uResponse)));
 
     RTSGSEG aReqSegs[2];
@@ -722,10 +694,10 @@
     aReqSegs[0].pvSeg = pRespHdr;
     aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize;
-    aReqSegs[1].pvSeg = abSenseBuf;
-
-    if (pbSense && pRespHdr->uSenseLen)
-        memcpy(abSenseBuf, pbSense, pRespHdr->uSenseLen);
+    aReqSegs[1].pvSeg = pabSenseBuf;
+
+    if (pbSense && pRespHdr->cbSenseLen)
+        memcpy(pabSenseBuf, pbSense, pRespHdr->cbSenseLen);
     else
-        pRespHdr->uSenseLen = 0;
+        pRespHdr->cbSenseLen = 0;
 
     RTSGBUF reqSegBuf;
@@ -738,5 +710,5 @@
     virtioQueueSync(pThis->hVirtio, qIdx);
 
-    RTMemFree(abSenseBuf);
+    RTMemFree(pabSenseBuf);
 
     if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
@@ -748,5 +720,5 @@
 }
 
-static void virtioSenseKeyToVirtioResp(struct REQ_RESP_HDR *respHdr, uint8_t uSenseKey)
+static void virtioScsiR3SenseKeyToVirtioResp(REQ_RESP_HDR_T *respHdr, uint8_t uSenseKey)
 {
     switch (uSenseKey)
@@ -772,9 +744,10 @@
     }
 }
+
 /**
  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
  */
-static DECLCALLBACK(int) virtioScsiIoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
-                                               void *pvIoReqAlloc, int rcReq)
+static DECLCALLBACK(int) virtioScsiR3IoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                 void *pvIoReqAlloc, int rcReq)
 {
     RT_NOREF(pInterface);
@@ -796,6 +769,6 @@
     Assert(!(cbXfer & 0xffffffff00000000));
     uint32_t cbXfer32 = cbXfer & 0xffffffff;
-    struct REQ_RESP_HDR respHdr = { 0 };
-    respHdr.uSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->uSenseLen;
+    REQ_RESP_HDR_T respHdr = { 0 };
+    respHdr.cbSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->cbSenseLen;
     AssertMsg(!(cbResidual & 0xffffffff00000000),
             ("WARNING: Residual size larger than sizeof(uint32_t), truncating"));
@@ -811,5 +784,5 @@
     else
     {
-        switch(rcReq)
+        switch (rcReq)
         {
             case SCSI_STATUS_OK:
@@ -818,9 +791,9 @@
                     respHdr.uResponse = VIRTIOSCSI_S_OK;
                 else
-                    virtioSenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
+                    virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
                 break;
             }
             case SCSI_STATUS_CHECK_CONDITION:
-                virtioSenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
+                virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);
                 break;
 
@@ -847,9 +820,9 @@
         const char *pszTxDirText = virtioGetTxDirText(pReq->enmTxDir);
         LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n",
-             pszTxDirText, respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize));
+                 pszTxDirText, respHdr.cbSenseLen, pThis->virtioScsiConfig.uSenseSize));
         RT_NOREF(pszTxDirText);
     }
 
-    if (respHdr.uSenseLen && LogIs2Enabled())
+    if (respHdr.cbSenseLen && LogIs2Enabled())
     {
         LogFunc(("Sense: %s\n", SCSISenseText(pReq->pbSense[2])));
@@ -859,16 +832,16 @@
     int cSegs = 0;
 
-    if (   (VIRTIO_IN_DIRECTION(pReq->enmTxDir)  && cbXfer32 > pReq->cbDataIn)
-        || (VIRTIO_OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut))
+    if (   (VIRTIO_IS_IN_DIRECTION(pReq->enmTxDir)  && cbXfer32 > pReq->cbDataIn)
+        || (VIRTIO_IS_OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut))
     {
         Log2Func((" * * * * Data overrun, returning sense\n"));
         uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
                               0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
-        respHdr.uSenseLen = sizeof(abSense);
-        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
-        respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;
-        respHdr.uResidual = pReq->cbDataIn;
-
-        virtioScsiReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);
+        respHdr.cbSenseLen = sizeof(abSense);
+        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
+        respHdr.uResponse  = VIRTIOSCSI_S_OVERRUN;
+        respHdr.uResidual  = pReq->cbDataIn;
+
+        virtioScsiR3ReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);
     }
     else
@@ -883,5 +856,5 @@
 
         aReqSegs[cSegs].pvSeg = pReq->pbSense;
-        aReqSegs[cSegs++].cbSeg = pReq->cbSense; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
+        aReqSegs[cSegs++].cbSeg = pReq->cbSenseAlloc; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */
 
         RTSGBUF reqSegBuf;
@@ -902,5 +875,5 @@
     }
 
-    virtioScsiFreeReq(pTarget, pReq);
+    virtioScsiR3FreeReq(pTarget, pReq);
 
     if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
@@ -915,5 +888,5 @@
  * Copy virtual memory from VSCSI layer to guest physical memory
  */
-static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
                                                       void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
 {
@@ -965,5 +938,5 @@
  * Copy guest physical memory to VSCSI layer virtual memory
  */
-static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
                                                     void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
 {
@@ -1003,5 +976,58 @@
 }
 
-static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
+ */
+static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
+{
+    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
+    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
+    LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
+    if (pThis->pMediaNotify)
+    {
+        int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
+                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
+                                   pThis->pMediaNotify, pTarget->iTarget);
+        AssertRC(rc);
+    }
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
+ */
+static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                        void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
+{
+    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
+    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
+
+    switch (enmState)
+    {
+        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
+        {
+            /* Stop considering this request active */
+            if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
+                PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
+            break;
+        }
+        case PDMMEDIAEXIOREQSTATE_ACTIVE:
+            ASMAtomicIncU32(&pThis->cActiveReqs);
+            break;
+        default:
+            AssertMsgFailed(("Invalid request state given %u\n", enmState));
+    }
+}
+
+
+/*********************************************************************************************************************************
+*   Worker Thread                                                                                                                *
+*********************************************************************************************************************************/
+
+/**
+ * Handles request queues for/on a worker thread.
+ *
+ * @returns VBox status code (logged by caller).
+ */
+static int virtioScsiR3ReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
 {
     AssertReturn(pDescChain->cbPhysSend, VERR_INVALID_PARAMETER);
@@ -1009,7 +1035,8 @@
     ASMAtomicIncU32(&pThis->cActiveReqs);
 
-    /* Extract command header and CDB from guest physical memory */
-
-    size_t cbReqHdr = sizeof(struct REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize;
+    /*
+     * Extract command header and CDB from guest physical memory
+     */
+    size_t cbReqHdr = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize;
     PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbReqHdr);
     AssertReturn(pVirtqReq, VERR_NO_MEMORY);
@@ -1024,24 +1051,23 @@
     }
 
-    uint8_t  uTarget  = pVirtqReq->ReqHdr.uVirtioLun[1];
-    uint32_t uScsiLun = (pVirtqReq->ReqHdr.uVirtioLun[2] << 8 | pVirtqReq->ReqHdr.uVirtioLun[3]) & 0x3fff;
+    uint8_t  uTarget  = pVirtqReq->ReqHdr.abVirtioLun[1];
+    uint32_t uScsiLun = (pVirtqReq->ReqHdr.abVirtioLun[2] << 8 | pVirtqReq->ReqHdr.abVirtioLun[3]) & 0x3fff;
     PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[uTarget];
 
     LogFunc(("[%s] (Target: %d LUN: %d)  CDB: %.*Rhxs\n",
-        SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun,
-        virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0],
-        pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
+             SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun,
+             virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb));
 
     Log3Func(("cmd id: %RX64, attr: %x, prio: %d, crn: %x\n",
-        pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));
+              pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));
 
     /*
      * Calculate request offsets
      */
-    off_t uDataOutOff = sizeof(REQ_CMD_HDR)  + pThis->virtioScsiConfig.uCdbSize;
-    off_t uDataInOff  = sizeof(REQ_RESP_HDR) + pThis->virtioScsiConfig.uSenseSize;
+    off_t uDataOutOff = sizeof(REQ_CMD_HDR_T)  + pThis->virtioScsiConfig.uCdbSize;
+    off_t uDataInOff  = sizeof(REQ_RESP_HDR_T) + pThis->virtioScsiConfig.uSenseSize;
     uint32_t cbDataOut = pDescChain->cbPhysSend - uDataOutOff;
     uint32_t cbDataIn  = pDescChain->cbPhysReturn - uDataInOff;
-    /**
+    /*
      * Handle submission errors
      */
@@ -1050,14 +1076,13 @@
     {
         Log2Func(("Aborting req submission because reset is in progress\n"));
-        struct REQ_RESP_HDR respHdr = { 0 };
-        respHdr.uSenseLen = 0;
-        respHdr.uStatus   = SCSI_STATUS_OK;
-        respHdr.uResponse = VIRTIOSCSI_S_RESET;
-        respHdr.uResidual = cbDataIn + cbDataOut;
-        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, NULL);
+        REQ_RESP_HDR_T respHdr = { 0 };
+        respHdr.cbSenseLen = 0;
+        respHdr.uStatus    = SCSI_STATUS_OK;
+        respHdr.uResponse  = VIRTIOSCSI_S_RESET;
+        respHdr.uResidual  = cbDataIn + cbDataOut;
+        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, NULL);
         RTMemFree(pVirtqReq);
         return VINF_SUCCESS;
     }
-    else
     if (RT_UNLIKELY(uScsiLun != 0))
     {
@@ -1066,14 +1091,13 @@
                               0, SCSI_SENSE_ILLEGAL_REQUEST,
                               0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 };
-        struct REQ_RESP_HDR respHdr = { 0 };
-        respHdr.uSenseLen = sizeof(abSense);
-        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
-        respHdr.uResponse = VIRTIOSCSI_S_OK;
-        respHdr.uResidual = cbDataOut + cbDataIn;
-        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
+        REQ_RESP_HDR_T respHdr = { 0 };
+        respHdr.cbSenseLen = sizeof(abSense);
+        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
+        respHdr.uResponse  = VIRTIOSCSI_S_OK;
+        respHdr.uResidual  = cbDataOut + cbDataIn;
+        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
         RTMemFree(pVirtqReq);
         return VINF_SUCCESS;
     }
-    else
     if (RT_UNLIKELY(uTarget >= pThis->cTargets || !pTarget->fPresent))
     {
@@ -1081,14 +1105,13 @@
         uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
                               0, SCSI_SENSE_NOT_READY, 0, 0, 0, 0, 10, 0, 0, 0 };
-        struct REQ_RESP_HDR respHdr = { 0 };
-        respHdr.uSenseLen = sizeof(abSense);
-        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
-        respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET;
-        respHdr.uResidual = cbDataIn + cbDataOut;
-        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
+        REQ_RESP_HDR_T respHdr = { 0 };
+        respHdr.cbSenseLen = sizeof(abSense);
+        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
+        respHdr.uResponse  = VIRTIOSCSI_S_BAD_TARGET;
+        respHdr.uResidual  = cbDataIn + cbDataOut;
+        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
         RTMemFree(pVirtqReq);
         return VINF_SUCCESS;
     }
-    else
     if (RT_UNLIKELY(cbDataIn && cbDataOut && !pThis->fHasInOutBufs)) /* VirtIO 1.0, 5.6.6.1.1 */
     {
@@ -1096,10 +1119,10 @@
         uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
                               0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 };
-        struct REQ_RESP_HDR respHdr = { 0 };
-        respHdr.uSenseLen = sizeof(abSense);
-        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
-        respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
-        respHdr.uResidual = cbDataIn + cbDataOut;
-        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
+        REQ_RESP_HDR_T respHdr = { 0 };
+        respHdr.cbSenseLen = sizeof(abSense);
+        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
+        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
+        respHdr.uResidual  = cbDataIn + cbDataOut;
+        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense);
         RTMemFree(pVirtqReq);
         return VINF_SUCCESS;
@@ -1114,10 +1137,10 @@
 
     int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
-                                  PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
+                                      PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
 
     if (RT_FAILURE(rc))
     {
         RTMemFree(pVirtqReq);
-        virtioScsiFreeReq(pTarget, NULL);
+        /** @todo r=bird: This *will* crash: virtioScsiR3FreeReq(pTarget, NULL); */
         AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
     }
@@ -1132,7 +1155,8 @@
     pReq->uDataOutOff = uDataOutOff;
 
-    pReq->cbSense = pThis->virtioScsiConfig.uSenseSize;
-    pReq->pbSense = (uint8_t *)RTMemAlloc(pReq->cbSense);
-    AssertMsgReturn(pReq->pbSense,  ("Out of memory allocating sense buffer"),  VERR_NO_MEMORY);
+    pReq->cbSenseAlloc = pThis->virtioScsiConfig.uSenseSize;
+    pReq->pbSense      = (uint8_t *)RTMemAllocZ(pReq->cbSenseAlloc);
+    AssertMsgReturnStmt(pReq->pbSense, ("Out of memory allocating sense buffer"),
+                        virtioScsiR3FreeReq(pTarget, pReq); RTMemFree(pVirtqReq), VERR_NO_MEMORY);
 
     /* Note: DrvSCSI allocates one virtual memory buffer for input and output phases of the request */
@@ -1140,7 +1164,7 @@
                                         pVirtqReq->uCdb, (size_t)pThis->virtioScsiConfig.uCdbSize,
                                         PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir,
-                                        (size_t)RT_MAX(cbDataIn, cbDataOut),
-                                        pReq->pbSense, (size_t)pReq->cbSense, &pReq->uSenseLen,
-                                        &pReq->uStatus, 30 * RT_MS_1SEC);
+                                        RT_MAX(cbDataIn, cbDataOut),
+                                        pReq->pbSense, pReq->cbSenseAlloc, &pReq->cbSenseLen,
+                                        &pReq->uStatus, RT_MS_30SEC);
 
     if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
@@ -1150,4 +1174,5 @@
          * and there will be no callback to the finished/completion function for this request
          */
+        Assert(RT_FAILURE_NP(rc));
         Log2Func(("Request submission error from lower-level driver\n"));
         uint8_t uASC, uASCQ = 0;
@@ -1164,11 +1189,11 @@
                               0, SCSI_SENSE_VENDOR_SPECIFIC,
                               0, 0, 0, 0, 10, uASC, uASCQ, 0 };
-        struct REQ_RESP_HDR respHdr = { 0 };
-        respHdr.uSenseLen = sizeof(abSense);
-        respHdr.uStatus   = SCSI_STATUS_CHECK_CONDITION;
-        respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
-        respHdr.uResidual = cbDataIn + cbDataOut;
-        virtioScsiReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
-        virtioScsiFreeReq(pTarget, pReq);
+        REQ_RESP_HDR_T respHdr = { 0 };
+        respHdr.cbSenseLen = sizeof(abSense);
+        respHdr.uStatus    = SCSI_STATUS_CHECK_CONDITION;
+        respHdr.uResponse  = VIRTIOSCSI_S_FAILURE;
+        respHdr.uResidual  = cbDataIn + cbDataOut;
+        virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense);
+        virtioScsiR3FreeReq(pTarget, pReq);
     }
 
@@ -1177,17 +1202,38 @@
 }
 
-static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
-{
-    RT_NOREF2(pThis, qIdx);
-
-    uint8_t uResponse = VIRTIOSCSI_S_OK;
-
-    PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion =
-        (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAlloc(sizeof(VIRTIO_SCSI_CTRL_UNION_T));
-
-    uint8_t *pb = (uint8_t *)pScsiCtrlUnion;
+/**
+ * Handles control transfers for/on a worker thread.
+ *
+ * @returns VBox status code (ignored by the caller).
+ * @param   pThis       The device instance data.
+ * @param   qIdx        CONTROLQ_IDX
+ * @param   pDescChain  Descriptor chain to process.
+ */
+static int virtioScsiR3Ctrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain)
+{
+    uint8_t bResponse = VIRTIOSCSI_S_OK;
+
+    /*
+     * Allocate buffer and read in the control request/whatever.
+     */
+    /** @todo r=bird: The following may misbehave if the guest is not feeding you
+     *        sufficient data.  There are no size checks below or with the caller
+     *        that I can see, and more importantly you're using RTMemAlloc rather
+     *        than RTMemAllocZ here, so you'll get random heap bytes.
+     *
+     *        I've changed it to RTMemAllocZ so the memory is all zeroed, but you
+     *        need to consider how to deal with incorrectly sized input.
+     */
+    PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion = (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAllocZ(sizeof(VIRTIO_SCSI_CTRL_UNION_T));
+    AssertPtrReturn(pScsiCtrlUnion, VERR_NO_MEMORY /*ignored*/);
+
+    uint8_t *pb = pScsiCtrlUnion->ab;
     for (size_t cb = RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T)); cb; )
     {
         size_t cbSeg = cb;
+        /** @todo r=bird: This is ABUSING the RTSgBuf, interchanging host context
+         * pointers with RTGCPHYS.  If we hadn't just dropped 32-bit host
+         * support, this would have been a serious problem.  Now it is just UGLY! */
+        AssertCompile(sizeof(RTGCPHYS) == sizeof(void *)); /* ASSUMING RTGCPHYS and host pointers are interchangable. (horrible!) */
         RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg);
         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pb, cbSeg);
@@ -1200,27 +1246,21 @@
      * See VirtIO 1.0 specification section 5.6.6.2
      */
-    uint32_t uSubscribedEvents  =
-                            VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
-                          | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST
-                          | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE
-                          | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY;
+    uint32_t fSubscribedEvents  = VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
+                                | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST
+                                | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE
+                                | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY;
 
     RTSGBUF reqSegBuf;
 
 
-    switch(pScsiCtrlUnion->scsiCtrl.uType)
+    switch (pScsiCtrlUnion->scsiCtrl.uType)
     {
         case VIRTIOSCSI_T_TMF: /* Task Management Functions */
         {
-            uint8_t  uTarget  = pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[1];
-            uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[2] << 8
-                               | pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[3]) & 0x3fff;
-            if (LogIs2Enabled())
-            {
-                const char *pszTmfTypeText = virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype);
-                Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
-                    QUEUENAME(qIdx), uTarget, uScsiLun, pszTmfTypeText));
-                RT_NOREF3(pszTmfTypeText, uTarget, uScsiLun);
-            }
+            uint8_t  uTarget  = pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[1];
+            uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[2] << 8
+                               | pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[3]) & 0x3fff;
+            Log2Func(("[%s] (Target: %d LUN: %d)  Task Mgt Function: %s\n",
+                      QUEUENAME(qIdx), uTarget, uScsiLun, virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype)));
 
             PVIRTIOSCSITARGET pTarget = NULL;
@@ -1229,42 +1269,42 @@
 
             if (uTarget >= pThis->cTargets || !pTarget->fPresent)
-                uResponse = VIRTIOSCSI_S_BAD_TARGET;
+                bResponse = VIRTIOSCSI_S_BAD_TARGET;
             else
             if (uScsiLun != 0)
-                uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
+                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
             else
-            switch(pScsiCtrlUnion->scsiCtrlTmf.uSubtype)
-            {
-                case VIRTIOSCSI_T_TMF_ABORT_TASK:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_CLEAR_ACA:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
-                    break;
-                case VIRTIOSCSI_T_TMF_QUERY_TASK:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
-                    break;
-                case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:
-                    uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
-                    break;
-                default:
-                    LogFunc(("Unknown TMF type\n"));
-                    uResponse = VIRTIOSCSI_S_FAILURE;
-            }
-
-            RTSGSEG aReqSegs[] = { { &uResponse,  sizeof(uResponse) } };
-            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
+                switch (pScsiCtrlUnion->scsiCtrlTmf.uSubtype)
+                {
+                    case VIRTIOSCSI_T_TMF_ABORT_TASK:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_CLEAR_ACA:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_QUERY_TASK:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
+                        break;
+                    case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:
+                        bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;
+                        break;
+                    default:
+                        LogFunc(("Unknown TMF type\n"));
+                        bResponse = VIRTIOSCSI_S_FAILURE;
+                }
+
+            RTSGSEG aReqSegs[] = { { &bResponse,  sizeof(bResponse) } };
+            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
 
             break;
@@ -1275,8 +1315,8 @@
             PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnQuery = &pScsiCtrlUnion->scsiCtrlAsyncNotify;
 
-            uSubscribedEvents &= pScsiCtrlAnQuery->uEventsRequested;
-
-            uint8_t  uTarget  = pScsiCtrlAnQuery->uScsiLun[1];
-            uint32_t uScsiLun = (pScsiCtrlAnQuery->uScsiLun[2] << 8 | pScsiCtrlAnQuery->uScsiLun[3]) & 0x3fff;
+            fSubscribedEvents &= pScsiCtrlAnQuery->fEventsRequested;
+
+            uint8_t  uTarget  = pScsiCtrlAnQuery->abScsiLun[1];
+            uint32_t uScsiLun = (pScsiCtrlAnQuery->abScsiLun[2] << 8 | pScsiCtrlAnQuery->abScsiLun[3]) & 0x3fff;
 
             PVIRTIOSCSITARGET pTarget = NULL;
@@ -1285,23 +1325,22 @@
 
             if (uTarget >= pThis->cTargets || !pTarget->fPresent)
-                uResponse = VIRTIOSCSI_S_BAD_TARGET;
+                bResponse = VIRTIOSCSI_S_BAD_TARGET;
             else
             if (uScsiLun != 0)
-                uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
+                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
             else
-                uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
-
+                bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
+
+#ifdef LOG_ENABLED
             if (LogIs2Enabled())
             {
                 char szTypeText[128];
-                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText),
-                    pScsiCtrlAnQuery->uEventsRequested);
+                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnQuery->fEventsRequested);
                 Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Query: %s\n",
-                    QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
-                RT_NOREF3(szTypeText, uTarget, uScsiLun);
-
+                          QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
             }
-            RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
-            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
+#endif
+            RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) },  { &bResponse, sizeof(bResponse)  } };
+            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
 
             break;
@@ -1312,24 +1351,23 @@
             PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnSubscribe = &pScsiCtrlUnion->scsiCtrlAsyncNotify;
 
-            if (pScsiCtrlAnSubscribe->uEventsRequested & ~SUBSCRIBABLE_EVENTS)
-                LogFunc(("Unsupported bits in event subscription event mask: 0x%x\n",
-                    pScsiCtrlAnSubscribe->uEventsRequested));
-
-            uSubscribedEvents &= pScsiCtrlAnSubscribe->uEventsRequested;
-            pThis->uAsyncEvtsEnabled = uSubscribedEvents;
-
-            uint8_t  uTarget  = pScsiCtrlAnSubscribe->uScsiLun[1];
-            uint32_t uScsiLun = (pScsiCtrlAnSubscribe->uScsiLun[2] << 8
-                               | pScsiCtrlAnSubscribe->uScsiLun[3]) & 0x3fff;
-
+            if (pScsiCtrlAnSubscribe->fEventsRequested & ~SUBSCRIBABLE_EVENTS)
+                LogFunc(("Unsupported bits in event subscription event mask: %#x\n", pScsiCtrlAnSubscribe->fEventsRequested));
+
+            fSubscribedEvents &= pScsiCtrlAnSubscribe->fEventsRequested;
+            pThis->fAsyncEvtsEnabled = fSubscribedEvents;
+
+            uint8_t  uTarget  = pScsiCtrlAnSubscribe->abScsiLun[1];
+            uint32_t uScsiLun = (pScsiCtrlAnSubscribe->abScsiLun[2] << 8
+                               | pScsiCtrlAnSubscribe->abScsiLun[3]) & 0x3fff;
+
+#ifdef LOG_ENABLED
             if (LogIs2Enabled())
             {
                 char szTypeText[128];
-                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->uEventsRequested);
+                virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->fEventsRequested);
                 Log2Func(("[%s] (Target: %d LUN: %d)  Async. Notification Subscribe: %s\n",
-                    QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
-                RT_NOREF3(szTypeText, uTarget, uScsiLun);
-
+                          QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText));
             }
+#endif
 
             PVIRTIOSCSITARGET pTarget = NULL;
@@ -1338,8 +1376,8 @@
 
             if (uTarget >= pThis->cTargets || !pTarget->fPresent)
-                uResponse = VIRTIOSCSI_S_BAD_TARGET;
+                bResponse = VIRTIOSCSI_S_BAD_TARGET;
             else
             if (uScsiLun != 0)
-                uResponse = VIRTIOSCSI_S_INCORRECT_LUN;
+                bResponse = VIRTIOSCSI_S_INCORRECT_LUN;
             else
             {
@@ -1348,28 +1386,27 @@
                  *      and confirm when to use 'complete' vs. 'succeeded' See VirtIO 1.0 spec section 5.6.6.2
                  *      and read SAM docs*/
-                if (uSubscribedEvents == pScsiCtrlAnSubscribe->uEventsRequested)
-                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
+                if (fSubscribedEvents == pScsiCtrlAnSubscribe->fEventsRequested)
+                    bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
                 else
-                    uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
+                    bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
             }
-            RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
-            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
+            RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) },  { &bResponse, sizeof(bResponse)  } };
+            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
 
             break;
         }
         default:
-            LogFunc(("Unknown control type extracted from %s: %d\n",
-                QUEUENAME(qIdx),  &pScsiCtrlUnion->scsiCtrl.uType));
-
-            uResponse = VIRTIOSCSI_S_FAILURE;
-
-            RTSGSEG aReqSegs[] = { { &uResponse,  sizeof(uResponse) } };
-            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
-    }
-
-    const char *pszCtrlRespText = virtioGetReqRespText(uResponse);
-    LogFunc(("Response code: %s\n", pszCtrlRespText));
-    RT_NOREF(pszCtrlRespText);
-    virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true);
+        {
+            LogFunc(("Unknown control type extracted from %s: %u\n", QUEUENAME(qIdx), pScsiCtrlUnion->scsiCtrl.uType));
+
+            bResponse = VIRTIOSCSI_S_FAILURE;
+
+            RTSGSEG aReqSegs[] = { { &bResponse, sizeof(bResponse) } };
+            RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
+        }
+    }
+
+    LogFunc(("Response code: %s\n", virtioGetReqRespText(bResponse)));
+    virtioQueuePut( pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true);
     virtioQueueSync(pThis->hVirtio, qIdx);
 
@@ -1377,25 +1414,23 @@
 }
 
-/*
- * Unblock the worker thread so it can respond to a state change.
- *
- * @returns VBox status code.
- * @param   pDevIns     The pcnet device instance.
- * @param   pThread     The send thread.
- */
-static DECLCALLBACK(int) virtioScsiWorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+/**
+ * @callback_method_impl{FNPDMTHREADWAKEUPDEV}
+ */
+static DECLCALLBACK(int) virtioScsiR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 {
     RT_NOREF(pThread);
     uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff;
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-    return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorker[qIdx].hEvtProcess);
-}
-
-static int virtioScsiWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
-{
-    int rc;
-    uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff;
+    return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorkers[qIdx].hEvtProcess);
+}
+
+/**
+ * @callback_method_impl{FNPDMTHREADDEV}
+ */
+static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+    uint16_t const qIdx = (uint16_t)(uintptr_t)pThread->pvUser;
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-    PWORKER pWorker = &pThis->aWorker[qIdx];
+    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
 
     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
@@ -1413,5 +1448,5 @@
                 Log6Func(("%s worker sleeping...\n", QUEUENAME(qIdx)));
                 Assert(ASMAtomicReadBool(&pWorker->fSleeping));
-                rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
+                int rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);
                 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
                 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
@@ -1423,5 +1458,5 @@
         }
 
-        if (!pThis->fQueueAttached[qIdx])
+        if (!pThis->afQueueAttached[qIdx])
         {
             LogFunc(("%s queue not attached, worker aborting...\n", QUEUENAME(qIdx)));
@@ -1432,5 +1467,5 @@
              Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx)));
              PVIRTIO_DESC_CHAIN_T pDescChain;
-             rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);
+             int rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);
              if (rc == VERR_NOT_AVAILABLE)
              {
@@ -1441,8 +1476,8 @@
              AssertRC(rc);
              if (qIdx == CONTROLQ_IDX)
-                 virtioScsiCtrl(pThis, qIdx, pDescChain);
+                 virtioScsiR3Ctrl(pThis, qIdx, pDescChain);
              else /* request queue index */
              {
-                  rc = virtioScsiReqSubmit(pThis, qIdx, pDescChain);
+                  rc = virtioScsiR3ReqSubmit(pThis, qIdx, pDescChain);
                   if (RT_FAILURE(rc))
                   {
@@ -1456,82 +1491,79 @@
 
 
-DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
+/*********************************************************************************************************************************
+*   Sending evnets
+*********************************************************************************************************************************/
+
+
+DECLINLINE(void) virtioScsiR3ReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
 }
 
 #if 0
-/* Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
+
+/** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
  * This effectively removes the SCSI Target/LUN on the guest side
  */
-DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
+DECLINLINE(void) virtioScsiR3ReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
 {
     if (pThis->fHasHotplug)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
-                VIRTIOSCSI_EVT_RESET_REMOVED);
-}
-
-/* Only invoke thi if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_REMOVED);
+}
+
+/** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization
  * This effectively adds the SCSI Target/LUN on the guest side
  */
-DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
+DECLINLINE(void) virtioScsiR3ReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
 {
     if (pThis->fHasHotplug)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
-                VIRTIOSCSI_EVT_RESET_RESCAN);
-}
-
-DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
-            VIRTIOSCSI_EVT_RESET_HARD);
-}
-
-DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
-}
-
-DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
-}
-
-DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
-}
-
-DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
-}
-
-DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
-}
-
-DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
-{
-    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
-        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
-                VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
-}
-
-DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_RESCAN);
+}
+
+DECLINLINE(void) virtioScsiR3ReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_HARD);
+}
+
+DECLINLINE(void) virtioScsiR3ReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
+}
+
+DECLINLINE(void) virtioScsiR3ReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
+}
+
+DECLINLINE(void) virtioScsiR3ReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
+}
+
+DECLINLINE(void) virtioScsiR3ReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
+}
+
+DECLINLINE(void) virtioScsiR3ReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
+}
+
+DECLINLINE(void) virtioScsiR3ReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
+{
+    if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
+        virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
+}
+
+DECLINLINE(void) virtioScsiR3ReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
 {
     uint32_t uReason = uSenseQualifier << 8 | uSenseCode;
-    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
+    virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
 
 }
@@ -1539,5 +1571,8 @@
 #endif
 
-static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
+/**
+ * @callback_method_impl{FNVIRTIOQUEUENOTIFIED}
+ */
+static DECLCALLBACK(void) virtioScsiR3Notified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
 {
     RT_NOREF(hVirtio);
@@ -1545,5 +1580,5 @@
     AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
     PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
-    PWORKER pWorker = &pThis->aWorker[qIdx];
+    PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
 
     RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));
@@ -1567,5 +1602,5 @@
         Log3Func(("Driver queued buffer(s) to %s\n", QUEUENAME(qIdx)));
         if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
-            virtioScsiReportEventsMissed(pThis, 0);
+            virtioScsiR3ReportEventsMissed(pThis, 0);
     }
     else
@@ -1573,5 +1608,8 @@
 }
 
-static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  uint32_t fVirtioReady)
+/**
+ * @callback_method_impl{FNVIRTIOSTATUSCHANGED}
+ */
+static DECLCALLBACK(void) virtioScsiR3StatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  uint32_t fVirtioReady)
 {
     RT_NOREF(hVirtio);
@@ -1592,5 +1630,5 @@
 
         for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
-            pThis->fQueueAttached[i] = true;
+            pThis->afQueueAttached[i] = true;
     }
     else
@@ -1598,23 +1636,22 @@
         LogFunc(("VirtIO is resetting\n"));
         for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
-            pThis->fQueueAttached[i] = false;
-    }
-}
-
-/**
- * virtio-scsi debugger info callback.
- *
- * @param   pDevIns     The device instance.
- * @param   pHlp        The output helpers.
- * @param   pszArgs     The arguments.
- */
-static DECLCALLBACK(void) virtioScsiInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+            pThis->afQueueAttached[i] = false;
+    }
+}
+
+
+/*********************************************************************************************************************************
+*   Misc                                                                                                                         *
+*********************************************************************************************************************************/
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV, virtio-scsi debugger info callback.}
+ */
+static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
 {
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-    bool fVerbose = false;
 
     /* Parse arguments. */
-    if (pszArgs)
-        fVerbose = strstr(pszArgs, "verbose") != NULL;
+    RT_NOREF(pszArgs); //bool fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL;
 
     /* Show basic information. */
@@ -1625,25 +1662,15 @@
 }
 
-/**
- * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
- */
-static DECLCALLBACK(void) virtioScsiMediumEjected(PPDMIMEDIAEXPORT pInterface)
-{
-    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
-    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
-    LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));
-    if (pThis->pMediaNotify)
-    {
-         int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
-                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
-                                    pThis->pMediaNotify, pTarget->iTarget);
-         AssertRC(rc);
-    }
-}
-
-/** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
-static DECLCALLBACK(int) virtioScsiLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
-{
-LogFunc(("LIVE EXEC!!\n"));
+
+/*********************************************************************************************************************************
+*   Saved state                                                                                                                  *
+*********************************************************************************************************************************/
+
+/**
+ * @callback_method_impl{FNSSMDEVLIVEEXEC}
+ */
+static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
+{
+    LogFunc(("LIVE EXEC!!\n"));
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     RT_NOREF(pThis);
@@ -1653,8 +1680,10 @@
 }
 
-/** @callback_method_impl{FNSSMDEVLOADEXEC}  */
-static DECLCALLBACK(int) virtioScsiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
-{
-LogFunc(("LOAD EXEC!!\n"));
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+    LogFunc(("LOAD EXEC!!\n"));
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uNumQueues);
@@ -1668,5 +1697,5 @@
     SSMR3GetU16(pSSM, &pThis->virtioScsiConfig.uMaxTarget);
     SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uMaxLun);
-    SSMR3GetU32(pSSM, &pThis->uAsyncEvtsEnabled);
+    SSMR3GetU32(pSSM, &pThis->fAsyncEvtsEnabled);
     SSMR3GetU32(pSSM, (uint32_t *)&pThis->cActiveReqs);
     SSMR3GetBool(pSSM, &pThis->fEventsMissed);
@@ -1680,11 +1709,13 @@
     RT_NOREF(uPass);
     RT_NOREF(uVersion);
-    return VINF_SSM_DONT_CALL_AGAIN;
-}
-
-/** @callback_method_impl{FNSSMDEVSAVEEXEC}  */
-static DECLCALLBACK(int) virtioScsiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
-{
-LogFunc(("SAVE EXEC!!\n"));
+    return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+    LogFunc(("SAVE EXEC!!\n"));
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
 
@@ -1699,6 +1730,9 @@
     SSMR3PutU16(pSSM, pThis->virtioScsiConfig.uMaxTarget);
     SSMR3PutU32(pSSM, pThis->virtioScsiConfig.uMaxLun);
-    SSMR3PutU32(pSSM, pThis->uAsyncEvtsEnabled);
-    SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs);
+    SSMR3PutU32(pSSM, pThis->fAsyncEvtsEnabled);
+    SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs); /** @todo r=bird: Shouldn't this be zero?  I don't think we can have
+                                                      * outstanding requests when the VM is suspended (which we are when this
+                                                      * function is called), and more importantely, I don't understand how they
+                                                      * would be restored by virtioScsiR3LoadExec. */
     SSMR3PutBool(pSSM, pThis->fEventsMissed);
     SSMR3PutU32(pSSM, pThis->fVirtioReady);
@@ -1708,11 +1742,13 @@
     SSMR3PutU32(pSSM, pThis->fHasLunChange);
     SSMR3PutU32(pSSM, pThis->fResetting);
-    SSMR3PutU32(pSSM, pThis->fQuiescing);
+    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 */
 
     return VINF_SUCCESS;
 }
 
-/** @callback_method_impl{FNSSMDEVLOADDONE}  */
-static DECLCALLBACK(int) virtioScsiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+/**
+ * @callback_method_impl{FNSSMDEVLOADDONE}
+ */
+static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 {
     LogFunc(("callback"));
@@ -1723,17 +1759,13 @@
 }
 
-/**
- * Is asynchronous handling of suspend or power off notification completed?
- *
- * This is called to check whether the device has quiesced.  Don't deadlock.
- * Avoid blocking.  Do NOT wait for anything.
- *
- * @returns true if done, false if more work to be done.
- *
- * @param   pDevIns             The device instance.
- * @remarks The caller will enter the device critical section.
- * @thread  EMT(0)
- */
-static DECLCALLBACK(bool) virtioScsiDeviceQuiesced(PPDMDEVINS pDevIns)
+
+/*********************************************************************************************************************************
+*   Device Interface - Misplaced.                                                                                                             *
+*********************************************************************************************************************************/
+
+/**
+ * @callback_method_impl{FNPDMDEVASYNCNOTIFY}
+ */
+static DECLCALLBACK(bool) virtioScsiR3DeviceQuiesced(PPDMDEVINS pDevIns)
 {
     LogFunc(("Device I/O activity quiesced.\n"));
@@ -1745,5 +1777,8 @@
 }
 
-static void virtioScsiQuiesceDevice(PPDMDEVINS pDevIns)
+/**
+ * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff().
+ */
+static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns)
 {
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
@@ -1752,5 +1787,5 @@
     pThis->fQuiescing = true;
 
-    PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiDeviceQuiesced);
+    PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3DeviceQuiesced);
 
     /* If already quiesced invoke async callback.  */
@@ -1760,38 +1795,12 @@
 
 /**
- * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
- */
-static DECLCALLBACK(void) virtioScsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
-                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
-{
-    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
-    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
-
-    switch (enmState)
-    {
-        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
-        {
-            /* Stop considering this request active */
-            if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
-                PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
-            break;
-        }
-        case PDMMEDIAEXIOREQSTATE_ACTIVE:
-            ASMAtomicIncU32(&pThis->cActiveReqs);
-            break;
-        default:
-            AssertMsgFailed(("Invalid request state given %u\n", enmState));
-    }
-}
-
-/**
- * @copydoc FNPDMDEVRESET
- */
-static DECLCALLBACK(void) virtioScsiReset(PPDMDEVINS pDevIns)
+ * @inter FNPDMDEVRESET
+ */
+static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
 {
     LogFunc(("\n"));
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     pThis->fResetting = true;
-    virtioScsiQuiesceDevice(pDevIns);
+    virtioScsiR3QuiesceDevice(pDevIns);
 }
 
@@ -1799,5 +1808,5 @@
  * @interface_method_impl{PDMDEVREG,pfnResume}
  */
-static DECLCALLBACK(void) virtioScsiResume(PPDMDEVINS pDevIns)
+static DECLCALLBACK(void) virtioScsiR3Resume(PPDMDEVINS pDevIns)
 {
     LogFunc(("\n"));
@@ -1811,7 +1820,7 @@
      * be awake due to new reqs coming in.
      */
-     for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
-    {
-        PWORKER pWorker = &pThis->aWorker[qIdx];
+    for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
+    {
+        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
 
         if (ASMAtomicReadBool(&pWorker->fSleeping))
@@ -1830,9 +1839,9 @@
  * @interface_method_impl{PDMDEVREG,pfnSuspend}
  */
-static DECLCALLBACK(void) virtioScsiSuspendOrPoweroff(PPDMDEVINS pDevIns)
+static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
 {
     LogFunc(("\n"));
 
-    virtioScsiQuiesceDevice(pDevIns);
+    virtioScsiR3QuiesceDevice(pDevIns);
 
     PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
@@ -1853,4 +1862,11 @@
 }
 
+
+/*********************************************************************************************************************************
+*   LEDs                                                                                                                         *
+*********************************************************************************************************************************/
+
+#if 0 /** @todo r=bird: LEDs are not being set it seems. */
+
 /**
  * Turns on/off the write status LED.
@@ -1859,5 +1875,5 @@
  * @param   fOn             New LED state.
  */
-void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
+static void virtioScsiR3SetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
 {
     LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
@@ -1865,5 +1881,5 @@
         pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
     else
-        pTarget->led.Actual.s.fWriting = fOn;
+        pTarget->led.Actual.s.fWriting = 0;
 }
 
@@ -1874,5 +1890,5 @@
  * @param   fOn             New LED state.
  */
-void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
+static void virtioScsiR3SetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
 {
     LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));
@@ -1880,18 +1896,15 @@
         pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
     else
-        pTarget->led.Actual.s.fReading = fOn;
-}
-
-/**
- * Gets the pointer to the status LED of a unit.
- *
- * @returns VBox status code.
- * @param   pInterface      Pointer to the interface structure containing the called function pointer.
- * @param   iTarget         The unit which status LED we desire.
- * @param   ppLed           Where to store the LED pointer.
- */
-static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
-{
-  PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
+        pTarget->led.Actual.s.fReading = 0;
+}
+
+#endif /* unused*/
+
+/**
+ * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Target level.}
+ */
+static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
+{
+    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
     if (iTarget == 0)
     {
@@ -1904,12 +1917,7 @@
 
 /**
- * Gets the pointer to the status LED of a unit.
- *
- * @returns VBox status code.
- * @param   pInterface      Pointer to the interface structure containing the called function pointer.
- * @param   iTarget         The unit which status LED we desire.
- * @param   ppLed           Where to store the LED pointer.
- */
-static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
+ * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Device level.}
+ */
+static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)
 {
     PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
@@ -1921,126 +1929,121 @@
     }
     return VERR_PDM_LUN_NOT_FOUND;
- }
-
-static int virtioScsiCfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
-                                    const void *pv, uint32_t cb, bool fWrite)
-{
-
+}
+
+
+/*********************************************************************************************************************************
+*   Virtio config.                                                                                                               *
+*********************************************************************************************************************************/
+
+/**
+ * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead.
+ */
+static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)
+{
     AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);
 
-    if (MATCH_SCSI_CONFIG(uNumQueues))
+/**
+ * Resolves to boolean true if uOffset matches a field offset and size exactly,
+ * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
+ * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
+ * (Easily re-written to allow unaligned bounded access to a field).
+ *
+ * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
+ * @result           - true or false
+ */
+#define MATCH_SCSI_CONFIG(member) \
+        (   (   RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
+             && (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
+                 || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
+             && cb == sizeof(uint32_t)) \
+         || (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
+             && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) )
+
+#define LOG_SCSI_CONFIG_ACCESSOR(member) \
+        virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
+                               pv, cb, offIntra, fWrite, false, 0);
+
+#define SCSI_CONFIG_ACCESSOR(member) \
+    do \
+    { \
+        uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
+        if (fWrite) \
+            memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \
+        else \
+            memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
+        LOG_SCSI_CONFIG_ACCESSOR(member); \
+    } while(0)
+
+#define SCSI_CONFIG_ACCESSOR_READONLY(member) \
+    do \
+    { \
+        uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
+        if (fWrite) \
+            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
+        else \
+        { \
+            memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
+            LOG_SCSI_CONFIG_ACCESSOR(member); \
+        } \
+    } while(0)
+
+    if (MATCH_SCSI_CONFIG(            uNumQueues))
         SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
-    else
-    if (MATCH_SCSI_CONFIG(uSegMax))
+    else if (MATCH_SCSI_CONFIG(       uSegMax))
         SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
-    else
-    if (MATCH_SCSI_CONFIG(uMaxSectors))
+    else if (MATCH_SCSI_CONFIG(       uMaxSectors))
         SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
-    else
-    if (MATCH_SCSI_CONFIG(uCmdPerLun))
+    else if (MATCH_SCSI_CONFIG(       uCmdPerLun))
         SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
-    else
-    if (MATCH_SCSI_CONFIG(uEventInfoSize))
+    else if (MATCH_SCSI_CONFIG(       uEventInfoSize))
         SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
-    else
-    if (MATCH_SCSI_CONFIG(uSenseSize))
-        SCSI_CONFIG_ACCESSOR(uSenseSize);
-    else
-    if (MATCH_SCSI_CONFIG(uCdbSize))
-        SCSI_CONFIG_ACCESSOR(uCdbSize);
-    else
-    if (MATCH_SCSI_CONFIG(uMaxChannel))
+    else if (MATCH_SCSI_CONFIG(       uSenseSize))
+        SCSI_CONFIG_ACCESSOR(         uSenseSize);
+    else if (MATCH_SCSI_CONFIG(       uCdbSize))
+        SCSI_CONFIG_ACCESSOR(         uCdbSize);
+    else if (MATCH_SCSI_CONFIG(       uMaxChannel))
         SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
-    else
-    if (MATCH_SCSI_CONFIG(uMaxTarget))
+    else if (MATCH_SCSI_CONFIG(       uMaxTarget))
         SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
-    else
-    if (MATCH_SCSI_CONFIG(uMaxLun))
+    else if (MATCH_SCSI_CONFIG(       uMaxLun))
         SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
     else
     {
-        LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
+        LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb));
         return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
     }
     return VINF_SUCCESS;
-}
-
-/**
- * virtio-scsi VirtIO Device-specific capabilities read callback
- * (other VirtIO capabilities and features are handled in VirtIO implementation)
- *
- * @param   pDevIns     The device instance.
- * @param   uOffset     Offset within device specific capabilities struct
- * @param   pv          Buffer in which to save read data
- * @param   cb          Number of bytes to read
- */
-static DECLCALLBACK(int) virtioScsiDevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
-{
-    int rc = VINF_SUCCESS;
-    PVIRTIOSCSI  pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-
-    rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, false);
-
-    return rc;
-}
-
-/**
- * virtio-scsi VirtIO Device-specific capabilities read callback
- * (other VirtIO capabilities and features are handled in VirtIO implementation)
- *
- * @param   pDevIns     The device instance.
- * @param   uOffset     Offset within device specific capabilities struct
- * @param   pv          Buffer in which to save read data
- * @param   cb          Number of bytes to write
- */
-static DECLCALLBACK(int) virtioScsiDevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
-{
-    int rc = VINF_SUCCESS;
-    PVIRTIOSCSI  pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-
-    rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, true);
-
-    return rc;
-}
-
-/**
- * Device relocation callback.
- *
- * When this callback is called the device instance data, and if the
- * device have a GC component, is being relocated, or/and the selectors
- * have been changed. The device must use the chance to perform the
- * necessary pointer relocations and data updates.
- *
- * Before the GC code is executed the first time, this function will be
- * called with a 0 delta so GC pointer calculations can be one in one place.
- *
- * @param   pDevIns     Pointer to the device instance.
- * @param   offDelta    The relocation delta relative to the old location.
- *
- * @remark  A relocation CANNOT fail.
- */
-static DECLCALLBACK(void) virtioScsiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
-{
-    LogFunc(("Relocating virtio-scsi"));
-    RT_NOREF(offDelta);
-    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
-
-    pThis->pDevInsR3 = pDevIns;
-
-    for (uint32_t i = 0; i < pThis->cTargets; i++)
-    {
-        PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[i];
-        pTarget->pVirtioScsi = pThis;
-    }
-
-    /*
-     * Important: Forward to virtio framework!
-     */
-    virtioRelocate(pDevIns, offDelta);
-
-}
-
-static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
-                                                       uint32_t *piInstance, uint32_t *piTarget)
+#undef SCSI_CONFIG_ACCESSOR_READONLY
+#undef SCSI_CONFIG_ACCESSOR
+#undef LOG_ACCESSOR
+#undef MATCH_SCSI_CONFIG
+}
+
+/**
+ * @callback_method_impl{FNVIRTIODEVCAPREAD}
+ */
+static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, void *pv, uint32_t cb)
+{
+    return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, pv, cb, false /*fRead*/);
+}
+
+/**
+ * @callback_method_impl{FNVIRTIODEVCAPWRITE}
+ */
+static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)
+{
+    return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, (void *)pv, cb, true /*fWrite*/);
+}
+
+
+/*********************************************************************************************************************************
+*   Will move tomorrow.                                                                                                          *
+*********************************************************************************************************************************/
+
+/**
+ * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation, Target level.}
+ */
+static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
+                                                         uint32_t *piInstance, uint32_t *piTarget)
 {
     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
@@ -2059,7 +2062,7 @@
 
 /**
- * @interface_method_impl{PDMIBASE,pfnQueryInterface}
- */
-static DECLCALLBACK(void *) virtioScsiTargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface, Target level.}
+ */
+static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
 {
      PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
@@ -2072,7 +2075,7 @@
 
 /**
- * @interface_method_impl{PDMIBASE,pfnQueryInterface}
- */
-static DECLCALLBACK(void *) virtioScsiDeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface, Device level.}
+ */
+static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
 {
     PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
@@ -2084,17 +2087,17 @@
 }
 
-/**
- * Detach notification.
+
+/*********************************************************************************************************************************
+*   Device interface.                                                                                                            *
+*********************************************************************************************************************************/
+
+/**
+ * @interface_method_impl{PDMDEVREGR3,pfnDetach}
  *
  * One harddisk at one port has been unplugged.
  * The VM is suspended at this point.
- *
- * @param   pDevIns     The device instance.
- * @param   iTarget        The logical unit which is being detached.
- * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
- */
-static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
-{
-    RT_NOREF(fFlags);
+ */
+static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
+{
     PVIRTIOSCSI       pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[iTarget];
@@ -2104,4 +2107,5 @@
     AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
               ("virtio-scsi: Device does not support hotplugging\n"));
+    RT_NOREF(fFlags);
 
     /*
@@ -2113,14 +2117,9 @@
 
 /**
- * Attach command.
+ * @interface_method_impl{PDMDEVREGR3,pfnAttach}
  *
  * This is called when we change block driver.
- *
- * @returns VBox status code.
- * @param   pDevIns     The device instance.
- * @param   iTarget        The logical unit which is being detached.
- * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
- */
-static DECLCALLBACK(int)  virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
+ */
+static DECLCALLBACK(int) virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags)
 {
     PVIRTIOSCSI       pThis   = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
@@ -2159,5 +2158,8 @@
 }
 
-static DECLCALLBACK(int) virtioScsiDestruct(PPDMDEVINS pDevIns)
+/**
+ * @interface_method_impl{PDMDEVREGR3,pfnDestruct}
+ */
+static DECLCALLBACK(int) virtioScsiR3Destruct(PPDMDEVINS pDevIns)
 {
     /*
@@ -2171,7 +2173,7 @@
     RTMemFree(pThis->paTargetInstances);
     pThis->paTargetInstances = NULL;
-    for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
-    {
-        PWORKER pWorker = &pThis->aWorker[qIdx];
+    for (unsigned qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
+    {
+        PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];
         if (pWorker->hEvtProcess != NIL_SUPSEMEVENT)
         {
@@ -2183,6 +2185,9 @@
 }
 
-static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg){
-
+/**
+ * @interface_method_impl{PDMDEVREGR3,pfnConstruct}
+ */
+static DECLCALLBACK(int) virtioScsiR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
+{
     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
 
@@ -2243,5 +2248,5 @@
     pVirtioPciParams->uInterruptPin  = 0x01;
 
-    pThis->IBase.pfnQueryInterface = virtioScsiDeviceQueryInterface;
+    pThis->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
 
     /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */
@@ -2259,12 +2264,12 @@
     rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
                          VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED,
-                         virtioScsiDevCapRead,
-                         virtioScsiDevCapWrite,
-                         virtioScsiStatusChanged,
-                         virtioScsiNotified,
-                         virtioScsiLiveExec,
-                         virtioScsiSaveExec,
-                         virtioScsiLoadExec,
-                         virtioScsiLoadDone,
+                         virtioScsiR3DevCapRead,
+                         virtioScsiR3DevCapWrite,
+                         virtioScsiR3StatusChanged,
+                         virtioScsiR3Notified,
+                         virtioScsiR3LiveExec,
+                         virtioScsiR3SaveExec,
+                         virtioScsiR3LoadExec,
+                         virtioScsiR3LoadDone,
                          sizeof(VIRTIOSCSI_CONFIG_T) /* cbDevSpecificCap */,
                          (void *)&pThis->virtioScsiConfig /* pDevSpecificCap */);
@@ -2273,30 +2278,30 @@
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
 
-    RTStrCopy((char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
-    RTStrCopy((char *)pThis->szQueueNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
+    RTStrCopy(pThis->aszQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");
+    RTStrCopy(pThis->aszQueueNames[EVENTQ_IDX],   VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");
     for (uint16_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)
-        RTStrPrintf((char *)pThis->szQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,
-            "requestq<%d>", qIdx - VIRTQ_REQ_BASE);
+        RTStrPrintf(pThis->aszQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,
+                    "requestq<%d>", qIdx - VIRTQ_REQ_BASE);
 
     for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     {
         rc = virtioQueueAttach(pThis->hVirtio, qIdx, QUEUENAME(qIdx));
-        pThis->fQueueAttached[qIdx] = (rc == VINF_SUCCESS);
+        pThis->afQueueAttached[qIdx] = (rc == VINF_SUCCESS);
 
         if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
         {
-            rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorker[qIdx].pThread,
-                                       (void *)(uint64_t)qIdx, virtioScsiWorker,
-                                       virtioScsiWorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
+            rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorkers[qIdx].pThread,
+                                       (void *)(uintptr_t)qIdx, virtioScsiR3WorkerThread,
+                                       virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
             if (rc != VINF_SUCCESS)
             {
-                LogRel(("Error creating thread for Virtual Queue %s\n", QUEUENAME(qIdx)));
+                LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", QUEUENAME(qIdx), rc));
                 return rc;
             }
 
-            rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorker[qIdx].hEvtProcess);
+            rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorkers[qIdx].hEvtProcess);
             if (RT_FAILURE(rc))
                 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
-                                     N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
+                                           N_("DevVirtioSCSI: Failed to create SUP event semaphore"));
          }
     }
@@ -2306,7 +2311,7 @@
     Log2Func(("Found %d targets attached to controller\n", pThis->cTargets));
 
-     pThis->paTargetInstances = (PVIRTIOSCSITARGET)RTMemAllocZ(sizeof(VIRTIOSCSITARGET) * pThis->cTargets);
-     if (!pThis->paTargetInstances)
-          return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate memory for target states"));
+    pThis->paTargetInstances = (PVIRTIOSCSITARGET)RTMemAllocZ(sizeof(VIRTIOSCSITARGET) * pThis->cTargets);
+    if (!pThis->paTargetInstances)
+        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate memory for target states"));
 
     for (RTUINT iTarget = 0; iTarget < pThis->cTargets; iTarget++)
@@ -2322,20 +2327,20 @@
         pTarget->led.u32Magic = PDMLED_MAGIC;
 
-        pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
+        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
 
         /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
-        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiQueryDeviceLocation;
-        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiIoReqFinish;
-        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiIoReqCopyFromBuf;
-        pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiIoReqCopyToBuf;
-        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiIoReqStateChanged;
-        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiMediumEjected;
+        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
+        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiR3IoReqFinish;
+        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiR3IoReqCopyFromBuf;
+        pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiR3IoReqCopyToBuf;
+        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
+        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
         pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL; /* When used avoids copyFromBuf CopyToBuf*/
         pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
 
 
-        pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
-        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiTargetQueryStatusLed;
-        pThis->ILeds.pfnQueryStatusLed                   = virtioScsiDeviceQueryStatusLed;
+        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
+        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3TargetQueryStatusLed;
+        pThis->ILeds.pfnQueryStatusLed                   = virtioScsiR3DeviceQueryStatusLed;
         pTarget->led.u32Magic                            = PDMLED_MAGIC;
 
@@ -2350,22 +2355,22 @@
             pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA);
             AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
-                         ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget),
-                         VERR_PDM_MISSING_INTERFACE);
+                            ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget),
+                            VERR_PDM_MISSING_INTERFACE);
 
             /* Get the extended media interface. */
             pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX);
             AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
-                         ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget),
-                         VERR_PDM_MISSING_INTERFACE);
+                            ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget),
+                            VERR_PDM_MISSING_INTERFACE);
 
             rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(VIRTIOSCSIREQ));
             AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
-                         ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget),
-                         rc);
+                            ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget),
+                            rc);
 
             pTarget->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIANOTIFY);
             AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
-                         ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n",
-                          iTarget), rc);
+                            ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n", iTarget),
+                            VERR_PDM_MISSING_INTERFACE);
 
         }
@@ -2374,6 +2379,6 @@
             pTarget->fPresent = false;
             pTarget->pDrvBase = NULL;
+            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));
             rc = VINF_SUCCESS;
-            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));
         }
         else
@@ -2395,5 +2400,5 @@
     char szTmp[128];
     RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
-    PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiInfo);
+    PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info);
 
     return rc;
@@ -2430,17 +2435,17 @@
     /* .pszRCMod = */               "VBoxDDRC.rc",
     /* .pszR0Mod = */               "VBoxDDR0.r0",
-    /* .pfnConstruct = */           virtioScsiConstruct,
-    /* .pfnDestruct = */            virtioScsiDestruct,
-    /* .pfnRelocate = */            virtioScsiRelocate,
+    /* .pfnConstruct = */           virtioScsiR3Construct,
+    /* .pfnDestruct = */            virtioScsiR3Destruct,
+    /* .pfnRelocate = */            NULL,
     /* .pfnMemSetup = */            NULL,
     /* .pfnPowerOn = */             NULL,
-    /* .pfnReset = */               virtioScsiReset,
-    /* .pfnSuspend = */             virtioScsiSuspendOrPoweroff,
-    /* .pfnResume = */              virtioScsiResume,
-    /* .pfnAttach = */              virtioScsiAttach,
-    /* .pfnDetach = */              virtioScsiDetach,
+    /* .pfnReset = */               virtioScsiR3Reset,
+    /* .pfnSuspend = */             virtioScsiR3SuspendOrPowerOff,
+    /* .pfnResume = */              virtioScsiR3Resume,
+    /* .pfnAttach = */              virtioScsiR3Attach,
+    /* .pfnDetach = */              virtioScsiR3Detach,
     /* .pfnQueryInterface = */      NULL,
     /* .pfnInitComplete = */        NULL,
-    /* .pfnPowerOff = */            virtioScsiSuspendOrPoweroff,
+    /* .pfnPowerOff = */            virtioScsiR3SuspendOrPowerOff,
     /* .pfnSoftReset = */           NULL,
     /* .pfnReserved0 = */           NULL,
Index: /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
===================================================================
--- /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp	(revision 81633)
+++ /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp	(revision 81634)
@@ -385,34 +385,4 @@
     }
 }
-
-/**
- * NOTE: The consumer (PDM device) must call this function to 'forward' a relocation call.
- *
- * Device relocation callback.
- *
- * When this callback is called the device instance data, and if the
- * device have a GC component, is being relocated, or/and the selectors
- * have been changed. The device must use the chance to perform the
- * necessary pointer relocations and data updates.
- *
- * Before the GC code is executed the first time, this function will be
- * called with a 0 delta so GC pointer calculations can be one in one place.
- *
- * @param   pDevIns     Pointer to the device instance.
- * @param   offDelta    The relocation delta relative to the old location.
- *
- * @remark  A relocation CANNOT fail.
- */
-void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
-{
-    RT_NOREF(offDelta);
-    PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
-    LogFunc(("\n"));
-
-    pVirtio->pDevInsR3 = pDevIns;
-    pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
-    pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
-}
-
 
 /**
@@ -1058,6 +1028,4 @@
 
     pVirtio->pDevInsR3 = pDevIns;
-    pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
-    pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     pVirtio->uDeviceStatus = 0;
     pVirtio->cbDevSpecificCfg = cbDevSpecificCfg;
Index: /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
===================================================================
--- /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h	(revision 81633)
+++ /trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h	(revision 81634)
@@ -132,5 +132,5 @@
  * @param   cbRead      Number of bytes to read
  */
-typedef DECLCALLBACK(int)   FNVIRTIODEVCAPREAD(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbRead);
+typedef DECLCALLBACK(int)   FNVIRTIODEVCAPREAD(PPDMDEVINS pDevIns, uint32_t uOffset, void *pvBuf, uint32_t cbRead);
 typedef FNVIRTIODEVCAPREAD *PFNVIRTIODEVCAPREAD;
 
@@ -140,21 +140,12 @@
 typedef struct VIRTIOCALLBACKS
 {
-     DECLCALLBACKMEMBER(void, pfnVirtioStatusChanged)
-                                  (VIRTIOHANDLE hVirtio, void *pClient, uint32_t fDriverOk);
-     DECLCALLBACKMEMBER(void, pfnVirtioQueueNotified)
-                                  (VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx);
-     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapRead)
-                                  (PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbRead);
-     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapWrite)
-                                  (PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbWrite);
-     DECLCALLBACKMEMBER(int,  pfnSSMDevLiveExec)
-                                  (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
-     DECLCALLBACKMEMBER(int,  pfnSSMDevSaveExec)
-                                  (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
-     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadExec)
-                                  (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
-     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadDone)
-                                  (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
-
+     DECLCALLBACKMEMBER(void, pfnVirtioStatusChanged)(VIRTIOHANDLE hVirtio, void *pClient, uint32_t fDriverOk);
+     DECLCALLBACKMEMBER(void, pfnVirtioQueueNotified)(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx);
+     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapRead)(PPDMDEVINS pDevIns, uint32_t uOffset, void *pvBuf, uint32_t cbRead);
+     DECLCALLBACKMEMBER(int,  pfnVirtioDevCapWrite)(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pvBuf, uint32_t cbWrite);
+     DECLCALLBACKMEMBER(int,  pfnSSMDevLiveExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
+     DECLCALLBACKMEMBER(int,  pfnSSMDevSaveExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadExec)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+     DECLCALLBACKMEMBER(int,  pfnSSMDevLoadDone)(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
 } VIRTIOCALLBACKS, *PVIRTIOCALLBACKS;
 /** @} */
@@ -319,7 +310,4 @@
  */
 uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);
-
-/** CLIENT MUST CALL ON RELOCATE CALLBACK! */
-void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
 
 /**
Index: /trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
===================================================================
--- /trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h	(revision 81633)
+++ /trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h	(revision 81634)
@@ -127,5 +127,5 @@
     struct virtio_pci_cap pciCap;                                /**< Notification MMIO mapping capability      */
     uint32_t uNotifyOffMultiplier;                               /**< notify_off_multiplier                     */
-}  VIRTIO_PCI_NOTIFY_CAP_T,   *PVIRTIO_PCI_NOTIFY_CAP_T;
+} VIRTIO_PCI_NOTIFY_CAP_T, *PVIRTIO_PCI_NOTIFY_CAP_T;
 
 typedef struct virtio_pci_cfg_cap
@@ -133,5 +133,5 @@
     struct virtio_pci_cap pciCap;                                /**< Cap. defines the BAR/off/len to access    */
     uint8_t uPciCfgData[4];                                      /**< I/O buf for above cap.                    */
-} VIRTIO_PCI_CFG_CAP_T,   *PVIRTIO_PCI_CFG_CAP_T;
+} VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T;
 
 /**
@@ -142,52 +142,50 @@
 typedef struct VIRTIOSTATE
 {
-    char                      szInstance[16];                    /**< Instance name, e.g. "VIRTIOSCSI0"         */
-    void *                    pClientContext;                    /**< Client callback returned on callbacks     */
-
-    PPDMDEVINSR3              pDevInsR3;                         /**< Device instance - R3                      */
-    PPDMDEVINSR0              pDevInsR0;                         /**< Device instance - R0                      */
-    PPDMDEVINSRC              pDevInsRC;                         /**< Device instance - RC                      */
-
-    RTGCPHYS                  pGcPhysPciCapBase;                 /**< Pointer to MMIO mapped capability data    */
-    RTGCPHYS                  pGcPhysCommonCfg;                  /**< Pointer to MMIO mapped capability data    */
-    RTGCPHYS                  pGcPhysNotifyCap;                  /**< Pointer to MMIO mapped capability data    */
-    RTGCPHYS                  pGcPhysIsrCap;                     /**< Pointer to MMIO mapped capability data    */
-    RTGCPHYS                  pGcPhysDeviceCap;                  /**< Pointer to MMIO mapped capability data    */
-
-    RTGCPHYS                  pGcPhysQueueDesc[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
-    RTGCPHYS                  pGcPhysQueueAvail[VIRTQ_MAX_CNT];  /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
-    RTGCPHYS                  pGcPhysQueueUsed[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q used structs   GUEST */
-    uint16_t                  uQueueNotifyOff[VIRTQ_MAX_CNT];    /**< (MMIO) per-Q notify offset           HOST */
-    uint16_t                  uQueueMsixVector[VIRTQ_MAX_CNT];   /**< (MMIO) Per-queue vector for MSI-X   GUEST */
-    uint16_t                  uQueueEnable[VIRTQ_MAX_CNT];       /**< (MMIO) Per-queue enable             GUEST */
-    uint16_t                  uQueueSize[VIRTQ_MAX_CNT];         /**< (MMIO) Per-queue size          HOST/GUEST */
-    uint16_t                  uQueueSelect;                      /**< (MMIO) queue selector               GUEST */
-    uint16_t                  padding;
-    uint64_t                  uDeviceFeatures;                   /**< (MMIO) Host features offered         HOST */
-    uint64_t                  uDriverFeatures;                   /**< (MMIO) Host features accepted       GUEST */
-    uint32_t                  uDeviceFeaturesSelect;             /**< (MMIO) hi/lo select uDeviceFeatures GUEST */
-    uint32_t                  uDriverFeaturesSelect;             /**< (MMIO) hi/lo select uDriverFeatures GUEST */
-    uint32_t                  uMsixConfig;                       /**< (MMIO) MSI-X vector                 GUEST */
-    uint32_t                  uNumQueues;                        /**< (MMIO) Actual number of queues      GUEST */
-    uint8_t                   uDeviceStatus;                     /**< (MMIO) Device Status                GUEST */
-    uint8_t                   uPrevDeviceStatus;                 /**< (MMIO) Prev Device Status           GUEST */
-    uint8_t                   uConfigGeneration;                 /**< (MMIO) Device config sequencer       HOST */
-
-    VIRTQSTATE                virtqState[VIRTQ_MAX_CNT];         /**< Local impl-specific queue context         */
-    VIRTIOCALLBACKS           virtioCallbacks;                   /**< Callback vectors to client                */
-
-    PVIRTIO_PCI_CFG_CAP_T     pPciCfgCap;                        /**< Pointer to struct in configuration area   */
-    PVIRTIO_PCI_NOTIFY_CAP_T  pNotifyCap;                        /**< Pointer to struct in configuration area   */
-    PVIRTIO_PCI_CAP_T         pCommonCfgCap;                     /**< Pointer to struct in configuration area   */
-    PVIRTIO_PCI_CAP_T         pIsrCap;                           /**< Pointer to struct in configuration area   */
-    PVIRTIO_PCI_CAP_T         pDeviceCap;                        /**< Pointer to struct in configuration area   */
-
-    uint32_t                  cbDevSpecificCfg;                  /**< Size of client's dev-specific config data */
-    void                     *pDevSpecificCfg;                   /**< Pointer to client's struct                */
-    void                     *pPrevDevSpecificCfg;               /**< Previous read dev-specific cfg of client  */
-    bool                      fGenUpdatePending;                 /**< If set, update cfg gen after driver reads */
-    uint8_t                   uPciCfgDataOff;
-    uint8_t                   uISR;                              /**< Interrupt Status Register.                */
-    uint8_t                   fMsiSupport;
+    char                        szInstance[16];                     /**< Instance name, e.g. "VIRTIOSCSI0"         */
+    R3PTRTYPE(void *)           pClientContext;                     /**< Client callback returned on callbacks     */
+
+    PPDMDEVINSR3                pDevInsR3;                          /**< Device instance - R3                      */
+
+    RTGCPHYS                    pGcPhysPciCapBase;                  /**< Pointer to MMIO mapped capability data    */
+    RTGCPHYS                    pGcPhysCommonCfg;                   /**< Pointer to MMIO mapped capability data    */
+    RTGCPHYS                    pGcPhysNotifyCap;                   /**< Pointer to MMIO mapped capability data    */
+    RTGCPHYS                    pGcPhysIsrCap;                      /**< Pointer to MMIO mapped capability data    */
+    RTGCPHYS                    pGcPhysDeviceCap;                   /**< Pointer to MMIO mapped capability data    */
+
+    RTGCPHYS                    pGcPhysQueueDesc[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q desc structs   GUEST */
+    RTGCPHYS                    pGcPhysQueueAvail[VIRTQ_MAX_CNT];   /**< (MMIO) PhysAdr per-Q avail structs  GUEST */
+    RTGCPHYS                    pGcPhysQueueUsed[VIRTQ_MAX_CNT];    /**< (MMIO) PhysAdr per-Q used structs   GUEST */
+    uint16_t                    uQueueNotifyOff[VIRTQ_MAX_CNT];     /**< (MMIO) per-Q notify offset           HOST */
+    uint16_t                    uQueueMsixVector[VIRTQ_MAX_CNT];    /**< (MMIO) Per-queue vector for MSI-X   GUEST */
+    uint16_t                    uQueueEnable[VIRTQ_MAX_CNT];        /**< (MMIO) Per-queue enable             GUEST */
+    uint16_t                    uQueueSize[VIRTQ_MAX_CNT];          /**< (MMIO) Per-queue size          HOST/GUEST */
+    uint16_t                    uQueueSelect;                       /**< (MMIO) queue selector               GUEST */
+    uint16_t                    padding;
+    uint64_t                    uDeviceFeatures;                    /**< (MMIO) Host features offered         HOST */
+    uint64_t                    uDriverFeatures;                    /**< (MMIO) Host features accepted       GUEST */
+    uint32_t                    uDeviceFeaturesSelect;              /**< (MMIO) hi/lo select uDeviceFeatures GUEST */
+    uint32_t                    uDriverFeaturesSelect;              /**< (MMIO) hi/lo select uDriverFeatures GUEST */
+    uint32_t                    uMsixConfig;                        /**< (MMIO) MSI-X vector                 GUEST */
+    uint32_t                    uNumQueues;                         /**< (MMIO) Actual number of queues      GUEST */
+    uint8_t                     uDeviceStatus;                      /**< (MMIO) Device Status                GUEST */
+    uint8_t                     uPrevDeviceStatus;                  /**< (MMIO) Prev Device Status           GUEST */
+    uint8_t                     uConfigGeneration;                  /**< (MMIO) Device config sequencer       HOST */
+
+    VIRTQSTATE                  virtqState[VIRTQ_MAX_CNT];          /**< Local impl-specific queue context         */
+    VIRTIOCALLBACKS             virtioCallbacks;                    /**< Callback vectors to client                */
+
+    PVIRTIO_PCI_CFG_CAP_T       pPciCfgCap;                         /**< Pointer to struct in configuration area   */
+    PVIRTIO_PCI_NOTIFY_CAP_T    pNotifyCap;                         /**< Pointer to struct in configuration area   */
+    PVIRTIO_PCI_CAP_T           pCommonCfgCap;                      /**< Pointer to struct in configuration area   */
+    PVIRTIO_PCI_CAP_T           pIsrCap;                            /**< Pointer to struct in configuration area   */
+    PVIRTIO_PCI_CAP_T           pDeviceCap;                         /**< Pointer to struct in configuration area   */
+
+    uint32_t                    cbDevSpecificCfg;                   /**< Size of client's dev-specific config data */
+    void                       *pDevSpecificCfg;                    /**< Pointer to client's struct                */
+    void                       *pPrevDevSpecificCfg;                /**< Previous read dev-specific cfg of client  */
+    bool                        fGenUpdatePending;                  /**< If set, update cfg gen after driver reads */
+    uint8_t                     uPciCfgDataOff;
+    uint8_t                     uISR;                               /**< Interrupt Status Register.                */
+    uint8_t                     fMsiSupport;
 
 } VIRTIOSTATE, *PVIRTIOSTATE;
