Statistics
| Branch: | Revision:

root / hw / virtio-scsi.c @ 7bc3018b

History | View | Annotate | Download (18.5 kB)

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

    
16
#include "virtio-scsi.h"
17
#include <hw/scsi.h>
18
#include <hw/scsi-defs.h>
19

    
20
#define VIRTIO_SCSI_VQ_SIZE     128
21
#define VIRTIO_SCSI_CDB_SIZE    32
22
#define VIRTIO_SCSI_SENSE_SIZE  96
23
#define VIRTIO_SCSI_MAX_CHANNEL 0
24
#define VIRTIO_SCSI_MAX_TARGET  255
25
#define VIRTIO_SCSI_MAX_LUN     16383
26

    
27
/* Response codes */
28
#define VIRTIO_SCSI_S_OK                       0
29
#define VIRTIO_SCSI_S_OVERRUN                  1
30
#define VIRTIO_SCSI_S_ABORTED                  2
31
#define VIRTIO_SCSI_S_BAD_TARGET               3
32
#define VIRTIO_SCSI_S_RESET                    4
33
#define VIRTIO_SCSI_S_BUSY                     5
34
#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
35
#define VIRTIO_SCSI_S_TARGET_FAILURE           7
36
#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
37
#define VIRTIO_SCSI_S_FAILURE                  9
38
#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
39
#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
40
#define VIRTIO_SCSI_S_INCORRECT_LUN            12
41

    
42
/* Controlq type codes.  */
43
#define VIRTIO_SCSI_T_TMF                      0
44
#define VIRTIO_SCSI_T_AN_QUERY                 1
45
#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
46

    
47
/* Valid TMF subtypes.  */
48
#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
49
#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
50
#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
51
#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
52
#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
53
#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
54
#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
55
#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
56

    
57
/* Events.  */
58
#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
59
#define VIRTIO_SCSI_T_NO_EVENT                 0
60
#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
61
#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
62

    
63
/* SCSI command request, followed by data-out */
64
typedef struct {
65
    uint8_t lun[8];              /* Logical Unit Number */
66
    uint64_t tag;                /* Command identifier */
67
    uint8_t task_attr;           /* Task attribute */
68
    uint8_t prio;
69
    uint8_t crn;
70
    uint8_t cdb[];
71
} QEMU_PACKED VirtIOSCSICmdReq;
72

    
73
/* Response, followed by sense data and data-in */
74
typedef struct {
75
    uint32_t sense_len;          /* Sense data length */
76
    uint32_t resid;              /* Residual bytes in data buffer */
77
    uint16_t status_qualifier;   /* Status qualifier */
78
    uint8_t status;              /* Command completion status */
79
    uint8_t response;            /* Response values */
80
    uint8_t sense[];
81
} QEMU_PACKED VirtIOSCSICmdResp;
82

    
83
/* Task Management Request */
84
typedef struct {
85
    uint32_t type;
86
    uint32_t subtype;
87
    uint8_t lun[8];
88
    uint64_t tag;
89
} QEMU_PACKED VirtIOSCSICtrlTMFReq;
90

    
91
typedef struct {
92
    uint8_t response;
93
} QEMU_PACKED VirtIOSCSICtrlTMFResp;
94

    
95
/* Asynchronous notification query/subscription */
96
typedef struct {
97
    uint32_t type;
98
    uint8_t lun[8];
99
    uint32_t event_requested;
100
} QEMU_PACKED VirtIOSCSICtrlANReq;
101

    
102
typedef struct {
103
    uint32_t event_actual;
104
    uint8_t response;
105
} QEMU_PACKED VirtIOSCSICtrlANResp;
106

    
107
typedef struct {
108
    uint32_t event;
109
    uint8_t lun[8];
110
    uint32_t reason;
111
} QEMU_PACKED VirtIOSCSIEvent;
112

    
113
typedef struct {
114
    uint32_t num_queues;
115
    uint32_t seg_max;
116
    uint32_t max_sectors;
117
    uint32_t cmd_per_lun;
118
    uint32_t event_info_size;
119
    uint32_t sense_size;
120
    uint32_t cdb_size;
121
    uint16_t max_channel;
122
    uint16_t max_target;
123
    uint32_t max_lun;
124
} QEMU_PACKED VirtIOSCSIConfig;
125

    
126
typedef struct {
127
    VirtIODevice vdev;
128
    DeviceState *qdev;
129
    VirtIOSCSIConf *conf;
130

    
131
    SCSIBus bus;
132
    uint32_t sense_size;
133
    uint32_t cdb_size;
134
    int resetting;
135
    VirtQueue *ctrl_vq;
136
    VirtQueue *event_vq;
137
    VirtQueue *cmd_vqs[0];
138
} VirtIOSCSI;
139

    
140
typedef struct VirtIOSCSIReq {
141
    VirtIOSCSI *dev;
142
    VirtQueue *vq;
143
    VirtQueueElement elem;
144
    QEMUSGList qsgl;
145
    SCSIRequest *sreq;
146
    union {
147
        char                  *buf;
148
        VirtIOSCSICmdReq      *cmd;
149
        VirtIOSCSICtrlTMFReq  *tmf;
150
        VirtIOSCSICtrlANReq   *an;
151
    } req;
152
    union {
153
        char                  *buf;
154
        VirtIOSCSICmdResp     *cmd;
155
        VirtIOSCSICtrlTMFResp *tmf;
156
        VirtIOSCSICtrlANResp  *an;
157
        VirtIOSCSIEvent       *event;
158
    } resp;
159
} VirtIOSCSIReq;
160

    
161
static inline int virtio_scsi_get_lun(uint8_t *lun)
162
{
163
    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
164
}
165

    
166
static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
167
{
168
    if (lun[0] != 1) {
169
        return NULL;
170
    }
171
    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
172
        return NULL;
173
    }
