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 virtio_scsi_parse_req(s
, vs
->cmd_vqs
[n
], req
);
154 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
156 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
158 assert(req
->sreq
->cmd
.mode
== req_mode
);
163 static void virtio_scsi_do_tmf(VirtIOSCSI
*s
, VirtIOSCSIReq
*req
)
165 SCSIDevice
*d
= virtio_scsi_device_find(s
, req
->req
.tmf
->lun
);
166 SCSIRequest
*r
, *next
;
170 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
171 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_OK
;
173 switch (req
->req
.tmf
->subtype
) {
174 case VIRTIO_SCSI_T_TMF_ABORT_TASK
:
175 case VIRTIO_SCSI_T_TMF_QUERY_TASK
:
179 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
182 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
183 VirtIOSCSIReq
*cmd_req
= r
->hba_private
;
184 if (cmd_req
&& cmd_req
->req
.cmd
->tag
== req
->req
.tmf
->tag
) {
190 * Assert that the request has not been completed yet, we
191 * check for it in the loop above.
193 assert(r
->hba_private
);
194 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK
) {
195 /* "If the specified command is present in the task set, then
196 * return a service response set to FUNCTION SUCCEEDED".
198 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
205 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET
:
209 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
213 qdev_reset_all(&d
->qdev
);
217 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET
:
218 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET
:
219 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
:
223 if (d
->lun
!= virtio_scsi_get_lun(req
->req
.tmf
->lun
)) {
226 QTAILQ_FOREACH_SAFE(r
, &d
->requests
, next
, next
) {
227 if (r
->hba_private
) {
228 if (req
->req
.tmf
->subtype
== VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
) {
229 /* "If there is any command present in the task set, then
230 * return a service response set to FUNCTION SUCCEEDED".
232 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_SUCCEEDED
;
241 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET
:
242 target
= req
->req
.tmf
->lun
[1];
244 QTAILQ_FOREACH(kid
, &s
->bus
.qbus
.children
, sibling
) {
245 d
= DO_UPCAST(SCSIDevice
, qdev
, kid
->child
);
246 if (d
->channel
== 0 && d
->id
== target
) {
247 qdev_reset_all(&d
->qdev
);
253 case VIRTIO_SCSI_T_TMF_CLEAR_ACA
:
255 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_FUNCTION_REJECTED
;
262 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_INCORRECT_LUN
;
266 req
->resp
.tmf
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
269 static void virtio_scsi_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
271 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
274 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
275 int out_size
, in_size
;
276 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
277 virtio_scsi_bad_req();
281 out_size
= req
->elem
.out_sg
[0].iov_len
;
282 in_size
= req
->elem
.in_sg
[0].iov_len
;
283 if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_TMF
) {
284 if (out_size
< sizeof(VirtIOSCSICtrlTMFReq
) ||
285 in_size
< sizeof(VirtIOSCSICtrlTMFResp
)) {
286 virtio_scsi_bad_req();
288 virtio_scsi_do_tmf(s
, req
);
290 } else if (req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_QUERY
||
291 req
->req
.tmf
->type
== VIRTIO_SCSI_T_AN_SUBSCRIBE
) {
292 if (out_size
< sizeof(VirtIOSCSICtrlANReq
) ||
293 in_size
< sizeof(VirtIOSCSICtrlANResp
)) {
294 virtio_scsi_bad_req();
296 req
->resp
.an
->event_actual
= 0;
297 req
->resp
.an
->response
= VIRTIO_SCSI_S_OK
;
299 virtio_scsi_complete_req(req
);
303 static void virtio_scsi_command_complete(SCSIRequest
*r
, uint32_t status
,
306 VirtIOSCSIReq
*req
= r
->hba_private
;
307 VirtIOSCSI
*s
= req
->dev
;
308 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
311 if (r
->io_canceled
) {
315 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
316 req
->resp
.cmd
->status
= status
;
317 if (req
->resp
.cmd
->status
== GOOD
) {
318 req
->resp
.cmd
->resid
= tswap32(resid
);
320 req
->resp
.cmd
->resid
= 0;
321 sense_len
= scsi_req_get_sense(r
, req
->resp
.cmd
->sense
,
323 req
->resp
.cmd
->sense_len
= tswap32(sense_len
);
325 virtio_scsi_complete_req(req
);
328 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
330 VirtIOSCSIReq
*req
= r
->hba_private
;
335 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
337 VirtIOSCSIReq
*req
= r
->hba_private
;
342 if (req
->dev
->resetting
) {
343 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
345 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
347 virtio_scsi_complete_req(req
);
350 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
352 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
353 virtio_scsi_complete_req(req
);
356 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
358 /* use non-QOM casts in the data path */
359 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
360 VirtIOSCSICommon
*vs
= &s
->parent_obj
;
365 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
367 int out_size
, in_size
;
368 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
369 virtio_scsi_bad_req();
372 out_size
= req
->elem
.out_sg
[0].iov_len
;
373 in_size
= req
->elem
.in_sg
[0].iov_len
;
374 if (out_size
< sizeof(VirtIOSCSICmdReq
) + vs
->cdb_size
||
375 in_size
< sizeof(VirtIOSCSICmdResp
) + vs
->sense_size
) {
376 virtio_scsi_bad_req();
379 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
380 virtio_scsi_fail_cmd_req(req
);
384 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
386 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
387 virtio_scsi_complete_req(req
);
390 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
391 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
392 req
->req
.cmd
->cdb
, req
);
394 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
396 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
398 if (req
->sreq
->cmd
.mode
!= req_mode
||
399 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
400 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
401 virtio_scsi_complete_req(req
);
406 n
= scsi_req_enqueue(req
->sreq
);
408 scsi_req_continue(req
->sreq
);
413 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
416 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
417 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(vdev
);
419 stl_raw(&scsiconf
->num_queues
, s
->conf
.num_queues
);
420 stl_raw(&scsiconf
->seg_max
, 128 - 2);
421 stl_raw(&scsiconf
->max_sectors
, s
->conf
.max_sectors
);
422 stl_raw(&scsiconf
->cmd_per_lun
, s
->conf
.cmd_per_lun
);
423 stl_raw(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
424 stl_raw(&scsiconf
->sense_size
, s
->sense_size
);
425 stl_raw(&scsiconf
->cdb_size
, s
->cdb_size
);
426 stw_raw(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
427 stw_raw(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
428 stl_raw(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
431 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
432 const uint8_t *config
)
434 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
435 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
437 if ((uint32_t) ldl_raw(&scsiconf
->sense_size
) >= 65536 ||
438 (uint32_t) ldl_raw(&scsiconf
->cdb_size
) >= 256) {
439 error_report("bad data written to virtio-scsi configuration space");
443 vs
->sense_size
= ldl_raw(&scsiconf
->sense_size
);
444 vs
->cdb_size
= ldl_raw(&scsiconf
->cdb_size
);
447 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
448 uint32_t requested_features
)
450 return requested_features
;
453 static void virtio_scsi_reset(VirtIODevice
*vdev
)
455 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
456 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
459 qbus_reset_all(&s
->bus
.qbus
);
462 vs
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
463 vs
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
464 s
->events_dropped
= false;
467 /* The device does not have anything to save beyond the virtio data.
468 * Request data is saved with callbacks from SCSI devices.
470 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
472 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
473 virtio_save(vdev
, f
);
476 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
478 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
481 ret
= virtio_load(vdev
, f
);
488 static void virtio_scsi_push_event(VirtIOSCSI
*s
, SCSIDevice
*dev
,
489 uint32_t event
, uint32_t reason
)
491 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
492 VirtIOSCSIReq
*req
= virtio_scsi_pop_req(s
, vs
->event_vq
);
493 VirtIOSCSIEvent
*evt
;
494 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
497 if (!(vdev
->status
& VIRTIO_CONFIG_S_DRIVER_OK
)) {
502 s
->events_dropped
= true;
506 if (req
->elem
.out_num
|| req
->elem
.in_num
!= 1) {
507 virtio_scsi_bad_req();
510 if (s
->events_dropped
) {
511 event
|= VIRTIO_SCSI_T_EVENTS_MISSED
;
512 s
->events_dropped
= false;
515 in_size
= req
->elem
.in_sg
[0].iov_len
;
516 if (in_size
< sizeof(VirtIOSCSIEvent
)) {
517 virtio_scsi_bad_req();
520 evt
= req
->resp
.event
;
521 memset(evt
, 0, sizeof(VirtIOSCSIEvent
));
523 evt
->reason
= reason
;
525 assert(event
== VIRTIO_SCSI_T_EVENTS_MISSED
);
528 evt
->lun
[1] = dev
->id
;
530 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
531 if (dev
->lun
>= 256) {
532 evt
->lun
[2] = (dev
->lun
>> 8) | 0x40;
534 evt
->lun
[3] = dev
->lun
& 0xFF;
536 virtio_scsi_complete_req(req
);
539 static void virtio_scsi_handle_event(VirtIODevice
*vdev
, VirtQueue
*vq
)
541 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
543 if (s
->events_dropped
) {
544 virtio_scsi_push_event(s
, NULL
, VIRTIO_SCSI_T_NO_EVENT
, 0);
548 static void virtio_scsi_change(SCSIBus
*bus
, SCSIDevice
*dev
, SCSISense sense
)
550 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
551 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
553 if (((vdev
->guest_features
>> VIRTIO_SCSI_F_CHANGE
) & 1) &&
554 dev
->type
!= TYPE_ROM
) {
555 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_PARAM_CHANGE
,
556 sense
.asc
| (sense
.ascq
<< 8));
560 static void virtio_scsi_hotplug(SCSIBus
*bus
, SCSIDevice
*dev
)
562 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
563 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
565 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
566 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
567 VIRTIO_SCSI_EVT_RESET_RESCAN
);
571 static void virtio_scsi_hot_unplug(SCSIBus
*bus
, SCSIDevice
*dev
)
573 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
574 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
576 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
577 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
578 VIRTIO_SCSI_EVT_RESET_REMOVED
);
582 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
584 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
585 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
586 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
588 .complete
= virtio_scsi_command_complete
,
589 .cancel
= virtio_scsi_request_cancelled
,
590 .change
= virtio_scsi_change
,
591 .hotplug
= virtio_scsi_hotplug
,
592 .hot_unplug
= virtio_scsi_hot_unplug
,
593 .get_sg_list
= virtio_scsi_get_sg_list
,
594 .save_request
= virtio_scsi_save_request
,
595 .load_request
= virtio_scsi_load_request
,
598 void virtio_scsi_common_realize(DeviceState
*dev
, Error
**errp
)
600 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
601 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(dev
);
604 virtio_init(vdev
, "virtio-scsi", VIRTIO_ID_SCSI
,
605 sizeof(VirtIOSCSIConfig
));
607 s
->cmd_vqs
= g_malloc0(s
->conf
.num_queues
* sizeof(VirtQueue
*));
608 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
609 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
611 s
->ctrl_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
612 virtio_scsi_handle_ctrl
);
613 s
->event_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
614 virtio_scsi_handle_event
);
615 for (i
= 0; i
< s
->conf
.num_queues
; i
++) {
616 s
->cmd_vqs
[i
] = virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
617 virtio_scsi_handle_cmd
);
621 static void virtio_scsi_device_realize(DeviceState
*dev
, Error
**errp
)
623 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
624 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
625 static int virtio_scsi_id
;
628 virtio_scsi_common_realize(dev
, &err
);
630 error_propagate(errp
, err
);
634 scsi_bus_new(&s
->bus
, sizeof(s
->bus
), dev
,
635 &virtio_scsi_scsi_info
, vdev
->bus_name
);
637 if (!dev
->hotplugged
) {
638 scsi_bus_legacy_handle_cmdline(&s
->bus
, &err
);
640 error_propagate(errp
, err
);
645 register_savevm(dev
, "virtio-scsi", virtio_scsi_id
++, 1,
646 virtio_scsi_save
, virtio_scsi_load
, s
);
649 void virtio_scsi_common_unrealize(DeviceState
*dev
, Error
**errp
)
651 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
652 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(dev
);
655 virtio_cleanup(vdev
);
658 static void virtio_scsi_device_unrealize(DeviceState
*dev
, Error
**errp
)
660 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
662 unregister_savevm(dev
, "virtio-scsi", s
);
664 virtio_scsi_common_unrealize(dev
, errp
);
667 static Property virtio_scsi_properties
[] = {
668 DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI
, parent_obj
.conf
),
669 DEFINE_PROP_END_OF_LIST(),
672 static void virtio_scsi_common_class_init(ObjectClass
*klass
, void *data
)
674 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
675 DeviceClass
*dc
= DEVICE_CLASS(klass
);
677 vdc
->get_config
= virtio_scsi_get_config
;
678 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
681 static void virtio_scsi_class_init(ObjectClass
*klass
, void *data
)
683 DeviceClass
*dc
= DEVICE_CLASS(klass
);
684 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
686 dc
->props
= virtio_scsi_properties
;
687 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
688 vdc
->realize
= virtio_scsi_device_realize
;
689 vdc
->unrealize
= virtio_scsi_device_unrealize
;
690 vdc
->set_config
= virtio_scsi_set_config
;
691 vdc
->get_features
= virtio_scsi_get_features
;
692 vdc
->reset
= virtio_scsi_reset
;
695 static const TypeInfo virtio_scsi_common_info
= {
696 .name
= TYPE_VIRTIO_SCSI_COMMON
,
697 .parent
= TYPE_VIRTIO_DEVICE
,
698 .instance_size
= sizeof(VirtIOSCSICommon
),
700 .class_init
= virtio_scsi_common_class_init
,
703 static const TypeInfo virtio_scsi_info
= {
704 .name
= TYPE_VIRTIO_SCSI
,
705 .parent
= TYPE_VIRTIO_SCSI_COMMON
,
706 .instance_size
= sizeof(VirtIOSCSI
),
707 .class_init
= virtio_scsi_class_init
,
710 static void virtio_register_types(void)
712 type_register_static(&virtio_scsi_common_info
);
713 type_register_static(&virtio_scsi_info
);
716 type_init(virtio_register_types
)