qemu/hw/scsi/scsi-generic.c
<<
>>
Prefs
   1/*
   2 * Generic SCSI Device support
   3 *
   4 * Copyright (c) 2007 Bull S.A.S.
   5 * Based on code by Paul Brook
   6 * Based on code by Fabrice Bellard
   7 *
   8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
   9 *
  10 * This code is licensed under the LGPL.
  11 *
  12 */
  13
  14#include "qemu-common.h"
  15#include "qemu/error-report.h"
  16#include "hw/scsi/scsi.h"
  17#include "sysemu/blockdev.h"
  18
  19#ifdef __linux__
  20
  21//#define DEBUG_SCSI
  22
  23#ifdef DEBUG_SCSI
  24#define DPRINTF(fmt, ...) \
  25do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
  26#else
  27#define DPRINTF(fmt, ...) do {} while(0)
  28#endif
  29
  30#define BADF(fmt, ...) \
  31do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
  32
  33#include <stdio.h>
  34#include <sys/types.h>
  35#include <sys/stat.h>
  36#include <unistd.h>
  37#include <scsi/sg.h>
  38#include "block/scsi.h"
  39
  40#define SCSI_SENSE_BUF_SIZE 96
  41
  42#define SG_ERR_DRIVER_TIMEOUT  0x06
  43#define SG_ERR_DRIVER_SENSE    0x08
  44
  45#define SG_ERR_DID_OK          0x00
  46#define SG_ERR_DID_NO_CONNECT  0x01
  47#define SG_ERR_DID_BUS_BUSY    0x02
  48#define SG_ERR_DID_TIME_OUT    0x03
  49
  50#ifndef MAX_UINT
  51#define MAX_UINT ((unsigned int)-1)
  52#endif
  53
  54typedef struct SCSIGenericReq {
  55    SCSIRequest req;
  56    uint8_t *buf;
  57    int buflen;
  58    int len;
  59    sg_io_hdr_t io_header;
  60} SCSIGenericReq;
  61
  62static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
  63{
  64    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
  65
  66    qemu_put_sbe32s(f, &r->buflen);
  67    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
  68        assert(!r->req.sg);
  69        qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
  70    }
  71}
  72
  73static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
  74{
  75    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
  76
  77    qemu_get_sbe32s(f, &r->buflen);
  78    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
  79        assert(!r->req.sg);
  80        qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
  81    }
  82}
  83
  84static void scsi_free_request(SCSIRequest *req)
  85{
  86    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
  87
  88    g_free(r->buf);
  89}
  90
  91/* Helper function for command completion.  */
  92static void scsi_command_complete(void *opaque, int ret)
  93{
  94    int status;
  95    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
  96
  97    r->req.aiocb = NULL;
  98    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
  99        r->req.sense_len = r->io_header.sb_len_wr;
 100    }
 101
 102    if (ret != 0) {
 103        switch (ret) {
 104        case -EDOM:
 105            status = TASK_SET_FULL;
 106            break;
 107        case -ENOMEM:
 108            status = CHECK_CONDITION;
 109            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
 110            break;
 111        default:
 112            status = CHECK_CONDITION;
 113            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
 114            break;
 115        }
 116    } else {
 117        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
 118            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
 119            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
 120            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
 121            status = BUSY;
 122            BADF("Driver Timeout\n");
 123        } else if (r->io_header.host_status) {
 124            status = CHECK_CONDITION;
 125            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
 126        } else if (r->io_header.status) {
 127            status = r->io_header.status;
 128        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
 129            status = CHECK_CONDITION;
 130        } else {
 131            status = GOOD;
 132        }
 133    }
 134    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
 135            r, r->req.tag, status);
 136
 137    scsi_req_complete(&r->req, status);
 138    if (!r->req.io_canceled) {
 139        scsi_req_unref(&r->req);
 140    }
 141}
 142
 143/* Cancel a pending data transfer.  */
 144static void scsi_cancel_io(SCSIRequest *req)
 145{
 146    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
 147
 148    DPRINTF("Cancel tag=0x%x\n", req->tag);
 149    if (r->req.aiocb) {
 150        bdrv_aio_cancel(r->req.aiocb);
 151
 152        /* This reference was left in by scsi_*_data.  We take ownership of
 153         * it independent of whether bdrv_aio_cancel completes the request
 154         * or not.  */
 155        scsi_req_unref(&r->req);
 156    }
 157    r->req.aiocb = NULL;
 158}
 159
 160static int execute_command(BlockDriverState *bdrv,
 161                           SCSIGenericReq *r, int direction,
 162                           BlockDriverCompletionFunc *complete)
 163{
 164    r->io_header.interface_id = 'S';
 165    r->io_header.dxfer_direction = direction;
 166    r->io_header.dxferp = r->buf;
 167    r->io_header.dxfer_len = r->buflen;
 168    r->io_header.cmdp = r->req.cmd.buf;
 169    r->io_header.cmd_len = r->req.cmd.len;
 170    r->io_header.mx_sb_len = sizeof(r->req.sense);
 171    r->io_header.sbp = r->req.sense;
 172    r->io_header.timeout = MAX_UINT;
 173    r->io_header.usr_ptr = r;
 174    r->io_header.flags |= SG_FLAG_DIRECT_IO;
 175
 176    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
 177    if (r->req.aiocb == NULL) {
 178        return -EIO;
 179    }
 180
 181    return 0;
 182}
 183
 184static void scsi_read_complete(void * opaque, int ret)
 185{
 186    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
 187    SCSIDevice *s = r->req.dev;
 188    int len;
 189
 190    r->req.aiocb = NULL;
 191    if (ret) {
 192        DPRINTF("IO error ret %d\n", ret);
 193        scsi_command_complete(r, ret);
 194        return;
 195    }
 196    len = r->io_header.dxfer_len - r->io_header.resid;
 197    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
 198
 199    r->len = -1;
 200    if (len == 0) {
 201        scsi_command_complete(r, 0);
 202    } else {
 203        /* Snoop READ CAPACITY output to set the blocksize.  */
 204        if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
 205            (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
 206            s->blocksize = ldl_be_p(&r->buf[4]);
 207            s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
 208        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
 209                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
 210            s->blocksize = ldl_be_p(&r->buf[8]);
 211            s->max_lba = ldq_be_p(&r->buf[0]);
 212        }
 213        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
 214
 215        scsi_req_data(&r->req, len);
 216        if (!r->req.io_canceled) {
 217            scsi_req_unref(&r->req);
 218        }
 219    }
 220}
 221
 222/* Read more data from scsi device into buffer.  */
 223static void scsi_read_data(SCSIRequest *req)
 224{
 225    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
 226    SCSIDevice *s = r->req.dev;
 227    int ret;
 228
 229    DPRINTF("scsi_read_data 0x%x\n", req->tag);
 230
 231    /* The request is used as the AIO opaque value, so add a ref.  */
 232    scsi_req_ref(&r->req);
 233    if (r->len == -1) {
 234        scsi_command_complete(r, 0);
 235        return;
 236    }
 237
 238    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
 239    if (ret < 0) {
 240        scsi_command_complete(r, ret);
 241    }
 242}
 243
 244static void scsi_write_complete(void * opaque, int ret)
 245{
 246    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
 247    SCSIDevice *s = r->req.dev;
 248
 249    DPRINTF("scsi_write_complete() ret = %d\n", ret);
 250    r->req.aiocb = NULL;
 251    if (ret) {
 252        DPRINTF("IO error\n");
 253        scsi_command_complete(r, ret);
 254        return;
 255    }
 256
 257    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
 258        s->type == TYPE_TAPE) {
 259        s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
 260        DPRINTF("block size %d\n", s->blocksize);
 261    }
 262
 263    scsi_command_complete(r, ret);
 264}
 265
 266/* Write data to a scsi device.  Returns nonzero on failure.
 267   The transfer may complete asynchronously.  */
 268static void scsi_write_data(SCSIRequest *req)
 269{
 270    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
 271    SCSIDevice *s = r->req.dev;
 272    int ret;
 273
 274    DPRINTF("scsi_write_data 0x%x\n", req->tag);
 275    if (r->len == 0) {
 276        r->len = r->buflen;
 277        scsi_req_data(&r->req, r->len);
 278        return;
 279    }
 280
 281    /* The request is used as the AIO opaque value, so add a ref.  */
 282    scsi_req_ref(&r->req);
 283    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
 284    if (ret < 0) {
 285        scsi_command_complete(r, ret);
 286    }
 287}
 288
 289/* Return a pointer to the data buffer.  */
 290static uint8_t *scsi_get_buf(SCSIRequest *req)
 291{
 292    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
 293
 294    return r->buf;
 295}
 296
 297/* Execute a scsi command.  Returns the length of the data expected by the
 298   command.  This will be Positive for data transfers from the device
 299   (eg. disk reads), negative for transfers to the device (eg. disk writes),
 300   and zero if the command does not transfer any data.  */
 301
 302static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
 303{
 304    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
 305    SCSIDevice *s = r->req.dev;
 306    int ret;
 307
 308    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
 309            r->req.cmd.xfer, cmd[0]);
 310
 311#ifdef DEBUG_SCSI
 312    {
 313        int i;
 314        for (i = 1; i < r->req.cmd.len; i++) {
 315            printf(" 0x%02x", cmd[i]);
 316        }
 317        printf("\n");
 318    }
 319#endif
 320
 321    if (r->req.cmd.xfer == 0) {
 322        if (r->buf != NULL)
 323            g_free(r->buf);
 324        r->buflen = 0;
 325        r->buf = NULL;
 326        /* The request is used as the AIO opaque value, so add a ref.  */
 327        scsi_req_ref(&r->req);
 328        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
 329        if (ret < 0) {
 330            scsi_command_complete(r, ret);
 331            return 0;
 332        }
 333        return 0;
 334    }
 335
 336    if (r->buflen != r->req.cmd.xfer) {
 337        if (r->buf != NULL)
 338            g_free(r->buf);
 339        r->buf = g_malloc(r->req.cmd.xfer);
 340        r->buflen = r->req.cmd.xfer;
 341    }
 342
 343    memset(r->buf, 0, r->buflen);
 344    r->len = r->req.cmd.xfer;
 345    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
 346        r->len = 0;
 347        return -r->req.cmd.xfer;
 348    } else {
 349        return r->req.cmd.xfer;
 350    }
 351}
 352
 353static int get_stream_blocksize(BlockDriverState *bdrv)
 354{
 355    uint8_t cmd[6];
 356    uint8_t buf[12];
 357    uint8_t sensebuf[8];
 358    sg_io_hdr_t io_header;
 359    int ret;
 360
 361    memset(cmd, 0, sizeof(cmd));
 362    memset(buf, 0, sizeof(buf));
 363    cmd[0] = MODE_SENSE;
 364    cmd[4] = sizeof(buf);
 365
 366    memset(&io_header, 0, sizeof(io_header));
 367    io_header.interface_id = 'S';
 368    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
 369    io_header.dxfer_len = sizeof(buf);
 370    io_header.dxferp = buf;
 371    io_header.cmdp = cmd;
 372    io_header.cmd_len = sizeof(cmd);
 373    io_header.mx_sb_len = sizeof(sensebuf);
 374    io_header.sbp = sensebuf;
 375    io_header.timeout = 6000; /* XXX */
 376
 377    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
 378    if (ret < 0 || io_header.driver_status || io_header.host_status) {
 379        return -1;
 380    }
 381    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
 382}
 383
 384static void scsi_generic_reset(DeviceState *dev)
 385{
 386    SCSIDevice *s = SCSI_DEVICE(dev);
 387
 388    scsi_device_purge_requests(s, SENSE_CODE(RESET));
 389}
 390
 391static void scsi_destroy(SCSIDevice *s)
 392{
 393    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
 394    blockdev_mark_auto_del(s->conf.bs);
 395}
 396
 397static int scsi_generic_initfn(SCSIDevice *s)
 398{
 399    int sg_version;
 400    struct sg_scsi_id scsiid;
 401
 402    if (!s->conf.bs) {
 403        error_report("drive property not set");
 404        return -1;
 405    }
 406
 407    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
 408        error_report("Device doesn't support drive option werror");
 409        return -1;
 410    }
 411    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
 412        error_report("Device doesn't support drive option rerror");
 413        return -1;
 414    }
 415
 416    /* check we are using a driver managing SG_IO (version 3 and after */
 417    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
 418        error_report("scsi generic interface not supported");
 419        return -1;
 420    }
 421    if (sg_version < 30000) {
 422        error_report("scsi generic interface too old");
 423        return -1;
 424    }
 425
 426    /* get LUN of the /dev/sg? */
 427    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
 428        error_report("SG_GET_SCSI_ID ioctl failed");
 429        return -1;
 430    }
 431
 432    /* define device state */
 433    s->type = scsiid.scsi_type;
 434    DPRINTF("device type %d\n", s->type);
 435    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
 436        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
 437    }
 438
 439    switch (s->type) {
 440    case TYPE_TAPE:
 441        s->blocksize = get_stream_blocksize(s->conf.bs);
 442        if (s->blocksize == -1) {
 443            s->blocksize = 0;
 444        }
 445        break;
 446
 447        /* Make a guess for block devices, we'll fix it when the guest sends.
 448         * READ CAPACITY.  If they don't, they likely would assume these sizes
 449         * anyway. (TODO: they could also send MODE SENSE).
 450         */
 451    case TYPE_ROM:
 452    case TYPE_WORM:
 453        s->blocksize = 2048;
 454        break;
 455    default:
 456        s->blocksize = 512;
 457        break;
 458    }
 459
 460    DPRINTF("block size %d\n", s->blocksize);
 461    return 0;
 462}
 463
 464const SCSIReqOps scsi_generic_req_ops = {
 465    .size         = sizeof(SCSIGenericReq),
 466    .free_req     = scsi_free_request,
 467    .send_command = scsi_send_command,
 468    .read_data    = scsi_read_data,
 469    .write_data   = scsi_write_data,
 470    .cancel_io    = scsi_cancel_io,
 471    .get_buf      = scsi_get_buf,
 472    .load_request = scsi_generic_load_request,
 473    .save_request = scsi_generic_save_request,
 474};
 475
 476static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 477                                     uint8_t *buf, void *hba_private)
 478{
 479    SCSIRequest *req;
 480
 481    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
 482    return req;
 483}
 484
 485static Property scsi_generic_properties[] = {
 486    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
 487    DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
 488    DEFINE_PROP_END_OF_LIST(),
 489};
 490
 491static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
 492{
 493    DeviceClass *dc = DEVICE_CLASS(klass);
 494    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
 495
 496    sc->init         = scsi_generic_initfn;
 497    sc->destroy      = scsi_destroy;
 498    sc->alloc_req    = scsi_new_request;
 499    dc->fw_name = "disk";
 500    dc->desc = "pass through generic scsi device (/dev/sg*)";
 501    dc->reset = scsi_generic_reset;
 502    dc->props = scsi_generic_properties;
 503    dc->vmsd  = &vmstate_scsi_device;
 504}
 505
 506static const TypeInfo scsi_generic_info = {
 507    .name          = "scsi-generic",
 508    .parent        = TYPE_SCSI_DEVICE,
 509    .instance_size = sizeof(SCSIDevice),
 510    .class_init    = scsi_generic_class_initfn,
 511};
 512
 513static void scsi_generic_register_types(void)
 514{
 515    type_register_static(&scsi_generic_info);
 516}
 517
 518type_init(scsi_generic_register_types)
 519
 520#endif /* __linux__ */
 521