~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to hw/virtio-scsi.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#define VIRTIO_SCSI_T_PARAM_CHANGE             3
63
 
 
64
 
/* Reasons for transport reset event */
65
 
#define VIRTIO_SCSI_EVT_RESET_HARD             0
66
 
#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
67
 
#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
68
 
 
69
 
/* SCSI command request, followed by data-out */
70
 
typedef struct {
71
 
    uint8_t lun[8];              /* Logical Unit Number */
72
 
    uint64_t tag;                /* Command identifier */
73
 
    uint8_t task_attr;           /* Task attribute */
74
 
    uint8_t prio;
75
 
    uint8_t crn;
76
 
    uint8_t cdb[];
77
 
} QEMU_PACKED VirtIOSCSICmdReq;
78
 
 
79
 
/* Response, followed by sense data and data-in */
80
 
typedef struct {
81
 
    uint32_t sense_len;          /* Sense data length */
82
 
    uint32_t resid;              /* Residual bytes in data buffer */
83
 
    uint16_t status_qualifier;   /* Status qualifier */
84
 
    uint8_t status;              /* Command completion status */
85
 
    uint8_t response;            /* Response values */
86
 
    uint8_t sense[];
87
 
} QEMU_PACKED VirtIOSCSICmdResp;
88
 
 
89
 
/* Task Management Request */
90
 
typedef struct {
91
 
    uint32_t type;
92
 
    uint32_t subtype;
93
 
    uint8_t lun[8];
94
 
    uint64_t tag;
95
 
} QEMU_PACKED VirtIOSCSICtrlTMFReq;
96
 
 
97
 
typedef struct {
98
 
    uint8_t response;
99
 
} QEMU_PACKED VirtIOSCSICtrlTMFResp;
100
 
 
101
 
/* Asynchronous notification query/subscription */
102
 
typedef struct {
103
 
    uint32_t type;
104
 
    uint8_t lun[8];
105
 
    uint32_t event_requested;
106
 
} QEMU_PACKED VirtIOSCSICtrlANReq;
107
 
 
108
 
typedef struct {
109
 
    uint32_t event_actual;
110
 
    uint8_t response;
111
 
} QEMU_PACKED VirtIOSCSICtrlANResp;
112
 
 
113
 
typedef struct {
114
 
    uint32_t event;
115
 
    uint8_t lun[8];
116
 
    uint32_t reason;
117
 
} QEMU_PACKED VirtIOSCSIEvent;
118
 
 
119
 
typedef struct {
120
 
    uint32_t num_queues;
121
 
    uint32_t seg_max;
122
 
    uint32_t max_sectors;
123
 
    uint32_t cmd_per_lun;
124
 
    uint32_t event_info_size;
125
 
    uint32_t sense_size;
126
 
    uint32_t cdb_size;
127
 
    uint16_t max_channel;
128
 
    uint16_t max_target;
129
 
    uint32_t max_lun;
130
 
} QEMU_PACKED VirtIOSCSIConfig;
131
 
 
132
 
typedef struct {
133
 
    VirtIODevice vdev;
134
 
    DeviceState *qdev;
135
 
    VirtIOSCSIConf *conf;
136
 
 
137
 
    SCSIBus bus;
138
 
    uint32_t sense_size;
139
 
    uint32_t cdb_size;
140
 
    int resetting;
141
 
    bool events_dropped;
142
 
    VirtQueue *ctrl_vq;
143
 
    VirtQueue *event_vq;
144
 
    VirtQueue *cmd_vqs[0];
145
 
} VirtIOSCSI;
146
 
 
147
 
