virtio-scsi.c 23.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Virtio SCSI HBA
 *
 * Copyright IBM, Corp. 2010
 * Copyright Red Hat, Inc. 2011
 *
 * Authors:
 *   Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
 *   Paolo Bonzini      <pbonzini@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

P
Paolo Bonzini 已提交
16
#include "hw/virtio/virtio-scsi.h"
17
#include "qemu/error-report.h"
18
#include "qemu/iov.h"
P
Paolo Bonzini 已提交
19 20 21
#include <hw/scsi/scsi.h>
#include <block/scsi.h>
#include <hw/virtio/virtio-bus.h>
22
#include "hw/virtio/virtio-access.h"
23

24 25 26 27 28 29
typedef struct VirtIOSCSIReq {
    VirtIOSCSI *dev;
    VirtQueue *vq;
    VirtQueueElement elem;
    QEMUSGList qsgl;
    SCSIRequest *sreq;
30
    size_t resp_size;
31 32
    enum SCSIXferMode mode;
    QEMUIOVector resp_iov;
33
    union {
34 35 36 37
        VirtIOSCSICmdResp     cmd;
        VirtIOSCSICtrlTMFResp tmf;
        VirtIOSCSICtrlANResp  an;
        VirtIOSCSIEvent       event;
38
    } resp;
39
    union {
40 41 42 43 44 45
        struct {
            VirtIOSCSICmdReq  cmd;
            uint8_t           cdb[];
        } QEMU_PACKED;
        VirtIOSCSICtrlTMFReq  tmf;
        VirtIOSCSICtrlANReq   an;
46
    } req;
47 48
} VirtIOSCSIReq;

49 50 51
QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) !=
                  offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq));

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
static inline int virtio_scsi_get_lun(uint8_t *lun)
{
    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
}

static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
{
    if (lun[0] != 1) {
        return NULL;
    }
    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
        return NULL;
    }
    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
}

68 69 70
static VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
{
    VirtIOSCSIReq *req;
71 72 73
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);

    req = g_malloc0(sizeof(*req) + vs->cdb_size);
74 75 76 77 78

    req->vq = vq;
    req->dev = s;
    req->sreq = NULL;
    qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
79
    qemu_iovec_init(&req->resp_iov, 1);
80 81 82 83 84
    return req;
}

static void virtio_scsi_free_req(VirtIOSCSIReq *req)
{
85
    qemu_iovec_destroy(&req->resp_iov);
86 87 88 89
    qemu_sglist_destroy(&req->qsgl);
    g_free(req);
}

90 91 92 93
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
{
    VirtIOSCSI *s = req->dev;
    VirtQueue *vq = req->vq;
94
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
95 96 97

    qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
    virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
98 99 100 101
    if (req->sreq) {
        req->sreq->hba_private = NULL;
        scsi_req_unref(req->sreq);
    }
102
    virtio_scsi_free_req(req);
103
    virtio_notify(vdev, vq);
104 105 106 107 108 109 110 111
}

static void virtio_scsi_bad_req(void)
{
    error_report("wrong size for virtio-scsi headers");
    exit(1);
}

112 113
static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
                              hwaddr *addr, int num, size_t skip)
114
{
115
    QEMUSGList *qsgl = &req->qsgl;
116 117 118 119 120 121 122 123 124 125 126 127 128
    size_t copied = 0;

    while (num) {
        if (skip >= iov->iov_len) {
            skip -= iov->iov_len;
        } else {
            qemu_sglist_add(qsgl, *addr + skip, iov->iov_len - skip);
            copied += iov->iov_len - skip;
            skip = 0;
        }
        iov++;
        addr++;
        num--;
129
    }
130 131 132

    assert(skip == 0);
    return copied;
133 134
}

135 136
static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
                                 unsigned req_size, unsigned resp_size)
137
{
138
    size_t in_size, out_size;
139

140 141
    if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
                   &req->req, req_size) < req_size) {
142 143 144
        return -EINVAL;
    }

145 146 147
    if (qemu_iovec_concat_iov(&req->resp_iov,
                              req->elem.in_sg, req->elem.in_num, 0,
                              resp_size) < resp_size) {
148 149
        return -EINVAL;
    }
