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_F_INOUT 0
29 #define VIRTIO_SCSI_F_HOTPLUG 1
30 #define VIRTIO_SCSI_F_CHANGE 2
33 #define VIRTIO_SCSI_S_OK 0
34 #define VIRTIO_SCSI_S_OVERRUN 1
35 #define VIRTIO_SCSI_S_ABORTED 2
36 #define VIRTIO_SCSI_S_BAD_TARGET 3
37 #define VIRTIO_SCSI_S_RESET 4
38 #define VIRTIO_SCSI_S_BUSY 5
39 #define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
40 #define VIRTIO_SCSI_S_TARGET_FAILURE 7
41 #define VIRTIO_SCSI_S_NEXUS_FAILURE 8
42 #define VIRTIO_SCSI_S_FAILURE 9
43 #define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
44 #define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
45 #define VIRTIO_SCSI_S_INCORRECT_LUN 12
47 /* Controlq type codes. */
48 #define VIRTIO_SCSI_T_TMF 0
49 #define VIRTIO_SCSI_T_AN_QUERY 1
50 #define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
52 /* Valid TMF subtypes. */
53 #define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
54 #define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
55 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
56 #define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
57 #define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
58 #define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
59 #define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
60 #define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
63 #define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
64 #define VIRTIO_SCSI_T_NO_EVENT 0
65 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1
66 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
67 #define VIRTIO_SCSI_T_PARAM_CHANGE 3
69 /* Reasons for transport reset event */
70 #define VIRTIO_SCSI_EVT_RESET_HARD 0
71 #define VIRTIO_SCSI_EVT_RESET_RESCAN 1
72 #define VIRTIO_SCSI_EVT_RESET_REMOVED 2
74 /* SCSI command request, followed by data-out */
76 uint8_t lun
[8]; /* Logical Unit Number */
77 uint64_t tag
; /* Command identifier */
78 uint8_t task_attr
; /* Task attribute */
82 } QEMU_PACKED VirtIOSCSICmdReq
;
84 /* Response, followed by sense data and data-in */
86 uint32_t sense_len
; /* Sense data length */
87 uint32_t resid
; /* Residual bytes in data buffer */
88 uint16_t status_qualifier
; /* Status qualifier */
89 uint8_t status
; /* Command completion status */
90 uint8_t response
; /* Response values */
92 } QEMU_PACKED VirtIOSCSICmdResp
;
94 /* Task Management Request */
100 } QEMU_PACKED VirtIOSCSICtrlTMFReq
;
104 } QEMU_PACKED VirtIOSCSICtrlTMFResp
;
106 /* Asynchronous notification query/subscription */
110 uint32_t event_requested
;
111 } QEMU_PACKED VirtIOSCSICtrlANReq
;
114 uint32_t event_actual
;
116 } QEMU_PACKED VirtIOSCSICtrlANResp
;
122 } QEMU_PACKED VirtIOSCSIEvent
;
127 uint32_t max_sectors
;
128 uint32_t cmd_per_lun
;
129 uint32_t event_info_size
;
132 uint16_t max_channel
;
135 } QEMU_PACKED VirtIOSCSIConfig
;
140 VirtIOSCSIConf
*conf
;
149 VirtQueue
*cmd_vqs
[0];
152 typedef struct VirtIOSCSIReq
{
155 VirtQueueElement elem
;
160 VirtIOSCSICmdReq
*cmd
;
161 VirtIOSCSICtrlTMFReq
*tmf
;
162 VirtIOSCSICtrlANReq
*an
;
166 VirtIOSCSICmdResp
*cmd
;
167 VirtIOSCSICtrlTMFResp
*tmf
;
168 VirtIOSCSICtrlANResp
*an
;
169 VirtIOSCSIEvent
*event
;
173 static inline int virtio_scsi_get_lun(uint8_t *lun
)
175 return ((lun
[2] << 8) | lun
[3]) & 0x3FFF;
178 static inline SCSIDevice
*virtio_scsi_device_find(VirtIOSCSI
*s
, uint8_t *lun
)
183 if (lun
[2] != 0 && !(lun
[2] >= 0x40 && lun
[2] < 0x80)) {
186 return scsi_device_find(&s
->bus
, 0, lun
[1], virtio_scsi_get_lun(lun
));
189 static void virtio_scsi_complete_req(VirtIOSCSIReq
*req
)
191 VirtIOSCSI
*s
= req
->dev
;
192 VirtQueue
*vq
= req
->vq
;
193 virtqueue_push(vq
, &req
->elem
, req
->qsgl
.size
+ req
->elem
.in_sg
[0].iov_len
);
194 qemu_sglist_destroy(&req
->qsgl
);
196 req
->sreq
->hba_private
= NULL
;
197 scsi_req_unref(req
->sreq
);
200 virtio_notify(&s
->vdev
, vq
);
203 static void virtio_scsi_bad_req(void)
205 error_report("wrong size for virtio-scsi headers");
209 static void qemu_sgl_init_external(QEMUSGList
*qsgl
, struct iovec
*sg
,
210 target_phys_addr_t
*addr
, int num
)
212 memset(qsgl
, 0, sizeof(*qsgl
));
214 qemu_sglist_add(qsgl
, *(addr
++), (sg
++)->iov_len
);
218 static void virtio_scsi_parse_req(VirtIOSCSI
*s
, VirtQueue
*vq
,
221 assert(req
->elem
.in_num
);
225 if (req
->elem
.out_num
) {
226 req
->req
.buf
= req
->elem
.out_sg
[0].iov_base
;
228 req
->resp
.buf
= req
->elem
.in_sg
[0].iov_base
;
230 if (req
->elem
.out_num
> 1) {
231 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.out_sg
[1],
232 &req
->elem
.out_addr
[1],
233 req
->elem
.out_num
- 1);
235 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.in_sg
[1],
236 &req
->elem
.in_addr
[1],
237 req
->elem
.in_num
- 1);
241 static VirtIOSCSIReq
*virtio_scsi_pop_req(VirtIOSCSI
*s
, VirtQueue
*vq
)
244 req
= g_malloc(sizeof(*req
));
245 if (!virtqueue_pop(vq
, &req
->elem
)) {
250 virtio_scsi_parse_req(s
, vq
, req
);
254 static void virtio_scsi_save_request(QEMUFile
*f
, SCSIRequest
*sreq
)
256 VirtIOSCSIReq
*req
= sreq
->hba_private
;
257 uint32_t n
= virtio_queue_get_id(req
->vq
) - 2;
259 assert(n
< req
->dev
->conf
->num_queues
);
260 qemu_put_be32s(f
, &n
);
261 qemu_put_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
264 static void *virtio_scsi_load_request(QEMUFile
*f
, SCSIRequest
*sreq
)
266 SCSIBus
*bus
= sreq
->bus
;
267 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
271 req
= g_malloc(sizeof(*req
));
272 qemu_get_be32s(f
, &n
);
273 assert(n
< s
->conf
->num_queues
);
274 qemu_get_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
275 virtio_scsi_parse_req(s
, s
->cmd_vqs
[n
], req
);
279 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
281 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
283 assert(req
->sreq
->cmd
.mode
== req_mode
);
288 static void virtio_scsi_do_tmf(VirtIOSCSI
*s
, VirtIOSCSIReq
*req
)
290 SCSIDevice
*d
= virtio_scsi_device_find(s
, req
->req
.tmf
->lun
);
291 SCSIRequest
*r
, *next
;
295 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
296 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_OK
;
298 switch (req
->req
.tmf
->subtype
) {
299 case VIRTIO_SCSI_T_TMF_ABORT_TASK
:
300 case VIRTIO_SCSI_T_TMF_QUERY_TASK
:
304 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
307 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
308 VirtIOSCSIReq
*cmd_req
= r
->hba_private
;
309 if (cmd_req
&& cmd_req
->req
.cmd
->tag
== req
->req
.tmf
->tag
) {
315 * Assert that the request has not been completed yet, we
316 * check for it in the loop above.
318 assert(r
->hba_private
);
319 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK
) {
320 /* "If the specified command is present in the task set, then
321 * return a service response set to FUNCTION SUCCEEDED".
323 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
330 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET
:
334 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
338 qdev_reset_all(&d
->qdev
);
342 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET
:
343 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET
:
344 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
:
348 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
351 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
352 if (r
->hba_private
) {
353 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
) {
354 /* "If there is any command present in the task set, then
355 * return a service response set to FUNCTION SUCCEEDED".
357 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
366 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET
:
367 target
= req
->req
.tmf
->lun
[1];
369 QTAILQ_FOREACH(kid
, &s
->bus
.qbus
.children
, sibling
) {
370 d
= DO_UPCAST(SCSIDevice
, qdev
, kid
->child
);
371 if (d
->channel
== 0 && d
->id
== target
) {
372 qdev_reset_all(&d
->qdev
);
378 case VIRTIO_SCSI_T_TMF_CLEAR_ACA
:
380 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_REJECTED
;
387 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_INCORRECT_LUN
;
391 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
394 static void virtio_scsi_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
396 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
399 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
400 int out_size
, in_size
;
401 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
402 virtio_scsi_bad_req();
406 out_size
= req
->elem
.out_sg
[0].iov_len
;
407 in_size
= req
->elem
.in_sg
[0].iov_len
;
408 if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_TMF
) {
409 if (out_size
< sizeof(VirtIOSCSICtrlTMFReq
) ||
410 in_size
< sizeof(VirtIOSCSICtrlTMFResp
)) {
411 virtio_scsi_bad_req();
413 virtio_scsi_do_tmf(s
, req
);
415 } else if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_QUERY
||
416 req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_SUBSCRIBE
) {
417 if (out_size
< sizeof(VirtIOSCSICtrlANReq
) ||
418 in_size
< sizeof(VirtIOSCSICtrlANResp
)) {
419 virtio_scsi_bad_req();
421 req
->resp
.an
->event_actual
= 0;
422 req
->resp
.an
->response
= VIRTIO_SCSI_S_OK
;
424 virtio_scsi_complete_req(req
);
428 static void virtio_scsi_command_complete(SCSIRequest
*r
, uint32_t status
,
431 VirtIOSCSIReq
*req
= r
->hba_private
;
433 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
434 req
->resp
.cmd
->status
= status
;
435 if (req
->resp
.cmd
->status
== GOOD
) {
436 req
->resp
.cmd
->resid
= resid
;
438 req
->resp
.cmd
->resid
= 0;
439 req
->resp
.cmd
->sense_len
=
440 scsi_req_get_sense(r
, req
->resp
.cmd
->sense
, VIRTIO_SCSI_SENSE_SIZE
);
442 virtio_scsi_complete_req(req
);
445 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
447 VirtIOSCSIReq
*req
= r
->hba_private
;
452 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
454 VirtIOSCSIReq
*req
= r
->hba_private
;
459 if (req
->dev
->resetting
) {
460 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
462 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
464 virtio_scsi_complete_req(req
);
467 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
469 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
470 virtio_scsi_complete_req(req
);
473 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
475 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
479 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
481 int out_size
, in_size
;
482 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
483 virtio_scsi_bad_req();
486 out_size
= req
->elem
.out_sg
[0].iov_len
;
487 in_size
= req
->elem
.in_sg
[0].iov_len
;
488 if (out_size
< sizeof(VirtIOSCSICmdReq
) + s
->cdb_size
||
489 in_size
< sizeof(VirtIOSCSICmdResp
) + s
->sense_size
) {
490 virtio_scsi_bad_req();
493 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
494 virtio_scsi_fail_cmd_req(req
);
498 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
500 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
501 virtio_scsi_complete_req(req
);
504 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
505 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
506 req
->req
.cmd
->cdb
, req
);
508 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
510 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
512 if (req
->sreq
->cmd
.mode
!= req_mode
||
513 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
514 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
515 virtio_scsi_complete_req(req
);
520 n
= scsi_req_enqueue(req
->sreq
);
522 scsi_req_continue(req
->sreq
);
527 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
530 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
531 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
533 stl_raw(&scsiconf
->num_queues
, s
->conf
->num_queues
);
534 stl_raw(&scsiconf
->seg_max
, 128 - 2);
535 stl_raw(&scsiconf
->max_sectors
, s
->conf
->max_sectors
);
536 stl_raw(&scsiconf
->cmd_per_lun
, s
->conf
->cmd_per_lun
);
537 stl_raw(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
538 stl_raw(&scsiconf
->sense_size
, s
->sense_size
);
539 stl_raw(&scsiconf
->cdb_size
, s
->cdb_size
);
540 stl_raw(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
541 stl_raw(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
542 stl_raw(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
545 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
546 const uint8_t *config
)
548 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
549 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
551 if ((uint32_t) ldl_raw(&scsiconf
->sense_size
) >= 65536 ||
552 (uint32_t) ldl_raw(&scsiconf
->cdb_size
) >= 256) {
553 error_report("bad data written to virtio-scsi configuration space");
557 s
->sense_size
= ldl_raw(&scsiconf
->sense_size
);
558 s
->cdb_size
= ldl_raw(&scsiconf
->cdb_size
);
561 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
562 uint32_t requested_features
)
564 requested_features
|= (1UL << VIRTIO_SCSI_F_HOTPLUG
);
565 requested_features
|= (1UL << VIRTIO_SCSI_F_CHANGE
);
566 return requested_features
;
569 static void virtio_scsi_reset(VirtIODevice
*vdev
)
571 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
573 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
574 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
575 s
->events_dropped
= false;
578 /* The device does not have anything to save beyond the virtio data.
579 * Request data is saved with callbacks from SCSI devices.
581 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
583 VirtIOSCSI
*s
= opaque
;
584 virtio_save(&s
->vdev
, f
);
587 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
589 VirtIOSCSI
*s
= opaque
;
592 ret
= virtio_load(&s
->vdev
, f
);
599 static void virtio_scsi_push_event(VirtIOSCSI
*s
, SCSIDevice
*dev
,
600 uint32_t event
, uint32_t reason
)
602 VirtIOSCSIReq
*req
= virtio_scsi_pop_req(s
, s
->event_vq
);
603 VirtIOSCSIEvent
*evt
;
607 s
->events_dropped
= true;
611 if (req
->elem
.out_num
|| req
->elem
.in_num
!= 1) {
612 virtio_scsi_bad_req();
615 if (s
->events_dropped
) {
616 event
|= VIRTIO_SCSI_T_EVENTS_MISSED
;
617 s
->events_dropped
= false;
620 in_size
= req
->elem
.in_sg
[0].iov_len
;
621 if (in_size
< sizeof(VirtIOSCSIEvent
)) {
622 virtio_scsi_bad_req();
625 evt
= req
->resp
.event
;
626 memset(evt
, 0, sizeof(VirtIOSCSIEvent
));
628 evt
->reason
= reason
;
630 assert(event
== VIRTIO_SCSI_T_NO_EVENT
);
633 evt
->lun
[1] = dev
->id
;
635 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
636 if (dev
->lun
>= 256) {
637 evt
->lun
[2] = (dev
->lun
>> 8) | 0x40;
639 evt
->lun
[3] = dev
->lun
& 0xFF;
641 virtio_scsi_complete_req(req
);
644 static void virtio_scsi_handle_event(VirtIODevice
*vdev
, VirtQueue
*vq
)
646 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
648 if (s
->events_dropped
) {
649 virtio_scsi_push_event(s
, NULL
, VIRTIO_SCSI_T_NO_EVENT
, 0);
653 static void virtio_scsi_change(SCSIBus
*bus
, SCSIDevice
*dev
, SCSISense sense
)
655 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
657 if (((s
->vdev
.guest_features
>> VIRTIO_SCSI_F_CHANGE
) & 1) &&
658 (s
->vdev
.status
& VIRTIO_CONFIG_S_DRIVER_OK
) &&
659 dev
->type
!= TYPE_ROM
) {
660 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_PARAM_CHANGE
,
661 sense
.asc
| (sense
.ascq
<< 8));
665 static void virtio_scsi_hotplug(SCSIBus
*bus
, SCSIDevice
*dev
)
667 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
669 if (((s
->vdev
.guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) &&
670 (s
->vdev
.status
& VIRTIO_CONFIG_S_DRIVER_OK
)) {
671 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
672 VIRTIO_SCSI_EVT_RESET_RESCAN
);
676 static void virtio_scsi_hot_unplug(SCSIBus
*bus
, SCSIDevice
*dev
)
678 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
680 if ((s
->vdev
.guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
681 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
682 VIRTIO_SCSI_EVT_RESET_REMOVED
);
686 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
688 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
689 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
690 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
692 .complete
= virtio_scsi_command_complete
,
693 .cancel
= virtio_scsi_request_cancelled
,
694 .change
= virtio_scsi_change
,
695 .hotplug
= virtio_scsi_hotplug
,
696 .hot_unplug
= virtio_scsi_hot_unplug
,
697 .get_sg_list
= virtio_scsi_get_sg_list
,
698 .save_request
= virtio_scsi_save_request
,
699 .load_request
= virtio_scsi_load_request
,
702 VirtIODevice
*virtio_scsi_init(DeviceState
*dev
, VirtIOSCSIConf
*proxyconf
)
705 static int virtio_scsi_id
;
709 sz
= sizeof(VirtIOSCSI
) + proxyconf
->num_queues
* sizeof(VirtQueue
*);
710 s
= (VirtIOSCSI
*)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI
,
711 sizeof(VirtIOSCSIConfig
), sz
);
716 /* TODO set up vdev function pointers */
717 s
->vdev
.get_config
= virtio_scsi_get_config
;
718 s
->vdev
.set_config
= virtio_scsi_set_config
;
719 s
->vdev
.get_features
= virtio_scsi_get_features
;
720 s
->vdev
.reset
= virtio_scsi_reset
;
722 s
->ctrl_vq
= virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
723 virtio_scsi_handle_ctrl
);
724 s
->event_vq
= virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
725 virtio_scsi_handle_event
);
726 for (i
= 0; i
< s
->conf
->num_queues
; i
++) {
727 s
->cmd_vqs
[i
] = virtio_add_queue(&s
->vdev
, VIRTIO_SCSI_VQ_SIZE
,
728 virtio_scsi_handle_cmd
);
731 scsi_bus_new(&s
->bus
, dev
, &virtio_scsi_scsi_info
);
732 if (!dev
->hotplugged
) {
733 scsi_bus_legacy_handle_cmdline(&s
->bus
);
736 register_savevm(dev
, "virtio-scsi", virtio_scsi_id
++, 1,
737 virtio_scsi_save
, virtio_scsi_load
, s
);
742 void virtio_scsi_exit(VirtIODevice
*vdev
)
744 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
745 unregister_savevm(s
->qdev
, "virtio-scsi", s
);
746 virtio_cleanup(vdev
);