Changeset 81634 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Nov 4, 2019 1:58:52 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r81628 r81634 3 3 * VBox storage devices - Virtio SCSI Driver 4 4 * 5 * Log-levels used: 6 * - Level 1: The most important (but usually rare) things to note 7 * - Level 2: SCSI command logging 8 * - Level 3: Vector and I/O transfer summary (shows what client sent an expects and fulfillment) 9 * - Level 6: Device ⟷ Guest Driver negotation, traffic, notifications and state handling 10 * - Level 12: Brief formatted hex dumps of I/O data 5 11 */ 6 12 … … 49 55 #include "VBoxDD.h" 50 56 51 /*52 * RT log-levels used:53 *54 * Level 1: The most important (but usually rare) things to note55 * Level 2: SCSI command logging56 * Level 3: Vector and I/O transfer summary (shows what client sent an expects and fulfillment)57 * Level 6: Device ⟷ Guest Driver negotation, traffic, notifications and state handling58 * Level 12: Brief formatted hex dumps of I/O data59 */60 57 61 58 #define LUN0 0 62 59 /** @name VirtIO 1.0 SCSI Host feature bits (See VirtIO 1.0 specification, Section 5.6.3) 63 60 * @{ */ 64 #define VIRTIO_SCSI_F_INOUT RT_BIT_64(0) 65 #define VIRTIO_SCSI_F_HOTPLUG RT_BIT_64(1) 66 #define VIRTIO_SCSI_F_CHANGE RT_BIT_64(2) 67 #define VIRTIO_SCSI_F_T10_PI RT_BIT_64(3) 61 #define VIRTIO_SCSI_F_INOUT RT_BIT_64(0) /** Request is device readable AND writeable */ 62 #define VIRTIO_SCSI_F_HOTPLUG RT_BIT_64(1) /** Host allows hotplugging SCSI LUNs & targets */ 63 #define VIRTIO_SCSI_F_CHANGE RT_BIT_64(2) /** Host LUNs chgs via VIRTIOSCSI_T_PARAM_CHANGE evt */ 64 #define VIRTIO_SCSI_F_T10_PI RT_BIT_64(3) /** Add T10 port info (DIF/DIX) in SCSI req hdr */ 68 65 /** @} */ 69 66 70 67 71 68 #define VIRTIOSCSI_HOST_SCSI_FEATURES_ALL \ 72 69 (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG | VIRTIO_SCSI_F_CHANGE | VIRTIO_SCSI_F_T10_PI) 73 70 74 71 #define VIRTIOSCSI_HOST_SCSI_FEATURES_NONE 0 75 72 76 #define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED \ 77 VIRTIOSCSI_HOST_SCSI_FEATURES_NONE 78 79 #define VIRTIOSCSI_REQ_QUEUE_CNT 1 /**< T.B.D. Consider increasing */ 73 #define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED VIRTIOSCSI_HOST_SCSI_FEATURES_NONE 74 75 #define VIRTIOSCSI_REQ_QUEUE_CNT 1 /**< T.B.D. Consider increasing */ 80 76 #define VIRTIOSCSI_QUEUE_CNT VIRTIOSCSI_REQ_QUEUE_CNT + 2 81 #define VIRTIOSCSI_MAX_LUN 256 /*< VirtIO specification, section 5.6.4 */82 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN 128 /*< T.B.D. What is a good value for this? */83 #define VIRTIOSCSI_MAX_SEG_COUNT 126 /*< T.B.D. What is a good value for this? */84 #define VIRTIOSCSI_MAX_SECTORS_HINT 0x10000 /*< VirtIO specification, section 5.6.4 */85 #define VIRTIOSCSI_MAX_CHANNEL_HINT 0 /*< VirtIO specification, section 5.6.4 should be 0 */86 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION 0x01 87 88 #define PCI_DEVICE_ID_VIRTIOSCSI_HOST 0x1048 89 #define PCI_CLASS_BASE_MASS_STORAGE 0x01 90 #define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER 0x00 91 #define PCI_CLASS_PROG_UNSPECIFIED 0x00 92 #define VIRTIOSCSI_PCI_CLASS 0x01 77 #define VIRTIOSCSI_MAX_LUN 256 /**< VirtIO specification, section 5.6.4 */ 78 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN 128 /**< T.B.D. What is a good value for this? */ 79 #define VIRTIOSCSI_MAX_SEG_COUNT 126 /**< T.B.D. What is a good value for this? */ 80 #define VIRTIOSCSI_MAX_SECTORS_HINT 0x10000 /**< VirtIO specification, section 5.6.4 */ 81 #define VIRTIOSCSI_MAX_CHANNEL_HINT 0 /**< VirtIO specification, section 5.6.4 should be 0 */ 82 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION 0x01 /**< SSM version # */ 83 84 #define PCI_DEVICE_ID_VIRTIOSCSI_HOST 0x1048 /**< Informs guest driver of type of VirtIO device */ 85 #define PCI_CLASS_BASE_MASS_STORAGE 0x01 /**< PCI Mass Storage device class */ 86 #define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER 0x00 /**< PCI SCSI Controller subclass */ 87 #define PCI_CLASS_PROG_UNSPECIFIED 0x00 /**< Programming interface. N/A. */ 88 #define VIRTIOSCSI_PCI_CLASS 0x01 /**< Base class Mass Storage? */ 93 89 94 90 #define VIRTIOSCSI_SENSE_SIZE_DEFAULT 96 /**< VirtIO 1.0: 96 on reset, guest can change */ … … 102 98 * (Note: # of request queues is determined by virtio_scsi_config.num_queues. VirtIO 1.0, 5.6.4) 103 99 */ 104 #define CONTROLQ_IDX 0 105 #define EVENTQ_IDX 1 106 #define VIRTQ_REQ_BASE 2 107 108 #define QUEUENAME(qIdx) (pThis-> szQueueNames[qIdx])/**< Macro to get queue name from its index */100 #define CONTROLQ_IDX 0 /**< Spec-defined Index of control queue */ 101 #define EVENTQ_IDX 1 /**< Spec-defined Index of event queue */ 102 #define VIRTQ_REQ_BASE 2 /**< Spec-defined base index of request queues */ 103 104 #define QUEUENAME(qIdx) (pThis->aszQueueNames[qIdx]) /**< Macro to get queue name from its index */ 109 105 #define CBQUEUENAME(qIdx) RTStrNLen(QUEUENAME(qIdx), sizeof(QUEUENAME(qIdx))) 110 106 111 107 #define IS_REQ_QUEUE(qIdx) (qIdx >= VIRTQ_REQ_BASE && qIdx < VIRTIOSCSI_QUEUE_CNT) 112 108 113 /** 114 * Resolves to boolean true if uOffset matches a field offset and size exactly, 115 * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access) 116 * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1) 117 * (Easily re-written to allow unaligned bounded access to a field). 118 * 119 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T 120 * @result - true or false 121 */ 122 #define MATCH_SCSI_CONFIG(member) \ 123 (RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \ 124 && ( uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 125 || uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \ 126 && cb == sizeof(uint32_t)) \ 127 || (uOffset == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 128 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) 129 130 #define LOG_ACCESSOR(member) \ 131 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \ 132 pv, cb, uIntraOffset, fWrite, false, 0); 133 134 #define SCSI_CONFIG_ACCESSOR(member) \ 135 do \ 136 { \ 137 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 138 if (fWrite) \ 139 memcpy(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \ 140 else \ 141 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \ 142 LOG_ACCESSOR(member); \ 143 } while(0) 144 145 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \ 146 do \ 147 { \ 148 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 149 if (fWrite) \ 150 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 151 else \ 152 { \ 153 memcpy((char *)pv, (const char *)(((char *)&pThis->virtioScsiConfig.member) + uIntraOffset), cb); \ 154 LOG_ACCESSOR(member); \ 155 } \ 156 } while(0) 157 158 #define VIRTIO_IN_DIRECTION(pMediaExTxDirEnumValue) \ 159 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE 160 161 #define VIRTIO_OUT_DIRECTION(pMediaExTxDirEnumValue) \ 162 pMediaExTxDirEnumValue == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE 109 #define VIRTIO_IS_IN_DIRECTION(pMediaExTxDirEnumValue) \ 110 ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE) 111 112 #define VIRTIO_IS_OUT_DIRECTION(pMediaExTxDirEnumValue) \ 113 ((pMediaExTxDirEnumValue) == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE) 114 163 115 /** 164 116 * VirtIO SCSI Host Device device-specific configuration (see VirtIO 1.0, section 5.6.4) … … 168 120 typedef struct virtio_scsi_config 169 121 { 170 uint32_t uNumQueues; /**< num_queues # of req q's exposed by dev*/171 uint32_t uSegMax; /**< seg_max Max # of segs allowed in cmd*/172 uint32_t uMaxSectors; 173 uint32_t uCmdPerLun; /**< cmd_per_lun Max# of link cmd sent per lun */174 uint32_t uEventInfoSize; 175 uint32_t uSenseSize; 176 uint32_t uCdbSize; 177 uint16_t uMaxChannel; 178 uint16_t uMaxTarget; 179 uint32_t uMaxLun; 122 uint32_t uNumQueues; /**< num_queues \# of req q's exposed by dev */ 123 uint32_t uSegMax; /**< seg_max Max \# of segs allowed in cmd */ 124 uint32_t uMaxSectors; /**< max_sectors Hint to guest max xfer to use */ 125 uint32_t uCmdPerLun; /**< cmd_per_lun Max \# of link cmd sent per lun */ 126 uint32_t uEventInfoSize; /**< event_info_size Fill max, evtq bufs */ 127 uint32_t uSenseSize; /**< sense_size Max sense data size dev writes */ 128 uint32_t uCdbSize; /**< cdb_size Max CDB size driver writes */ 129 uint16_t uMaxChannel; /**< max_channel Hint to guest driver */ 130 uint16_t uMaxTarget; /**< max_target Hint to guest driver */ 131 uint32_t uMaxLun; /**< max_lun Hint to guest driver */ 180 132 } VIRTIOSCSI_CONFIG_T, PVIRTIOSCSI_CONFIG_T; 181 133 … … 191 143 * Device operation: eventq 192 144 */ 193 #define VIRTIOSCSI_T_EVENTS_MISSED 0x80000000 194 typedef struct virtio_scsi_event { 145 #define VIRTIOSCSI_T_EVENTS_MISSED UINT32_C(0x80000000) 146 typedef struct virtio_scsi_event 147 { 195 148 // Device-writable part 196 149 uint32_t uEvent; /**< event: */ 197 uint8_t uVirtioLun[8];/**< lun */150 uint8_t abVirtioLun[8]; /**< lun */ 198 151 uint32_t uReason; /**< reason */ 199 152 } VIRTIOSCSI_EVENT_T, *PVIRTIOSCSI_EVENT_T; … … 207 160 208 161 162 163 /** 164 * Device operation: reqestq 165 */ 209 166 #pragma pack(1) 210 211 /** 212 * Device operation: reqestq 213 */ 214 struct REQ_CMD_HDR 215 { 216 uint8_t uVirtioLun[8]; /**< lun */ 167 typedef struct REQ_CMD_HDR_T 168 { 169 uint8_t abVirtioLun[8]; /**< lun */ 217 170 uint64_t uId; /**< id */ 218 171 uint8_t uTaskAttr; /**< task_attr */ 219 172 uint8_t uPrio; /**< prio */ 220 173 uint8_t uCrn; /**< crn */ 221 }; 222 223 struct REQ_CMD_PI 174 } REQ_CMD_HDR_T; 175 #pragma pack() 176 AssertCompileSize(REQ_CMD_HDR_T, 19); 177 178 typedef struct REQ_CMD_PI_T 224 179 { 225 180 uint32_t uPiBytesOut; /**< pi_bytesout */ 226 181 uint32_t uPiBytesIn; /**< pi_bytesin */ 227 }; 228 229 struct REQ_RESP_HDR 230 { 231 uint32_t uSenseLen; /**< sense_len */ 182 } REQ_CMD_PI_T; 183 AssertCompileSize(REQ_CMD_PI_T, 8); 184 185 typedef struct REQ_RESP_HDR_T 186 { 187 uint32_t cbSenseLen; /**< sense_len */ 232 188 uint32_t uResidual; /**< residual */ 233 189 uint16_t uStatusQualifier; /**< status_qualifier */ 234 190 uint8_t uStatus; /**< status SCSI status code */ 235 191 uint8_t uResponse; /**< response */ 236 }; 237 238 typedef struct virtio_scsi_req_cmd 239 { 240 /* Device-readable section */ 241 242 struct REQ_CMD_HDR ReqHdr; 192 } REQ_RESP_HDR_T; 193 AssertCompileSize(REQ_RESP_HDR_T, 12); 194 195 #pragma pack(1) 196 typedef struct VIRTIOSCSI_REQ_CMD_T 197 { 198 /** Device-readable section 199 * @{ */ 200 REQ_CMD_HDR_T ReqHdr; 243 201 uint8_t uCdb[1]; /**< cdb */ 244 202 245 struct REQ_CMD_PI piHdr;/** T10 Pi block integrity (optional feature) */203 REQ_CMD_PI_T piHdr; /** T10 Pi block integrity (optional feature) */ 246 204 uint8_t uPiOut[1]; /**< pi_out[] T10 pi block integrity */ 247 205 uint8_t uDataOut[1]; /**< dataout */ 248 249 /** Device writable section */ 250 251 struct REQ_RESP_HDR respHdr; 206 /** @} */ 207 208 /** @name Device writable section 209 * @{ */ 210 REQ_RESP_HDR_T respHdr; 252 211 uint8_t uSense[1]; /**< sense */ 253 212 uint8_t uPiIn[1]; /**< pi_in[] T10 Pi block integrity */ 254 213 uint8_t uDataIn[1]; /**< detain; */ 255 256 } 214 /** @} */ 215 } VIRTIOSCSI_REQ_CMD_T, *PVIRTIOSCSI_REQ_CMD_T; 257 216 #pragma pack() 217 AssertCompileSize(VIRTIOSCSI_REQ_CMD_T, 19+8+12+6); 258 218 259 219 /** @name VirtIO 1.0 SCSI Host Device Req command-specific response values 260 220 * @{ */ 261 #define VIRTIOSCSI_S_OK 0 /**< control, command */262 #define VIRTIOSCSI_S_OVERRUN 1 /**< control */263 #define VIRTIOSCSI_S_ABORTED 2 /**< control */264 #define VIRTIOSCSI_S_BAD_TARGET 3 /**< control, command */265 #define VIRTIOSCSI_S_RESET 4 /**< control */266 #define VIRTIOSCSI_S_BUSY 5 /**< control, command */267 #define VIRTIOSCSI_S_TRANSPORT_FAILURE 6 /**< control, command */268 #define VIRTIOSCSI_S_TARGET_FAILURE 7 /**< control, command */269 #define VIRTIOSCSI_S_NEXUS_FAILURE 8 /**< control, command */270 #define VIRTIOSCSI_S_FAILURE 9 /**< control, command */271 #define VIRTIOSCSI_S_INCORRECT_LUN 12 /**< command */221 #define VIRTIOSCSI_S_OK 0 /**< control, command */ 222 #define VIRTIOSCSI_S_OVERRUN 1 /**< control */ 223 #define VIRTIOSCSI_S_ABORTED 2 /**< control */ 224 #define VIRTIOSCSI_S_BAD_TARGET 3 /**< control, command */ 225 #define VIRTIOSCSI_S_RESET 4 /**< control */ 226 #define VIRTIOSCSI_S_BUSY 5 /**< control, command */ 227 #define VIRTIOSCSI_S_TRANSPORT_FAILURE 6 /**< control, command */ 228 #define VIRTIOSCSI_S_TARGET_FAILURE 7 /**< control, command */ 229 #define VIRTIOSCSI_S_NEXUS_FAILURE 8 /**< control, command */ 230 #define VIRTIOSCSI_S_FAILURE 9 /**< control, command */ 231 #define VIRTIOSCSI_S_INCORRECT_LUN 12 /**< command */ 272 232 /** @} */ 273 233 274 234 /** @name VirtIO 1.0 SCSI Host Device command-specific task_attr values 275 235 * @{ */ 276 #define VIRTIOSCSI_S_SIMPLE 0 /**< */277 #define VIRTIOSCSI_S_ORDERED 1 /**< */278 #define VIRTIOSCSI_S_HEAD 2 /**< */279 #define VIRTIOSCSI_S_ACA 3 /**< */236 #define VIRTIOSCSI_S_SIMPLE 0 /**< */ 237 #define VIRTIOSCSI_S_ORDERED 1 /**< */ 238 #define VIRTIOSCSI_S_HEAD 2 /**< */ 239 #define VIRTIOSCSI_S_ACA 3 /**< */ 280 240 /** @} */ 281 241 … … 283 243 * VirtIO 1.0 SCSI Host Device Control command before we know type (5.6.6.2) 284 244 */ 285 typedef struct virtio_scsi_ctrl245 typedef struct VIRTIOSCSI_CTRL_T 286 246 { 287 247 uint32_t uType; … … 290 250 /** @name VirtIO 1.0 SCSI Host Device command-specific TMF values 291 251 * @{ */ 292 #define VIRTIOSCSI_T_TMF 0 /**< */293 #define VIRTIOSCSI_T_TMF_ABORT_TASK 0 /**< */294 #define VIRTIOSCSI_T_TMF_ABORT_TASK_SET 1 /**< */295 #define VIRTIOSCSI_T_TMF_CLEAR_ACA 2 /**< */296 #define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET 3 /**< */297 #define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET 4 /**< */298 #define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET 5 /**< */299 #define VIRTIOSCSI_T_TMF_QUERY_TASK 6 /**< */300 #define VIRTIOSCSI_T_TMF_QUERY_TASK_SET 7 /**< */252 #define VIRTIOSCSI_T_TMF 0 /**< */ 253 #define VIRTIOSCSI_T_TMF_ABORT_TASK 0 /**< */ 254 #define VIRTIOSCSI_T_TMF_ABORT_TASK_SET 1 /**< */ 255 #define VIRTIOSCSI_T_TMF_CLEAR_ACA 2 /**< */ 256 #define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET 3 /**< */ 257 #define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET 4 /**< */ 258 #define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET 5 /**< */ 259 #define VIRTIOSCSI_T_TMF_QUERY_TASK 6 /**< */ 260 #define VIRTIOSCSI_T_TMF_QUERY_TASK_SET 7 /**< */ 301 261 /** @} */ 302 262 303 263 #pragma pack(1) 304 typedef struct virtio_scsi_ctrl_tmf264 typedef struct VIRTIOSCSI_CTRL_TMF_T 305 265 { 306 266 // Device-readable part 307 uint32_t uType; /** type*/308 uint32_t uSubtype; /** subtype*/309 uint8_t uScsiLun[8]; /** lun*/310 uint64_t uId; /** id*/267 uint32_t uType; /**< type */ 268 uint32_t uSubtype; /**< subtype */ 269 uint8_t abScsiLun[8]; /**< lun */ 270 uint64_t uId; /**< id */ 311 271 // Device-writable part 312 uint8_t uResponse; /** response*/272 uint8_t uResponse; /**< response */ 313 273 } VIRTIOSCSI_CTRL_TMF_T, *PVIRTIOSCSI_CTRL_TMF_T; 314 274 #pragma pack() 275 AssertCompileSize(VIRTIOSCSI_CTRL_TMF_T, 25); 315 276 316 277 /** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values 317 278 * @{ */ 318 #define VIRTIOSCSI_S_FUNCTION_COMPLETE 0 /**< */319 #define VIRTIOSCSI_S_FUNCTION_SUCCEEDED 10 /**< */320 #define VIRTIOSCSI_S_FUNCTION_REJECTED 11 /**< */279 #define VIRTIOSCSI_S_FUNCTION_COMPLETE 0 /**< */ 280 #define VIRTIOSCSI_S_FUNCTION_SUCCEEDED 10 /**< */ 281 #define VIRTIOSCSI_S_FUNCTION_REJECTED 11 /**< */ 321 282 /** @} */ 322 283 323 #define VIRTIOSCSI_T_AN_QUERY 1 /**Asynchronous notification query */324 #define VIRTIOSCSI_T_AN_SUBSCRIBE 2 /**Asynchronous notification subscription */284 #define VIRTIOSCSI_T_AN_QUERY 1 /**<Asynchronous notification query */ 285 #define VIRTIOSCSI_T_AN_SUBSCRIBE 2 /**<Asynchronous notification subscription */ 325 286 326 287 #pragma pack(1) 327 typedef struct virtio_scsi_ctrl_an288 typedef struct VIRTIOSCSI_CTRL_AN_T 328 289 { 329 290 // Device-readable part 330 uint32_t uType; /** type*/331 uint8_t uScsiLun[8]; /** lun*/332 uint32_t uEventsRequested; /** event_requested*/291 uint32_t uType; /**< type */ 292 uint8_t abScsiLun[8]; /**< lun */ 293 uint32_t fEventsRequested; /**< event_requested */ 333 294 // Device-writable part 334 uint32_t uEventActual; /** event_actual*/335 uint8_t uResponse; /** response*/295 uint32_t uEventActual; /**< event_actual */ 296 uint8_t uResponse; /**< response */ 336 297 } VIRTIOSCSI_CTRL_AN_T, *PVIRTIOSCSI_CTRL_AN_T; 337 298 #pragma pack() 338 339 typedef union virtio_scsi_ctrl_union 340 { 341 VIRTIOSCSI_CTRL_T scsiCtrl; 342 VIRTIOSCSI_CTRL_TMF_T scsiCtrlTmf; 343 VIRTIOSCSI_CTRL_AN_T scsiCtrlAsyncNotify; 299 AssertCompileSize(VIRTIOSCSI_CTRL_AN_T, 21); 300 301 typedef union VIRTIO_SCSI_CTRL_UNION_T 302 { 303 VIRTIOSCSI_CTRL_T scsiCtrl; 304 VIRTIOSCSI_CTRL_TMF_T scsiCtrlTmf; 305 VIRTIOSCSI_CTRL_AN_T scsiCtrlAsyncNotify; 306 uint8_t ab[25]; 344 307 } VIRTIO_SCSI_CTRL_UNION_T, *PVIRTIO_SCSI_CTRL_UNION_T; 308 AssertCompile(sizeof(VIRTIO_SCSI_CTRL_UNION_T) == 28); /* VIRTIOSCSI_CTRL_T forces 4 byte alignment, the other two are byte packed. */ 345 309 346 310 /** @name VirtIO 1.0 SCSI Host Device device specific tmf control response values 347 311 * @{ */ 348 #define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2 /**< */349 #define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 4 /**< */350 #define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST 8 /**< */351 #define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE 16 /**< */352 #define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST 32 /**< */353 #define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY 64 /**< */312 #define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2 /**< */ 313 #define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 4 /**< */ 314 #define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST 8 /**< */ 315 #define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE 16 /**< */ 316 #define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST 32 /**< */ 317 #define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY 64 /**< */ 354 318 /** @} */ 355 319 356 320 #define SUBSCRIBABLE_EVENTS \ 357 358 &VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \359 &VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \360 &VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \361 &VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \362 & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY321 ( VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \ 322 | VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \ 323 | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \ 324 | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \ 325 | VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \ 326 | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY ) 363 327 364 328 /** 365 329 * Worker thread context 366 330 */ 367 typedef struct WORKER 368 { 369 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 370 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 371 bool fSleeping; /**< Flags whether worker thread is sleeping or not */ 372 bool fNotified; /**< Flags whether worker thread notified */ 373 } WORKER, *PWORKER; 331 typedef struct VIRTIOSCSIWORKER 332 { 333 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 334 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 335 bool fSleeping; /**< Flags whether worker thread is sleeping or not */ 336 bool fNotified; /**< Flags whether worker thread notified */ 337 } VIRTIOSCSIWORKER; 338 typedef VIRTIOSCSIWORKER *PVIRTIOSCSIWORKER; 374 339 375 340 /** … … 407 372 PPDMIMEDIANOTIFY pMediaNotify; 408 373 409 374 /** Pointer to the attached driver's extended media interface. */ 410 375 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx; 411 376 … … 419 384 420 385 /** 421 * 386 * PDM instance data (state) for VirtIO Host SCSI device 422 387 * 423 388 * @extends PDMPCIDEV … … 434 399 R3PTRTYPE(PVIRTIOSCSITARGET) paTargetInstances; 435 400 #if HC_ARCH_BITS == 32 436 RTR3PTRR3PtrPadding0;401 RTR3PTR R3PtrPadding0; 437 402 #endif 438 403 439 404 /** Per device-bound virtq worker-thread contexts (eventq slot unused) */ 440 WORKER aWorker[VIRTIOSCSI_QUEUE_CNT];405 VIRTIOSCSIWORKER aWorkers[VIRTIOSCSI_QUEUE_CNT]; 441 406 442 407 bool fBootable; … … 444 409 bool fR0Enabled; 445 410 /** Instance name */ 446 c onst charszInstance[16];411 char szInstance[16]; 447 412 448 413 /** Device-specific spec-based VirtIO queuenames */ 449 c onst charszQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE];414 char aszQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE]; 450 415 451 416 /** Track which VirtIO queues we've attached to */ 452 bool fQueueAttached[VIRTIOSCSI_QUEUE_CNT];417 bool afQueueAttached[VIRTIOSCSI_QUEUE_CNT]; 453 418 454 419 /** Device base interface. */ … … 480 445 481 446 /** Mask of VirtIO Async Event types this device will deliver */ 482 uint32_t uAsyncEvtsEnabled;447 uint32_t fAsyncEvtsEnabled; 483 448 484 449 /** Total number of requests active across all targets */ … … 489 454 490 455 /** Events the guest has subscribed to get notifications of */ 491 uint32_t uSubscribedEvents;456 uint32_t fSubscribedEvents; 492 457 493 458 /** Set if events missed due to lack of bufs avail on eventq */ 494 bool fEventsMissed;459 bool fEventsMissed; 495 460 496 461 /** VirtIO Host SCSI device runtime configuration parameters */ … … 522 487 /** 523 488 * Request structure for IMediaEx (Associated Interfaces implemented by DrvSCSI) 524 * (NOTE: cbIn, cbOUt, cbDataOut mostly for debugging)489 * @note cbIn, cbOUt, cbDataOut mostly for debugging 525 490 */ 526 491 typedef struct VIRTIOSCSIREQ 527 492 { 528 PDMMEDIAEXIOREQ hIoReq; /**< Handle of I/O request */529 PVIRTIOSCSITARGET pTarget; /**< Target */530 uint16_t qIdx; /**< Index of queue this request arrived on */531 PVIRTIO_DESC_CHAIN_T pDescChain; /**< Prepared desc chain pulled from virtq avail ring */532 uint32_t cbDataIn; /**< size of dataout buffer */533 uint32_t cbDataOut; /**< size of dataout buffer */534 uint16_t uDataInOff; /**< Fixed size of respHdr + sense (precede datain) */535 uint16_t uDataOutOff; /**< Fixed size of respHdr + sense (precede datain) */536 uint32_t cbSense ;/**< Size of sense buffer */537 size_t uSenseLen; /**< Receives # bytes written into sense buffer*/538 uint8_t *pbSense; /**< Pointer to R3 sense buffer */539 PDMMEDIAEXIOREQSCSITXDIR enmTxDir; /**< Receives transfer direction of I/O req */540 uint8_t uStatus; /**< SCSI status code */493 PDMMEDIAEXIOREQ hIoReq; /**< Handle of I/O request */ 494 PVIRTIOSCSITARGET pTarget; /**< Target */ 495 uint16_t qIdx; /**< Index of queue this request arrived on */ 496 PVIRTIO_DESC_CHAIN_T pDescChain; /**< Prepared desc chain pulled from virtq avail ring */ 497 uint32_t cbDataIn; /**< size of dataout buffer */ 498 uint32_t cbDataOut; /**< size of dataout buffer */ 499 uint16_t uDataInOff; /**< Fixed size of respHdr + sense (precede datain) */ 500 uint16_t uDataOutOff; /**< Fixed size of respHdr + sense (precede datain) */ 501 uint32_t cbSenseAlloc; /**< Size of sense buffer */ 502 size_t cbSenseLen; /**< Receives \# bytes written into sense buffer */ 503 uint8_t *pbSense; /**< Pointer to R3 sense buffer */ 504 PDMMEDIAEXIOREQSCSITXDIR enmTxDir; /**< Receives transfer direction of I/O req */ 505 uint8_t uStatus; /**< SCSI status code */ 541 506 } VIRTIOSCSIREQ; 507 typedef VIRTIOSCSIREQ *PVIRTIOSCSIREQ; 542 508 543 509 DECLINLINE(const char *) virtioGetTxDirText(uint32_t enmTxDir) … … 590 556 } 591 557 592 DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t uAsyncTypesMask)558 DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, uint32_t cbOutput, uint32_t fAsyncTypesMask) 593 559 { 594 560 RTStrPrintf(pszOutput, cbOutput, "%s%s%s%s%s%s", 595 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) ? "CHANGE_OPERATION " : "", 596 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT) ? "POWER_MGMT " : "", 597 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST) ? "EXTERNAL_REQ " : "", 598 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE) ? "MEDIA_CHANGE " : "", 599 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST) ? "MULTI_HOST " : "", 600 (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY) ? "DEVICE_BUSY " : ""); 601 } 602 603 uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax) 561 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE ? "CHANGE_OPERATION " : "", 562 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT ? "POWER_MGMT " : "", 563 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST ? "EXTERNAL_REQ " : "", 564 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE ? "MEDIA_CHANGE " : "", 565 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST ? "MULTI_HOST " : "", 566 fAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY ? "DEVICE_BUSY " : ""); 567 } 568 569 #ifdef LOG_ENABLED 570 static uint8_t virtioScsiEstimateCdbLen(uint8_t uCmd, uint8_t cbMax) 604 571 { 605 572 if (uCmd < 0x1f) 606 573 return 6; 607 elseif (uCmd >= 0x20 && uCmd < 0x60)574 if (uCmd >= 0x20 && uCmd < 0x60) 608 575 return 10; 609 elseif (uCmd >= 0x60 && uCmd < 0x80)576 if (uCmd >= 0x60 && uCmd < 0x80) 610 577 return cbMax; 611 elseif (uCmd >= 0x80 && uCmd < 0xa0)578 if (uCmd >= 0x80 && uCmd < 0xa0) 612 579 return 16; 613 else if (uCmd >= 0xa0 && uCmd < 0xC0)580 if (uCmd >= 0xa0 && uCmd < 0xc0) 614 581 return 12; 615 else 616 return cbMax; 617 } 618 619 typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ; 620 621 static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason) 582 return cbMax; 583 } 584 #endif /* LOG_ENABLED */ 585 586 587 static int virtioScsiR3SendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason) 622 588 { 623 589 … … 625 591 event.uEvent = uEventType; 626 592 event.uReason = uReason; 627 event.uVirtioLun[0] = 1; 628 event.uVirtioLun[1] = uTarget; 629 event.uVirtioLun[2] = (LUN0 >> 8) & 0x40; 630 event.uVirtioLun[3] = LUN0 & 0xff; 631 event.uVirtioLun[4] = event.uVirtioLun[5] = event.uVirtioLun[6] = event.uVirtioLun[7] = 0; 632 633 switch(uEventType) 593 event.abVirtioLun[0] = 1; 594 event.abVirtioLun[1] = uTarget; 595 event.abVirtioLun[2] = (LUN0 >> 8) & 0x40; 596 event.abVirtioLun[3] = LUN0 & 0xff; 597 event.abVirtioLun[4] = event.abVirtioLun[5] = event.abVirtioLun[6] = event.abVirtioLun[7] = 0; 598 599 /** @todo r=bird: This switch is missing some masking, right? Because 'VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED' 600 * will never end up here but be disregarded in the 'default' case. Given that the only caller of this function 601 * is virtioScsiR3ReportEventsMissed(), I find this a bit confusing. 602 * 603 * For the time being I've added a VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED case to make the code make sense, 604 * but it migth not be what you had in mind. I've also changed uEventType to fEventType since that's more appropriate. */ 605 switch (uEventType) 634 606 { 635 607 case VIRTIOSCSI_T_NO_EVENT: 636 if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED) 637 Log6Func(("(target=%d, LUN=%d) Warning driver that events were missed\n", uTarget, LUN0)); 638 else 639 Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n", 640 uTarget, LUN0)); 608 Log6Func(("(target=%d, LUN=%d): Warning event info guest queued is shorter than configured\n", uTarget, LUN0)); 609 break; 610 case VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED: 611 Log6Func(("(target=%d, LUN=%d): Warning driver that events were missed\n", uTarget, LUN0)); 641 612 break; 642 613 case VIRTIOSCSI_T_TRANSPORT_RESET: 643 switch (uReason)614 switch (uReason) 644 615 { 645 616 case VIRTIOSCSI_EVT_RESET_REMOVED: … … 655 626 break; 656 627 case VIRTIOSCSI_T_ASYNC_NOTIFY: 628 { 629 #ifdef LOG_ENABLED 657 630 char szTypeText[128]; 658 631 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason); 659 Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", 660 uTarget, LUN0, szTypeText)); 632 Log6Func(("(target=%d, LUN=%d): Delivering subscribed async notification %s\n", uTarget, LUN0, szTypeText)); 633 #endif 661 634 break; 635 } 662 636 case VIRTIOSCSI_T_PARAM_CHANGE: 663 637 LogFunc(("(target=%d, LUN=%d): PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n", 664 638 uTarget, LUN0, uReason & 0xff, (uReason >> 8) & 0xff)); 665 639 break; 666 640 default: 667 Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", 668 uTarget, LUN0, uEventType)); 641 Log6Func(("(target=%d, LUN=%d): Unknown event type: %d, ignoring\n", uTarget, LUN0, uEventType)); 669 642 return VINF_SUCCESS; 670 643 } … … 682 655 RTSGBUF reqSegBuf; 683 656 RTSGSEG aReqSegs[] = { { &event, sizeof(event) } }; 684 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));685 686 virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true);657 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 658 659 virtioQueuePut( pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true); 687 660 virtioQueueSync(pThis->hVirtio, EVENTQ_IDX); 688 661 … … 690 663 } 691 664 692 static void virtioScsiFreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq) 665 /** Internal worker. */ 666 static void virtioScsiR3FreeReq(PVIRTIOSCSITARGET pTarget, PVIRTIOSCSIREQ pReq) 693 667 { 694 668 RTMemFree(pReq->pbSense); 669 pReq->pbSense = NULL; 695 670 pTarget->pDrvMediaEx->pfnIoReqFree(pTarget->pDrvMediaEx, pReq->hIoReq); 696 671 } … … 699 674 * This is called to complete a request immediately 700 675 * 701 * @param pThis -PDM driver instance state702 * @param qIdx -Queue index703 * @param pDescChain -Pointer to pre-processed descriptor chain pulled from virtq704 * @param pRespHdr -Response header705 * @param pbSense -Pointer to sense buffer or NULL if none.676 * @param pThis PDM driver instance state 677 * @param qIdx Queue index 678 * @param pDescChain Pointer to pre-processed descriptor chain pulled from virtq 679 * @param pRespHdr Response header 680 * @param pbSense Pointer to sense buffer or NULL if none. 706 681 * 707 * @returns virtual box status code 708 */ 709 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain, 710 struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense) 711 { 712 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 713 AssertReturn(abSenseBuf, VERR_NO_MEMORY); 714 715 const char *pszCtrlRespText = virtioGetReqRespText(pRespHdr->uResponse); 716 Log2Func((" status: %s response: %s\n", 717 SCSIStatusText(pRespHdr->uStatus), pszCtrlRespText)); 718 RT_NOREF(pszCtrlRespText); 682 * @returns VBox status code. 683 */ 684 static int virtioScsiR3ReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain, 685 REQ_RESP_HDR_T *pRespHdr, uint8_t *pbSense) 686 { 687 uint8_t *pabSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 688 AssertReturn(pabSenseBuf, VERR_NO_MEMORY); 689 690 Log2Func((" status: %s response: %s\n", SCSIStatusText(pRespHdr->uStatus), virtioGetReqRespText(pRespHdr->uResponse))); 719 691 720 692 RTSGSEG aReqSegs[2]; … … 722 694 aReqSegs[0].pvSeg = pRespHdr; 723 695 aReqSegs[1].cbSeg = pThis->virtioScsiConfig.uSenseSize; 724 aReqSegs[1].pvSeg = abSenseBuf;725 726 if (pbSense && pRespHdr-> uSenseLen)727 memcpy( abSenseBuf, pbSense, pRespHdr->uSenseLen);696 aReqSegs[1].pvSeg = pabSenseBuf; 697 698 if (pbSense && pRespHdr->cbSenseLen) 699 memcpy(pabSenseBuf, pbSense, pRespHdr->cbSenseLen); 728 700 else 729 pRespHdr-> uSenseLen = 0;701 pRespHdr->cbSenseLen = 0; 730 702 731 703 RTSGBUF reqSegBuf; … … 738 710 virtioQueueSync(pThis->hVirtio, qIdx); 739 711 740 RTMemFree( abSenseBuf);712 RTMemFree(pabSenseBuf); 741 713 742 714 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) … … 748 720 } 749 721 750 static void virtioS enseKeyToVirtioResp(struct REQ_RESP_HDR*respHdr, uint8_t uSenseKey)722 static void virtioScsiR3SenseKeyToVirtioResp(REQ_RESP_HDR_T *respHdr, uint8_t uSenseKey) 751 723 { 752 724 switch (uSenseKey) … … 772 744 } 773 745 } 746 774 747 /** 775 748 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 776 749 */ 777 static DECLCALLBACK(int) virtioScsi IoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,778 void *pvIoReqAlloc, int rcReq)750 static DECLCALLBACK(int) virtioScsiR3IoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 751 void *pvIoReqAlloc, int rcReq) 779 752 { 780 753 RT_NOREF(pInterface); … … 796 769 Assert(!(cbXfer & 0xffffffff00000000)); 797 770 uint32_t cbXfer32 = cbXfer & 0xffffffff; 798 struct REQ_RESP_HDRrespHdr = { 0 };799 respHdr. uSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->uSenseLen;771 REQ_RESP_HDR_T respHdr = { 0 }; 772 respHdr.cbSenseLen = pReq->pbSense[2] == SCSI_SENSE_NONE ? 0 : (uint32_t)pReq->cbSenseLen; 800 773 AssertMsg(!(cbResidual & 0xffffffff00000000), 801 774 ("WARNING: Residual size larger than sizeof(uint32_t), truncating")); … … 811 784 else 812 785 { 813 switch (rcReq)786 switch (rcReq) 814 787 { 815 788 case SCSI_STATUS_OK: … … 818 791 respHdr.uResponse = VIRTIOSCSI_S_OK; 819 792 else 820 virtioS enseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);793 virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]); 821 794 break; 822 795 } 823 796 case SCSI_STATUS_CHECK_CONDITION: 824 virtioS enseKeyToVirtioResp(&respHdr, pReq->pbSense[2]);797 virtioScsiR3SenseKeyToVirtioResp(&respHdr, pReq->pbSense[2]); 825 798 break; 826 799 … … 847 820 const char *pszTxDirText = virtioGetTxDirText(pReq->enmTxDir); 848 821 LogFunc(("xfer direction: %s, sense written = %d, sense size = %d\n", 849 pszTxDirText, respHdr.uSenseLen, pThis->virtioScsiConfig.uSenseSize));822 pszTxDirText, respHdr.cbSenseLen, pThis->virtioScsiConfig.uSenseSize)); 850 823 RT_NOREF(pszTxDirText); 851 824 } 852 825 853 if (respHdr. uSenseLen && LogIs2Enabled())826 if (respHdr.cbSenseLen && LogIs2Enabled()) 854 827 { 855 828 LogFunc(("Sense: %s\n", SCSISenseText(pReq->pbSense[2]))); … … 859 832 int cSegs = 0; 860 833 861 if ( (VIRTIO_I N_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataIn)862 || (VIRTIO_ OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut))834 if ( (VIRTIO_IS_IN_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataIn) 835 || (VIRTIO_IS_OUT_DIRECTION(pReq->enmTxDir) && cbXfer32 > pReq->cbDataOut)) 863 836 { 864 837 Log2Func((" * * * * Data overrun, returning sense\n")); 865 838 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 866 839 0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 }; 867 respHdr. uSenseLen = sizeof(abSense);868 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION;869 respHdr.uResponse = VIRTIOSCSI_S_OVERRUN;870 respHdr.uResidual = pReq->cbDataIn;871 872 virtioScsiR eqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense);840 respHdr.cbSenseLen = sizeof(abSense); 841 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 842 respHdr.uResponse = VIRTIOSCSI_S_OVERRUN; 843 respHdr.uResidual = pReq->cbDataIn; 844 845 virtioScsiR3ReqErr(pThis, pReq->qIdx, pReq->pDescChain, &respHdr, abSense); 873 846 } 874 847 else … … 883 856 884 857 aReqSegs[cSegs].pvSeg = pReq->pbSense; 885 aReqSegs[cSegs++].cbSeg = pReq->cbSense ; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */858 aReqSegs[cSegs++].cbSeg = pReq->cbSenseAlloc; /* VirtIO 1.0 spec 5.6.4/5.6.6.1 */ 886 859 887 860 RTSGBUF reqSegBuf; … … 902 875 } 903 876 904 virtioScsi FreeReq(pTarget, pReq);877 virtioScsiR3FreeReq(pTarget, pReq); 905 878 906 879 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) … … 915 888 * Copy virtual memory from VSCSI layer to guest physical memory 916 889 */ 917 static DECLCALLBACK(int) virtioScsi IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,890 static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 918 891 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy) 919 892 { … … 965 938 * Copy guest physical memory to VSCSI layer virtual memory 966 939 */ 967 static DECLCALLBACK(int) virtioScsi IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,940 static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 968 941 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy) 969 942 { … … 1003 976 } 1004 977 1005 static int virtioScsiReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 978 /** 979 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 980 */ 981 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface) 982 { 983 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 984 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 985 LogFunc(("LUN %d Ejected!\n", pTarget->iTarget)); 986 if (pThis->pMediaNotify) 987 { 988 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY, 989 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 990 pThis->pMediaNotify, pTarget->iTarget); 991 AssertRC(rc); 992 } 993 } 994 995 /** 996 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 997 */ 998 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 999 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 1000 { 1001 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState); 1002 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); 1003 1004 switch (enmState) 1005 { 1006 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 1007 { 1008 /* Stop considering this request active */ 1009 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) 1010 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns)); 1011 break; 1012 } 1013 case PDMMEDIAEXIOREQSTATE_ACTIVE: 1014 ASMAtomicIncU32(&pThis->cActiveReqs); 1015 break; 1016 default: 1017 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 1018 } 1019 } 1020 1021 1022 /********************************************************************************************************************************* 1023 * Worker Thread * 1024 *********************************************************************************************************************************/ 1025 1026 /** 1027 * Handles request queues for/on a worker thread. 1028 * 1029 * @returns VBox status code (logged by caller). 1030 */ 1031 static int virtioScsiR3ReqSubmit(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 1006 1032 { 1007 1033 AssertReturn(pDescChain->cbPhysSend, VERR_INVALID_PARAMETER); … … 1009 1035 ASMAtomicIncU32(&pThis->cActiveReqs); 1010 1036 1011 /* Extract command header and CDB from guest physical memory */ 1012 1013 size_t cbReqHdr = sizeof(struct REQ_CMD_HDR) + pThis->virtioScsiConfig.uCdbSize; 1037 /* 1038 * Extract command header and CDB from guest physical memory 1039 */ 1040 size_t cbReqHdr = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize; 1014 1041 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAlloc(cbReqHdr); 1015 1042 AssertReturn(pVirtqReq, VERR_NO_MEMORY); … … 1024 1051 } 1025 1052 1026 uint8_t uTarget = pVirtqReq->ReqHdr. uVirtioLun[1];1027 uint32_t uScsiLun = (pVirtqReq->ReqHdr. uVirtioLun[2] << 8 | pVirtqReq->ReqHdr.uVirtioLun[3]) & 0x3fff;1053 uint8_t uTarget = pVirtqReq->ReqHdr.abVirtioLun[1]; 1054 uint32_t uScsiLun = (pVirtqReq->ReqHdr.abVirtioLun[2] << 8 | pVirtqReq->ReqHdr.abVirtioLun[3]) & 0x3fff; 1028 1055 PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[uTarget]; 1029 1056 1030 1057 LogFunc(("[%s] (Target: %d LUN: %d) CDB: %.*Rhxs\n", 1031 SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun, 1032 virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], 1033 pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb)); 1058 SCSICmdText(pVirtqReq->uCdb[0]), uTarget, uScsiLun, 1059 virtioScsiEstimateCdbLen(pVirtqReq->uCdb[0], pThis->virtioScsiConfig.uCdbSize), pVirtqReq->uCdb)); 1034 1060 1035 1061 Log3Func(("cmd id: %RX64, attr: %x, prio: %d, crn: %x\n", 1036 pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn));1062 pVirtqReq->ReqHdr.uId, pVirtqReq->ReqHdr.uTaskAttr, pVirtqReq->ReqHdr.uPrio, pVirtqReq->ReqHdr.uCrn)); 1037 1063 1038 1064 /* 1039 1065 * Calculate request offsets 1040 1066 */ 1041 off_t uDataOutOff = sizeof(REQ_CMD_HDR ) + pThis->virtioScsiConfig.uCdbSize;1042 off_t uDataInOff = sizeof(REQ_RESP_HDR ) + pThis->virtioScsiConfig.uSenseSize;1067 off_t uDataOutOff = sizeof(REQ_CMD_HDR_T) + pThis->virtioScsiConfig.uCdbSize; 1068 off_t uDataInOff = sizeof(REQ_RESP_HDR_T) + pThis->virtioScsiConfig.uSenseSize; 1043 1069 uint32_t cbDataOut = pDescChain->cbPhysSend - uDataOutOff; 1044 1070 uint32_t cbDataIn = pDescChain->cbPhysReturn - uDataInOff; 1045 /* *1071 /* 1046 1072 * Handle submission errors 1047 1073 */ … … 1050 1076 { 1051 1077 Log2Func(("Aborting req submission because reset is in progress\n")); 1052 struct REQ_RESP_HDRrespHdr = { 0 };1053 respHdr. uSenseLen = 0;1054 respHdr.uStatus = SCSI_STATUS_OK;1055 respHdr.uResponse = VIRTIOSCSI_S_RESET;1056 respHdr.uResidual = cbDataIn + cbDataOut;1057 virtioScsiR eqErr(pThis, qIdx, pDescChain, &respHdr, NULL);1078 REQ_RESP_HDR_T respHdr = { 0 }; 1079 respHdr.cbSenseLen = 0; 1080 respHdr.uStatus = SCSI_STATUS_OK; 1081 respHdr.uResponse = VIRTIOSCSI_S_RESET; 1082 respHdr.uResidual = cbDataIn + cbDataOut; 1083 virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, NULL); 1058 1084 RTMemFree(pVirtqReq); 1059 1085 return VINF_SUCCESS; 1060 1086 } 1061 else1062 1087 if (RT_UNLIKELY(uScsiLun != 0)) 1063 1088 { … … 1066 1091 0, SCSI_SENSE_ILLEGAL_REQUEST, 1067 1092 0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 }; 1068 struct REQ_RESP_HDRrespHdr = { 0 };1069 respHdr. uSenseLen = sizeof(abSense);1070 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION;1071 respHdr.uResponse = VIRTIOSCSI_S_OK;1072 respHdr.uResidual = cbDataOut + cbDataIn;1073 virtioScsiR eqErr(pThis, qIdx, pDescChain, &respHdr, abSense);1093 REQ_RESP_HDR_T respHdr = { 0 }; 1094 respHdr.cbSenseLen = sizeof(abSense); 1095 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 1096 respHdr.uResponse = VIRTIOSCSI_S_OK; 1097 respHdr.uResidual = cbDataOut + cbDataIn; 1098 virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense); 1074 1099 RTMemFree(pVirtqReq); 1075 1100 return VINF_SUCCESS; 1076 1101 } 1077 else1078 1102 if (RT_UNLIKELY(uTarget >= pThis->cTargets || !pTarget->fPresent)) 1079 1103 { … … 1081 1105 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 1082 1106 0, SCSI_SENSE_NOT_READY, 0, 0, 0, 0, 10, 0, 0, 0 }; 1083 struct REQ_RESP_HDRrespHdr = { 0 };1084 respHdr. uSenseLen = sizeof(abSense);1085 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION;1086 respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET;1087 respHdr.uResidual = cbDataIn + cbDataOut;1088 virtioScsiR eqErr(pThis, qIdx, pDescChain, &respHdr , abSense);1107 REQ_RESP_HDR_T respHdr = { 0 }; 1108 respHdr.cbSenseLen = sizeof(abSense); 1109 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 1110 respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET; 1111 respHdr.uResidual = cbDataIn + cbDataOut; 1112 virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense); 1089 1113 RTMemFree(pVirtqReq); 1090 1114 return VINF_SUCCESS; 1091 1115 } 1092 else1093 1116 if (RT_UNLIKELY(cbDataIn && cbDataOut && !pThis->fHasInOutBufs)) /* VirtIO 1.0, 5.6.6.1.1 */ 1094 1117 { … … 1096 1119 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 1097 1120 0, SCSI_SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 10, 0, 0, 0 }; 1098 struct REQ_RESP_HDRrespHdr = { 0 };1099 respHdr. uSenseLen = sizeof(abSense);1100 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION;1101 respHdr.uResponse = VIRTIOSCSI_S_FAILURE;1102 respHdr.uResidual = cbDataIn + cbDataOut;1103 virtioScsiR eqErr(pThis, qIdx, pDescChain, &respHdr , abSense);1121 REQ_RESP_HDR_T respHdr = { 0 }; 1122 respHdr.cbSenseLen = sizeof(abSense); 1123 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 1124 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 1125 respHdr.uResidual = cbDataIn + cbDataOut; 1126 virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr , abSense); 1104 1127 RTMemFree(pVirtqReq); 1105 1128 return VINF_SUCCESS; … … 1114 1137 1115 1138 int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */, 1116 PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);1139 PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 1117 1140 1118 1141 if (RT_FAILURE(rc)) 1119 1142 { 1120 1143 RTMemFree(pVirtqReq); 1121 virtioScsiFreeReq(pTarget, NULL);1144 /** @todo r=bird: This *will* crash: virtioScsiR3FreeReq(pTarget, NULL); */ 1122 1145 AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc); 1123 1146 } … … 1132 1155 pReq->uDataOutOff = uDataOutOff; 1133 1156 1134 pReq->cbSense = pThis->virtioScsiConfig.uSenseSize; 1135 pReq->pbSense = (uint8_t *)RTMemAlloc(pReq->cbSense); 1136 AssertMsgReturn(pReq->pbSense, ("Out of memory allocating sense buffer"), VERR_NO_MEMORY); 1157 pReq->cbSenseAlloc = pThis->virtioScsiConfig.uSenseSize; 1158 pReq->pbSense = (uint8_t *)RTMemAllocZ(pReq->cbSenseAlloc); 1159 AssertMsgReturnStmt(pReq->pbSense, ("Out of memory allocating sense buffer"), 1160 virtioScsiR3FreeReq(pTarget, pReq); RTMemFree(pVirtqReq), VERR_NO_MEMORY); 1137 1161 1138 1162 /* Note: DrvSCSI allocates one virtual memory buffer for input and output phases of the request */ … … 1140 1164 pVirtqReq->uCdb, (size_t)pThis->virtioScsiConfig.uCdbSize, 1141 1165 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, &pReq->enmTxDir, 1142 (size_t)RT_MAX(cbDataIn, cbDataOut),1143 pReq->pbSense, (size_t)pReq->cbSense, &pReq->uSenseLen,1144 &pReq->uStatus, 30 * RT_MS_1SEC);1166 RT_MAX(cbDataIn, cbDataOut), 1167 pReq->pbSense, pReq->cbSenseAlloc, &pReq->cbSenseLen, 1168 &pReq->uStatus, RT_MS_30SEC); 1145 1169 1146 1170 if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) … … 1150 1174 * and there will be no callback to the finished/completion function for this request 1151 1175 */ 1176 Assert(RT_FAILURE_NP(rc)); 1152 1177 Log2Func(("Request submission error from lower-level driver\n")); 1153 1178 uint8_t uASC, uASCQ = 0; … … 1164 1189 0, SCSI_SENSE_VENDOR_SPECIFIC, 1165 1190 0, 0, 0, 0, 10, uASC, uASCQ, 0 }; 1166 struct REQ_RESP_HDRrespHdr = { 0 };1167 respHdr. uSenseLen = sizeof(abSense);1168 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION;1169 respHdr.uResponse = VIRTIOSCSI_S_FAILURE;1170 respHdr.uResidual = cbDataIn + cbDataOut;1171 virtioScsiR eqErr(pThis, qIdx, pDescChain, &respHdr, abSense);1172 virtioScsi FreeReq(pTarget, pReq);1191 REQ_RESP_HDR_T respHdr = { 0 }; 1192 respHdr.cbSenseLen = sizeof(abSense); 1193 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 1194 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 1195 respHdr.uResidual = cbDataIn + cbDataOut; 1196 virtioScsiR3ReqErr(pThis, qIdx, pDescChain, &respHdr, abSense); 1197 virtioScsiR3FreeReq(pTarget, pReq); 1173 1198 } 1174 1199 … … 1177 1202 } 1178 1203 1179 static int virtioScsiCtrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 1180 { 1181 RT_NOREF2(pThis, qIdx); 1182 1183 uint8_t uResponse = VIRTIOSCSI_S_OK; 1184 1185 PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion = 1186 (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAlloc(sizeof(VIRTIO_SCSI_CTRL_UNION_T)); 1187 1188 uint8_t *pb = (uint8_t *)pScsiCtrlUnion; 1204 /** 1205 * Handles control transfers for/on a worker thread. 1206 * 1207 * @returns VBox status code (ignored by the caller). 1208 * @param pThis The device instance data. 1209 * @param qIdx CONTROLQ_IDX 1210 * @param pDescChain Descriptor chain to process. 1211 */ 1212 static int virtioScsiR3Ctrl(PVIRTIOSCSI pThis, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 1213 { 1214 uint8_t bResponse = VIRTIOSCSI_S_OK; 1215 1216 /* 1217 * Allocate buffer and read in the control request/whatever. 1218 */ 1219 /** @todo r=bird: The following may misbehave if the guest is not feeding you 1220 * sufficient data. There are no size checks below or with the caller 1221 * that I can see, and more importantly you're using RTMemAlloc rather 1222 * than RTMemAllocZ here, so you'll get random heap bytes. 1223 * 1224 * I've changed it to RTMemAllocZ so the memory is all zeroed, but you 1225 * need to consider how to deal with incorrectly sized input. 1226 */ 1227 PVIRTIO_SCSI_CTRL_UNION_T pScsiCtrlUnion = (PVIRTIO_SCSI_CTRL_UNION_T)RTMemAllocZ(sizeof(VIRTIO_SCSI_CTRL_UNION_T)); 1228 AssertPtrReturn(pScsiCtrlUnion, VERR_NO_MEMORY /*ignored*/); 1229 1230 uint8_t *pb = pScsiCtrlUnion->ab; 1189 1231 for (size_t cb = RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T)); cb; ) 1190 1232 { 1191 1233 size_t cbSeg = cb; 1234 /** @todo r=bird: This is ABUSING the RTSgBuf, interchanging host context 1235 * pointers with RTGCPHYS. If we hadn't just dropped 32-bit host 1236 * support, this would have been a serious problem. Now it is just UGLY! */ 1237 AssertCompile(sizeof(RTGCPHYS) == sizeof(void *)); /* ASSUMING RTGCPHYS and host pointers are interchangable. (horrible!) */ 1192 1238 RTGCPHYS GCPhys = (RTGCPHYS)RTSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg); 1193 1239 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pb, cbSeg); … … 1200 1246 * See VirtIO 1.0 specification section 5.6.6.2 1201 1247 */ 1202 uint32_t uSubscribedEvents = 1203 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 1204 | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST 1205 | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE 1206 | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY; 1248 uint32_t fSubscribedEvents = VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 1249 | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST 1250 | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE 1251 | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY; 1207 1252 1208 1253 RTSGBUF reqSegBuf; 1209 1254 1210 1255 1211 switch (pScsiCtrlUnion->scsiCtrl.uType)1256 switch (pScsiCtrlUnion->scsiCtrl.uType) 1212 1257 { 1213 1258 case VIRTIOSCSI_T_TMF: /* Task Management Functions */ 1214 1259 { 1215 uint8_t uTarget = pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[1]; 1216 uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[2] << 8 1217 | pScsiCtrlUnion->scsiCtrlTmf.uScsiLun[3]) & 0x3fff; 1218 if (LogIs2Enabled()) 1219 { 1220 const char *pszTmfTypeText = virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype); 1221 Log2Func(("[%s] (Target: %d LUN: %d) Task Mgt Function: %s\n", 1222 QUEUENAME(qIdx), uTarget, uScsiLun, pszTmfTypeText)); 1223 RT_NOREF3(pszTmfTypeText, uTarget, uScsiLun); 1224 } 1260 uint8_t uTarget = pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[1]; 1261 uint32_t uScsiLun = (pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[2] << 8 1262 | pScsiCtrlUnion->scsiCtrlTmf.abScsiLun[3]) & 0x3fff; 1263 Log2Func(("[%s] (Target: %d LUN: %d) Task Mgt Function: %s\n", 1264 QUEUENAME(qIdx), uTarget, uScsiLun, virtioGetTMFTypeText(pScsiCtrlUnion->scsiCtrlTmf.uSubtype))); 1225 1265 1226 1266 PVIRTIOSCSITARGET pTarget = NULL; … … 1229 1269 1230 1270 if (uTarget >= pThis->cTargets || !pTarget->fPresent) 1231 uResponse = VIRTIOSCSI_S_BAD_TARGET;1271 bResponse = VIRTIOSCSI_S_BAD_TARGET; 1232 1272 else 1233 1273 if (uScsiLun != 0) 1234 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;1274 bResponse = VIRTIOSCSI_S_INCORRECT_LUN; 1235 1275 else 1236 switch(pScsiCtrlUnion->scsiCtrlTmf.uSubtype)1237 {1238 case VIRTIOSCSI_T_TMF_ABORT_TASK:1239 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1240 break;1241 case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:1242 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1243 break;1244 case VIRTIOSCSI_T_TMF_CLEAR_ACA:1245 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1246 break;1247 case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:1248 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1249 break;1250 case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:1251 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1252 break;1253 case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:1254 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1255 break;1256 case VIRTIOSCSI_T_TMF_QUERY_TASK:1257 uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;1258 break;1259 case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:1260 uResponse = VIRTIOSCSI_S_FUNCTION_REJECTED;1261 break;1262 default:1263 LogFunc(("Unknown TMF type\n"));1264 uResponse = VIRTIOSCSI_S_FAILURE;1265 }1266 1267 RTSGSEG aReqSegs[] = { { & uResponse, sizeof(uResponse) } };1268 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));1276 switch (pScsiCtrlUnion->scsiCtrlTmf.uSubtype) 1277 { 1278 case VIRTIOSCSI_T_TMF_ABORT_TASK: 1279 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1280 break; 1281 case VIRTIOSCSI_T_TMF_ABORT_TASK_SET: 1282 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1283 break; 1284 case VIRTIOSCSI_T_TMF_CLEAR_ACA: 1285 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1286 break; 1287 case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET: 1288 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1289 break; 1290 case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET: 1291 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1292 break; 1293 case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET: 1294 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1295 break; 1296 case VIRTIOSCSI_T_TMF_QUERY_TASK: 1297 bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED; 1298 break; 1299 case VIRTIOSCSI_T_TMF_QUERY_TASK_SET: 1300 bResponse = VIRTIOSCSI_S_FUNCTION_REJECTED; 1301 break; 1302 default: 1303 LogFunc(("Unknown TMF type\n")); 1304 bResponse = VIRTIOSCSI_S_FAILURE; 1305 } 1306 1307 RTSGSEG aReqSegs[] = { { &bResponse, sizeof(bResponse) } }; 1308 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 1269 1309 1270 1310 break; … … 1275 1315 PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnQuery = &pScsiCtrlUnion->scsiCtrlAsyncNotify; 1276 1316 1277 uSubscribedEvents &= pScsiCtrlAnQuery->uEventsRequested;1278 1279 uint8_t uTarget = pScsiCtrlAnQuery-> uScsiLun[1];1280 uint32_t uScsiLun = (pScsiCtrlAnQuery-> uScsiLun[2] << 8 | pScsiCtrlAnQuery->uScsiLun[3]) & 0x3fff;1317 fSubscribedEvents &= pScsiCtrlAnQuery->fEventsRequested; 1318 1319 uint8_t uTarget = pScsiCtrlAnQuery->abScsiLun[1]; 1320 uint32_t uScsiLun = (pScsiCtrlAnQuery->abScsiLun[2] << 8 | pScsiCtrlAnQuery->abScsiLun[3]) & 0x3fff; 1281 1321 1282 1322 PVIRTIOSCSITARGET pTarget = NULL; … … 1285 1325 1286 1326 if (uTarget >= pThis->cTargets || !pTarget->fPresent) 1287 uResponse = VIRTIOSCSI_S_BAD_TARGET;1327 bResponse = VIRTIOSCSI_S_BAD_TARGET; 1288 1328 else 1289 1329 if (uScsiLun != 0) 1290 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;1330 bResponse = VIRTIOSCSI_S_INCORRECT_LUN; 1291 1331 else 1292 uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE; 1293 1332 bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE; 1333 1334 #ifdef LOG_ENABLED 1294 1335 if (LogIs2Enabled()) 1295 1336 { 1296 1337 char szTypeText[128]; 1297 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), 1298 pScsiCtrlAnQuery->uEventsRequested); 1338 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnQuery->fEventsRequested); 1299 1339 Log2Func(("[%s] (Target: %d LUN: %d) Async. Notification Query: %s\n", 1300 QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText)); 1301 RT_NOREF3(szTypeText, uTarget, uScsiLun); 1302 1340 QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText)); 1303 1341 } 1304 RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) }, { &uResponse, sizeof(uResponse) } }; 1305 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG)); 1342 #endif 1343 RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) }, { &bResponse, sizeof(bResponse) } }; 1344 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 1306 1345 1307 1346 break; … … 1312 1351 PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnSubscribe = &pScsiCtrlUnion->scsiCtrlAsyncNotify; 1313 1352 1314 if (pScsiCtrlAnSubscribe-> uEventsRequested & ~SUBSCRIBABLE_EVENTS)1315 LogFunc(("Unsupported bits in event subscription event mask: 0x%x\n",1316 pScsiCtrlAnSubscribe->uEventsRequested)); 1317 1318 uSubscribedEvents &= pScsiCtrlAnSubscribe->uEventsRequested;1319 pThis->uAsyncEvtsEnabled = uSubscribedEvents; 1320 1321 uint 8_t uTarget = pScsiCtrlAnSubscribe->uScsiLun[1];1322 uint32_t uScsiLun = (pScsiCtrlAnSubscribe->uScsiLun[2] << 81323 | pScsiCtrlAnSubscribe->uScsiLun[3]) & 0x3fff; 1324 1353 if (pScsiCtrlAnSubscribe->fEventsRequested & ~SUBSCRIBABLE_EVENTS) 1354 LogFunc(("Unsupported bits in event subscription event mask: %#x\n", pScsiCtrlAnSubscribe->fEventsRequested)); 1355 1356 fSubscribedEvents &= pScsiCtrlAnSubscribe->fEventsRequested; 1357 pThis->fAsyncEvtsEnabled = fSubscribedEvents; 1358 1359 uint8_t uTarget = pScsiCtrlAnSubscribe->abScsiLun[1]; 1360 uint32_t uScsiLun = (pScsiCtrlAnSubscribe->abScsiLun[2] << 8 1361 | pScsiCtrlAnSubscribe->abScsiLun[3]) & 0x3fff; 1362 1363 #ifdef LOG_ENABLED 1325 1364 if (LogIs2Enabled()) 1326 1365 { 1327 1366 char szTypeText[128]; 1328 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe-> uEventsRequested);1367 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->fEventsRequested); 1329 1368 Log2Func(("[%s] (Target: %d LUN: %d) Async. Notification Subscribe: %s\n", 1330 QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText)); 1331 RT_NOREF3(szTypeText, uTarget, uScsiLun); 1332 1369 QUEUENAME(qIdx), uTarget, uScsiLun, szTypeText)); 1333 1370 } 1371 #endif 1334 1372 1335 1373 PVIRTIOSCSITARGET pTarget = NULL; … … 1338 1376 1339 1377 if (uTarget >= pThis->cTargets || !pTarget->fPresent) 1340 uResponse = VIRTIOSCSI_S_BAD_TARGET;1378 bResponse = VIRTIOSCSI_S_BAD_TARGET; 1341 1379 else 1342 1380 if (uScsiLun != 0) 1343 uResponse = VIRTIOSCSI_S_INCORRECT_LUN;1381 bResponse = VIRTIOSCSI_S_INCORRECT_LUN; 1344 1382 else 1345 1383 { … … 1348 1386 * and confirm when to use 'complete' vs. 'succeeded' See VirtIO 1.0 spec section 5.6.6.2 1349 1387 * and read SAM docs*/ 1350 if ( uSubscribedEvents == pScsiCtrlAnSubscribe->uEventsRequested)1351 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;1388 if (fSubscribedEvents == pScsiCtrlAnSubscribe->fEventsRequested) 1389 bResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1352 1390 else 1353 uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;1391 bResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE; 1354 1392 } 1355 RTSGSEG aReqSegs[] = { { & uSubscribedEvents, sizeof(uSubscribedEvents) }, { &uResponse, sizeof(uResponse) } };1356 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));1393 RTSGSEG aReqSegs[] = { { &fSubscribedEvents, sizeof(fSubscribedEvents) }, { &bResponse, sizeof(bResponse) } }; 1394 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 1357 1395 1358 1396 break; 1359 1397 } 1360 1398 default: 1361 LogFunc(("Unknown control type extracted from %s: %d\n", 1362 QUEUENAME(qIdx), &pScsiCtrlUnion->scsiCtrl.uType)); 1363 1364 uResponse = VIRTIOSCSI_S_FAILURE; 1365 1366 RTSGSEG aReqSegs[] = { { &uResponse, sizeof(uResponse) } }; 1367 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG)); 1368 } 1369 1370 const char *pszCtrlRespText = virtioGetReqRespText(uResponse); 1371 LogFunc(("Response code: %s\n", pszCtrlRespText)); 1372 RT_NOREF(pszCtrlRespText); 1373 virtioQueuePut (pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true); 1399 { 1400 LogFunc(("Unknown control type extracted from %s: %u\n", QUEUENAME(qIdx), pScsiCtrlUnion->scsiCtrl.uType)); 1401 1402 bResponse = VIRTIOSCSI_S_FAILURE; 1403 1404 RTSGSEG aReqSegs[] = { { &bResponse, sizeof(bResponse) } }; 1405 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 1406 } 1407 } 1408 1409 LogFunc(("Response code: %s\n", virtioGetReqRespText(bResponse))); 1410 virtioQueuePut( pThis->hVirtio, qIdx, &reqSegBuf, pDescChain, true); 1374 1411 virtioQueueSync(pThis->hVirtio, qIdx); 1375 1412 … … 1377 1414 } 1378 1415 1379 /* 1380 * Unblock the worker thread so it can respond to a state change. 1381 * 1382 * @returns VBox status code. 1383 * @param pDevIns The pcnet device instance. 1384 * @param pThread The send thread. 1385 */ 1386 static DECLCALLBACK(int) virtioScsiWorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1416 /** 1417 * @callback_method_impl{FNPDMTHREADWAKEUPDEV} 1418 */ 1419 static DECLCALLBACK(int) virtioScsiR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1387 1420 { 1388 1421 RT_NOREF(pThread); 1389 1422 uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff; 1390 1423 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1391 return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorker[qIdx].hEvtProcess); 1392 } 1393 1394 static int virtioScsiWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1395 { 1396 int rc; 1397 uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff; 1424 return SUPSemEventSignal(pThis->pSupDrvSession, pThis->aWorkers[qIdx].hEvtProcess); 1425 } 1426 1427 /** 1428 * @callback_method_impl{FNPDMTHREADDEV} 1429 */ 1430 static DECLCALLBACK(int) virtioScsiR3WorkerThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1431 { 1432 uint16_t const qIdx = (uint16_t)(uintptr_t)pThread->pvUser; 1398 1433 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1399 P WORKER pWorker = &pThis->aWorker[qIdx];1434 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 1400 1435 1401 1436 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) … … 1413 1448 Log6Func(("%s worker sleeping...\n", QUEUENAME(qIdx))); 1414 1449 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 1415 rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT);1450 int rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); 1416 1451 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 1417 1452 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) … … 1423 1458 } 1424 1459 1425 if (!pThis-> fQueueAttached[qIdx])1460 if (!pThis->afQueueAttached[qIdx]) 1426 1461 { 1427 1462 LogFunc(("%s queue not attached, worker aborting...\n", QUEUENAME(qIdx))); … … 1432 1467 Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx))); 1433 1468 PVIRTIO_DESC_CHAIN_T pDescChain; 1434 rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true);1469 int rc = virtioQueueGet(pThis->hVirtio, qIdx, &pDescChain, true); 1435 1470 if (rc == VERR_NOT_AVAILABLE) 1436 1471 { … … 1441 1476 AssertRC(rc); 1442 1477 if (qIdx == CONTROLQ_IDX) 1443 virtioScsi Ctrl(pThis, qIdx, pDescChain);1478 virtioScsiR3Ctrl(pThis, qIdx, pDescChain); 1444 1479 else /* request queue index */ 1445 1480 { 1446 rc = virtioScsiR eqSubmit(pThis, qIdx, pDescChain);1481 rc = virtioScsiR3ReqSubmit(pThis, qIdx, pDescChain); 1447 1482 if (RT_FAILURE(rc)) 1448 1483 { … … 1456 1491 1457 1492 1458 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget) 1459 { 1460 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0); 1493 /********************************************************************************************************************************* 1494 * Sending evnets 1495 *********************************************************************************************************************************/ 1496 1497 1498 DECLINLINE(void) virtioScsiR3ReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget) 1499 { 1500 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0); 1461 1501 } 1462 1502 1463 1503 #if 0 1464 /* Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization 1504 1505 /** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization 1465 1506 * This effectively removes the SCSI Target/LUN on the guest side 1466 1507 */ 1467 DECLINLINE(void) virtioScsiR eportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)1508 DECLINLINE(void) virtioScsiR3ReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget) 1468 1509 { 1469 1510 if (pThis->fHasHotplug) 1470 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1471 VIRTIOSCSI_EVT_RESET_REMOVED); 1472 } 1473 1474 /* Only invoke thi if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization 1511 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_REMOVED); 1512 } 1513 1514 /** Only invoke this if VIRTIOSCSI_F_HOTPLUG is negotiated during intiailization 1475 1515 * This effectively adds the SCSI Target/LUN on the guest side 1476 1516 */ 1477 DECLINLINE(void) virtioScsiR eportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)1517 DECLINLINE(void) virtioScsiR3ReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget) 1478 1518 { 1479 1519 if (pThis->fHasHotplug) 1480 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1481 VIRTIOSCSI_EVT_RESET_RESCAN); 1482 } 1483 1484 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget) 1485 { 1486 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1487 VIRTIOSCSI_EVT_RESET_HARD); 1488 } 1489 1490 DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1491 { 1492 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) 1493 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1494 VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE); 1495 } 1496 1497 DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget) 1498 { 1499 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT) 1500 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1501 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT); 1502 } 1503 1504 DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget) 1505 { 1506 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST) 1507 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1508 VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST); 1509 } 1510 1511 DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1512 { 1513 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE) 1514 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1515 VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE); 1516 } 1517 1518 DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget) 1519 { 1520 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST) 1521 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1522 VIRTIOSCSI_EVT_ASYNC_MULTI_HOST); 1523 } 1524 1525 DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget) 1526 { 1527 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY) 1528 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1529 VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY); 1530 } 1531 1532 DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier) 1520 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_RESCAN); 1521 } 1522 1523 DECLINLINE(void) virtioScsiR3ReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget) 1524 { 1525 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, VIRTIOSCSI_EVT_RESET_HARD); 1526 } 1527 1528 DECLINLINE(void) virtioScsiR3ReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1529 { 1530 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) 1531 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE); 1532 } 1533 1534 DECLINLINE(void) virtioScsiR3ReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget) 1535 { 1536 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT) 1537 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_POWER_MGMT); 1538 } 1539 1540 DECLINLINE(void) virtioScsiR3ReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget) 1541 { 1542 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST) 1543 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST); 1544 } 1545 1546 DECLINLINE(void) virtioScsiR3ReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1547 { 1548 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE) 1549 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE); 1550 } 1551 1552 DECLINLINE(void) virtioScsiR3ReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget) 1553 { 1554 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST) 1555 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_MULTI_HOST); 1556 } 1557 1558 DECLINLINE(void) virtioScsiR3ReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget) 1559 { 1560 if (pThis->fSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY) 1561 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY); 1562 } 1563 1564 DECLINLINE(void) virtioScsiR3ReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier) 1533 1565 { 1534 1566 uint32_t uReason = uSenseQualifier << 8 | uSenseCode; 1535 virtioScsi SendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);1567 virtioScsiR3SendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason); 1536 1568 1537 1569 } … … 1539 1571 #endif 1540 1572 1541 static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx) 1573 /** 1574 * @callback_method_impl{FNVIRTIOQUEUENOTIFIED} 1575 */ 1576 static DECLCALLBACK(void) virtioScsiR3Notified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx) 1542 1577 { 1543 1578 RT_NOREF(hVirtio); … … 1545 1580 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT); 1546 1581 PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient; 1547 P WORKER pWorker = &pThis->aWorker[qIdx];1582 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 1548 1583 1549 1584 RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX))); … … 1567 1602 Log3Func(("Driver queued buffer(s) to %s\n", QUEUENAME(qIdx))); 1568 1603 if (ASMAtomicXchgBool(&pThis->fEventsMissed, false)) 1569 virtioScsiR eportEventsMissed(pThis, 0);1604 virtioScsiR3ReportEventsMissed(pThis, 0); 1570 1605 } 1571 1606 else … … 1573 1608 } 1574 1609 1575 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient, uint32_t fVirtioReady) 1610 /** 1611 * @callback_method_impl{FNVIRTIOSTATUSCHANGED} 1612 */ 1613 static DECLCALLBACK(void) virtioScsiR3StatusChanged(VIRTIOHANDLE hVirtio, void *pClient, uint32_t fVirtioReady) 1576 1614 { 1577 1615 RT_NOREF(hVirtio); … … 1592 1630 1593 1631 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++) 1594 pThis-> fQueueAttached[i] = true;1632 pThis->afQueueAttached[i] = true; 1595 1633 } 1596 1634 else … … 1598 1636 LogFunc(("VirtIO is resetting\n")); 1599 1637 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++) 1600 pThis->fQueueAttached[i] = false; 1601 } 1602 } 1603 1604 /** 1605 * virtio-scsi debugger info callback. 1606 * 1607 * @param pDevIns The device instance. 1608 * @param pHlp The output helpers. 1609 * @param pszArgs The arguments. 1610 */ 1611 static DECLCALLBACK(void) virtioScsiInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 1638 pThis->afQueueAttached[i] = false; 1639 } 1640 } 1641 1642 1643 /********************************************************************************************************************************* 1644 * Misc * 1645 *********************************************************************************************************************************/ 1646 1647 /** 1648 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-scsi debugger info callback.} 1649 */ 1650 static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 1612 1651 { 1613 1652 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1614 bool fVerbose = false;1615 1653 1616 1654 /* Parse arguments. */ 1617 if (pszArgs) 1618 fVerbose = strstr(pszArgs, "verbose") != NULL; 1655 RT_NOREF(pszArgs); //bool fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL; 1619 1656 1620 1657 /* Show basic information. */ … … 1625 1662 } 1626 1663 1627 /** 1628 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 1629 */ 1630 static DECLCALLBACK(void) virtioScsiMediumEjected(PPDMIMEDIAEXPORT pInterface) 1631 { 1632 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 1633 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 1634 LogFunc(("LUN %d Ejected!\n", pTarget->iTarget)); 1635 if (pThis->pMediaNotify) 1636 { 1637 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY, 1638 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 1639 pThis->pMediaNotify, pTarget->iTarget); 1640 AssertRC(rc); 1641 } 1642 } 1643 1644 /** @callback_method_impl{FNSSMDEVLIVEEXEC} */ 1645 static DECLCALLBACK(int) virtioScsiLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1646 { 1647 LogFunc(("LIVE EXEC!!\n")); 1664 1665 /********************************************************************************************************************************* 1666 * Saved state * 1667 *********************************************************************************************************************************/ 1668 1669 /** 1670 * @callback_method_impl{FNSSMDEVLIVEEXEC} 1671 */ 1672 static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1673 { 1674 LogFunc(("LIVE EXEC!!\n")); 1648 1675 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1649 1676 RT_NOREF(pThis); … … 1653 1680 } 1654 1681 1655 /** @callback_method_impl{FNSSMDEVLOADEXEC} */ 1656 static DECLCALLBACK(int) virtioScsiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1657 { 1658 LogFunc(("LOAD EXEC!!\n")); 1682 /** 1683 * @callback_method_impl{FNSSMDEVLOADEXEC} 1684 */ 1685 static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1686 { 1687 LogFunc(("LOAD EXEC!!\n")); 1659 1688 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1660 1689 SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uNumQueues); … … 1668 1697 SSMR3GetU16(pSSM, &pThis->virtioScsiConfig.uMaxTarget); 1669 1698 SSMR3GetU32(pSSM, &pThis->virtioScsiConfig.uMaxLun); 1670 SSMR3GetU32(pSSM, &pThis-> uAsyncEvtsEnabled);1699 SSMR3GetU32(pSSM, &pThis->fAsyncEvtsEnabled); 1671 1700 SSMR3GetU32(pSSM, (uint32_t *)&pThis->cActiveReqs); 1672 1701 SSMR3GetBool(pSSM, &pThis->fEventsMissed); … … 1680 1709 RT_NOREF(uPass); 1681 1710 RT_NOREF(uVersion); 1682 return VINF_SSM_DONT_CALL_AGAIN; 1683 } 1684 1685 /** @callback_method_impl{FNSSMDEVSAVEEXEC} */ 1686 static DECLCALLBACK(int) virtioScsiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1687 { 1688 LogFunc(("SAVE EXEC!!\n")); 1711 return VINF_SUCCESS; 1712 } 1713 1714 /** 1715 * @callback_method_impl{FNSSMDEVSAVEEXEC} 1716 */ 1717 static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1718 { 1719 LogFunc(("SAVE EXEC!!\n")); 1689 1720 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1690 1721 … … 1699 1730 SSMR3PutU16(pSSM, pThis->virtioScsiConfig.uMaxTarget); 1700 1731 SSMR3PutU32(pSSM, pThis->virtioScsiConfig.uMaxLun); 1701 SSMR3PutU32(pSSM, pThis->uAsyncEvtsEnabled); 1702 SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs); 1732 SSMR3PutU32(pSSM, pThis->fAsyncEvtsEnabled); 1733 SSMR3PutU32(pSSM, (uint32_t)pThis->cActiveReqs); /** @todo r=bird: Shouldn't this be zero? I don't think we can have 1734 * outstanding requests when the VM is suspended (which we are when this 1735 * function is called), and more importantely, I don't understand how they 1736 * would be restored by virtioScsiR3LoadExec. */ 1703 1737 SSMR3PutBool(pSSM, pThis->fEventsMissed); 1704 1738 SSMR3PutU32(pSSM, pThis->fVirtioReady); … … 1708 1742 SSMR3PutU32(pSSM, pThis->fHasLunChange); 1709 1743 SSMR3PutU32(pSSM, pThis->fResetting); 1710 SSMR3PutU32(pSSM, pThis->fQuiescing); 1744 SSMR3PutU32(pSSM, pThis->fQuiescing); /** @todo r=bird: This shall always be false, as the VM is suspended when saving, so no need to save this */ 1711 1745 1712 1746 return VINF_SUCCESS; 1713 1747 } 1714 1748 1715 /** @callback_method_impl{FNSSMDEVLOADDONE} */ 1716 static DECLCALLBACK(int) virtioScsiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1749 /** 1750 * @callback_method_impl{FNSSMDEVLOADDONE} 1751 */ 1752 static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1717 1753 { 1718 1754 LogFunc(("callback")); … … 1723 1759 } 1724 1760 1725 /** 1726 * Is asynchronous handling of suspend or power off notification completed? 1727 * 1728 * This is called to check whether the device has quiesced. Don't deadlock. 1729 * Avoid blocking. Do NOT wait for anything. 1730 * 1731 * @returns true if done, false if more work to be done. 1732 * 1733 * @param pDevIns The device instance. 1734 * @remarks The caller will enter the device critical section. 1735 * @thread EMT(0) 1736 */ 1737 static DECLCALLBACK(bool) virtioScsiDeviceQuiesced(PPDMDEVINS pDevIns) 1761 1762 /********************************************************************************************************************************* 1763 * Device Interface - Misplaced. * 1764 *********************************************************************************************************************************/ 1765 1766 /** 1767 * @callback_method_impl{FNPDMDEVASYNCNOTIFY} 1768 */ 1769 static DECLCALLBACK(bool) virtioScsiR3DeviceQuiesced(PPDMDEVINS pDevIns) 1738 1770 { 1739 1771 LogFunc(("Device I/O activity quiesced.\n")); … … 1745 1777 } 1746 1778 1747 static void virtioScsiQuiesceDevice(PPDMDEVINS pDevIns) 1779 /** 1780 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff(). 1781 */ 1782 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns) 1748 1783 { 1749 1784 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); … … 1752 1787 pThis->fQuiescing = true; 1753 1788 1754 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsi DeviceQuiesced);1789 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3DeviceQuiesced); 1755 1790 1756 1791 /* If already quiesced invoke async callback. */ … … 1760 1795 1761 1796 /** 1762 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 1763 */ 1764 static DECLCALLBACK(void) virtioScsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1765 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 1766 { 1767 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState); 1768 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); 1769 1770 switch (enmState) 1771 { 1772 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 1773 { 1774 /* Stop considering this request active */ 1775 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) 1776 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns)); 1777 break; 1778 } 1779 case PDMMEDIAEXIOREQSTATE_ACTIVE: 1780 ASMAtomicIncU32(&pThis->cActiveReqs); 1781 break; 1782 default: 1783 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 1784 } 1785 } 1786 1787 /** 1788 * @copydoc FNPDMDEVRESET 1789 */ 1790 static DECLCALLBACK(void) virtioScsiReset(PPDMDEVINS pDevIns) 1797 * @inter FNPDMDEVRESET 1798 */ 1799 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns) 1791 1800 { 1792 1801 LogFunc(("\n")); 1793 1802 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1794 1803 pThis->fResetting = true; 1795 virtioScsi QuiesceDevice(pDevIns);1804 virtioScsiR3QuiesceDevice(pDevIns); 1796 1805 } 1797 1806 … … 1799 1808 * @interface_method_impl{PDMDEVREG,pfnResume} 1800 1809 */ 1801 static DECLCALLBACK(void) virtioScsiR esume(PPDMDEVINS pDevIns)1810 static DECLCALLBACK(void) virtioScsiR3Resume(PPDMDEVINS pDevIns) 1802 1811 { 1803 1812 LogFunc(("\n")); … … 1811 1820 * be awake due to new reqs coming in. 1812 1821 */ 1813 1814 { 1815 P WORKER pWorker = &pThis->aWorker[qIdx];1822 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++) 1823 { 1824 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 1816 1825 1817 1826 if (ASMAtomicReadBool(&pWorker->fSleeping)) … … 1830 1839 * @interface_method_impl{PDMDEVREG,pfnSuspend} 1831 1840 */ 1832 static DECLCALLBACK(void) virtioScsi SuspendOrPoweroff(PPDMDEVINS pDevIns)1841 static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns) 1833 1842 { 1834 1843 LogFunc(("\n")); 1835 1844 1836 virtioScsi QuiesceDevice(pDevIns);1845 virtioScsiR3QuiesceDevice(pDevIns); 1837 1846 1838 1847 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); … … 1853 1862 } 1854 1863 1864 1865 /********************************************************************************************************************************* 1866 * LEDs * 1867 *********************************************************************************************************************************/ 1868 1869 #if 0 /** @todo r=bird: LEDs are not being set it seems. */ 1870 1855 1871 /** 1856 1872 * Turns on/off the write status LED. … … 1859 1875 * @param fOn New LED state. 1860 1876 */ 1861 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)1877 static void virtioScsiR3SetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1862 1878 { 1863 1879 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); … … 1865 1881 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1; 1866 1882 else 1867 pTarget->led.Actual.s.fWriting = fOn;1883 pTarget->led.Actual.s.fWriting = 0; 1868 1884 } 1869 1885 … … 1874 1890 * @param fOn New LED state. 1875 1891 */ 1876 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)1892 static void virtioScsiR3SetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1877 1893 { 1878 1894 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); … … 1880 1896 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1; 1881 1897 else 1882 pTarget->led.Actual.s.fReading = fOn; 1883 } 1884 1885 /** 1886 * Gets the pointer to the status LED of a unit. 1887 * 1888 * @returns VBox status code. 1889 * @param pInterface Pointer to the interface structure containing the called function pointer. 1890 * @param iTarget The unit which status LED we desire. 1891 * @param ppLed Where to store the LED pointer. 1892 */ 1893 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1894 { 1895 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed); 1898 pTarget->led.Actual.s.fReading = 0; 1899 } 1900 1901 #endif /* unused*/ 1902 1903 /** 1904 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Target level.} 1905 */ 1906 static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1907 { 1908 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed); 1896 1909 if (iTarget == 0) 1897 1910 { … … 1904 1917 1905 1918 /** 1906 * Gets the pointer to the status LED of a unit. 1907 * 1908 * @returns VBox status code. 1909 * @param pInterface Pointer to the interface structure containing the called function pointer. 1910 * @param iTarget The unit which status LED we desire. 1911 * @param ppLed Where to store the LED pointer. 1912 */ 1913 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1919 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Device level.} 1920 */ 1921 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1914 1922 { 1915 1923 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds); … … 1921 1929 } 1922 1930 return VERR_PDM_LUN_NOT_FOUND; 1923 } 1924 1925 static int virtioScsiCfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset, 1926 const void *pv, uint32_t cb, bool fWrite) 1927 { 1928 1931 } 1932 1933 1934 /********************************************************************************************************************************* 1935 * Virtio config. * 1936 *********************************************************************************************************************************/ 1937 1938 /** 1939 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead. 1940 */ 1941 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite) 1942 { 1929 1943 AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00); 1930 1944 1931 if (MATCH_SCSI_CONFIG(uNumQueues)) 1945 /** 1946 * Resolves to boolean true if uOffset matches a field offset and size exactly, 1947 * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access) 1948 * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1) 1949 * (Easily re-written to allow unaligned bounded access to a field). 1950 * 1951 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T 1952 * @result - true or false 1953 */ 1954 #define MATCH_SCSI_CONFIG(member) \ 1955 ( ( RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \ 1956 && ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 1957 || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \ 1958 && cb == sizeof(uint32_t)) \ 1959 || ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 1960 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) ) 1961 1962 #define LOG_SCSI_CONFIG_ACCESSOR(member) \ 1963 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \ 1964 pv, cb, offIntra, fWrite, false, 0); 1965 1966 #define SCSI_CONFIG_ACCESSOR(member) \ 1967 do \ 1968 { \ 1969 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 1970 if (fWrite) \ 1971 memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \ 1972 else \ 1973 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \ 1974 LOG_SCSI_CONFIG_ACCESSOR(member); \ 1975 } while(0) 1976 1977 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \ 1978 do \ 1979 { \ 1980 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 1981 if (fWrite) \ 1982 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 1983 else \ 1984 { \ 1985 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \ 1986 LOG_SCSI_CONFIG_ACCESSOR(member); \ 1987 } \ 1988 } while(0) 1989 1990 if (MATCH_SCSI_CONFIG( uNumQueues)) 1932 1991 SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues); 1933 else 1934 if (MATCH_SCSI_CONFIG(uSegMax)) 1992 else if (MATCH_SCSI_CONFIG( uSegMax)) 1935 1993 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax); 1936 else 1937 if (MATCH_SCSI_CONFIG(uMaxSectors)) 1994 else if (MATCH_SCSI_CONFIG( uMaxSectors)) 1938 1995 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors); 1939 else 1940 if (MATCH_SCSI_CONFIG(uCmdPerLun)) 1996 else if (MATCH_SCSI_CONFIG( uCmdPerLun)) 1941 1997 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun); 1942 else 1943 if (MATCH_SCSI_CONFIG(uEventInfoSize)) 1998 else if (MATCH_SCSI_CONFIG( uEventInfoSize)) 1944 1999 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize); 1945 else 1946 if (MATCH_SCSI_CONFIG(uSenseSize)) 1947 SCSI_CONFIG_ACCESSOR(uSenseSize); 1948 else 1949 if (MATCH_SCSI_CONFIG(uCdbSize)) 1950 SCSI_CONFIG_ACCESSOR(uCdbSize); 1951 else 1952 if (MATCH_SCSI_CONFIG(uMaxChannel)) 2000 else if (MATCH_SCSI_CONFIG( uSenseSize)) 2001 SCSI_CONFIG_ACCESSOR( uSenseSize); 2002 else if (MATCH_SCSI_CONFIG( uCdbSize)) 2003 SCSI_CONFIG_ACCESSOR( uCdbSize); 2004 else if (MATCH_SCSI_CONFIG( uMaxChannel)) 1953 2005 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel); 1954 else 1955 if (MATCH_SCSI_CONFIG(uMaxTarget)) 2006 else if (MATCH_SCSI_CONFIG( uMaxTarget)) 1956 2007 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget); 1957 else 1958 if (MATCH_SCSI_CONFIG(uMaxLun)) 2008 else if (MATCH_SCSI_CONFIG( uMaxLun)) 1959 2009 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun); 1960 2010 else 1961 2011 { 1962 LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));2012 LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb)); 1963 2013 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1964 2014 } 1965 2015 return VINF_SUCCESS; 1966 } 1967 1968 /** 1969 * virtio-scsi VirtIO Device-specific capabilities read callback 1970 * (other VirtIO capabilities and features are handled in VirtIO implementation) 1971 * 1972 * @param pDevIns The device instance. 1973 * @param uOffset Offset within device specific capabilities struct 1974 * @param pv Buffer in which to save read data 1975 * @param cb Number of bytes to read 1976 */ 1977 static DECLCALLBACK(int) virtioScsiDevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb) 1978 { 1979 int rc = VINF_SUCCESS; 1980 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 1981 1982 rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, false); 1983 1984 return rc; 1985 } 1986 1987 /** 1988 * virtio-scsi VirtIO Device-specific capabilities read callback 1989 * (other VirtIO capabilities and features are handled in VirtIO implementation) 1990 * 1991 * @param pDevIns The device instance. 1992 * @param uOffset Offset within device specific capabilities struct 1993 * @param pv Buffer in which to save read data 1994 * @param cb Number of bytes to write 1995 */ 1996 static DECLCALLBACK(int) virtioScsiDevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb) 1997 { 1998 int rc = VINF_SUCCESS; 1999 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2000 2001 rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, true); 2002 2003 return rc; 2004 } 2005 2006 /** 2007 * Device relocation callback. 2008 * 2009 * When this callback is called the device instance data, and if the 2010 * device have a GC component, is being relocated, or/and the selectors 2011 * have been changed. The device must use the chance to perform the 2012 * necessary pointer relocations and data updates. 2013 * 2014 * Before the GC code is executed the first time, this function will be 2015 * called with a 0 delta so GC pointer calculations can be one in one place. 2016 * 2017 * @param pDevIns Pointer to the device instance. 2018 * @param offDelta The relocation delta relative to the old location. 2019 * 2020 * @remark A relocation CANNOT fail. 2021 */ 2022 static DECLCALLBACK(void) virtioScsiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 2023 { 2024 LogFunc(("Relocating virtio-scsi")); 2025 RT_NOREF(offDelta); 2026 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2027 2028 pThis->pDevInsR3 = pDevIns; 2029 2030 for (uint32_t i = 0; i < pThis->cTargets; i++) 2031 { 2032 PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[i]; 2033 pTarget->pVirtioScsi = pThis; 2034 } 2035 2036 /* 2037 * Important: Forward to virtio framework! 2038 */ 2039 virtioRelocate(pDevIns, offDelta); 2040 2041 } 2042 2043 static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 2044 uint32_t *piInstance, uint32_t *piTarget) 2016 #undef SCSI_CONFIG_ACCESSOR_READONLY 2017 #undef SCSI_CONFIG_ACCESSOR 2018 #undef LOG_ACCESSOR 2019 #undef MATCH_SCSI_CONFIG 2020 } 2021 2022 /** 2023 * @callback_method_impl{FNVIRTIODEVCAPREAD} 2024 */ 2025 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, void *pv, uint32_t cb) 2026 { 2027 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, pv, cb, false /*fRead*/); 2028 } 2029 2030 /** 2031 * @callback_method_impl{FNVIRTIODEVCAPWRITE} 2032 */ 2033 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb) 2034 { 2035 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, (void *)pv, cb, true /*fWrite*/); 2036 } 2037 2038 2039 /********************************************************************************************************************************* 2040 * Will move tomorrow. * 2041 *********************************************************************************************************************************/ 2042 2043 /** 2044 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation, Target level.} 2045 */ 2046 static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 2047 uint32_t *piInstance, uint32_t *piTarget) 2045 2048 { 2046 2049 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort); … … 2059 2062 2060 2063 /** 2061 * @interface_method_impl{PDMIBASE,pfnQueryInterface }2062 */ 2063 static DECLCALLBACK(void *) virtioScsi TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)2064 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Target level.} 2065 */ 2066 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID) 2064 2067 { 2065 2068 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase); … … 2072 2075 2073 2076 /** 2074 * @interface_method_impl{PDMIBASE,pfnQueryInterface }2075 */ 2076 static DECLCALLBACK(void *) virtioScsi DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)2077 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Device level.} 2078 */ 2079 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID) 2077 2080 { 2078 2081 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); … … 2084 2087 } 2085 2088 2086 /** 2087 * Detach notification. 2089 2090 /********************************************************************************************************************************* 2091 * Device interface. * 2092 *********************************************************************************************************************************/ 2093 2094 /** 2095 * @interface_method_impl{PDMDEVREGR3,pfnDetach} 2088 2096 * 2089 2097 * One harddisk at one port has been unplugged. 2090 2098 * The VM is suspended at this point. 2091 * 2092 * @param pDevIns The device instance. 2093 * @param iTarget The logical unit which is being detached. 2094 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2095 */ 2096 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2097 { 2098 RT_NOREF(fFlags); 2099 */ 2100 static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2101 { 2099 2102 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2100 2103 PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[iTarget]; … … 2104 2107 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, 2105 2108 ("virtio-scsi: Device does not support hotplugging\n")); 2109 RT_NOREF(fFlags); 2106 2110 2107 2111 /* … … 2113 2117 2114 2118 /** 2115 * Attach command.2119 * @interface_method_impl{PDMDEVREGR3,pfnAttach} 2116 2120 * 2117 2121 * This is called when we change block driver. 2118 * 2119 * @returns VBox status code. 2120 * @param pDevIns The device instance. 2121 * @param iTarget The logical unit which is being detached. 2122 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2123 */ 2124 static DECLCALLBACK(int) virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2122 */ 2123 static DECLCALLBACK(int) virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iTarget, uint32_t fFlags) 2125 2124 { 2126 2125 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); … … 2159 2158 } 2160 2159 2161 static DECLCALLBACK(int) virtioScsiDestruct(PPDMDEVINS pDevIns) 2160 /** 2161 * @interface_method_impl{PDMDEVREGR3,pfnDestruct} 2162 */ 2163 static DECLCALLBACK(int) virtioScsiR3Destruct(PPDMDEVINS pDevIns) 2162 2164 { 2163 2165 /* … … 2171 2173 RTMemFree(pThis->paTargetInstances); 2172 2174 pThis->paTargetInstances = NULL; 2173 for ( intqIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)2174 { 2175 P WORKER pWorker = &pThis->aWorker[qIdx];2175 for (unsigned qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 2176 { 2177 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 2176 2178 if (pWorker->hEvtProcess != NIL_SUPSEMEVENT) 2177 2179 { … … 2183 2185 } 2184 2186 2185 static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg){ 2186 2187 /** 2188 * @interface_method_impl{PDMDEVREGR3,pfnConstruct} 2189 */ 2190 static DECLCALLBACK(int) virtioScsiR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 2191 { 2187 2192 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 2188 2193 … … 2243 2248 pVirtioPciParams->uInterruptPin = 0x01; 2244 2249 2245 pThis->IBase.pfnQueryInterface = virtioScsi DeviceQueryInterface;2250 pThis->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface; 2246 2251 2247 2252 /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */ … … 2259 2264 rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance, 2260 2265 VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED, 2261 virtioScsi DevCapRead,2262 virtioScsi DevCapWrite,2263 virtioScsi StatusChanged,2264 virtioScsi Notified,2265 virtioScsi LiveExec,2266 virtioScsi SaveExec,2267 virtioScsi LoadExec,2268 virtioScsi LoadDone,2266 virtioScsiR3DevCapRead, 2267 virtioScsiR3DevCapWrite, 2268 virtioScsiR3StatusChanged, 2269 virtioScsiR3Notified, 2270 virtioScsiR3LiveExec, 2271 virtioScsiR3SaveExec, 2272 virtioScsiR3LoadExec, 2273 virtioScsiR3LoadDone, 2269 2274 sizeof(VIRTIOSCSI_CONFIG_T) /* cbDevSpecificCap */, 2270 2275 (void *)&pThis->virtioScsiConfig /* pDevSpecificCap */); … … 2273 2278 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO")); 2274 2279 2275 RTStrCopy( (char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq");2276 RTStrCopy( (char *)pThis->szQueueNames[EVENTQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq");2280 RTStrCopy(pThis->aszQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq"); 2281 RTStrCopy(pThis->aszQueueNames[EVENTQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq"); 2277 2282 for (uint16_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++) 2278 RTStrPrintf( (char *)pThis->szQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE,2279 "requestq<%d>", qIdx - VIRTQ_REQ_BASE);2283 RTStrPrintf(pThis->aszQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE, 2284 "requestq<%d>", qIdx - VIRTQ_REQ_BASE); 2280 2285 2281 2286 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 2282 2287 { 2283 2288 rc = virtioQueueAttach(pThis->hVirtio, qIdx, QUEUENAME(qIdx)); 2284 pThis-> fQueueAttached[qIdx] = (rc == VINF_SUCCESS);2289 pThis->afQueueAttached[qIdx] = (rc == VINF_SUCCESS); 2285 2290 2286 2291 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx)) 2287 2292 { 2288 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorker [qIdx].pThread,2289 (void *)(uint 64_t)qIdx, virtioScsiWorker,2290 virtioScsi WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));2293 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorkers[qIdx].pThread, 2294 (void *)(uintptr_t)qIdx, virtioScsiR3WorkerThread, 2295 virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx)); 2291 2296 if (rc != VINF_SUCCESS) 2292 2297 { 2293 LogRel(("Error creating thread for Virtual Queue %s \n", QUEUENAME(qIdx)));2298 LogRel(("Error creating thread for Virtual Queue %s: %Rrc\n", QUEUENAME(qIdx), rc)); 2294 2299 return rc; 2295 2300 } 2296 2301 2297 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorker [qIdx].hEvtProcess);2302 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->aWorkers[qIdx].hEvtProcess); 2298 2303 if (RT_FAILURE(rc)) 2299 2304 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 2300 N_("DevVirtioSCSI: Failed to create SUP event semaphore"));2305 N_("DevVirtioSCSI: Failed to create SUP event semaphore")); 2301 2306 } 2302 2307 } … … 2306 2311 Log2Func(("Found %d targets attached to controller\n", pThis->cTargets)); 2307 2312 2308 2309 2310 2313 pThis->paTargetInstances = (PVIRTIOSCSITARGET)RTMemAllocZ(sizeof(VIRTIOSCSITARGET) * pThis->cTargets); 2314 if (!pThis->paTargetInstances) 2315 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate memory for target states")); 2311 2316 2312 2317 for (RTUINT iTarget = 0; iTarget < pThis->cTargets; iTarget++) … … 2322 2327 pTarget->led.u32Magic = PDMLED_MAGIC; 2323 2328 2324 pTarget->IBase.pfnQueryInterface = virtioScsi TargetQueryInterface;2329 pTarget->IBase.pfnQueryInterface = virtioScsiR3TargetQueryInterface; 2325 2330 2326 2331 /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */ 2327 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsi QueryDeviceLocation;2328 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsi IoReqFinish;2329 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsi IoReqCopyFromBuf;2330 pTarget->IMediaExPort.pfnIoReqCopyToBuf = virtioScsi IoReqCopyToBuf;2331 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsi IoReqStateChanged;2332 pTarget->IMediaExPort.pfnMediumEjected = virtioScsi MediumEjected;2332 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsiR3QueryDeviceLocation; 2333 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsiR3IoReqFinish; 2334 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsiR3IoReqCopyFromBuf; 2335 pTarget->IMediaExPort.pfnIoReqCopyToBuf = virtioScsiR3IoReqCopyToBuf; 2336 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsiR3IoReqStateChanged; 2337 pTarget->IMediaExPort.pfnMediumEjected = virtioScsiR3MediumEjected; 2333 2338 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL; /* When used avoids copyFromBuf CopyToBuf*/ 2334 2339 pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 2335 2340 2336 2341 2337 pTarget->IBase.pfnQueryInterface = virtioScsi TargetQueryInterface;2338 pTarget->ILed.pfnQueryStatusLed = virtioScsi TargetQueryStatusLed;2339 pThis->ILeds.pfnQueryStatusLed = virtioScsi DeviceQueryStatusLed;2342 pTarget->IBase.pfnQueryInterface = virtioScsiR3TargetQueryInterface; 2343 pTarget->ILed.pfnQueryStatusLed = virtioScsiR3TargetQueryStatusLed; 2344 pThis->ILeds.pfnQueryStatusLed = virtioScsiR3DeviceQueryStatusLed; 2340 2345 pTarget->led.u32Magic = PDMLED_MAGIC; 2341 2346 … … 2350 2355 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA); 2351 2356 AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia), 2352 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget),2353 VERR_PDM_MISSING_INTERFACE);2357 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", iTarget), 2358 VERR_PDM_MISSING_INTERFACE); 2354 2359 2355 2360 /* Get the extended media interface. */ 2356 2361 pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX); 2357 2362 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2358 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget),2359 VERR_PDM_MISSING_INTERFACE);2363 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", iTarget), 2364 VERR_PDM_MISSING_INTERFACE); 2360 2365 2361 2366 rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(VIRTIOSCSIREQ)); 2362 2367 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2363 ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget),2364 rc);2368 ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", iTarget), 2369 rc); 2365 2370 2366 2371 pTarget->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIANOTIFY); 2367 2372 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 2368 ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n",2369 iTarget), rc);2373 ("virtio-scsi configuration error: LUN#%u: Failed to get set Media notify obj!\n", iTarget), 2374 VERR_PDM_MISSING_INTERFACE); 2370 2375 2371 2376 } … … 2374 2379 pTarget->fPresent = false; 2375 2380 pTarget->pDrvBase = NULL; 2381 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName)); 2376 2382 rc = VINF_SUCCESS; 2377 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszTargetName));2378 2383 } 2379 2384 else … … 2395 2400 char szTmp[128]; 2396 2401 RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance); 2397 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsi Info);2402 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info); 2398 2403 2399 2404 return rc; … … 2430 2435 /* .pszRCMod = */ "VBoxDDRC.rc", 2431 2436 /* .pszR0Mod = */ "VBoxDDR0.r0", 2432 /* .pfnConstruct = */ virtioScsi Construct,2433 /* .pfnDestruct = */ virtioScsi Destruct,2434 /* .pfnRelocate = */ virtioScsiRelocate,2437 /* .pfnConstruct = */ virtioScsiR3Construct, 2438 /* .pfnDestruct = */ virtioScsiR3Destruct, 2439 /* .pfnRelocate = */ NULL, 2435 2440 /* .pfnMemSetup = */ NULL, 2436 2441 /* .pfnPowerOn = */ NULL, 2437 /* .pfnReset = */ virtioScsiR eset,2438 /* .pfnSuspend = */ virtioScsi SuspendOrPoweroff,2439 /* .pfnResume = */ virtioScsiR esume,2440 /* .pfnAttach = */ virtioScsi Attach,2441 /* .pfnDetach = */ virtioScsi Detach,2442 /* .pfnReset = */ virtioScsiR3Reset, 2443 /* .pfnSuspend = */ virtioScsiR3SuspendOrPowerOff, 2444 /* .pfnResume = */ virtioScsiR3Resume, 2445 /* .pfnAttach = */ virtioScsiR3Attach, 2446 /* .pfnDetach = */ virtioScsiR3Detach, 2442 2447 /* .pfnQueryInterface = */ NULL, 2443 2448 /* .pfnInitComplete = */ NULL, 2444 /* .pfnPowerOff = */ virtioScsi SuspendOrPoweroff,2449 /* .pfnPowerOff = */ virtioScsiR3SuspendOrPowerOff, 2445 2450 /* .pfnSoftReset = */ NULL, 2446 2451 /* .pfnReserved0 = */ NULL,
Note:
See TracChangeset
for help on using the changeset viewer.