150
    req->resp_size = resp_size;
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    out_size = qemu_sgl_concat(req, req->elem.out_sg,
                               &req->elem.out_addr[0], req->elem.out_num,
                               req_size);
    in_size = qemu_sgl_concat(req, req->elem.in_sg,
                              &req->elem.in_addr[0], req->elem.in_num,
                              resp_size);

    if (out_size && in_size) {
        return -ENOTSUP;
    }

    if (out_size) {
        req->mode = SCSI_XFER_TO_DEV;
    } else if (in_size) {
        req->mode = SCSI_XFER_FROM_DEV;
167
    }
168 169

    return 0;
170 171 172 173
}

static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
{
174
    VirtIOSCSIReq *req = virtio_scsi_init_req(s, vq);
175
    if (!virtqueue_pop(vq, &req->elem)) {
176
        virtio_scsi_free_req(req);
177 178 179 180 181
        return NULL;
    }
    return req;
}

182 183 184
static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
{
    VirtIOSCSIReq *req = sreq->hba_private;
185
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
186
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
187

188
    assert(n < vs->conf.num_queues);
189
    qemu_put_be32s(f, &n);
190 191 192 193 194 195 196
    qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
}

static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
{
    SCSIBus *bus = sreq->bus;
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
197
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
198
    VirtIOSCSIReq *req;
199
    uint32_t n;
200

201
    qemu_get_be32s(f, &n);
202
    assert(n < vs->conf.num_queues);
203
    req = virtio_scsi_init_req(s, vs->cmd_vqs[n]);
204
    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
205 206 207 208 209 210 211 212 213
    /* TODO: add a way for SCSIBusInfo's load_request to fail,
     * and fail migration instead of asserting here.
     * When we do, we might be able to re-enable NDEBUG below.
     */
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
    assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg));
    assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg));
214 215 216 217 218 219

    if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
                              sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) {
        error_report("invalid SCSI request migration data");
        exit(1);
    }
220 221 222 223

    scsi_req_ref(sreq);
    req->sreq = sreq;
    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
224
        assert(req->sreq->cmd.mode == req->mode);
225 226 227 228
    }
    return req;
}

229
static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
230
{
231
    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf.lun);
232
    SCSIRequest *r, *next;
A
Anthony Liguori 已提交
233
    BusChild *kid;
234 235 236
    int target;

    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
237
    req->resp.tmf.response = VIRTIO_SCSI_S_OK;
238

239
    virtio_tswap32s(VIRTIO_DEVICE(s), &req->req.tmf.subtype);
240
    switch (req->req.tmf.subtype) {
241 242 243 244 245
    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
        if (!d) {
            goto fail;
        }
246
        if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
247 248 249
            goto incorrect_lun;
        }
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
250
            VirtIOSCSIReq *cmd_req = r->hba_private;
251
            if (cmd_req && cmd_req->req.cmd.tag == req->req.tmf.tag) {
252 253 254
                break;
            }
        }
255 256 257 258 259 260
        if (r) {
            /*
             * Assert that the request has not been completed yet, we
             * check for it in the loop above.
             */
            assert(r->hba_private);
261
            if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
262 263 264
                /* "If the specified command is present in the task set, then
                 * return a service response set to FUNCTION SUCCEEDED".
                 */
265
                req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
266 267 268 269 270 271 272 273 274 275
            } else {
                scsi_req_cancel(r);
            }
        }
        break;

    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
        if (!d) {
            goto fail;
        }
276
        if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
277 278 279 280 281 282 283 284 285 286 287 288 289
            goto incorrect_lun;
        }
        s->resetting++;
        qdev_reset_all(&d->qdev);
        s->resetting--;
        break;

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

    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
309
        target = req->req.tmf.lun[1];
310
        s->resetting++;
A
Anthony Liguori 已提交
311 312
        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
             d = DO_UPCAST(SCSIDevice, qdev, kid->child);
313 314 315 316 317 318 319 320 321
             if (d->channel == 0 && d->id == target) {
                qdev_reset_all(&d->qdev);
             }
        }
        s->resetting--;
        break;

    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
    default:
322
        req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
323
        break;
324 325
    }

326 327 328
    return;

incorrect_lun:
329
    req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
330 331 332
    return;

fail:
333
    req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
334 335
}