174
    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
175
}
176

    
177
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
178
{
179
    VirtIOSCSI *s = req->dev;
180
    VirtQueue *vq = req->vq;
181
    virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
182
    qemu_sglist_destroy(&req->qsgl);
183
    if (req->sreq) {
184
        req->sreq->hba_private = NULL;
185
        scsi_req_unref(req->sreq);
186
    }
187
    g_free(req);
188
    virtio_notify(&s->vdev, vq);
189
}
190

    
191
static void virtio_scsi_bad_req(void)
192
{
193
    error_report("wrong size for virtio-scsi headers");
194
    exit(1);
195
}
196

    
197
static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
198
                                   target_phys_addr_t *addr, int num)
199
{
200
    memset(qsgl, 0, sizeof(*qsgl));
201
    while (num--) {
202
        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
203
    }
204
}
205

    
206
static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
207
                                  VirtIOSCSIReq *req)
208
{
209
    assert(req->elem.out_num && req->elem.in_num);
210
    req->vq = vq;
211
    req->dev = s;
212
    req->sreq = NULL;
213
    req->req.buf = req->elem.out_sg[0].iov_base;
214
    req->resp.buf = req->elem.in_sg[0].iov_base;
215

    
216
    if (req->elem.out_num > 1) {
217
        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
218
                               &req->elem.out_addr[1],
219
                               req->elem.out_num - 1);
220
    } else {
221
        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
222
                               &req->elem.in_addr[1],
223
                               req->elem.in_num - 1);
224
    }
225
}
226

    
227
static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
228
{
229
    VirtIOSCSIReq *req;
230
    req = g_malloc(sizeof(*req));
231
    if (!virtqueue_pop(vq, &req->elem)) {
232
        g_free(req);
233
        return NULL;
234
    }
235

    
236
    virtio_scsi_parse_req(s, vq, req);
237
    return req;
238
}
239

    
240
static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
241
{
242
    VirtIOSCSIReq *req = sreq->hba_private;
243
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
244

    
245
    assert(n < req->dev->conf->num_queues);
246
    qemu_put_be32s(f, &n);
247
    qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
248
}
249

    
250
static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
251
{
252
    SCSIBus *bus = sreq->bus;
253
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
254
    VirtIOSCSIReq *req;
255
    uint32_t n;
256

    
257
    req = g_malloc(sizeof(*req));
258
    qemu_get_be32s(f, &n);
259
    assert(n < s->conf->num_queues);
260
    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
261
    virtio_scsi_parse_req(s, s->cmd_vqs[n], req);
262

    
263
    scsi_req_ref(sreq);
264
    req->sreq = sreq;
265
    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
266
        int req_mode =
267
            (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
268

    
269
        assert(req->sreq->cmd.mode == req_mode);
270
    }
271
    return req;
272
}
273

    
274
static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
275
{
276
    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
277
    SCSIRequest *r, *next;
278
    DeviceState *qdev;
279
    int target;
280

    
281
    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
282
    req->resp.tmf->response = VIRTIO_SCSI_S_OK;
283

    
284
    switch (req->req.tmf->subtype) {
285
    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
286
    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
287
        if (!d) {
288
            goto fail;
289
        }
290
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
291
            goto incorrect_lun;
292
        }
293
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
294
            if (r->tag == req->req.tmf->tag) {
295
                break;
296
            }
297
        }
