4 * Copyright IBM, Corp. 2010
5 * Copyright Red Hat, Inc. 2011
8 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
9 * Paolo Bonzini <pbonzini@redhat.com>
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
16 #include "virtio-scsi.h"
18 #include <hw/scsi-defs.h>
20 #define VIRTIO_SCSI_VQ_SIZE 128
21 #define VIRTIO_SCSI_CDB_SIZE 32
22 #define VIRTIO_SCSI_SENSE_SIZE 96
23 #define VIRTIO_SCSI_MAX_CHANNEL 0
24 #define VIRTIO_SCSI_MAX_TARGET 255
25 #define VIRTIO_SCSI_MAX_LUN 16383
28 #define VIRTIO_SCSI_S_OK 0
29 #define VIRTIO_SCSI_S_OVERRUN 1
30 #define VIRTIO_SCSI_S_ABORTED 2
31 #define VIRTIO_SCSI_S_BAD_TARGET 3
32 #define VIRTIO_SCSI_S_RESET 4
33 #define VIRTIO_SCSI_S_BUSY 5
34 #define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
35 #define VIRTIO_SCSI_S_TARGET_FAILURE 7
36 #define VIRTIO_SCSI_S_NEXUS_FAILURE 8
37 #define VIRTIO_SCSI_S_FAILURE 9
38 #define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
39 #define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
40 #define VIRTIO_SCSI_S_INCORRECT_LUN 12
42 /* Controlq type codes. */
43 #define VIRTIO_SCSI_T_TMF 0
44 #define VIRTIO_SCSI_T_AN_QUERY 1
45 #define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
47 /* Valid TMF subtypes. */
48 #define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
49 #define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
50 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
51 #define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
52 #define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
53 #define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
54 #define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
55 #define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
58 #define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
59 #define VIRTIO_SCSI_T_NO_EVENT 0
60 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1
61 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
63 /* SCSI command request, followed by data-out */
65 uint8_t lun
[8]; /* Logical Unit Number */
66 uint64_t tag
; /* Command identifier */
67 uint8_t task_attr
; /* Task attribute */
71 } QEMU_PACKED VirtIOSCSICmdReq
;
73 /* Response, followed by sense data and data-in */
75 uint32_t sense_len
; /* Sense data length */
76 uint32_t resid
; /* Residual bytes in data buffer */
77 uint16_t status_qualifier
; /* Status qualifier */
78 uint8_t status
; /* Command completion status */
79 uint8_t response
; /* Response values */
81 } QEMU_PACKED VirtIOSCSICmdResp
;
83 /* Task Management Request */
89 } QEMU_PACKED VirtIOSCSICtrlTMFReq
;
93 } QEMU_PACKED VirtIOSCSICtrlTMFResp
;
95 /* Asynchronous notification query/subscription */
99 uint32_t event_requested
;
100 } QEMU_PACKED VirtIOSCSICtrlANReq
;
103 uint32_t event_actual
;
105 } QEMU_PACKED VirtIOSCSICtrlANResp
;
111 } QEMU_PACKED VirtIOSCSIEvent
;
116 uint32_t max_sectors
;
117 uint32_t cmd_per_lun
;
118 uint32_t event_info_size
;
121 uint16_t max_channel
;
124 } QEMU_PACKED VirtIOSCSIConfig
;
129 VirtIOSCSIConf
*conf
;
140 typedef struct VirtIOSCSIReq
{
143 VirtQueueElement elem
;
148 VirtIOSCSICmdReq
*cmd
;
149 VirtIOSCSICtrlTMFReq
*tmf
;
150 VirtIOSCSICtrlANReq
*an
;
154 VirtIOSCSICmdResp
*cmd
;
155 VirtIOSCSICtrlTMFResp
*tmf
;
156 VirtIOSCSICtrlANResp
*an
;
157 VirtIOSCSIEvent
*event
;
161 static inline int virtio_scsi_get_lun(uint8_t *lun
)
163 return ((lun
[2] << 8) | lun
[3]) & 0x3FFF;
166 static inline SCSIDevice
*virtio_scsi_device_find(VirtIOSCSI
*s
, uint8_t *lun
)
171 if (lun
[2] != 0 && !(lun
[2] >= 0x40 && lun
[2] < 0x80)) {
174 return scsi_device_find(&s
->bus
, 0, lun
[1], virtio_scsi_get_lun(lun
));
177 static void virtio_scsi_complete_req(VirtIOSCSIReq
*req
)
179 VirtIOSCSI
*s
= req
->dev
;
180 VirtQueue
*vq
= req
->vq
;
181 virtqueue_push(vq
, &req
->elem
, req
->qsgl
.size
+ req
->elem
.in_sg
[0].iov_len
);
182 qemu_sglist_destroy(&req
->qsgl
);
184 req
->sreq
->hba_private
= NULL
;
185 scsi_req_unref(req
->sreq
);
188 virtio_notify(&s
->vdev
, vq
);
191 static void virtio_scsi_bad_req(void)
193 error_report("wrong size for virtio-scsi headers");
197 static void qemu_sgl_init_external(QEMUSGList
*qsgl
, struct iovec
*sg
,
198 target_phys_addr_t
*addr
, int num
)
200 memset(qsgl
, 0, sizeof(*qsgl
));
202 qemu_sglist_add(qsgl
, *(addr
++), (sg
++)->iov_len
);
206 static void virtio_scsi_parse_req(VirtIOSCSI
*s
, VirtQueue
*vq
,
209 assert(req
->elem
.out_num
&& req
->elem
.in_num
);
213 req
->req
.buf
= req
->elem
.out_sg
[0].iov_base
;
214 req
->resp
.buf
= req
->elem
.in_sg
[0].iov_base
;
216 if (req
->elem
.out_num
> 1) {
217 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.out_sg
[1],
218 &req
->elem
.out_addr
[1],
219 req
->elem
.out_num
- 1);
221 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.in_sg
[1],
222 &req
->elem
.in_addr
[1],
223 req
->elem
.in_num
- 1);
227 static VirtIOSCSIReq
*virtio_scsi_pop_req(VirtIOSCSI
*s
, VirtQueue
*vq
)
230 req
= g_malloc(sizeof(*req
));
231 if (!virtqueue_pop(vq
, &req
->elem
)) {
236 virtio_scsi_parse_req(s
, vq
, req
);
240 static void virtio_scsi_save_request(QEMUFile
*f
, SCSIRequest
*sreq
)
242 VirtIOSCSIReq
*req
= sreq
->hba_private
;
244 qemu_put_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
247 static void *virtio_scsi_load_request(QEMUFile
*f
, SCSIRequest
*sreq
)
249 SCSIBus
*bus
= sreq
->bus
;
250 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
253 req
= g_malloc(sizeof(*req
));
254 qemu_get_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
255 virtio_scsi_parse_req(s
, s
->cmd_vq
, req
);
259 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
261 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
263 assert(req
->sreq
->cmd
.mode
== req_mode
);
268 static void virtio_scsi_do_tmf(VirtIOSCSI
*s
, VirtIOSCSIReq
*req
)
270 SCSIDevice
*d
= virtio_scsi_device_find(s
, req
->req
.tmf
->lun
);
271 SCSIRequest
*r
, *next
;
275 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
276 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_OK
;
278 switch (req
->req
.tmf
->subtype
) {
279 case VIRTIO_SCSI_T_TMF_ABORT_TASK
:
280 case VIRTIO_SCSI_T_TMF_QUERY_TASK
:
284 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
287 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
288 if (r
->tag
== req
->req
.tmf
->tag
) {
292 if (r
&& r
->hba_private
) {
293 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK
) {
294 /* "If the specified command is present in the task set, then
295 * return a service response set to FUNCTION SUCCEEDED".
297 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
304 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET
:
308 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
312 qdev_reset_all(&d
->qdev
);
316 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET
:
317 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET
:
318 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
:
322 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
325 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
326 if (r
->hba_private
) {
327 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
) {
328 /* "If there is any command present in the task set, then
329 * return a service response set to FUNCTION SUCCEEDED".
331 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
340 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET
:
341 target
= req
->req
.tmf
->lun
[1];
343 QTAILQ_FOREACH(qdev
, &s
->bus
.qbus
.children
, sibling
) {
344 d
= DO_UPCAST(SCSIDevice
, qdev
, qdev
);
345 if (d
->channel
== 0 && d
->id
== target
) {
346 qdev_reset_all(&d
->qdev
);
352 case VIRTIO_SCSI_T_TMF_CLEAR_ACA
:
354 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_REJECTED
;
361 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_INCORRECT_LUN
;
365 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
368 static void virtio_scsi_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
370 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
373 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
374 int out_size
, in_size
;
375 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
376 virtio_scsi_bad_req();
380 out_size
= req
->elem
.out_sg
[0].iov_len
;
381 in_size
= req
->elem
.in_sg
[0].iov_len
;
382 if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_TMF
) {
383 if (out_size
< sizeof(VirtIOSCSICtrlTMFReq
) ||
384 in_size
< sizeof(VirtIOSCSICtrlTMFResp
)) {
385 virtio_scsi_bad_req();
387 virtio_scsi_do_tmf(s
, req
);
389 } else if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_QUERY
||
390 req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_SUBSCRIBE
) {
391 if (out_size
< sizeof(VirtIOSCSICtrlANReq
) ||
392 in_size
< sizeof(VirtIOSCSICtrlANResp
)) {
393 virtio_scsi_bad_req();
395 req
->resp
.an
->event_actual
= 0;
396 req
->resp
.an
->response
= VIRTIO_SCSI_S_OK
;
398 virtio_scsi_complete_req(req
);
402 static void virtio_scsi_command_complete(SCSIRequest
*r
, uint32_t status
,
405 VirtIOSCSIReq
*req
= r
->hba_private
;
407 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
408 req
->resp
.cmd
->status
= status
;
409 if (req
->resp
.cmd
->status
== GOOD
) {
410 req
->resp
.cmd
->resid
= resid
;
412 req
->resp
.cmd
->resid
= 0;
413 req
->resp
.cmd
->sense_len
=
414 scsi_req_get_sense(r
, req
->resp
.cmd
->sense
, VIRTIO_SCSI_SENSE_SIZE
);
416 virtio_scsi_complete_req(req
);
419 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
421 VirtIOSCSIReq
*req
= r
->hba_private
;
426 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
428 VirtIOSCSIReq
*req
= r
->hba_private
;
433 if (req
->dev
->resetting
) {
434 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
436 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
438 virtio_scsi_complete_req(req
);
441 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
443 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
444 virtio_scsi_complete_req(req
);
447 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
449 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
453 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
455 int out_size
, in_size
;
456 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
457 virtio_scsi_bad_req();
460 out_size
= req
->elem
.out_sg
[0].iov_len
;
461 in_size
= req
->elem
.in_sg
[0].iov_len
;
462 if (out_size
< sizeof(VirtIOSCSICmdReq
) + s
->cdb_size
||
463 in_size
< sizeof(VirtIOSCSICmdResp
) + s
->sense_size
) {
464 virtio_scsi_bad_req();
467 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
468 virtio_scsi_fail_cmd_req(req
);
472 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
474 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
475 virtio_scsi_complete_req(req
);
478 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
479 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
480 req
->req
.cmd
->cdb
, req
);
482 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
484 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
486 if (req
->sreq
->cmd
.mode
!= req_mode
||
487 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
488 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
489 virtio_scsi_complete_req(req
);
494 n
= scsi_req_enqueue(req
->sreq
);
496 scsi_req_continue(req
->sreq
);
501 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
504 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
505 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
507 stl_raw(&scsiconf
->num_queues
, s
->conf
->num_queues
);
508 stl_raw(&scsiconf
->seg_max
, 128 - 2);
509 stl_raw(&scsiconf
->max_sectors
, s
->conf
->max_sectors
);
510 stl_raw(&scsiconf
->cmd_per_lun
, s
->conf
->cmd_per_lun
);
511 stl_raw(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
512 stl_raw(&scsiconf
->sense_size
, s
->sense_size
);
513 stl_raw(&scsiconf
->cdb_size
, s
->cdb_size
);
514 stl_raw(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
515 stl_raw(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
516 stl_raw(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
519 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
520 const uint8_t *config
)
522 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
523 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
525 if ((uint32_t) ldl_raw(&scsiconf
->sense_size
) >= 65536 ||
526 (uint32_t) ldl_raw(&scsiconf
->cdb_size
) >= 256) {
527 error_report("bad data written to virtio-scsi configuration space");
531 s
->sense_size
= ldl_raw(&scsiconf
->sense_size
);
532 s
->cdb_size
= ldl_raw(&scsiconf
->cdb_size
);
535 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
536 uint32_t requested_features
)
538 return requested_features
;
541 static void virtio_scsi_reset(VirtIODevice
*vdev
)
543 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
545 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
546 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
549 /* The device does not have anything to save beyond the virtio data.
550 * Request data is saved with callbacks from SCSI devices.
552 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
554 VirtIOSCSI
*s
= opaque
;
555 virtio_save(&s
->vdev
, f
);
558 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
560 VirtIOSCSI
*s
= opaque
;
561 virtio_load(&s
->vdev
, f
);
565 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
567 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
568 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
569 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
571 .complete
= virtio_scsi_command_complete
,
572 .cancel
= virtio_scsi_request_cancelled
,
573 .get_sg_list
= virtio_scsi_get_sg_list
,
574 .save_request
= virtio_scsi_save_request
,
575 .load_request
= virtio_scsi_load_request
,
578 VirtIODevice
*virtio_scsi_init(DeviceState
*dev
, VirtIOSCSIConf
*proxyconf
)
581 static int virtio_scsi_id
;
583 s
= (VirtIOSCSI
*)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI
,
584 sizeof(VirtIOSCSIConfig
),
590 /* TODO set up vdev function pointers */
591 s
->vdev
.get_config
= virtio_scsi_get_config
;
592 s
->vdev
.set_config
= virtio_scsi_set_config
;
593 s
->vdev
.get_features
= virtio_scsi_get_features
;
594 s
->vdev
.reset
= virtio_scsi_reset
;
596 s
->ctrl_vq
= virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
597 virtio_scsi_handle_ctrl
);
598 s
->event_vq
= virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
600 s
->cmd_vq
= virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
601 virtio_scsi_handle_cmd
);
603 scsi_bus_new(&s
->bus
, dev
, &virtio_scsi_scsi_info
);
604 if (!dev
->hotplugged
) {
605 scsi_bus_legacy_handle_cmdline(&s
->bus
);
608 register_savevm(dev
, "virtio-scsi", virtio_scsi_id
++, 1,
609 virtio_scsi_save
, virtio_scsi_load
, s
);
614 void virtio_scsi_exit(VirtIODevice
*vdev
)
616 virtio_cleanup(vdev
);