336 337
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
338 339 340 341
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
    VirtIOSCSIReq *req;

    while ((req = virtio_scsi_pop_req(s, vq))) {
342 343 344 345
        int type;

        if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
                       &type, sizeof(type)) < sizeof(type)) {
346
            virtio_scsi_bad_req();
347 348
            continue;
        }
349

350
        virtio_tswap32s(vdev, &req->req.tmf.type);
351
        if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) {
352 353
            if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
                                      sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
354
                virtio_scsi_bad_req();
355 356
            } else {
                virtio_scsi_do_tmf(s, req);
357 358
            }

359 360
        } else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY ||
                   req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
361 362
            if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
                                      sizeof(VirtIOSCSICtrlANResp)) < 0) {
363
                virtio_scsi_bad_req();
364
            } else {
365 366
                req->resp.an.event_actual = 0;
                req->resp.an.response = VIRTIO_SCSI_S_OK;
367 368 369
            }
        }
        virtio_scsi_complete_req(req);
370 371 372
    }
}

373 374
static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
{
375 376 377 378
    /* Sense data is not in req->resp and is copied separately
     * in virtio_scsi_command_complete.
     */
    req->resp_size = sizeof(VirtIOSCSICmdResp);
379 380 381
    virtio_scsi_complete_req(req);
}

382 383 384 385
static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
                                         size_t resid)
{
    VirtIOSCSIReq *req = r->hba_private;
386
    uint8_t sense[SCSI_SENSE_BUF_SIZE];
387
    uint32_t sense_len;
388
    VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
389

390 391 392 393
    if (r->io_canceled) {
        return;
    }

394 395 396
    req->resp.cmd.response = VIRTIO_SCSI_S_OK;
    req->resp.cmd.status = status;
    if (req->resp.cmd.status == GOOD) {
397
        req->resp.cmd.resid = virtio_tswap32(vdev, resid);
398
    } else {
399
        req->resp.cmd.resid = 0;
400
        sense_len = scsi_req_get_sense(r, sense, sizeof(sense));
401 402 403
        sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
        qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd),
                            &req->resp, sense_len);
404
        req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
405
    }
406
    virtio_scsi_complete_cmd_req(req);
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
}

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

    return &req->qsgl;
}

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

    if (!req) {
        return;
    }
423
    if (req->dev->resetting) {
424
        req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
425
    } else {
426
        req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
427
    }
428
    virtio_scsi_complete_cmd_req(req);
429 430 431
}

static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
432
{
433
    req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
434
    virtio_scsi_complete_cmd_req(req);
435 436 437 438
}

static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
439
    /* use non-QOM casts in the data path */
440
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
441 442
    VirtIOSCSICommon *vs = &s->parent_obj;

443
    VirtIOSCSIReq *req;
444
    int n;
445 446

    while ((req = virtio_scsi_pop_req(s, vq))) {
447
        SCSIDevice *d;
448
        int rc;
449

450 451 452
        rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
                                   sizeof(VirtIOSCSICmdResp) + vs->sense_size);
        if (rc < 0) {
453 454 455 456 457 458
            if (rc == -ENOTSUP) {
                virtio_scsi_fail_cmd_req(req);
            } else {
                virtio_scsi_bad_req();
            }
            continue;
459 460
        }

461
        d = virtio_scsi_device_find(s, req->req.cmd.lun);
462
        if (!d) {
463
            req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
464
            virtio_scsi_complete_cmd_req(req);
465 466
            continue;
        }
467 468 469 470 471 472 473 474 475 476
        req->sreq = scsi_req_new(d, req->req.cmd.tag,
                                 virtio_scsi_get_lun(req->req.cmd.lun),
                                 req->req.cdb, req);

        if (req->sreq->cmd.mode != SCSI_XFER_NONE
            && (req->sreq->cmd.mode != req->mode ||
                req->sreq->cmd.xfer > req->qsgl.size)) {
            req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
            virtio_scsi_complete_cmd_req(req);
            continue;
477 478 479 480 481 482
        }

        n = scsi_req_enqueue(req->sreq);
        if (n) {
            scsi_req_continue(req->sreq);
        }
483
    }
484 485 486 487 488 489
}

