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
;
309 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OK
;
310 req
->resp
.cmd
->status
= status
;
311 if (req
->resp
.cmd
->status
== GOOD
) {
312 req
->resp
.cmd
->resid
= tswap32(resid
);
314 req
->resp
.cmd
->resid
= 0;
315 sense_len
= scsi_req_get_sense(r
, req
->resp
.cmd
->sense
,
316 VIRTIO_SCSI_SENSE_SIZE
);
317 req
->resp
.cmd
->sense_len
= tswap32(sense_len
);
319 virtio_scsi_complete_req(req
);
322 static QEMUSGList
*virtio_scsi_get_sg_list(SCSIRequest
*r
)
324 VirtIOSCSIReq
*req
= r
->hba_private
;
329 static void virtio_scsi_request_cancelled(SCSIRequest
*r
)
331 VirtIOSCSIReq
*req
= r
->hba_private
;
336 if (req
->dev
->resetting
) {
337 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_RESET
;
339 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_ABORTED
;
341 virtio_scsi_complete_req(req
);
344 static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq
*req
)
346 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_FAILURE
;
347 virtio_scsi_complete_req(req
);
350 static void virtio_scsi_handle_cmd(VirtIODevice
*vdev
, VirtQueue
*vq
)
352 /* use non-QOM casts in the data path */
353 VirtIOSCSI
*s
= (VirtIOSCSI
*)vdev
;
354 VirtIOSCSICommon
*vs
= &s
->parent_obj
;
359 while ((req
= virtio_scsi_pop_req(s
, vq
))) {
361 int out_size
, in_size
;
362 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
363 virtio_scsi_bad_req();
366 out_size
= req
->elem
.out_sg
[0].iov_len
;
367 in_size
= req
->elem
.in_sg
[0].iov_len
;
368 if (out_size
< sizeof(VirtIOSCSICmdReq
) + vs
->cdb_size
||
369 in_size
< sizeof(VirtIOSCSICmdResp
) + vs
->sense_size
) {
370 virtio_scsi_bad_req();
373 if (req
->elem
.out_num
> 1 && req
->elem
.in_num
> 1) {
374 virtio_scsi_fail_cmd_req(req
);
378 d
= virtio_scsi_device_find(s
, req
->req
.cmd
->lun
);
380 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_BAD_TARGET
;
381 virtio_scsi_complete_req(req
);
384 req
->sreq
= scsi_req_new(d
, req
->req
.cmd
->tag
,
385 virtio_scsi_get_lun(req
->req
.cmd
->lun
),
386 req
->req
.cmd
->cdb
, req
);
388 if (req
->sreq
->cmd
.mode
!= SCSI_XFER_NONE
) {
390 (req
->elem
.in_num
> 1 ? SCSI_XFER_FROM_DEV
: SCSI_XFER_TO_DEV
);
392 if (req
->sreq
->cmd
.mode
!= req_mode
||
393 req
->sreq
->cmd
.xfer
> req
->qsgl
.size
) {
394 req
->resp
.cmd
->response
= VIRTIO_SCSI_S_OVERRUN
;
395 virtio_scsi_complete_req(req
);
400 n
= scsi_req_enqueue(req
->sreq
);
402 scsi_req_continue(req
->sreq
);
407 static void virtio_scsi_get_config(VirtIODevice
*vdev
,
410 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
411 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(vdev
);
413 stl_raw(&scsiconf
->num_queues
, s
->conf
.num_queues
);
414 stl_raw(&scsiconf
->seg_max
, 128 - 2);
415 stl_raw(&scsiconf
->max_sectors
, s
->conf
.max_sectors
);
416 stl_raw(&scsiconf
->cmd_per_lun
, s
->conf
.cmd_per_lun
);
417 stl_raw(&scsiconf
->event_info_size
, sizeof(VirtIOSCSIEvent
));
418 stl_raw(&scsiconf
->sense_size
, s
->sense_size
);
419 stl_raw(&scsiconf
->cdb_size
, s
->cdb_size
);
420 stw_raw(&scsiconf
->max_channel
, VIRTIO_SCSI_MAX_CHANNEL
);
421 stw_raw(&scsiconf
->max_target
, VIRTIO_SCSI_MAX_TARGET
);
422 stl_raw(&scsiconf
->max_lun
, VIRTIO_SCSI_MAX_LUN
);
425 static void virtio_scsi_set_config(VirtIODevice
*vdev
,
426 const uint8_t *config
)
428 VirtIOSCSIConfig
*scsiconf
= (VirtIOSCSIConfig
*)config
;
429 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
431 if ((uint32_t) ldl_raw(&scsiconf
->sense_size
) >= 65536 ||
432 (uint32_t) ldl_raw(&scsiconf
->cdb_size
) >= 256) {
433 error_report("bad data written to virtio-scsi configuration space");
437 vs
->sense_size
= ldl_raw(&scsiconf
->sense_size
);
438 vs
->cdb_size
= ldl_raw(&scsiconf
->cdb_size
);
441 static uint32_t virtio_scsi_get_features(VirtIODevice
*vdev
,
442 uint32_t requested_features
)
444 return requested_features
;
447 static void virtio_scsi_reset(VirtIODevice
*vdev
)
449 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
450 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(vdev
);
453 qbus_reset_all(&s
->bus
.qbus
);
456 vs
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
457 vs
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
458 s
->events_dropped
= false;
461 /* The device does not have anything to save beyond the virtio data.
462 * Request data is saved with callbacks from SCSI devices.
464 static void virtio_scsi_save(QEMUFile
*f
, void *opaque
)
466 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
467 virtio_save(vdev
, f
);
470 static int virtio_scsi_load(QEMUFile
*f
, void *opaque
, int version_id
)
472 VirtIODevice
*vdev
= VIRTIO_DEVICE(opaque
);
475 ret
= virtio_load(vdev
, f
);
482 static void virtio_scsi_push_event(VirtIOSCSI
*s
, SCSIDevice
*dev
,
483 uint32_t event
, uint32_t reason
)
485 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(s
);
486 VirtIOSCSIReq
*req
= virtio_scsi_pop_req(s
, vs
->event_vq
);
487 VirtIOSCSIEvent
*evt
;
488 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
491 if (!(vdev
->status
& VIRTIO_CONFIG_S_DRIVER_OK
)) {
496 s
->events_dropped
= true;
500 if (req
->elem
.out_num
|| req
->elem
.in_num
!= 1) {
501 virtio_scsi_bad_req();
504 if (s
->events_dropped
) {
505 event
|= VIRTIO_SCSI_T_EVENTS_MISSED
;
506 s
->events_dropped
= false;
509 in_size
= req
->elem
.in_sg
[0].iov_len
;
510 if (in_size
< sizeof(VirtIOSCSIEvent
)) {
511 virtio_scsi_bad_req();
514 evt
= req
->resp
.event
;
515 memset(evt
, 0, sizeof(VirtIOSCSIEvent
));
517 evt
->reason
= reason
;
519 assert(event
== VIRTIO_SCSI_T_NO_EVENT
);
522 evt
->lun
[1] = dev
->id
;
524 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
525 if (dev
->lun
>= 256) {
526 evt
->lun
[2] = (dev
->lun
>> 8) | 0x40;
528 evt
->lun
[3] = dev
->lun
& 0xFF;
530 virtio_scsi_complete_req(req
);
533 static void virtio_scsi_handle_event(VirtIODevice
*vdev
, VirtQueue
*vq
)
535 VirtIOSCSI
*s
= VIRTIO_SCSI(vdev
);
537 if (s
->events_dropped
) {
538 virtio_scsi_push_event(s
, NULL
, VIRTIO_SCSI_T_NO_EVENT
, 0);
542 static void virtio_scsi_change(SCSIBus
*bus
, SCSIDevice
*dev
, SCSISense sense
)
544 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
545 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
547 if (((vdev
->guest_features
>> VIRTIO_SCSI_F_CHANGE
) & 1) &&
548 dev
->type
!= TYPE_ROM
) {
549 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_PARAM_CHANGE
,
550 sense
.asc
| (sense
.ascq
<< 8));
554 static void virtio_scsi_hotplug(SCSIBus
*bus
, SCSIDevice
*dev
)
556 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
557 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
559 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
560 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
561 VIRTIO_SCSI_EVT_RESET_RESCAN
);
565 static void virtio_scsi_hot_unplug(SCSIBus
*bus
, SCSIDevice
*dev
)
567 VirtIOSCSI
*s
= container_of(bus
, VirtIOSCSI
, bus
);
568 VirtIODevice
*vdev
= VIRTIO_DEVICE(s
);
570 if ((vdev
->guest_features
>> VIRTIO_SCSI_F_HOTPLUG
) & 1) {
571 virtio_scsi_push_event(s
, dev
, VIRTIO_SCSI_T_TRANSPORT_RESET
,
572 VIRTIO_SCSI_EVT_RESET_REMOVED
);
576 static struct SCSIBusInfo virtio_scsi_scsi_info
= {
578 .max_channel
= VIRTIO_SCSI_MAX_CHANNEL
,
579 .max_target
= VIRTIO_SCSI_MAX_TARGET
,
580 .max_lun
= VIRTIO_SCSI_MAX_LUN
,
582 .complete
= virtio_scsi_command_complete
,
583 .cancel
= virtio_scsi_request_cancelled
,
584 .change
= virtio_scsi_change
,
585 .hotplug
= virtio_scsi_hotplug
,
586 .hot_unplug
= virtio_scsi_hot_unplug
,
587 .get_sg_list
= virtio_scsi_get_sg_list
,
588 .save_request
= virtio_scsi_save_request
,
589 .load_request
= virtio_scsi_load_request
,
592 void virtio_scsi_common_realize(DeviceState
*dev
, Error
**errp
)
594 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
595 VirtIOSCSICommon
*s
= VIRTIO_SCSI_COMMON(dev
);
598 virtio_init(vdev
, "virtio-scsi", VIRTIO_ID_SCSI
,
599 sizeof(VirtIOSCSIConfig
));
601 s
->cmd_vqs
= g_malloc0(s
->conf
.num_queues
* sizeof(VirtQueue
*));
602 s
->sense_size
= VIRTIO_SCSI_SENSE_SIZE
;
603 s
->cdb_size
= VIRTIO_SCSI_CDB_SIZE
;
605 s
->ctrl_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
606 virtio_scsi_handle_ctrl
);
607 s
->event_vq
= virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
608 virtio_scsi_handle_event
);
609 for (i
= 0; i
< s
->conf
.num_queues
; i
++) {
610 s
->cmd_vqs
[i
] = virtio_add_queue(vdev
, VIRTIO_SCSI_VQ_SIZE
,
611 virtio_scsi_handle_cmd
);
615 static void virtio_scsi_device_realize(DeviceState
*dev
, Error
**errp
)
617 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
618 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
619 static int virtio_scsi_id
;
622 virtio_scsi_common_realize(dev
, &err
);
624 error_propagate(errp
, err
);
628 scsi_bus_new(&s
->bus
, sizeof(s
->bus
), dev
,
629 &virtio_scsi_scsi_info
, vdev
->bus_name
);
631 if (!dev
->hotplugged
) {
632 scsi_bus_legacy_handle_cmdline(&s
->bus
, &err
);
634 error_propagate(errp
, err
);
639 register_savevm(dev
, "virtio-scsi", virtio_scsi_id
++, 1,
640 virtio_scsi_save
, virtio_scsi_load
, s
);
643 void virtio_scsi_common_unrealize(DeviceState
*dev
, Error
**errp
)
645 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
646 VirtIOSCSICommon
*vs
= VIRTIO_SCSI_COMMON(dev
);
649 virtio_cleanup(vdev
);
652 static void virtio_scsi_device_unrealize(DeviceState
*dev
, Error
**errp
)
654 VirtIOSCSI
*s
= VIRTIO_SCSI(dev
);
656 unregister_savevm(dev
, "virtio-scsi", s
);
658 virtio_scsi_common_unrealize(dev
, errp
);
661 static Property virtio_scsi_properties
[] = {
662 DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI
, parent_obj
.conf
),
663 DEFINE_PROP_END_OF_LIST(),
666 static void virtio_scsi_common_class_init(ObjectClass
*klass
, void *data
)
668 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
669 DeviceClass
*dc
= DEVICE_CLASS(klass
);
671 vdc
->get_config
= virtio_scsi_get_config
;
672 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
675 static void virtio_scsi_class_init(ObjectClass
*klass
, void *data
)
677 DeviceClass
*dc
= DEVICE_CLASS(klass
);
678 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
680 dc
->props
= virtio_scsi_properties
;
681 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
682 vdc
->realize
= virtio_scsi_device_realize
;
683 vdc
->unrealize
= virtio_scsi_device_unrealize
;
684 vdc
->set_config
= virtio_scsi_set_config
;
685 vdc
->get_features
= virtio_scsi_get_features
;
686 vdc
->reset
= virtio_scsi_reset
;
689 static const TypeInfo virtio_scsi_common_info
= {
690 .name
= TYPE_VIRTIO_SCSI_COMMON
,
691 .parent
= TYPE_VIRTIO_DEVICE
,
692 .instance_size
= sizeof(VirtIOSCSICommon
),
694 .class_init
= virtio_scsi_common_class_init
,
697 static const TypeInfo virtio_scsi_info
= {
698 .name
= TYPE_VIRTIO_SCSI
,
699 .parent
= TYPE_VIRTIO_SCSI_COMMON
,
700 .instance_size
= sizeof(VirtIOSCSI
),
701 .class_init
= virtio_scsi_class_init
,
704 static void virtio_register_types(void)
706 type_register_static(&virtio_scsi_common_info
);
707 type_register_static(&virtio_scsi_info
);
710 type_init(virtio_register_types
)