298
        if (r && r->hba_private) {
299
            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
300
                /* "If the specified command is present in the task set, then
301
                 * return a service response set to FUNCTION SUCCEEDED".
302
                 */
303
                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
304
            } else {
305
                scsi_req_cancel(r);
306
            }
307
        }
308
        break;
309

    
310
    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
311
        if (!d) {
312
            goto fail;
313
        }
314
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
315
            goto incorrect_lun;
316
        }
317
        s->resetting++;
318
        qdev_reset_all(&d->qdev);
319
        s->resetting--;
320
        break;
321

    
322
    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
323
    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
324
    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
325
        if (!d) {
326
            goto fail;
327
        }
328
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
329
            goto incorrect_lun;
330
        }
331
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
332
            if (r->hba_private) {
333
                if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
334
                    /* "If there is any command present in the task set, then
335
                     * return a service response set to FUNCTION SUCCEEDED".
336
                     */
337
                    req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
338
                    break;
339
                } else {
340
                    scsi_req_cancel(r);
341
                }
342
            }
343
        }
344
        break;
345

    
346
    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
347
        target = req->req.tmf->lun[1];
348
        s->resetting++;
349
        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
350
             d = DO_UPCAST(SCSIDevice, qdev, qdev);
351
             if (d->channel == 0 && d->id == target) {
352
                qdev_reset_all(&d->qdev);
353
             }
354
        }
355
        s->resetting--;
356
        break;
357

    
358
    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
359
    default:
360
        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
361
        break;
362
    }
363

    
364
    return;
365

    
366
incorrect_lun:
367
    req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
368
    return;
369

    
370
fail:
371
    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
372
}
373

    
374
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
375
{
376
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
377
    VirtIOSCSIReq *req;
378

    
379
    while ((req = virtio_scsi_pop_req(s, vq))) {
380
        int out_size, in_size;
381
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
382
            virtio_scsi_bad_req();
383
            continue;
384
        }
385

    
386
        out_size = req->elem.out_sg[0].iov_len;
387
        in_size = req->elem.in_sg[0].iov_len;
388
        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
389
            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
390
                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
391
                virtio_scsi_bad_req();
392
            }
393
            virtio_scsi_do_tmf(s, req);
394

    
395
        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
396
                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
397
            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
398
                in_size < sizeof(VirtIOSCSICtrlANResp)) {
399
                virtio_scsi_bad_req();
400
            }
401
            req->resp.an->event_actual = 0;
402
            req->resp.an->response = VIRTIO_SCSI_S_OK;
403
        }
404
        virtio_scsi_complete_req(req);
405
    }
406
}
407

    
408
static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
409
                                         size_t resid)
410
{
411
    VirtIOSCSIReq *req = r->hba_private;
412

    
413
    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
414
    req->resp.cmd->status = status;
415
    if (req->resp.cmd->status == GOOD) {
416
        req->resp.cmd->resid = resid;
417
    } else {
418
        req->resp.cmd->resid = 0;
419
        req->resp.cmd->sense_len =
420
            scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
421
    }
422
    virtio_scsi_complete_req(req);
423
}
424

    
425
static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
426
{
427
    VirtIOSCSIReq *req = r->hba_private;
428

    
429
    return &req->qsgl;
430
}
431

    
432
static void virtio_scsi_request_cancelled(SCSIRequest *r)
433
{
434
    VirtIOSCSIReq *req = r->hba_private;
435

    
436
    if (!req) {
437
        return;
438
    }
439
    if (req->dev->resetting) {
440
        req->resp.cmd->response = VIRTIO_SCSI_S_RESET;
441
    } else {
442
        req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
443
    }
444
    virtio_scsi_complete_req(req);
445
}
446

    
447
static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
448
{
449
    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
450
    virtio_scsi_complete_req(req);
451
}
452

    
453
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
454
{
455
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
456
    VirtIOSCSIReq *req;
457
    int n;
458

    
459
    while ((req = virtio_scsi_pop_req(s, vq))) {
460
        SCSIDevice *d;
461
        int out_size, in_size;
462
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
463
            virtio_scsi_bad_req();
464
        }
465

    
466
        out_size = req->elem.out_sg[0].iov_len;
467
        in_size = req->elem.in_sg[0].iov_len;
468
        if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
469
            in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
470
            virtio_scsi_bad_req();
471
        }
472

    
473
        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
474
            virtio_scsi_fail_cmd_req(req);
475
            continue;
476
        }
477

    
478
        d = virtio_scsi_device_find(s, req->req.cmd->lun);
479
        if (!d) {
480
            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
481
            virtio_scsi_complete_req(req);
482
            continue;
483
        }
