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 "hw/virtio/virtio-scsi.h"
17 #include "qemu/error-report.h"
18 #include <hw/scsi/scsi.h>
19 #include <block/scsi.h>
20 #include <hw/virtio/virtio-bus.h>
22 typedef struct VirtIOSCSIReq
{
25 VirtQueueElement elem
;
30 VirtIOSCSICmdReq
*cmd
;
31 VirtIOSCSICtrlTMFReq
*tmf
;
32 VirtIOSCSICtrlANReq
*an
;
36 VirtIOSCSICmdResp
*cmd
;
37 VirtIOSCSICtrlTMFResp
*tmf
;
38 VirtIOSCSICtrlANResp
*an
;
39 VirtIOSCSIEvent
*event
;
43 static inline int virtio_scsi_get_lun(uint8_t *lun
)
45 return ((lun
[2] << 8) | lun
[3]) & 0x3FFF;
48 static inline SCSIDevice
*virtio_scsi_device_find(VirtIOSCSI
*s
, uint8_t *lun
)
53 if (lun
[2] != 0 && !(lun
[2] >= 0x40 && lun
[2] < 0x80)) {
56 return scsi_device_find(&s
->bus
, 0, lun
[1], virtio_scsi_get_lun(lun
));
59 static void virtio_scsi_complete_req(VirtIOSCSIReq
*req
)
61 VirtIOSCSI
*s
= req
->dev
;
62 VirtQueue
*vq
= req
->vq
;
63 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
64 virtqueue_push(vq
, &req
->elem
, req
->qsgl
.size
+ req
->elem
.in_sg
[0].iov_len
);
65 qemu_sglist_destroy(&req
->qsgl
);
67 req
->sreq
->hba_private
= NULL
;
68 scsi_req_unref(req
->sreq
);
71 virtio_notify(vdev
, vq
);
74 static void virtio_scsi_bad_req(void)
76 error_report("wrong size for virtio-scsi headers");
80 static void qemu_sgl_init_external(VirtIOSCSIReq
*req
, struct iovec
*sg
,
81 hwaddr
*addr
, int num
)
83 QEMUSGList
*qsgl
= &req
->qsgl
;
85 qemu_sglist_init(qsgl
, DEVICE(req
->dev
), num
, &address_space_memory
);
87 qemu_sglist_add(qsgl
, *(addr
++), (sg
++)->iov_len
);
91 static void virtio_scsi_parse_req(VirtIOSCSI
*s
, VirtQueue
*vq
,
94 assert(req
->elem
.in_num
);
98 if (req
->elem
.out_num
) {
99 req
->req
.buf
= req
->elem
.out_sg
[0].iov_base
;
101 req
->resp
.buf
= req
->elem
.in_sg
[0].iov_base
;
103 if (req
->elem
.out_num
> 1) {
104 qemu_sgl_init_external(req
, &req
->elem
.out_sg
[1],
105 &req
->elem
.out_addr
[1],
106 req
->elem
.out_num
- 1);
108 qemu_sgl_init_external(req
, &req
->elem
.in_sg
[1],
109 &req
->elem
.in_addr
[1],
110 req
->elem
.in_num
- 1);
114 static VirtIOSCSIReq
*virtio_scsi_pop_req(VirtIOSCSI
*s
, VirtQueue
*vq
)
117 req
= g_malloc(sizeof(*req
));
118 if (!virtqueue_pop(vq
, &req
->elem
)) {
123 virtio_scsi_parse_req(s
, vq
, req
);
127 static void virtio_scsi_save_request(QEMUFile
*f
, SCSIRequest
*sreq
)
129 VirtIOSCSIReq
*req
= sreq
->hba_private
;
130 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(req
->dev
);
131 uint32_t n
= virtio_queue_get_id(req
->vq
) - 2;
133 assert(n
< vs
->conf
.num_queues
);
134 qemu_put_be32s(f
, &n
);
135 qemu_put_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
138 static void *virtio_scsi_load_request(QEMUFile
*f
, SCSIRequest
*sreq
)
140 SCSIBus
*bus
= sreq
->bus
;
141 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
142 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
146 req
= g_malloc(sizeof(*req
));
147 qemu_get_be32s(f
, &n
);
148 assert(n
< vs
->conf
.num_queues
);
149 qemu_get_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
150 /* TODO: add a way for SCSIBusInfo's load_request to fail,
151 * and fail migration instead of asserting here.
152 * When we do, we might be able to re-enable NDEBUG below.
155 #error building with NDEBUG is not supported
157 assert(req
->elem
.in_num
<= ARRAY_SIZE(req
->elem
.in_sg
));
158 assert(req
->elem
.out_num
<= ARRAY_SIZE(req
->elem
.out_sg
));
159 virtio_scsi_parse_req(s
, vs
->cmd_vqs
[n
], req
);
163 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
165 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
167 assert(req
->sreq
->cmd
.mode
== req_mode
);
172 static void virtio_scsi_do_tmf(VirtIOSCSI
*s
, VirtIOSCSIReq
*req
)
174 SCSIDevice
*d
= virtio_scsi_device_find(s
, req
->req
.tmf
->lun
);
175 SCSIRequest
*r
, *next
;
179 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
180 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_OK
;
182 switch (req
->req
.tmf
->subtype
) {
183 case VIRTIO_SCSI_T_TMF_ABORT_TASK
:
184 case VIRTIO_SCSI_T_TMF_QUERY_TASK
:
188 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
191 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
192 VirtIOSCSIReq
*cmd_req
= r
->hba_private
;
193 if (cmd_req
&& cmd_req
->req
.cmd
->tag
== req
->req
.tmf
->tag
) {
199 * Assert that the request has not been completed yet, we
200 * check for it in the loop above.
202 assert(r
->hba_private
);
203 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK
) {
204 /* "If the specified command is present in the task set, then
205 * return a service response set to FUNCTION SUCCEEDED".
207 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
214 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET
:
218 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
222 qdev_reset_all(&d
->qdev
);
226 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET
:
227 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET
:
228 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
:
232 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
235 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
236 if (r
->hba_private
) {
237 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
) {
238 /* "If there is any command present in the task set, then
239 * return a service response set to FUNCTION SUCCEEDED".
241 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
250 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET
:
251 target
= req
->req
.tmf
->lun
[1];
253 QTAILQ_FOREACH(kid
, &s
->bus
.qbus
.children
, sibling
) {
254 d
= DO_UPCAST(SCSIDevice
, qdev
, kid
->child
);
255 if (d
->channel
== 0 && d
->id
== target
) {
256 qdev_reset_all(&d
->qdev
);
262 case VIRTIO_SCSI_T_TMF_CLEAR_ACA
:
264 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_REJECTED
;
271 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_INCORRECT_LUN
;
275 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
278 static void virtio_scsi_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
280 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
283 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
284 int out_size
, in_size
;
285 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
286 virtio_scsi_bad_req();
290 out_size
= req
->elem
.out_sg
[0].iov_len
;
291 in_size
= req
->elem
.in_sg
[0].iov_len
;
292 if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_TMF
) {
293 if (out_size
< sizeof(VirtIOSCSICtrlTMFReq
) ||
294 in_size
< sizeof(VirtIOSCSICtrlTMFResp
)) {
295 virtio_scsi_bad_req();
297 virtio_scsi_do_tmf(s
, req
);
299 } else if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_QUERY
||
300 req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_SUBSCRIBE
) {
301 if (out_size
< sizeof(VirtIOSCSICtrlANReq
) ||
302 in_size
< sizeof(VirtIOSCSICtrlANResp
)) {
303 virtio_scsi_bad_req();
305 req
->resp
.an
->event_actual
= 0;
306 req
->resp
.an
->response
= VIRTIO_SCSI_S_OK
;
308 virtio_scsi_complete_req(req
);
312 static void virtio_scsi_command_complete(SCSIRequest
*r
, uint32_t status
,
315 VirtIOSCSIReq
*req
= r
->hba_private
;
316 VirtIOSCSI
*s
= req
->dev
;
317 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
320 if (r
->io_canceled
) {
324 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
325 req
->resp
.cmd
->status
= status
;
326 if (req
->resp
.cmd
->status
== GOOD
) {
327 req
->resp
.cmd
->resid
= tswap32(resid
);
329 req
->resp
.cmd
->resid
= 0;
330 sense_len
= scsi_req_get_sense(r
, req
->resp
.cmd
->sense
,
332 req
->resp
.cmd
->sense_len
= tswap32(sense_len
);
334 virtio_scsi_complete_req(req
);
337 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
339 VirtIOSCSIReq
*req
= r
->hba_private
;
344 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
346 VirtIOSCSIReq
*req
= r
->hba_private
;
351 if (req
->dev
->resetting
) {
352 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
354 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
356 virtio_scsi_complete_req(req
);
359 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
361 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
362 virtio_scsi_complete_req(req
);
365 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
367 /* use non-QOM casts in the data path */
368 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
369 VirtIOSCSICommon
*vs
= &s
->parent_obj
;
374 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
376 int out_size
, in_size
;
377 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
378 virtio_scsi_bad_req();
381 out_size
= req
->elem
.out_sg
[0].iov_len
;
382 in_size
= req
->elem
.in_sg
[0].iov_len
;
383 if (out_size
< sizeof(VirtIOSCSICmdReq
) + vs
->cdb_size
||
384 in_size
< sizeof(VirtIOSCSICmdResp
) + vs
->sense_size
) {
385 virtio_scsi_bad_req();
388 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
389 virtio_scsi_fail_cmd_req(req
);
393 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
395 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
396 virtio_scsi_complete_req(req
);
399 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
400 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
401 req
->req
.cmd
->cdb
, req
);
403 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
405 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
407 if (req
->sreq
->cmd
.mode
!= req_mode
||
408 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
409 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
410 virtio_scsi_complete_req(req
);
415 n
= scsi_req_enqueue(req
->sreq
);
417 scsi_req_continue(req
->sreq
);
422 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
425 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
426 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(vdev
);
428 stl_p(&scsiconf
->num_queues
, s
->conf
.num_queues
);
429 stl_p(&scsiconf
->seg_max
, 128 - 2);
430 stl_p(&scsiconf
->max_sectors
, s
->conf
.max_sectors
);
431 stl_p(&scsiconf
->cmd_per_lun
, s
->conf
.cmd_per_lun
);
432 stl_p(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
433 stl_p(&scsiconf
->sense_size
, s
->sense_size
);
434 stl_p(&scsiconf
->cdb_size
, s
->cdb_size
);
435 stw_p(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
436 stw_p(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
437 stl_p(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
440 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
441 const uint8_t *config
)
443 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
444 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
446 if ((uint32_t) ldl_p(&scsiconf
->sense_size
) >= 65536 ||
447 (uint32_t) ldl_p(&scsiconf
->cdb_size
) >= 256) {
448 error_report("bad data written to virtio-scsi configuration space");
452 vs
->sense_size
= ldl_p(&scsiconf
->sense_size
);
453 vs
->cdb_size
= ldl_p(&scsiconf
->cdb_size
);
456 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
457 uint32_t requested_features
)
459 return requested_features
;
462 static void virtio_scsi_reset(VirtIODevice
*vdev
)
464 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
465 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
468 qbus_reset_all(&s
->bus
.qbus
);
471 vs
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
472 vs
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
473 s
->events_dropped
= false;
476 /* The device does not have anything to save beyond the virtio data.
477 * Request data is saved with callbacks from SCSI devices.
479 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
481 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
482 virtio_save(vdev
, f
);
485 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
487 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
490 ret
= virtio_load(vdev
, f
);
497 static void virtio_scsi_push_event(VirtIOSCSI
*s
, SCSIDevice
*dev
,
498 uint32_t event
, uint32_t reason
)
500 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
502 VirtIOSCSIEvent
*evt
;
503 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
506 if (!(vdev
->status
& VIRTIO_CONFIG_S_DRIVER_OK
)) {
510 req
= virtio_scsi_pop_req(s
, vs
->event_vq
);
512 s
->events_dropped
= true;
516 if (req
->elem
.out_num
|| req
->elem
.in_num
!= 1) {
517 virtio_scsi_bad_req();
520 if (s
->events_dropped
) {
521 event
|= VIRTIO_SCSI_T_EVENTS_MISSED
;
522 s
->events_dropped
= false;
525 in_size
= req
->elem
.in_sg
[0].iov_len
;
526 if (in_size
< sizeof(VirtIOSCSIEvent
)) {
527 virtio_scsi_bad_req();
530 evt
= req
->resp
.event
;
531 memset(evt
, 0, sizeof(VirtIOSCSIEvent
));
533 evt
->reason
= reason
;
535 assert(event
== VIRTIO_SCSI_T_EVENTS_MISSED
);
538 evt
->lun
[1] = dev
->id
;
540 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
541 if (dev
->lun
>= 256) {
542 evt
->lun
[2] = (dev
->lun
>> 8) | 0x40;
544 evt
->lun
[3] = dev
->lun
& 0xFF;
546 virtio_scsi_complete_req(req
);
549 static void virtio_scsi_handle_event(VirtIODevice
*vdev
, VirtQueue
*vq
)
551 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
553 if (s
->events_dropped
) {
554 virtio_scsi_push_event(s
, NULL
, VIRTIO_SCSI_T_NO_EVENT
, 0);
558 static void virtio_scsi_change(SCSIBus
*bus
, SCSIDevice
*dev
, SCSISense sense
)
560 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
561 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
563 if (((vdev
->guest_features
>> VIRTIO_SCSI_F_CHANGE
) & 1) &&
564 dev
->type
!= TYPE_ROM
) {
565 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_PARAM_CHANGE
,
566 sense
.asc
| (sense
.ascq
<< 8));
570 static void virtio_scsi_hotplug(SCSIBus
*bus
, SCSIDevice
*dev
)
572 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
573 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
575 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
576 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
577 VIRTIO_SCSI_EVT_RESET_RESCAN
);
581 static void virtio_scsi_hot_unplug(SCSIBus
*bus
, SCSIDevice
*dev
)
583 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
584 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
586 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
587 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
588 VIRTIO_SCSI_EVT_RESET_REMOVED
);
592 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
594 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
595 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
596 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
598 .complete
= virtio_scsi_command_complete
,
599 .cancel
= virtio_scsi_request_cancelled
,
600 .change
= virtio_scsi_change
,
601 .hotplug
= virtio_scsi_hotplug
,
602 .hot_unplug
= virtio_scsi_hot_unplug
,
603 .get_sg_list
= virtio_scsi_get_sg_list
,
604 .save_request
= virtio_scsi_save_request
,
605 .load_request
= virtio_scsi_load_request
,
608 void virtio_scsi_common_realize(DeviceState
*dev
, Error
**errp
)
610 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
611 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(dev
);
614 virtio_init(vdev
, "virtio-scsi", VIRTIO_ID_SCSI
,
615 sizeof(VirtIOSCSIConfig
));
617 s
->cmd_vqs
= g_malloc0(s
->conf
.num_queues
* sizeof(VirtQueue
*));
618 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
619 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
621 s
->ctrl_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
622 virtio_scsi_handle_ctrl
);
623 s
->event_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
624 virtio_scsi_handle_event
);
625 for (i
= 0; i
< s
->conf
.num_queues
; i
++) {
626 s
->cmd_vqs
[i
] = virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
627 virtio_scsi_handle_cmd
);
631 static void virtio_scsi_device_realize(DeviceState
*dev
, Error
**errp
)
633 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
634 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
635 static int virtio_scsi_id
;
638 virtio_scsi_common_realize(dev
, &err
);
640 error_propagate(errp
, err
);
644 scsi_bus_new(&s
->bus
, sizeof(s
->bus
), dev
,
645 &virtio_scsi_scsi_info
, vdev
->bus_name
);
647 if (!dev
->hotplugged
) {
648 scsi_bus_legacy_handle_cmdline(&s
->bus
, &err
);
650 error_propagate(errp
, err
);
655 register_savevm(dev
, "virtio-scsi", virtio_scsi_id
++, 1,
656 virtio_scsi_save
, virtio_scsi_load
, s
);
659 void virtio_scsi_common_unrealize(DeviceState
*dev
, Error
**errp
)
661 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
662 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(dev
);
665 virtio_cleanup(vdev
);
668 static void virtio_scsi_device_unrealize(DeviceState
*dev
, Error
**errp
)
670 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
672 unregister_savevm(dev
, "virtio-scsi", s
);
674 virtio_scsi_common_unrealize(dev
, errp
);
677 static Property virtio_scsi_properties
[] = {
678 DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI
, parent_obj
.conf
),
679 DEFINE_PROP_END_OF_LIST(),
682 static void virtio_scsi_common_class_init(ObjectClass
*klass
, void *data
)
684 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
685 DeviceClass
*dc
= DEVICE_CLASS(klass
);
687 vdc
->get_config
= virtio_scsi_get_config
;
688 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
691 static void virtio_scsi_class_init(ObjectClass
*klass
, void *data
)
693 DeviceClass
*dc
= DEVICE_CLASS(klass
);
694 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
696 dc
->props
= virtio_scsi_properties
;
697 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
698 vdc
->realize
= virtio_scsi_device_realize
;
699 vdc
->unrealize
= virtio_scsi_device_unrealize
;
700 vdc
->set_config
= virtio_scsi_set_config
;
701 vdc
->get_features
= virtio_scsi_get_features
;
702 vdc
->reset
= virtio_scsi_reset
;
705 static const TypeInfo virtio_scsi_common_info
= {
706 .name
= TYPE_VIRTIO_SCSI_COMMON
,
707 .parent
= TYPE_VIRTIO_DEVICE
,
708 .instance_size
= sizeof(VirtIOSCSICommon
),
710 .class_init
= virtio_scsi_common_class_init
,
713 static const TypeInfo virtio_scsi_info
= {
714 .name
= TYPE_VIRTIO_SCSI
,
715 .parent
= TYPE_VIRTIO_SCSI_COMMON
,
716 .instance_size
= sizeof(VirtIOSCSI
),
717 .class_init
= virtio_scsi_class_init
,
720 static void virtio_register_types(void)
722 type_register_static(&virtio_scsi_common_info
);
723 type_register_static(&virtio_scsi_info
);
726 type_init(virtio_register_types
)