typedef struct VirtIOSCSIReq {
148
 
    VirtIOSCSI *dev;
149
 
    VirtQueue *vq;
150
 
    VirtQueueElement elem;
151
 
    QEMUSGList qsgl;
152
 
    SCSIRequest *sreq;
153
 
    union {
154
 
        char                  *buf;
155
 
        VirtIOSCSICmdReq      *cmd;
156
 
        VirtIOSCSICtrlTMFReq  *tmf;
157
 
        VirtIOSCSICtrlANReq   *an;
158
 
    } req;
159
 
    union {
160
 
        char                  *buf;
161
 
        VirtIOSCSICmdResp     *cmd;
162
 
        VirtIOSCSICtrlTMFResp *tmf;
163
 
        VirtIOSCSICtrlANResp  *an;
164
 
        VirtIOSCSIEvent       *event;
165
 
    } resp;
166
 
} VirtIOSCSIReq;
167
 
 
168
 
static inline int virtio_scsi_get_lun(uint8_t *lun)
169
 
{
170
 
    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
171
 
}
172
 
 
173
 
static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
174
 
{
175
 
    if (lun[0] != 1) {
176
 
        return NULL;
177
 
    }
178
 
    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
179
 
        return NULL;
180
 
    }
181
 
    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
182
 
}
183
 
 
184
 
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
185
 
{
186
 
    VirtIOSCSI *s = req->dev;
187
 
    VirtQueue *vq = req->vq;
188
 
    virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
189
 
    qemu_sglist_destroy(&req->qsgl);
190
 
    if (req->sreq) {
191
 
        req->sreq->hba_private = NULL;
192
 
        scsi_req_unref(req->sreq);
193
 
    }
194
 
    g_free(req);
195
 
    virtio_notify(&s->vdev, vq);
196
 
}
197
 
 
198
 
static void virtio_scsi_bad_req(void)
199
 
{
200
 
    error_report("wrong size for virtio-scsi headers");
201
 
    exit(1);
202
 
}
203
 
 
204
 
static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
205
 
                                   hwaddr *addr, int num)
206
 
{
207
 
    qemu_sglist_init(qsgl, num, &dma_context_memory);
208
 
    while (num--) {
209
 
        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
210
 
    }
211
 
}
212
 
 
213
 
static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
214
 
                                  VirtIOSCSIReq *req)
215
 
{
216
 
    assert(req->elem.in_num);
217
 
    req->vq = vq;
218
 
    req->dev = s;
219
 
    req->sreq = NULL;
220
 
    if (req->elem.out_num) {
221
 
        req->req.buf = req->elem.out_sg[0].iov_base;
222
 
    }
223
 
    req->resp.buf = req->elem.in_sg[0].iov_base;
224
 
 
225
 
    if (req->elem.out_num > 1) {
226
 
        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
227
 
                               &req->elem.out_addr[1],
228
 
                               req->elem.out_num - 1);
229
 
    } else {
230
 
        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
231
 
                               &req->elem.in_addr[1],
232
 
                               req->elem.in_num - 1);
233
 
    }
234
 
}
235
 
 
236
 
static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
237
 
{
238
 
    VirtIOSCSIReq *req;
239
 
    req = g_malloc(sizeof(*req));
240
 
    if (!virtqueue_pop(vq, &req->elem)) {
241
 
        g_free(req);
242
 
        return NULL;
243
 
    }
244
 
 
245
 
    virtio_scsi_parse_req(s, vq, req);
246
 
    return req;
247
 
}
248
 
 
249
 
static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
250
 
{
251
 
    VirtIOSCSIReq *req = sreq->hba_private;
252
 
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
253
 
 
254
 
    assert(n < req->dev->conf->num_queues);
255
 
    qemu_put_be32s(f, &n);
256
 
    qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
257
 
}
258
 
 
259
 
static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
260
 
