]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/virtio-scsi.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / hw / scsi / virtio-scsi.c
CommitLineData
973abc7f
SH
1/*
2 * Virtio SCSI HBA
3 *
4 * Copyright IBM, Corp. 2010
5 * Copyright Red Hat, Inc. 2011
6 *
7 * Authors:
8 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
9 * Paolo Bonzini <pbonzini@redhat.com>
10 *
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.
13 *
14 */
15
9b8bfe21 16#include "qemu/osdep.h"
da34e65c 17#include "qapi/error.h"
019adbd3 18#include "standard-headers/linux/virtio_ids.h"
0d09e41a 19#include "hw/virtio/virtio-scsi.h"
b4a42f81 20#include "qemu/error-report.h"
36b15c79 21#include "qemu/iov.h"
4be74634 22#include "sysemu/block-backend.h"
a9c94277 23#include "hw/scsi/scsi.h"
08e2c9f1 24#include "scsi/constants.h"
a9c94277 25#include "hw/virtio/virtio-bus.h"
8c085dbe 26#include "hw/virtio/virtio-access.h"
973abc7f 27
2ccdcd8d
PB
28static inline int virtio_scsi_get_lun(uint8_t *lun)
29{
30 return ((lun[2] << 8) | lun[3]) & 0x3FFF;
31}
32
33static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
34{
35 if (lun[0] != 1) {
36 return NULL;
37 }
38 if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
39 return NULL;
40 }
41 return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
42}
43
51b19ebe 44void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req)
36b15c79 45{
025bdeab 46 VirtIODevice *vdev = VIRTIO_DEVICE(s);
e24a47c5
PB
47 const size_t zero_skip =
48 offsetof(VirtIOSCSIReq, resp_iov) + sizeof(req->resp_iov);
36b15c79
PB
49
50 req->vq = vq;
51 req->dev = s;
025bdeab 52 qemu_sglist_init(&req->qsgl, DEVICE(s), 8, vdev->dma_as);
3eff1f46 53 qemu_iovec_init(&req->resp_iov, 1);
faf1e1fb 54 memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip);
36b15c79
PB
55}
56
aa8e8f83 57void virtio_scsi_free_req(VirtIOSCSIReq *req)
36b15c79 58{
3eff1f46 59 qemu_iovec_destroy(&req->resp_iov);
36b15c79 60 qemu_sglist_destroy(&req->qsgl);
633dccb4 61 g_free(req);
36b15c79
PB
62}
63
326799c0
SH
64static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
65{
66 VirtIOSCSI *s = req->dev;
67 VirtQueue *vq = req->vq;
0ac8e139 68 VirtIODevice *vdev = VIRTIO_DEVICE(s);
3eff1f46
PB
69
70 qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
e24a47c5 71 virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
43c696a2 72 if (s->dataplane_started && !s->dataplane_fenced) {
83d768b5 73 virtio_notify_irqfd(vdev, vq);
63c7e542 74 } else {
63c7e542
FZ
75 virtio_notify(vdev, vq);
76 }
77
326799c0
SH
78 if (req->sreq) {
79 req->sreq->hba_private = NULL;
80 scsi_req_unref(req->sreq);
81 }
36b15c79 82 virtio_scsi_free_req(req);
326799c0
SH
83}
84
661e32fb 85static void virtio_scsi_bad_req(VirtIOSCSIReq *req)
326799c0 86{
661e32fb
GK
87 virtio_error(VIRTIO_DEVICE(req->dev), "wrong size for virtio-scsi headers");
88 virtqueue_detach_element(req->vq, &req->elem, 0);
89 virtio_scsi_free_req(req);
326799c0
SH
90}
91
57fbae6e
PB
92static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
93 hwaddr *addr, int num, size_t skip)
326799c0 94{
f487b677 95 QEMUSGList *qsgl = &req->qsgl;
57fbae6e
PB
96 size_t copied = 0;
97
98 while (num) {
99 if (skip >= iov->iov_len) {
100 skip -= iov->iov_len;
101 } else {
102 qemu_sglist_add(qsgl, *addr + skip, iov->iov_len - skip);
103 copied += iov->iov_len - skip;
104 skip = 0;
105 }
106 iov++;
107 addr++;
108 num--;
326799c0 109 }
57fbae6e
PB
110
111 assert(skip == 0);
112 return copied;
326799c0
SH
113}
114
36b15c79
PB
115static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
116 unsigned req_size, unsigned resp_size)
326799c0 117{
55783a55 118 VirtIODevice *vdev = (VirtIODevice *) req->dev;
3eff1f46 119 size_t in_size, out_size;
36b15c79 120
3eff1f46
PB
121 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
122 &req->req, req_size) < req_size) {
36b15c79
PB
123 return -EINVAL;
124 }
36b15c79 125
3eff1f46
PB
126 if (qemu_iovec_concat_iov(&req->resp_iov,
127 req->elem.in_sg, req->elem.in_num, 0,
128 resp_size) < resp_size) {
36b15c79
PB
129 return -EINVAL;
130 }
55783a55 131
489c7901 132 req->resp_size = resp_size;
326799c0 133
55783a55
PB
134 /* Old BIOSes left some padding by mistake after the req_size/resp_size.
135 * As a workaround, always consider the first buffer as the virtio-scsi
136 * request/response, making the payload start at the second element
137 * of the iovec.
138 *
139 * The actual length of the response header, stored in req->resp_size,
140 * does not change.
141 *
142 * TODO: always disable this workaround for virtio 1.0 devices.
143 */
95129d6f 144 if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
2034e324
FZ
145 if (req->elem.out_num) {
146 req_size = req->elem.out_sg[0].iov_len;
147 }
148 if (req->elem.in_num) {
149 resp_size = req->elem.in_sg[0].iov_len;
150 }
55783a55
PB
151 }
152
3eff1f46
PB
153 out_size = qemu_sgl_concat(req, req->elem.out_sg,
154 &req->elem.out_addr[0], req->elem.out_num,
155 req_size);
156 in_size = qemu_sgl_concat(req, req->elem.in_sg,
157 &req->elem.in_addr[0], req->elem.in_num,
158 resp_size);
159
160 if (out_size && in_size) {
161 return -ENOTSUP;
162 }
163
164 if (out_size) {
165 req->mode = SCSI_XFER_TO_DEV;
166 } else if (in_size) {
167 req->mode = SCSI_XFER_FROM_DEV;
326799c0 168 }
36b15c79
PB
169
170 return 0;
326799c0
SH
171}
172
173static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
174{
51b19ebe
PB
175 VirtIOSCSICommon *vs = (VirtIOSCSICommon *)s;
176 VirtIOSCSIReq *req;
177
178 req = virtqueue_pop(vq, sizeof(VirtIOSCSIReq) + vs->cdb_size);
179 if (!req) {
326799c0
SH
180 return NULL;
181 }
51b19ebe 182 virtio_scsi_init_req(s, vq, req);
326799c0
SH
183 return req;
184}
185
5db1764c
PB
186static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
187{
188 VirtIOSCSIReq *req = sreq->hba_private;
292c8e50 189 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
3a90c4ac 190 uint32_t n = virtio_get_queue_index(req->vq) - 2;
5db1764c 191
292c8e50 192 assert(n < vs->conf.num_queues);
fcf104a7 193 qemu_put_be32s(f, &n);
ab281c17 194 qemu_put_virtqueue_element(f, &req->elem);
5db1764c
PB
195}
196
197static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
198{
199 SCSIBus *bus = sreq->bus;
200 VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
292c8e50 201 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
8607f5c3 202 VirtIODevice *vdev = VIRTIO_DEVICE(s);
5db1764c 203 VirtIOSCSIReq *req;
fcf104a7 204 uint32_t n;
5db1764c 205
fcf104a7 206 qemu_get_be32s(f, &n);
292c8e50 207 assert(n < vs->conf.num_queues);
8607f5c3
JW
208 req = qemu_get_virtqueue_element(vdev, f,
209 sizeof(VirtIOSCSIReq) + vs->cdb_size);
51b19ebe 210 virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
4ada5331 211
36b15c79
PB
212 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
213 sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) {
214 error_report("invalid SCSI request migration data");
215 exit(1);
216 }
5db1764c
PB
217
218 scsi_req_ref(sreq);
219 req->sreq = sreq;
220 if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
3eff1f46 221 assert(req->sreq->cmd.mode == req->mode);
5db1764c
PB
222 }
223 return req;
224}
225
49e7e31a
FZ
226typedef struct {
227 Notifier notifier;
228 VirtIOSCSIReq *tmf_req;
229} VirtIOSCSICancelNotifier;
230
231static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
232{
233 VirtIOSCSICancelNotifier *n = container_of(notifier,
234 VirtIOSCSICancelNotifier,
235 notifier);
236
237 if (--n->tmf_req->remaining == 0) {
238 virtio_scsi_complete_req(n->tmf_req);
239 }
633dccb4 240 g_free(n);
49e7e31a
FZ
241}
242
2a2d69f4
FZ
243static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
244{
245 if (s->dataplane_started && d && blk_is_available(d->conf.blk)) {
246 assert(blk_get_aio_context(d->conf.blk) == s->ctx);
247 }
248}
249
49e7e31a
FZ
250/* Return 0 if the request is ready to be completed and return to guest;
251 * -EINPROGRESS if the request is submitted and will be completed later, in the
252 * case of async cancellation. */
253static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
326799c0 254{
3eff1f46 255 SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf.lun);
06114d72 256 SCSIRequest *r, *next;
0866aca1 257 BusChild *kid;
06114d72 258 int target;
49e7e31a 259 int ret = 0;
06114d72 260
2a2d69f4 261 virtio_scsi_ctx_check(s, d);
06114d72 262 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
3eff1f46 263 req->resp.tmf.response = VIRTIO_SCSI_S_OK;
06114d72 264
d804232d
GK
265 /*
266 * req->req.tmf has the QEMU_PACKED attribute. Don't use virtio_tswap32s()
267 * to avoid compiler errors.
268 */
269 req->req.tmf.subtype =
270 virtio_tswap32(VIRTIO_DEVICE(s), req->req.tmf.subtype);
271
3eff1f46 272 switch (req->req.tmf.subtype) {
06114d72
PB
273 case VIRTIO_SCSI_T_TMF_ABORT_TASK:
274 case VIRTIO_SCSI_T_TMF_QUERY_TASK:
275 if (!d) {
276 goto fail;
277 }
3eff1f46 278 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
279 goto incorrect_lun;
280 }
281 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
4dd7c82c 282 VirtIOSCSIReq *cmd_req = r->hba_private;
3eff1f46 283 if (cmd_req && cmd_req->req.cmd.tag == req->req.tmf.tag) {
06114d72
PB
284 break;
285 }
286 }
4dd7c82c
PB
287 if (r) {
288 /*
289 * Assert that the request has not been completed yet, we
290 * check for it in the loop above.
291 */
292 assert(r->hba_private);
3eff1f46 293 if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
06114d72
PB
294 /* "If the specified command is present in the task set, then
295 * return a service response set to FUNCTION SUCCEEDED".
296 */
3eff1f46 297 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
06114d72 298 } else {
49e7e31a
FZ
299 VirtIOSCSICancelNotifier *notifier;
300
301 req->remaining = 1;
633dccb4 302 notifier = g_new(VirtIOSCSICancelNotifier, 1);
49e7e31a
FZ
303 notifier->tmf_req = req;
304 notifier->notifier.notify = virtio_scsi_cancel_notify;
305 scsi_req_cancel_async(r, &notifier->notifier);
306 ret = -EINPROGRESS;
06114d72
PB
307 }
308 }
309 break;
310
311 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
312 if (!d) {
313 goto fail;
314 }
3eff1f46 315 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
316 goto incorrect_lun;
317 }
318 s->resetting++;
319 qdev_reset_all(&d->qdev);
320 s->resetting--;
321 break;
322
323 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
324 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
325 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
326 if (!d) {
327 goto fail;
328 }
3eff1f46 329 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
330 goto incorrect_lun;
331 }
49e7e31a
FZ
332
333 /* Add 1 to "remaining" until virtio_scsi_do_tmf returns.
334 * This way, if the bus starts calling back to the notifiers
335 * even before we finish the loop, virtio_scsi_cancel_notify
336 * will not complete the TMF too early.
337 */
338 req->remaining = 1;
06114d72
PB
339 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
340 if (r->hba_private) {
3eff1f46 341 if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
06114d72
PB
342 /* "If there is any command present in the task set, then
343 * return a service response set to FUNCTION SUCCEEDED".
344 */
3eff1f46 345 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
06114d72
PB
346 break;
347 } else {
49e7e31a
FZ
348 VirtIOSCSICancelNotifier *notifier;
349
350 req->remaining++;
633dccb4 351 notifier = g_new(VirtIOSCSICancelNotifier, 1);
49e7e31a
FZ
352 notifier->notifier.notify = virtio_scsi_cancel_notify;
353 notifier->tmf_req = req;
354 scsi_req_cancel_async(r, &notifier->notifier);
06114d72
PB
355 }
356 }
357 }
49e7e31a
FZ
358 if (--req->remaining > 0) {
359 ret = -EINPROGRESS;
360 }
06114d72
PB
361 break;
362
363 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
3eff1f46 364 target = req->req.tmf.lun[1];
06114d72 365 s->resetting++;
0866aca1 366 QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
e1dc6815 367 d = SCSI_DEVICE(kid->child);
06114d72
PB
368 if (d->channel == 0 && d->id == target) {
369 qdev_reset_all(&d->qdev);
370 }
371 }
372 s->resetting--;
373 break;
374
375 case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
376 default:
3eff1f46 377 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
06114d72 378 break;
326799c0
SH
379 }
380
49e7e31a 381 return ret;
06114d72
PB
382
383incorrect_lun:
3eff1f46 384 req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
49e7e31a 385 return ret;
06114d72
PB
386
387fail:
3eff1f46 388 req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
49e7e31a 389 return ret;
326799c0
SH
390}
391
a8f2e5c8 392static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
973abc7f 393{
dc56b7c4 394 VirtIODevice *vdev = (VirtIODevice *)s;
024d9adc 395 uint32_t type;
49e7e31a 396 int r = 0;
326799c0 397
dc56b7c4
FZ
398 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
399 &type, sizeof(type)) < sizeof(type)) {
661e32fb 400 virtio_scsi_bad_req(req);
dc56b7c4
FZ
401 return;
402 }
36b15c79 403
024d9adc
BW
404 virtio_tswap32s(vdev, &type);
405 if (type == VIRTIO_SCSI_T_TMF) {
dc56b7c4
FZ
406 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
407 sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
661e32fb
GK
408 virtio_scsi_bad_req(req);
409 return;
dc56b7c4 410 } else {
49e7e31a 411 r = virtio_scsi_do_tmf(s, req);
b0b4ea17 412 }
06114d72 413
024d9adc
BW
414 } else if (type == VIRTIO_SCSI_T_AN_QUERY ||
415 type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
dc56b7c4
FZ
416 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
417 sizeof(VirtIOSCSICtrlANResp)) < 0) {
661e32fb
GK
418 virtio_scsi_bad_req(req);
419 return;
dc56b7c4
FZ
420 } else {
421 req->resp.an.event_actual = 0;
422 req->resp.an.response = VIRTIO_SCSI_S_OK;
06114d72 423 }
dc56b7c4 424 }
49e7e31a
FZ
425 if (r == 0) {
426 virtio_scsi_complete_req(req);
427 } else {
428 assert(r == -EINPROGRESS);
429 }
dc56b7c4
FZ
430}
431
07931698 432bool virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
dc56b7c4 433{
dc56b7c4 434 VirtIOSCSIReq *req;
07931698 435 bool progress = false;
dc56b7c4
FZ
436
437 while ((req = virtio_scsi_pop_req(s, vq))) {
07931698 438 progress = true;
dc56b7c4 439 virtio_scsi_handle_ctrl_req(s, req);
326799c0 440 }
07931698 441 return progress;
326799c0
SH
442}
443
a8f2e5c8
PB
444static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
445{
446 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
447
448 if (s->ctx) {
ad07cd69 449 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
450 if (!s->dataplane_fenced) {
451 return;
452 }
453 }
71407786 454 virtio_scsi_acquire(s);
a8f2e5c8 455 virtio_scsi_handle_ctrl_vq(s, vq);
71407786 456 virtio_scsi_release(s);
a8f2e5c8
PB
457}
458
a3de269c
PB
459static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
460{
3eff1f46
PB
461 /* Sense data is not in req->resp and is copied separately
462 * in virtio_scsi_command_complete.
463 */
464 req->resp_size = sizeof(VirtIOSCSICmdResp);
a3de269c
PB
465 virtio_scsi_complete_req(req);
466}
467
2ccdcd8d
PB
468static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
469 size_t resid)
470{
471 VirtIOSCSIReq *req = r->hba_private;
489c7901 472 uint8_t sense[SCSI_SENSE_BUF_SIZE];
474ee55a 473 uint32_t sense_len;
8c085dbe 474 VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
2ccdcd8d 475
e9c0f0f5
EF
476 if (r->io_canceled) {
477 return;
478 }
479
3eff1f46
PB
480 req->resp.cmd.response = VIRTIO_SCSI_S_OK;
481 req->resp.cmd.status = status;
482 if (req->resp.cmd.status == GOOD) {
8c085dbe 483 req->resp.cmd.resid = virtio_tswap32(vdev, resid);
2ccdcd8d 484 } else {
3eff1f46 485 req->resp.cmd.resid = 0;
489c7901 486 sense_len = scsi_req_get_sense(r, sense, sizeof(sense));
3eff1f46
PB
487 sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
488 qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd),
b7890c40 489 sense, sense_len);
8c085dbe 490 req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
2ccdcd8d 491 }
a3de269c 492 virtio_scsi_complete_cmd_req(req);
2ccdcd8d
PB
493}
494
33cbb2c5
PB
495static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
496 uint8_t *buf, void *hba_private)
497{
498 VirtIOSCSIReq *req = hba_private;
499
500 if (cmd->len == 0) {
03325525 501 cmd->len = MIN(VIRTIO_SCSI_CDB_DEFAULT_SIZE, SCSI_CMD_BUF_SIZE);
33cbb2c5
PB
502 memcpy(cmd->buf, buf, cmd->len);
503 }
504
505 /* Extract the direction and mode directly from the request, for
506 * host device passthrough.
507 */
508 cmd->xfer = req->qsgl.size;
9df7bfdd 509 cmd->mode = req->mode;
33cbb2c5
PB
510 return 0;
511}
512
2ccdcd8d
PB
513static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
514{
515 VirtIOSCSIReq *req = r->hba_private;
516
517 return &req->qsgl;
518}
519
520static void virtio_scsi_request_cancelled(SCSIRequest *r)
521{
522 VirtIOSCSIReq *req = r->hba_private;
523
524 if (!req) {
525 return;
526 }
06114d72 527 if (req->dev->resetting) {
3eff1f46 528 req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
06114d72 529 } else {
3eff1f46 530 req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
06114d72 531 }
a3de269c 532 virtio_scsi_complete_cmd_req(req);
2ccdcd8d
PB
533}
534
535static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
326799c0 536{
3eff1f46 537 req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
a3de269c 538 virtio_scsi_complete_cmd_req(req);
973abc7f
SH
539}
540
661e32fb 541static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
bf359a44
FZ
542{
543 VirtIOSCSICommon *vs = &s->parent_obj;
bf359a44
FZ
544 SCSIDevice *d;
545 int rc;
546
547 rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
548 sizeof(VirtIOSCSICmdResp) + vs->sense_size);
549 if (rc < 0) {
550 if (rc == -ENOTSUP) {
551 virtio_scsi_fail_cmd_req(req);
661e32fb 552 return -ENOTSUP;
bf359a44 553 } else {
661e32fb
GK
554 virtio_scsi_bad_req(req);
555 return -EINVAL;
bf359a44 556 }
bf359a44
FZ
557 }
558
559 d = virtio_scsi_device_find(s, req->req.cmd.lun);
560 if (!d) {
561 req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
562 virtio_scsi_complete_cmd_req(req);
661e32fb 563 return -ENOENT;
bf359a44 564 }
2a2d69f4 565 virtio_scsi_ctx_check(s, d);
bf359a44
FZ
566 req->sreq = scsi_req_new(d, req->req.cmd.tag,
567 virtio_scsi_get_lun(req->req.cmd.lun),
bb72463b 568 req->req.cmd.cdb, req);
bf359a44
FZ
569
570 if (req->sreq->cmd.mode != SCSI_XFER_NONE
571 && (req->sreq->cmd.mode != req->mode ||
572 req->sreq->cmd.xfer > req->qsgl.size)) {
573 req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
574 virtio_scsi_complete_cmd_req(req);
661e32fb 575 return -ENOBUFS;
bf359a44 576 }
5170f40b 577 scsi_req_ref(req->sreq);
4be74634 578 blk_io_plug(d->conf.blk);
661e32fb 579 return 0;
359eea71 580}
bf359a44 581
a8f2e5c8 582static void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
359eea71 583{
35e4e96c
PB
584 SCSIRequest *sreq = req->sreq;
585 if (scsi_req_enqueue(sreq)) {
586 scsi_req_continue(sreq);
bf359a44 587 }
4be74634 588 blk_io_unplug(sreq->dev->conf.blk);
35e4e96c 589 scsi_req_unref(sreq);
bf359a44
FZ
590}
591
07931698 592bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
973abc7f 593{
1880ad4f 594 VirtIOSCSIReq *req, *next;
23425cc2 595 int ret = 0;
07931698 596 bool progress = false;
661e32fb 597
1880ad4f 598 QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
326799c0 599
23425cc2
SH
600 do {
601 virtio_queue_set_notification(vq, 0);
602
603 while ((req = virtio_scsi_pop_req(s, vq))) {
07931698 604 progress = true;
23425cc2
SH
605 ret = virtio_scsi_handle_cmd_req_prepare(s, req);
606 if (!ret) {
607 QTAILQ_INSERT_TAIL(&reqs, req, next);
608 } else if (ret == -EINVAL) {
609 /* The device is broken and shouldn't process any request */
610 while (!QTAILQ_EMPTY(&reqs)) {
611 req = QTAILQ_FIRST(&reqs);
612 QTAILQ_REMOVE(&reqs, req, next);
613 blk_io_unplug(req->sreq->dev->conf.blk);
614 scsi_req_unref(req->sreq);
615 virtqueue_detach_element(req->vq, &req->elem, 0);
616 virtio_scsi_free_req(req);
617 }
661e32fb 618 }
359eea71 619 }
23425cc2
SH
620
621 virtio_queue_set_notification(vq, 1);
622 } while (ret != -EINVAL && !virtio_queue_empty(vq));
1880ad4f
FZ
623
624 QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
625 virtio_scsi_handle_cmd_req_submit(s, req);
626 }
07931698 627 return progress;
973abc7f
SH
628}
629
a8f2e5c8
PB
630static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
631{
632 /* use non-QOM casts in the data path */
633 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
634
635 if (s->ctx) {
ad07cd69 636 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
637 if (!s->dataplane_fenced) {
638 return;
639 }
640 }
71407786 641 virtio_scsi_acquire(s);
a8f2e5c8 642 virtio_scsi_handle_cmd_vq(s, vq);
71407786 643 virtio_scsi_release(s);
a8f2e5c8
PB
644}
645
973abc7f
SH
646static void virtio_scsi_get_config(VirtIODevice *vdev,
647 uint8_t *config)
648{
649 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
292c8e50 650 VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
973abc7f 651
8c085dbe
RR
652 virtio_stl_p(vdev, &scsiconf->num_queues, s->conf.num_queues);
653 virtio_stl_p(vdev, &scsiconf->seg_max, 128 - 2);
654 virtio_stl_p(vdev, &scsiconf->max_sectors, s->conf.max_sectors);
655 virtio_stl_p(vdev, &scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
656 virtio_stl_p(vdev, &scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
657 virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size);
658 virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size);
659 virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
660 virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
661 virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
973abc7f
SH
662}
663
664static void virtio_scsi_set_config(VirtIODevice *vdev,
665 const uint8_t *config)
666{
667 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
292c8e50 668 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
973abc7f 669
8c085dbe
RR
670 if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) >= 65536 ||
671 (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) >= 256) {
ad14a46a
GK
672 virtio_error(vdev,
673 "bad data written to virtio-scsi configuration space");
674 return;
973abc7f
SH
675 }
676
8c085dbe
RR
677 vs->sense_size = virtio_ldl_p(vdev, &scsiconf->sense_size);
678 vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
973abc7f
SH
679}
680
019a3edb 681static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
9d5b731d
JW
682 uint64_t requested_features,
683 Error **errp)
973abc7f 684{
da2f84d1
SZ
685 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
686
687 /* Firstly sync all virtio-scsi possible supported features */
688 requested_features |= s->host_features;
973abc7f
SH
689 return requested_features;
690}
691
692static void virtio_scsi_reset(VirtIODevice *vdev)
693{
292c8e50
PB
694 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
695 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
973abc7f 696
ad07cd69 697 assert(!s->dataplane_started);
47a150a4
PB
698 s->resetting++;
699 qbus_reset_all(&s->bus.qbus);
700 s->resetting--;
701
03325525
MT
702 vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
703 vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
2baa1beb 704 s->events_dropped = false;
973abc7f
SH
705}
706
20e6dca1
FZ
707void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
708 uint32_t event, uint32_t reason)
b6866fee 709{
292c8e50 710 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
91e7fcca 711 VirtIOSCSIReq *req;
b6866fee 712 VirtIOSCSIEvent *evt;
0ac8e139 713 VirtIODevice *vdev = VIRTIO_DEVICE(s);
b6866fee 714
0ac8e139 715 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
cd41a671
PB
716 return;
717 }
718
e24a47c5 719 req = virtio_scsi_pop_req(s, vs->event_vq);
64f64855
PB
720 if (!req) {
721 s->events_dropped = true;
71407786 722 return;
64f64855 723 }
b6866fee 724
64f64855
PB
725 if (s->events_dropped) {
726 event |= VIRTIO_SCSI_T_EVENTS_MISSED;
727 s->events_dropped = false;
728 }
729
dfecbb95 730 if (virtio_scsi_parse_req(req, 0, sizeof(VirtIOSCSIEvent))) {
661e32fb 731 virtio_scsi_bad_req(req);
71407786 732 return;
64f64855
PB
733 }
734
3eff1f46 735 evt = &req->resp.event;
64f64855 736 memset(evt, 0, sizeof(VirtIOSCSIEvent));
424baff5
CLG
737 evt->event = virtio_tswap32(vdev, event);
738 evt->reason = virtio_tswap32(vdev, reason);
64f64855 739 if (!dev) {
49fb65c7 740 assert(event == VIRTIO_SCSI_T_EVENTS_MISSED);
64f64855 741 } else {
b6866fee
CM
742 evt->lun[0] = 1;
743 evt->lun[1] = dev->id;
744
745 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
746 if (dev->lun >= 256) {
747 evt->lun[2] = (dev->lun >> 8) | 0x40;
748 }
749 evt->lun[3] = dev->lun & 0xFF;
64f64855
PB
750 }
751 virtio_scsi_complete_req(req);
752}
753
07931698 754bool virtio_scsi_handle_event_vq(VirtIOSCSI *s, VirtQueue *vq)
a8f2e5c8
PB
755{
756 if (s->events_dropped) {
757 virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
07931698 758 return true;
a8f2e5c8 759 }
07931698 760 return false;
a8f2e5c8
PB
761}
762
64f64855
PB
763static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
764{
0ac8e139 765 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
64f64855 766
a8f2e5c8 767 if (s->ctx) {
ad07cd69 768 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
769 if (!s->dataplane_fenced) {
770 return;
771 }
b6866fee 772 }
71407786 773 virtio_scsi_acquire(s);
a8f2e5c8 774 virtio_scsi_handle_event_vq(s, vq);
71407786 775 virtio_scsi_release(s);
b6866fee
CM
776}
777
feda01e4
PB
778static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
779{
780 VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
0ac8e139 781 VirtIODevice *vdev = VIRTIO_DEVICE(s);
feda01e4 782
95129d6f 783 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
feda01e4 784 dev->type != TYPE_ROM) {
71407786 785 virtio_scsi_acquire(s);
feda01e4
PB
786 virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
787 sense.asc | (sense.ascq << 8));
71407786 788 virtio_scsi_release(s);
feda01e4
PB
789 }
790}
791
02206e52
IM
792static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
793 Error **errp)
b6866fee 794{
02206e52 795 VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
3e2b2a9c
FZ
796 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
797 SCSIDevice *sd = SCSI_DEVICE(dev);
798
43c696a2 799 if (s->ctx && !s->dataplane_fenced) {
eb97813f 800 AioContext *ctx;
3e2b2a9c
FZ
801 if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
802 return;
eb97813f
AG
803 }
804 ctx = blk_get_aio_context(sd->conf.blk);
805 if (ctx != s->ctx && ctx != qemu_get_aio_context()) {
806 error_setg(errp, "Cannot attach a blockdev that is using "
807 "a different iothread");
808 return;
3e2b2a9c 809 }
e7a9f353 810 virtio_scsi_acquire(s);
05430559 811 blk_set_aio_context(sd->conf.blk, s->ctx);
e7a9f353 812 virtio_scsi_release(s);
8449bcf9 813
8b5e6caf 814 }
b6866fee 815
95129d6f 816 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
71407786 817 virtio_scsi_acquire(s);
3e2b2a9c 818 virtio_scsi_push_event(s, sd,
02206e52 819 VIRTIO_SCSI_T_TRANSPORT_RESET,
b6866fee 820 VIRTIO_SCSI_EVT_RESET_RESCAN);
71407786 821 virtio_scsi_release(s);
b6866fee
CM
822 }
823}
824
02206e52
IM
825static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
826 Error **errp)
b6866fee 827{
02206e52 828 VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
3e2b2a9c
FZ
829 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
830 SCSIDevice *sd = SCSI_DEVICE(dev);
b6866fee 831
95129d6f 832 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
71407786 833 virtio_scsi_acquire(s);
3e2b2a9c 834 virtio_scsi_push_event(s, sd,
02206e52 835 VIRTIO_SCSI_T_TRANSPORT_RESET,
b6866fee 836 VIRTIO_SCSI_EVT_RESET_REMOVED);
71407786 837 virtio_scsi_release(s);
b6866fee 838 }
3e2b2a9c 839
a6f230c8
AG
840 if (s->ctx) {
841 virtio_scsi_acquire(s);
842 blk_set_aio_context(sd->conf.blk, qemu_get_aio_context());
843 virtio_scsi_release(s);
844 }
845
02206e52 846 qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
b6866fee
CM
847}
848
2ccdcd8d
PB
849static struct SCSIBusInfo virtio_scsi_scsi_info = {
850 .tcq = true,
851 .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
852 .max_target = VIRTIO_SCSI_MAX_TARGET,
853 .max_lun = VIRTIO_SCSI_MAX_LUN,
854
855 .complete = virtio_scsi_command_complete,
856 .cancel = virtio_scsi_request_cancelled,
feda01e4 857 .change = virtio_scsi_change,
33cbb2c5 858 .parse_cdb = virtio_scsi_parse_cdb,
2ccdcd8d 859 .get_sg_list = virtio_scsi_get_sg_list,
5db1764c
PB
860 .save_request = virtio_scsi_save_request,
861 .load_request = virtio_scsi_load_request,
2ccdcd8d
PB
862};
863
bf46e67d 864void virtio_scsi_common_realize(DeviceState *dev,
209b27bb
FZ
865 VirtIOHandleOutput ctrl,
866 VirtIOHandleOutput evt,
bf46e67d
FZ
867 VirtIOHandleOutput cmd,
868 Error **errp)
973abc7f 869{
71a6520b
AF
870 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
871 VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
d2ad7dd4 872 int i;
973abc7f 873
7598f0f3 874 virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
763684be 875 sizeof(VirtIOSCSIConfig));
3ab1dfdd 876
0ba1f531 877 if (s->conf.num_queues == 0 ||
87b3bd1c 878 s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) {
0ba1f531 879 error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
c9f65528 880 "must be a positive integer less than %d.",
87b3bd1c 881 s->conf.num_queues, VIRTIO_QUEUE_MAX - 2);
93bd49af 882 virtio_cleanup(vdev);
c9f65528
FZ
883 return;
884 }
3c55fe2a 885 s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues);
03325525
MT
886 s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
887 s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
3ab1dfdd 888
5c0919d0
RJ
889 s->ctrl_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, ctrl);
890 s->event_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, evt);
394e2e4c 891 for (i = 0; i < s->conf.num_queues; i++) {
5c0919d0 892 s->cmd_vqs[i] = virtio_add_queue(vdev, s->conf.virtqueue_size, cmd);
9786b592 893 }
292c8e50
PB
894}
895
71a6520b 896static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
292c8e50 897{
71a6520b 898 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
7598f0f3 899 VirtIOSCSI *s = VIRTIO_SCSI(dev);
caad4eb3 900 Error *err = NULL;
292c8e50 901
bf46e67d
FZ
902 virtio_scsi_common_realize(dev,
903 virtio_scsi_handle_ctrl,
91d670fb 904 virtio_scsi_handle_event,
bf46e67d
FZ
905 virtio_scsi_handle_cmd,
906 &err);
71a6520b
AF
907 if (err != NULL) {
908 error_propagate(errp, err);
909 return;
292c8e50
PB
910 }
911
7598f0f3 912 scsi_bus_new(&s->bus, sizeof(s->bus), dev,
b1187b51 913 &virtio_scsi_scsi_info, vdev->bus_name);
02206e52 914 /* override default SCSI bus hotplug-handler, with virtio-scsi's one */
94d1cc5f 915 qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort);
6f32a6b4 916
ad07cd69 917 virtio_scsi_dataplane_setup(s, errp);
3ab1dfdd
FK
918}
919
306ec6c3 920void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
292c8e50 921{
306ec6c3
AF
922 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
923 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
292c8e50
PB
924
925 g_free(vs->cmd_vqs);
6a1a8cc7 926 virtio_cleanup(vdev);
292c8e50
PB
927}
928
306ec6c3 929static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
3ab1dfdd 930{
2cbe2de5
FZ
931 VirtIOSCSI *s = VIRTIO_SCSI(dev);
932
933 qbus_set_hotplug_handler(BUS(&s->bus), NULL, &error_abort);
306ec6c3 934 virtio_scsi_common_unrealize(dev, errp);
3ab1dfdd
FK
935}
936
937static Property virtio_scsi_properties[] = {
0c63237a 938 DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
5c0919d0
RJ
939 DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
940 parent_obj.conf.virtqueue_size, 128),
0c63237a
SZ
941 DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
942 0xFFFF),
943 DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
944 128),
0c63237a
SZ
945 DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features,
946 VIRTIO_SCSI_F_HOTPLUG, true),
947 DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
948 VIRTIO_SCSI_F_CHANGE, true),
08f1ecd8
FZ
949 DEFINE_PROP_LINK("iothread", VirtIOSCSI, parent_obj.conf.iothread,
950 TYPE_IOTHREAD, IOThread *),
3ab1dfdd
FK
951 DEFINE_PROP_END_OF_LIST(),
952};
953
f20476b9
HP
954static const VMStateDescription vmstate_virtio_scsi = {
955 .name = "virtio-scsi",
956 .minimum_version_id = 1,
957 .version_id = 1,
958 .fields = (VMStateField[]) {
959 VMSTATE_VIRTIO_DEVICE,
960 VMSTATE_END_OF_LIST()
961 },
962};
5a289a28 963
292c8e50
PB
964static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
965{
966 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
125ee0ed 967 DeviceClass *dc = DEVICE_CLASS(klass);
292c8e50
PB
968
969 vdc->get_config = virtio_scsi_get_config;
125ee0ed 970 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
292c8e50
PB
971}
972
3ab1dfdd
FK
973static void virtio_scsi_class_init(ObjectClass *klass, void *data)
974{
975 DeviceClass *dc = DEVICE_CLASS(klass);
976 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
02206e52 977 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
71a6520b 978
3ab1dfdd 979 dc->props = virtio_scsi_properties;
5a289a28 980 dc->vmsd = &vmstate_virtio_scsi;
125ee0ed 981 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
71a6520b 982 vdc->realize = virtio_scsi_device_realize;
306ec6c3 983 vdc->unrealize = virtio_scsi_device_unrealize;
3ab1dfdd
FK
984 vdc->set_config = virtio_scsi_set_config;
985 vdc->get_features = virtio_scsi_get_features;
986 vdc->reset = virtio_scsi_reset;
ad07cd69
PB
987 vdc->start_ioeventfd = virtio_scsi_dataplane_start;
988 vdc->stop_ioeventfd = virtio_scsi_dataplane_stop;
02206e52
IM
989 hc->plug = virtio_scsi_hotplug;
990 hc->unplug = virtio_scsi_hotunplug;
3ab1dfdd
FK
991}
992
292c8e50
PB
993static const TypeInfo virtio_scsi_common_info = {
994 .name = TYPE_VIRTIO_SCSI_COMMON,
995 .parent = TYPE_VIRTIO_DEVICE,
996 .instance_size = sizeof(VirtIOSCSICommon),
a27292b5 997 .abstract = true,
292c8e50
PB
998 .class_init = virtio_scsi_common_class_init,
999};
1000
3ab1dfdd
FK
1001static const TypeInfo virtio_scsi_info = {
1002 .name = TYPE_VIRTIO_SCSI,
292c8e50 1003 .parent = TYPE_VIRTIO_SCSI_COMMON,
3ab1dfdd
FK
1004 .instance_size = sizeof(VirtIOSCSI),
1005 .class_init = virtio_scsi_class_init,
02206e52
IM
1006 .interfaces = (InterfaceInfo[]) {
1007 { TYPE_HOTPLUG_HANDLER },
1008 { }
1009 }
3ab1dfdd
FK
1010};
1011
1012static void virtio_register_types(void)
1013{
292c8e50 1014 type_register_static(&virtio_scsi_common_info);
3ab1dfdd
FK
1015 type_register_static(&virtio_scsi_info);
1016}
1017
1018type_init(virtio_register_types)