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(QEMUSGList
*qsgl
, struct iovec
*sg
,
81 hwaddr
*addr
, int num
)
83 qemu_sglist_init(qsgl
, num
, &dma_context_memory
);
85 qemu_sglist_add(qsgl
, *(addr
++), (sg
++)->iov_len
);
89 static void virtio_scsi_parse_req(VirtIOSCSI
*s
, VirtQueue
*vq
,
92 assert(req
->elem
.in_num
);
96 if (req
->elem
.out_num
) {
97 req
->req
.buf
= req
->elem
.out_sg
[0].iov_base
;
99 req
->resp
.buf
= req
->elem
.in_sg
[0].iov_base
;
101 if (req
->elem
.out_num
> 1) {
102 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.out_sg
[1],
103 &req
->elem
.out_addr
[1],
104 req
->elem
.out_num
- 1);
106 qemu_sgl_init_external(&req
->qsgl
, &req
->elem
.in_sg
[1],
107 &req
->elem
.in_addr
[1],
108 req
->elem
.in_num
- 1);
112 static VirtIOSCSIReq
*virtio_scsi_pop_req(VirtIOSCSI
*s
, VirtQueue
*vq
)
115 req
= g_malloc(sizeof(*req
));
116 if (!virtqueue_pop(vq
, &req
->elem
)) {
121 virtio_scsi_parse_req(s
, vq
, req
);
125 static void virtio_scsi_save_request(QEMUFile
*f
, SCSIRequest
*sreq
)
127 VirtIOSCSIReq
*req
= sreq
->hba_private
;
128 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(req
->dev
);
129 uint32_t n
= virtio_queue_get_id(req
->vq
) - 2;
131 assert(n
< vs
->conf
.num_queues
);
132 qemu_put_be32s(f
, &n
);
133 qemu_put_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
136 static void *virtio_scsi_load_request(QEMUFile
*f
, SCSIRequest
*sreq
)
138 SCSIBus
*bus
= sreq
->bus
;
139 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
140 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
144 req
= g_malloc(sizeof(*req
));
145 qemu_get_be32s(f
, &n
);
146 assert(n
< vs
->conf
.num_queues
);
147 qemu_get_buffer(f
, (unsigned char *)&req
->elem
, sizeof(req
->elem
));
148 virtio_scsi_parse_req(s
, vs
->cmd_vqs
[n
], req
);
152 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
154 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
156 assert(req
->sreq
->cmd
.mode
== req_mode
);
161 static void virtio_scsi_do_tmf(VirtIOSCSI
*s
, VirtIOSCSIReq
*req
)
163 SCSIDevice
*d
= virtio_scsi_device_find(s
, req
->req
.tmf
->lun
);
164 SCSIRequest
*r
, *next
;
168 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
169 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_OK
;
171 switch (req
->req
.tmf
->subtype
) {
172 case VIRTIO_SCSI_T_TMF_ABORT_TASK
:
173 case VIRTIO_SCSI_T_TMF_QUERY_TASK
:
177 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
180 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
181 VirtIOSCSIReq
*cmd_req
= r
->hba_private
;
182 if (cmd_req
&& cmd_req
->req
.cmd
->tag
== req
->req
.tmf
->tag
) {
188 * Assert that the request has not been completed yet, we
189 * check for it in the loop above.
191 assert(r
->hba_private
);
192 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK
) {
193 /* "If the specified command is present in the task set, then
194 * return a service response set to FUNCTION SUCCEEDED".
196 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
203 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET
:
207 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
211 qdev_reset_all(&d
->qdev
);
215 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET
:
216 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET
:
217 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
:
221 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
224 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
225 if (r
->hba_private
) {
226 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
) {
227 /* "If there is any command present in the task set, then
228 * return a service response set to FUNCTION SUCCEEDED".
230 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
239 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET
:
240 target
= req
->req
.tmf
->lun
[1];
242 QTAILQ_FOREACH(kid
, &s
->bus
.qbus
.children
, sibling
) {
243 d
= DO_UPCAST(SCSIDevice
, qdev
, kid
->child
);
244 if (d
->channel
== 0 && d
->id
== target
) {
245 qdev_reset_all(&d
->qdev
);
251 case VIRTIO_SCSI_T_TMF_CLEAR_ACA
:
253 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_REJECTED
;
260 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_INCORRECT_LUN
;
264 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
267 static void virtio_scsi_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
269 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
272 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
273 int out_size
, in_size
;
274 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
275 virtio_scsi_bad_req();
279 out_size
= req
->elem
.out_sg
[0].iov_len
;
280 in_size
= req
->elem
.in_sg
[0].iov_len
;
281 if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_TMF
) {
282 if (out_size
< sizeof(VirtIOSCSICtrlTMFReq
) ||
283 in_size
< sizeof(VirtIOSCSICtrlTMFResp
)) {
284 virtio_scsi_bad_req();
286 virtio_scsi_do_tmf(s
, req
);
288 } else if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_QUERY
||
289 req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_SUBSCRIBE
) {
290 if (out_size
< sizeof(VirtIOSCSICtrlANReq
) ||
291 in_size
< sizeof(VirtIOSCSICtrlANResp
)) {
292 virtio_scsi_bad_req();
294 req
->resp
.an
->event_actual
= 0;
295 req
->resp
.an
->response
= VIRTIO_SCSI_S_OK
;
297 virtio_scsi_complete_req(req
);
301 static void virtio_scsi_command_complete(SCSIRequest
*r
, uint32_t status
,
304 VirtIOSCSIReq
*req
= r
->hba_private
;
307 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
308 req
->resp
.cmd
->status
= status
;
309 if (req
->resp
.cmd
->status
== GOOD
) {
310 req
->resp
.cmd
->resid
= tswap32(resid
);
312 req
->resp
.cmd
->resid
= 0;
313 sense_len
= scsi_req_get_sense(r
, req
->resp
.cmd
->sense
,
314 VIRTIO_SCSI_SENSE_SIZE
);
315 req
->resp
.cmd
->sense_len
= tswap32(sense_len
);
317 virtio_scsi_complete_req(req
);
320 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
322 VirtIOSCSIReq
*req
= r
->hba_private
;
327 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
329 VirtIOSCSIReq
*req
= r
->hba_private
;
334 if (req
->dev
->resetting
) {
335 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
337 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
339 virtio_scsi_complete_req(req
);
342 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
344 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
345 virtio_scsi_complete_req(req
);
348 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
350 /* use non-QOM casts in the data path */
351 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
352 VirtIOSCSICommon
*vs
= &s
->parent_obj
;
357 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
359 int out_size
, in_size
;
360 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
361 virtio_scsi_bad_req();
364 out_size
= req
->elem
.out_sg
[0].iov_len
;
365 in_size
= req
->elem
.in_sg
[0].iov_len
;
366 if (out_size
< sizeof(VirtIOSCSICmdReq
) + vs
->cdb_size
||
367 in_size
< sizeof(VirtIOSCSICmdResp
) + vs
->sense_size
) {
368 virtio_scsi_bad_req();
371 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
372 virtio_scsi_fail_cmd_req(req
);
376 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
378 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
379 virtio_scsi_complete_req(req
);
382 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
383 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
384 req
->req
.cmd
->cdb
, req
);
386 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
388 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
390 if (req
->sreq
->cmd
.mode
!= req_mode
||
391 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
392 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
393 virtio_scsi_complete_req(req
);
398 n
= scsi_req_enqueue(req
->sreq
);
400 scsi_req_continue(req
->sreq
);
405 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
408 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
409 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(vdev
);
411 stl_raw(&scsiconf
->num_queues
, s
->conf
.num_queues
);
412 stl_raw(&scsiconf
->seg_max
, 128 - 2);
413 stl_raw(&scsiconf
->max_sectors
, s
->conf
.max_sectors
);
414 stl_raw(&scsiconf
->cmd_per_lun
, s
->conf
.cmd_per_lun
);
415 stl_raw(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
416 stl_raw(&scsiconf
->sense_size
, s
->sense_size
);
417 stl_raw(&scsiconf
->cdb_size
, s
->cdb_size
);
418 stw_raw(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
419 stw_raw(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
420 stl_raw(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
423 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
424 const uint8_t *config
)
426 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
427 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
429 if ((uint32_t) ldl_raw(&scsiconf
->sense_size
) >= 65536 ||
430 (uint32_t) ldl_raw(&scsiconf
->cdb_size
) >= 256) {
431 error_report("bad data written to virtio-scsi configuration space");
435 vs
->sense_size
= ldl_raw(&scsiconf
->sense_size
);
436 vs
->cdb_size
= ldl_raw(&scsiconf
->cdb_size
);
439 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
440 uint32_t requested_features
)
442 return requested_features
;
445 static void virtio_scsi_reset(VirtIODevice
*vdev
)
447 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
448 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
451 qbus_reset_all(&s
->bus
.qbus
);
454 vs
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
455 vs
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
456 s
->events_dropped
= false;
459 /* The device does not have anything to save beyond the virtio data.
460 * Request data is saved with callbacks from SCSI devices.
462 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
464 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
465 virtio_save(vdev
, f
);
468 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
470 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
473 ret
= virtio_load(vdev
, f
);
480 static void virtio_scsi_push_event(VirtIOSCSI
*s
, SCSIDevice
*dev
,
481 uint32_t event
, uint32_t reason
)
483 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
484 VirtIOSCSIReq
*req
= virtio_scsi_pop_req(s
, vs
->event_vq
);
485 VirtIOSCSIEvent
*evt
;
486 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
489 if (!(vdev
->status
& VIRTIO_CONFIG_S_DRIVER_OK
)) {
494 s
->events_dropped
= true;
498 if (req
->elem
.out_num
|| req
->elem
.in_num
!= 1) {
499 virtio_scsi_bad_req();
502 if (s
->events_dropped
) {
503 event
|= VIRTIO_SCSI_T_EVENTS_MISSED
;
504 s
->events_dropped
= false;
507 in_size
= req
->elem
.in_sg
[0].iov_len
;
508 if (in_size
< sizeof(VirtIOSCSIEvent
)) {
509 virtio_scsi_bad_req();
512 evt
= req
->resp
.event
;
513 memset(evt
, 0, sizeof(VirtIOSCSIEvent
));
515 evt
->reason
= reason
;
517 assert(event
== VIRTIO_SCSI_T_NO_EVENT
);
520 evt
->lun
[1] = dev
->id
;
522 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
523 if (dev
->lun
>= 256) {
524 evt
->lun
[2] = (dev
->lun
>> 8) | 0x40;
526 evt
->lun
[3] = dev
->lun
& 0xFF;
528 virtio_scsi_complete_req(req
);
531 static void virtio_scsi_handle_event(VirtIODevice
*vdev
, VirtQueue
*vq
)
533 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
535 if (s
->events_dropped
) {
536 virtio_scsi_push_event(s
, NULL
, VIRTIO_SCSI_T_NO_EVENT
, 0);
540 static void virtio_scsi_change(SCSIBus
*bus
, SCSIDevice
*dev
, SCSISense sense
)
542 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
543 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
545 if (((vdev
->guest_features
>> VIRTIO_SCSI_F_CHANGE
) & 1) &&
546 dev
->type
!= TYPE_ROM
) {
547 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_PARAM_CHANGE
,
548 sense
.asc
| (sense
.ascq
<< 8));
552 static void virtio_scsi_hotplug(SCSIBus
*bus
, SCSIDevice
*dev
)
554 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
555 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
557 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
558 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
559 VIRTIO_SCSI_EVT_RESET_RESCAN
);
563 static void virtio_scsi_hot_unplug(SCSIBus
*bus
, SCSIDevice
*dev
)
565 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
566 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
568 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
569 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
570 VIRTIO_SCSI_EVT_RESET_REMOVED
);
574 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
576 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
577 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
578 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
580 .complete
= virtio_scsi_command_complete
,
581 .cancel
= virtio_scsi_request_cancelled
,
582 .change
= virtio_scsi_change
,
583 .hotplug
= virtio_scsi_hotplug
,
584 .hot_unplug
= virtio_scsi_hot_unplug
,
585 .get_sg_list
= virtio_scsi_get_sg_list
,
586 .save_request
= virtio_scsi_save_request
,
587 .load_request
= virtio_scsi_load_request
,
590 int virtio_scsi_common_init(VirtIOSCSICommon
*s
)
592 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
595 virtio_init(VIRTIO_DEVICE(s
), "virtio-scsi", VIRTIO_ID_SCSI
,
596 sizeof(VirtIOSCSIConfig
));
598 s
->cmd_vqs
= g_malloc0(s
->conf
.num_queues
* sizeof(VirtQueue
*));
599 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
600 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
602 s
->ctrl_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
603 virtio_scsi_handle_ctrl
);
604 s
->event_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
605 virtio_scsi_handle_event
);
606 for (i
= 0; i
< s
->conf
.num_queues
; i
++) {
607 s
->cmd_vqs
[i
] = virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
608 virtio_scsi_handle_cmd
);
614 static int virtio_scsi_device_init(VirtIODevice
*vdev
)
616 DeviceState
*qdev
= DEVICE(vdev
);
617 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
618 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
619 static int virtio_scsi_id
;
622 ret
= virtio_scsi_common_init(vs
);
627 scsi_bus_new(&s
->bus
, qdev
, &virtio_scsi_scsi_info
, vdev
->bus_name
);
629 if (!qdev
->hotplugged
) {
630 scsi_bus_legacy_handle_cmdline(&s
->bus
);
633 register_savevm(qdev
, "virtio-scsi", virtio_scsi_id
++, 1,
634 virtio_scsi_save
, virtio_scsi_load
, s
);
639 int virtio_scsi_common_exit(VirtIOSCSICommon
*vs
)
641 VirtIODevice
*vdev
= VIRTIO_DEVICE(vs
);
644 virtio_cleanup(vdev
);
648 static int virtio_scsi_device_exit(DeviceState
*qdev
)
650 VirtIOSCSI
*s
= VIRTIO_SCSI(qdev
);
651 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(qdev
);
653 unregister_savevm(qdev
, "virtio-scsi", s
);
654 return virtio_scsi_common_exit(vs
);
657 static Property virtio_scsi_properties
[] = {
658 DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI
, parent_obj
.conf
),
659 DEFINE_PROP_END_OF_LIST(),
662 static void virtio_scsi_common_class_init(ObjectClass
*klass
, void *data
)
664 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
666 vdc
->get_config
= virtio_scsi_get_config
;
669 static void virtio_scsi_class_init(ObjectClass
*klass
, void *data
)
671 DeviceClass
*dc
= DEVICE_CLASS(klass
);
672 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
673 dc
->exit
= virtio_scsi_device_exit
;
674 dc
->props
= virtio_scsi_properties
;
675 vdc
->init
= virtio_scsi_device_init
;
676 vdc
->set_config
= virtio_scsi_set_config
;
677 vdc
->get_features
= virtio_scsi_get_features
;
678 vdc
->reset
= virtio_scsi_reset
;
681 static const TypeInfo virtio_scsi_common_info
= {
682 .name
= TYPE_VIRTIO_SCSI_COMMON
,
683 .parent
= TYPE_VIRTIO_DEVICE
,
684 .instance_size
= sizeof(VirtIOSCSICommon
),
685 .class_init
= virtio_scsi_common_class_init
,
688 static const TypeInfo virtio_scsi_info
= {
689 .name
= TYPE_VIRTIO_SCSI
,
690 .parent
= TYPE_VIRTIO_SCSI_COMMON
,
691 .instance_size
= sizeof(VirtIOSCSI
),
692 .class_init
= virtio_scsi_class_init
,
695 static void virtio_register_types(void)
697 type_register_static(&virtio_scsi_common_info
);
698 type_register_static(&virtio_scsi_info
);
701 type_init(virtio_register_types
)