{
261
 
    SCSIBus *bus = sreq->bus;
262
 
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
263
 
    VirtIOSCSIReq *req;
264
 
    uint32_t n;
265
 
 
266
 
    req = g_malloc(sizeof(*req));
267
 
    qemu_get_be32s(f, &n);
268
 
    assert(n < s->conf->num_queues);
269
 
    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
270
 
    virtio_scsi_parse_req(s, s->cmd_vqs[n], req);
271
 
 
272
 
    scsi_req_ref(sreq);
273
 
    req->sreq = sreq;
274
 
    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
275
 
        int req_mode =
276
 
            (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
277
 
 
278
 
        assert(req->sreq->cmd.mode == req_mode);
279
 
    }
280
 
    return req;
281
 
}
282
 
 
283
 
static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
284
 
{
285
 
    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
286
 
    SCSIRequest *r, *next;
287
 
    BusChild *kid;
288
 
    int target;
289
 
 
290
 
    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
291
 
    req->resp.tmf->response = VIRTIO_SCSI_S_OK;
292
 
 
293
 
    switch (req->req.tmf->subtype) {
294
 
    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
295
 
    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
296
 
        if (!d) {
297
 
            goto fail;
298
 
        }
299
 
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
300
 
            goto incorrect_lun;
301
 
        }
302
 
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
303
 
            VirtIOSCSIReq *cmd_req = r->hba_private;
304
 
            if (cmd_req && cmd_req->req.cmd->tag == req->req.tmf->tag) {
305
 
                break;
306
 
            }
307
 
        }
308
 
        if (r) {
309
 
            /*
310
 
             * Assert that the request has not been completed yet, we
311
 
             * check for it in the loop above.
312
 
             */
313
 
            assert(r->hba_private);
314
 
            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
315
 
                /* "If the specified command is present in the task set, then
316
 
                 * return a service response set to FUNCTION SUCCEEDED".
317
 
                 */
318
 
                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
319
 
            } else {
320
 
                scsi_req_cancel(r);
321
 
            }
322
 
        }
323
 
        break;
324
 
 
325
 
    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
326
 
        if (!d) {
327
 
            goto fail;
328
 
        }
329
 
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
330
 
            goto incorrect_lun;
331
 
        }
332
 
        s->resetting++;
333
 
        qdev_reset_all(&d->qdev);
334
 
        s->resetting--;
335
 
        break;
336
 
 
337
 
    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
338
 
    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
339
 
    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
340
 
        if (!d) {
341
 
            goto fail;
342
 
        }
343
 
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
344
 
            goto incorrect_lun;
345
 
        }
346
 
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
347
 
            if (r->hba_private) {
348
 
                if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
349
 
                    /* "If there is any command present in the task set, then
350
 
                     * return a service response set to FUNCTION SUCCEEDED".
351
 
                     */
352
 
                    req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
353
 
                    break;
354
 
                } else {
355
 
                    scsi_req_cancel(r);
356
 
                }
357
 
            }
358
 
        }
359
 
        break;
360
 
 
361
 
    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
362
 
        target = req->req.tmf->lun[1];
363
 
        s->resetting++;
364
 
        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
365
 
             d = DO_UPCAST(SCSIDevice, qdev, kid->child);
366
 
             if (d->channel == 0 && d->id == target) {
367
 
                qdev_reset_all(&d->qdev);
368
 
             }
369
 
        }
370
 
        s->resetting--;
371
 
        break;
372
 
 
373
 
    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
374
 
    default:
375
 
        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
376
 
        break;
377
 
    }
378
 
 
379
 
    return;
380
 
 
381
 
incorrect_lun:
382
 
    req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
383
 
    return;
384
 
 
385
 
fail:
386
 
    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
387
 
}
388
 
 
389
 
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
390
 
{
391
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
392
 
    VirtIOSCSIReq *req;
393
 
 
394
 
    while ((req = virtio_scsi_pop_req(s, vq))) {
395
 
        int out_size, in_size;
396
 
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
397
 
            virtio_scsi_bad_req();
398
 
            continue;
399
 
        }
400
 
 
401
 
        out_size = req->elem.out_sg[0].iov_len;
402
 
        in_size = req->elem.in_sg[0].iov_len;
403
 
        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
404
 
            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
405
 
                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
406
 
                virtio_scsi_bad_req();
407
 
            }