484
        req->sreq = scsi_req_new(d, req->req.cmd->tag,
485
                                 virtio_scsi_get_lun(req->req.cmd->lun),
486
                                 req->req.cmd->cdb, req);
487

    
488
        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
489
            int req_mode =
490
                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
491

    
492
            if (req->sreq->cmd.mode != req_mode ||
493
                req->sreq->cmd.xfer > req->qsgl.size) {
494
                req->resp.cmd->response = VIRTIO_SCSI_S_OVERRUN;
495
                virtio_scsi_complete_req(req);
496
                continue;
497
            }
498
        }
499

    
500
        n = scsi_req_enqueue(req->sreq);
501
        if (n) {
502
            scsi_req_continue(req->sreq);
503
        }
504
    }
505
}
506

    
507
static void virtio_scsi_get_config(VirtIODevice *vdev,
508
                                   uint8_t *config)
509
{
510
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
511
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
512

    
513
    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
514
    stl_raw(&scsiconf->seg_max, 128 - 2);
515
    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
516
    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
517
    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
518
    stl_raw(&scsiconf->sense_size, s->sense_size);
519
    stl_raw(&scsiconf->cdb_size, s->cdb_size);
520
    stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
521
    stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
522
    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
523
}
524

    
525
static void virtio_scsi_set_config(VirtIODevice *vdev,
526
                                   const uint8_t *config)
527
{
528
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
529
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
530

    
531
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
532
        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
533
        error_report("bad data written to virtio-scsi configuration space");
534
        exit(1);
535
    }
536

    
537
    s->sense_size = ldl_raw(&scsiconf->sense_size);
538
    s->cdb_size = ldl_raw(&scsiconf->cdb_size);
539
}
540

    
541
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
542
                                         uint32_t requested_features)
543
{
544
    return requested_features;
545
}
546

    
547
static void virtio_scsi_reset(VirtIODevice *vdev)
548
{
549
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
550

    
551
    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
552
    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
553
}
554

    
555
/* The device does not have anything to save beyond the virtio data.
556
 * Request data is saved with callbacks from SCSI devices.
557
 */
558
static void virtio_scsi_save(QEMUFile *f, void *opaque)
559
{
560
    VirtIOSCSI *s = opaque;
561
    virtio_save(&s->vdev, f);
562
}
563

    
564
static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
565
{
566
    VirtIOSCSI *s = opaque;
567
    int ret;
568

    
569
    ret = virtio_load(&s->vdev, f);
570
    if (ret) {
571
        return ret;
572
    }
573
    return 0;
574
}
575

    
576
static struct SCSIBusInfo virtio_scsi_scsi_info = {
577
    .tcq = true,
578
    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
579
    .max_target = VIRTIO_SCSI_MAX_TARGET,
580
    .max_lun = VIRTIO_SCSI_MAX_LUN,
581

    
582
    .complete = virtio_scsi_command_complete,
583
    .cancel = virtio_scsi_request_cancelled,
584
    .get_sg_list = virtio_scsi_get_sg_list,
585
    .save_request = virtio_scsi_save_request,
586
    .load_request = virtio_scsi_load_request,
587
};
588

    
589
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
590
{
591
    VirtIOSCSI *s;
592
    static int virtio_scsi_id;
593
    size_t sz;
594
    int i;
595

    
596
    sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
597
    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
598
                                         sizeof(VirtIOSCSIConfig), sz);
599

    
600
    s->qdev = dev;
601
    s->conf = proxyconf;
602

    
603
    /* TODO set up vdev function pointers */
604
    s->vdev.get_config = virtio_scsi_get_config;
605
    s->vdev.set_config = virtio_scsi_set_config;
606
    s->vdev.get_features = virtio_scsi_get_features;
607
    s->vdev.reset = virtio_scsi_reset;
608

    
609
    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
610
                                   virtio_scsi_handle_ctrl);
611
    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
612
                                   NULL);
613
    for (i = 0; i < s->conf->num_queues; i++) {
614
        s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
615
                                         virtio_scsi_handle_cmd);
616
    }
617

    
618
    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
619
    if (!dev->hotplugged) {
620
        scsi_bus_legacy_handle_cmdline(&s->bus);
621
    }
622

    
623
    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
624
                    virtio_scsi_save, virtio_scsi_load, s);
625

    
626
    return &s->vdev;
627
}
628

    
629
void virtio_scsi_exit(VirtIODevice *vdev)
630
{
631
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
632
    unregister_savevm(s->qdev, "virtio-scsi", s);
633
    virtio_cleanup(vdev);
634
}