static void virtio_scsi_get_config(VirtIODevice *vdev,
                                   uint8_t *config)
{
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
490
    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
491

492 493 494 495 496 497 498 499 500 501
    virtio_stl_p(vdev, &scsiconf->num_queues, s->conf.num_queues);
    virtio_stl_p(vdev, &scsiconf->seg_max, 128 - 2);
    virtio_stl_p(vdev, &scsiconf->max_sectors, s->conf.max_sectors);
    virtio_stl_p(vdev, &scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
    virtio_stl_p(vdev, &scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
    virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size);
    virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size);
    virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
    virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
    virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
502 503 504 505 506 507
}

static void virtio_scsi_set_config(VirtIODevice *vdev,
                                   const uint8_t *config)
{
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
508
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
509

510 511
    if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) >= 65536 ||
        (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) >= 256) {
512 513 514 515
        error_report("bad data written to virtio-scsi configuration space");
        exit(1);
    }

516 517
    vs->sense_size = virtio_ldl_p(vdev, &scsiconf->sense_size);
    vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
518 519 520 521 522 523 524 525 526 527
}

static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
                                         uint32_t requested_features)
{
    return requested_features;
}

static void virtio_scsi_reset(VirtIODevice *vdev)
{
528 529
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
530

531 532 533 534
    s->resetting++;
    qbus_reset_all(&s->bus.qbus);
    s->resetting--;

535 536
    vs->sense_size = VIRTIO_SCSI_SENSE_SIZE;
    vs->cdb_size = VIRTIO_SCSI_CDB_SIZE;
537
    s->events_dropped = false;
538 539
}

540 541 542 543 544
/* The device does not have anything to save beyond the virtio data.
 * Request data is saved with callbacks from SCSI devices.
 */
static void virtio_scsi_save(QEMUFile *f, void *opaque)
{
545 546
    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
    virtio_save(vdev, f);
547 548 549 550
}

static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
{
551
    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
552 553
    int ret;

554
    ret = virtio_load(vdev, f, version_id);
555 556 557
    if (ret) {
        return ret;
    }
558 559 560
    return 0;
}

561 562 563
static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
                                   uint32_t event, uint32_t reason)
{
564
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
565
    VirtIOSCSIReq *req;
566
    VirtIOSCSIEvent *evt;
567
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
568

569
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
570 571 572
        return;
    }

573
    req = virtio_scsi_pop_req(s, vs->event_vq);
574 575 576 577
    if (!req) {
        s->events_dropped = true;
        return;
    }
578

579 580 581 582 583
    if (s->events_dropped) {
        event |= VIRTIO_SCSI_T_EVENTS_MISSED;
        s->events_dropped = false;
    }

584
    if (virtio_scsi_parse_req(req, 0, sizeof(VirtIOSCSIEvent))) {
585 586 587
        virtio_scsi_bad_req();
    }

588
    evt = &req->resp.event;
589
    memset(evt, 0, sizeof(VirtIOSCSIEvent));
590 591
    evt->event = virtio_tswap32(vdev, event);
    evt->reason = virtio_tswap32(vdev, reason);
592
    if (!dev) {
593
        assert(event == VIRTIO_SCSI_T_EVENTS_MISSED);
594
    } else {
595 596 597 598 599 600 601 602
        evt->lun[0] = 1;
        evt->lun[1] = dev->id;

        /* Linux wants us to keep the same encoding we use for REPORT LUNS.  */
        if (dev->lun >= 256) {
            evt->lun[2] = (dev->lun >> 8) | 0x40;
        }
        evt->lun[3] = dev->lun & 0xFF;
603 604 605 606 607 608
    }
    virtio_scsi_complete_req(req);
}

static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
{
609
    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
610 611 612

    if (s->events_dropped) {
        virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
613 614 615
    }
}

616 617 618
static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
{
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
619
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
620

621
    if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
622 623 624 625 626 627
        dev->type != TYPE_ROM) {
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                               sense.asc | (sense.ascq << 8));
    }
}

628 629 630
static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
{
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
631
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
632

633
    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
634 635 636 637 638 639 640 641
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                               VIRTIO_SCSI_EVT_RESET_RESCAN);
    }
}

static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
{
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
642
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
643

644
    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
645 646 647 648 649
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                               VIRTIO_SCSI_EVT_RESET_REMOVED);
    }
}