408
 
            virtio_scsi_do_tmf(s, req);
409
 
 
410
 
        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
411
 
                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
412
 
            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
413
 
                in_size < sizeof(VirtIOSCSICtrlANResp)) {
414
 
                virtio_scsi_bad_req();
415
 
            }
416
 
            req->resp.an->event_actual = 0;
417
 
            req->resp.an->response = VIRTIO_SCSI_S_OK;
418
 
        }
419
 
        virtio_scsi_complete_req(req);
420
 
    }
421
 
}
422
 
 
423
 
static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
424
 
                                         size_t resid)
425
 
{
426
 
    VirtIOSCSIReq *req = r->hba_private;
427
 
    uint32_t sense_len;
428
 
 
429
 
    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
430
 
    req->resp.cmd->status = status;
431
 
    if (req->resp.cmd->status == GOOD) {
432
 
        req->resp.cmd->resid = tswap32(resid);
433
 
    } else {
434
 
        req->resp.cmd->resid = 0;
435
 
        sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
436
 
                                       VIRTIO_SCSI_SENSE_SIZE);
437
 
        req->resp.cmd->sense_len = tswap32(sense_len);
438
 
    }
439
 
    virtio_scsi_complete_req(req);
440
 
}
441
 
 
442
 
static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
443
 
{
444
 
    VirtIOSCSIReq *req = r->hba_private;
445
 
 
446
 
    return &req->qsgl;
447
 
}
448
 
 
449
 
static void virtio_scsi_request_cancelled(SCSIRequest *r)
450
 
{
451
 
    VirtIOSCSIReq *req = r->hba_private;
452
 
 
453
 
    if (!req) {
454
 
        return;
455
 
    }
456
 
    if (req->dev->resetting) {
457
 
        req->resp.cmd->response = VIRTIO_SCSI_S_RESET;
458
 
    } else {
459
 
        req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
460
 
    }
461
 
    virtio_scsi_complete_req(req);
462
 
}
463
 
 
464
 
static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
465
 
{
466
 
    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
467
 
    virtio_scsi_complete_req(req);
468
 
}
469
 
 
470
 
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
471
 
{
472
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
473
 
    VirtIOSCSIReq *req;
474
 
    int n;
475
 
 
476
 
    while ((req = virtio_scsi_pop_req(s, vq))) {
477
 
        SCSIDevice *d;
478
 
        int out_size, in_size;
479
 
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
480
 
            virtio_scsi_bad_req();
481
 
        }
482
 
 
483
 
        out_size = req->elem.out_sg[0].iov_len;
484
 
        in_size = req->elem.in_sg[0].iov_len;
485
 
        if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
486
 
            in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
487
 
            virtio_scsi_bad_req();
488
 
        }
489
 
 
490
 
        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
491
 
            virtio_scsi_fail_cmd_req(req);
492
 
            continue;
493
 
        }
494
 
 
495
 
        d = virtio_scsi_device_find(s, req->req.cmd->lun);
496
 
        if (!d) {
497
 
            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
498
 
            virtio_scsi_complete_req(req);
499
 
            continue;
500
 
        }
501
 
        req->sreq = scsi_req_new(d, req->req.cmd->tag,
502
 
                                 virtio_scsi_get_lun(req->req.cmd->lun),
503
 
                                 req->req.cmd->cdb, req);
504
 
 
505
 
        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
506
 
            int req_mode =
507
 
                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
508
 
 
509
 
            if (req->sreq->cmd.mode != req_mode ||
510
 
                req->sreq->cmd.xfer > req->qsgl.size) {
511
 
                req->resp.cmd->response = VIRTIO_SCSI_S_OVERRUN;
512
 
                virtio_scsi_complete_req(req);
513
 
                continue;
514
 
            }
515
 
        }
