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