650 651 652 653 654 655 656 657
static struct SCSIBusInfo virtio_scsi_scsi_info = {
    .tcq = true,
    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
    .max_target = VIRTIO_SCSI_MAX_TARGET,
    .max_lun = VIRTIO_SCSI_MAX_LUN,

    .complete = virtio_scsi_command_complete,
    .cancel = virtio_scsi_request_cancelled,
658
    .change = virtio_scsi_change,
659 660
    .hotplug = virtio_scsi_hotplug,
    .hot_unplug = virtio_scsi_hot_unplug,
661
    .get_sg_list = virtio_scsi_get_sg_list,
662 663
    .save_request = virtio_scsi_save_request,
    .load_request = virtio_scsi_load_request,
664 665
};

666 667 668
void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
                                HandleOutput ctrl, HandleOutput evt,
                                HandleOutput cmd)
669
{
670 671
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
672
    int i;
673

674
    virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
675
                sizeof(VirtIOSCSIConfig));
676

677
    s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
678 679
    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
680

681
    s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
682
                                  ctrl);
683
    s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
684
                                   evt);
685
    for (i = 0; i < s->conf.num_queues; i++) {
686
        s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
687
                                         cmd);
688
    }
689 690
}

691
static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
692
{
693
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
694
    VirtIOSCSI *s = VIRTIO_SCSI(dev);
695
    static int virtio_scsi_id;
696
    Error *err = NULL;
697

698 699 700
    virtio_scsi_common_realize(dev, &err, virtio_scsi_handle_ctrl,
                               virtio_scsi_handle_event,
                               virtio_scsi_handle_cmd);
701 702 703
    if (err != NULL) {
        error_propagate(errp, err);
        return;
704 705
    }

706
    scsi_bus_new(&s->bus, sizeof(s->bus), dev,
707
                 &virtio_scsi_scsi_info, vdev->bus_name);
708

709
    if (!dev->hotplugged) {
710 711
        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
        if (err != NULL) {
712 713
            error_propagate(errp, err);
            return;
714
        }
715 716
    }

717
    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
718
                    virtio_scsi_save, virtio_scsi_load, s);
719 720
}

721
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
722
{
723 724
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
725 726

    g_free(vs->cmd_vqs);
727
    virtio_cleanup(vdev);
728 729
}

730
static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
731
{
732 733 734
    VirtIOSCSI *s = VIRTIO_SCSI(dev);

    unregister_savevm(dev, "virtio-scsi", s);
735

736
    virtio_scsi_common_unrealize(dev, errp);
737 738 739
}

static Property virtio_scsi_properties[] = {
740
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf),
741 742 743
    DEFINE_PROP_END_OF_LIST(),
};

744 745 746
static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
{
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
747
    DeviceClass *dc = DEVICE_CLASS(klass);
748 749

    vdc->get_config = virtio_scsi_get_config;
750
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
751 752
}

753 754 755 756
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
757

758
    dc->props = virtio_scsi_properties;
759
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
760
    vdc->realize = virtio_scsi_device_realize;
761
    vdc->unrealize = virtio_scsi_device_unrealize;
762 763 764 765 766
    vdc->set_config = virtio_scsi_set_config;
    vdc->get_features = virtio_scsi_get_features;
    vdc->reset = virtio_scsi_reset;
}

767 768 769 770
static const TypeInfo virtio_scsi_common_info = {
    .name = TYPE_VIRTIO_SCSI_COMMON,
    .parent = TYPE_VIRTIO_DEVICE,
    .instance_size = sizeof(VirtIOSCSICommon),
771
    .abstract = true,
772 773 774
    .class_init = virtio_scsi_common_class_init,
};

775 776
static const TypeInfo virtio_scsi_info = {
    .name = TYPE_VIRTIO_SCSI,
777
    .parent = TYPE_VIRTIO_SCSI_COMMON,
778 779 780 781 782 783
    .instance_size = sizeof(VirtIOSCSI),
    .class_init = virtio_scsi_class_init,
};

static void virtio_register_types(void)
{
784
    type_register_static(&virtio_scsi_common_info);
785 786 787 788
    type_register_static(&virtio_scsi_info);
}

type_init(virtio_register_types)