516
 
 
517
 
        n = scsi_req_enqueue(req->sreq);
518
 
        if (n) {
519
 
            scsi_req_continue(req->sreq);
520
 
        }
521
 
    }
522
 
}
523
 
 
524
 
static void virtio_scsi_get_config(VirtIODevice *vdev,
525
 
                                   uint8_t *config)
526
 
{
527
 
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
528
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
529
 
 
530
 
    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
531
 
    stl_raw(&scsiconf->seg_max, 128 - 2);
532
 
    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
533
 
    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
534
 
    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
535
 
    stl_raw(&scsiconf->sense_size, s->sense_size);
536
 
    stl_raw(&scsiconf->cdb_size, s->cdb_size);
537
 
    stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
538
 
    stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
539
 
    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
540
 
}
541
 
 
542
 
static void virtio_scsi_set_config(VirtIODevice *vdev,
543
 
                                   const uint8_t *config)
544
 
{
545
 
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
546
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
547
 
 
548
 
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
549
 
        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
550
 
        error_report("bad data written to virtio-scsi configuration space");
551
 
        exit(1);
552
 
    }
553
 
 
554
 
    s->sense_size = ldl_raw(&scsiconf->sense_size);
555
 
    s->cdb_size = ldl_raw(&scsiconf->cdb_size);
556
 
}
557
 
 
558
 
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
559
 
                                         uint32_t requested_features)
560
 
{
561
 
    return requested_features;
562
 
}
563
 
 
564
 
static void virtio_scsi_reset(VirtIODevice *vdev)
565
 
{
566
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
567
 
 
568
 
    s->resetting++;
569
 
    qbus_reset_all(&s->bus.qbus);
570
 
    s->resetting--;
571
 
 
572
 
    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
573
 
    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
574
 
    s->events_dropped = false;
575
 
}
576
 
 
577
 
/* The device does not have anything to save beyond the virtio data.
578
 
 * Request data is saved with callbacks from SCSI devices.
579
 
 */
580
 
static void virtio_scsi_save(QEMUFile *f, void *opaque)
581
 
{
582
 
    VirtIOSCSI *s = opaque;
583
 
    virtio_save(&s->vdev, f);
584
 
}
585
 
 
586
 
static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
587
 
{
588
 
    VirtIOSCSI *s = opaque;
589
 
    int ret;
590
 
 
591
 
    ret = virtio_load(&s->vdev, f);
592
 
    if (ret) {
593
 
        return ret;
594
 
    }
595
 
    return 0;
596
 
}
597
 
 
598
 
static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
599
 
                                   uint32_t event, uint32_t reason)
600
 
{
601
 
    VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq);
602
 
    VirtIOSCSIEvent *evt;
603
 
    int in_size;
604
 
 
605
 
    if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
606
 
        return;
607
 
    }
608
 
 
609
 
    if (!req) {
610
 
        s->events_dropped = true;
611
 
        return;
612
 
    }
613
 
 
614
 
    if (req->elem.out_num || req->elem.in_num != 1) {
615
 
        virtio_scsi_bad_req();
616
 
    }
617
 
 
618
 
    if (s->events_dropped) {
619
 
        event |= VIRTIO_SCSI_T_EVENTS_MISSED;
620
 
        s->events_dropped = false;
621
 
    }
622
 
 
623
 
    in_size = req->elem.in_sg[0].iov_len;
624
 
    if (in_size < sizeof(VirtIOSCSIEvent)) {
625
 
        virtio_scsi_bad_req();
626
 
    }
627
 
 
628
 
    evt = req->resp.event;
629
 
    memset(evt, 0, sizeof(VirtIOSCSIEvent));
630
 
    evt->event = event;
631
 
    evt->reason = reason;
632
 
    if (!dev) {
633
 
        assert(event == VIRTIO_SCSI_T_NO_EVENT);
634
 
    } else {
635
 
        evt->lun[0] = 1;
636
 
        evt->lun[1] = dev->id;
637
 
 
638
 
        /* Linux wants us to keep the same encoding we use for REPORT LUNS.  */
639
 
        if (dev->lun >= 256) {
640
 
            evt->lun[2] = (dev->lun >> 8) | 0x40;
641
 
        }
642
 
        evt->lun[3] = dev->lun & 0xFF;
643
 
    }
644
 
    virtio_scsi_complete_req(req);
645
 
}
646
 
 
647
 
static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
648
 
{
649
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
650
 
 
651
 
    if (s->events_dropped) {
652
 
        virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
653
 
    }
654
 
}
655
 
 
656
 
static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
657
 
{
658
 
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
659
 
 
660
 
    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
661
 
        dev->type != TYPE_ROM) {
662
 
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
663
 
                               sense.asc | (sense.ascq << 8));
664
 
    }
665
 
}
666
 
 
667
 
static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
668
 
{
669
 
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
670
 
 
671
 
    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
672
 
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
673
 
                               VIRTIO_SCSI_EVT_RESET_RESCAN);
674
 
    }
675
 
}
676
 
 
677
 
static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
678
 
{
679
 
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
680
 
 
681
 
    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
682
 
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
683
 
                               VIRTIO_SCSI_EVT_RESET_REMOVED);
684
 
    }
685
 
}
686
 
 
687
 
static struct SCSIBusInfo virtio_scsi_scsi_info = {
688
 
    .tcq = true,
689
 
    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
690
 
    .max_target = VIRTIO_SCSI_MAX_TARGET,
691
 
    .max_lun = VIRTIO_SCSI_MAX_LUN,
692
 
 
693
 
    .complete = virtio_scsi_command_complete,
694
 
    .cancel = virtio_scsi_request_cancelled,
695
 
    .change = virtio_scsi_change,
696
 
    .hotplug = virtio_scsi_hotplug,
697
 
    .hot_unplug = virtio_scsi_hot_unplug,
698
 
    .get_sg_list = virtio_scsi_get_sg_list,
699
 
    .save_request = virtio_scsi_save_request,
700
 
    .load_request = virtio_scsi_load_request,
701
 
};
702
 
 
703
 
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
704
 
{
705
 
    VirtIOSCSI *s;
706
 
    static int virtio_scsi_id;
707
 
    size_t sz;
708
 
    int i;
709
 
 
710
 
    sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
711
 
    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
712
 
                                         sizeof(VirtIOSCSIConfig), sz);
713
 
 
714
 
    s->qdev = dev;
715
 
    s->conf = proxyconf;
716
 
 
717
 
    /* TODO set up vdev function pointers */
718
 
    s->vdev.get_config = virtio_scsi_get_config;
719
 
    s->vdev.set_config = virtio_scsi_set_config;
720
 
    s->vdev.get_features = virtio_scsi_get_features;
721
 
    s->vdev.reset = virtio_scsi_reset;
722
 
 
723
 
    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
724
 
                                   virtio_scsi_handle_ctrl);
725
 
    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
726
 
                                   virtio_scsi_handle_event);
727
 
    for (i = 0; i < s->conf->num_queues; i++) {
728
 
        s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
729
 
                                         virtio_scsi_handle_cmd);
730
 
    }
731
 
 
732
 
    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
733
 
    if (!dev->hotplugged) {
734
 
        scsi_bus_legacy_handle_cmdline(&s->bus);
735
 
    }
736
 
 
737
 
    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
738
 
                    virtio_scsi_save, virtio_scsi_load, s);
739
 
 
740
 
    return &s->vdev;
741
 
}
742
 
 
743
 
void virtio_scsi_exit(VirtIODevice *vdev)
744
 
{
745
 
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
746
 
    unregister_savevm(s->qdev, "virtio-scsi", s);
747
 
    virtio_cleanup(vdev);
748
 
}