scsi-generic.c 16.5 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Generic SCSI Device support
 *
 * Copyright (c) 2007 Bull S.A.S.
 * Based on code by Paul Brook
 * Based on code by Fabrice Bellard
 *
 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
 *
M
Matthew Fernandez 已提交
10
 * This code is licensed under the LGPL.
11 12 13
 *
 */

P
Peter Maydell 已提交
14
#include "qemu/osdep.h"
15
#include "qapi/error.h"
16
#include "qemu-common.h"
17
#include "qemu/error-report.h"
P
Paolo Bonzini 已提交
18
#include "hw/scsi/scsi.h"
19
#include "sysemu/block-backend.h"
20
#include "sysemu/blockdev.h"
21

22
#ifdef __linux__
23 24 25 26

//#define DEBUG_SCSI

#ifdef DEBUG_SCSI
27 28
#define DPRINTF(fmt, ...) \
do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
29
#else
30
#define DPRINTF(fmt, ...) do {} while(0)
31 32
#endif

33 34
#define BADF(fmt, ...) \
do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
35 36

#include <scsi/sg.h>
37
#include "scsi/constants.h"
38 39 40 41 42

#ifndef MAX_UINT
#define MAX_UINT ((unsigned int)-1)
#endif

43 44
typedef struct SCSIGenericReq {
    SCSIRequest req;
45 46 47 48
    uint8_t *buf;
    int buflen;
    int len;
    sg_io_hdr_t io_header;
49
} SCSIGenericReq;
50

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
{
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

    qemu_put_sbe32s(f, &r->buflen);
    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        assert(!r->req.sg);
        qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
    }
}

static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
{
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

    qemu_get_sbe32s(f, &r->buflen);
    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        assert(!r->req.sg);
        qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
    }
}

P
Paolo Bonzini 已提交
73
static void scsi_free_request(SCSIRequest *req)
74
{
P
Paolo Bonzini 已提交
75 76
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

77
    g_free(r->buf);
78 79 80
}

/* Helper function for command completion.  */
81
static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
82
{
83
    int status;
84
    SCSISense sense;
85

86 87
    assert(r->req.aiocb == NULL);

88
    if (r->req.io_canceled) {
89
        scsi_req_cancel_complete(&r->req);
90 91
        goto done;
    }
92 93 94 95
    status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
    if (status == CHECK_CONDITION) {
        if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
            r->req.sense_len = r->io_header.sb_len_wr;
96
        } else {
97
            scsi_req_build_sense(&r->req, sense);
98
        }
99
    }
100

A
aurel32 已提交
101
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
102
            r, r->req.tag, status);
G
Gerd Hoffmann 已提交
103

104
    scsi_req_complete(&r->req, status);
105
done:
106
    scsi_req_unref(&r->req);
107 108
}

109 110 111
static void scsi_command_complete(void *opaque, int ret)
{
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
112
    SCSIDevice *s = r->req.dev;
113 114 115

    assert(r->req.aiocb != NULL);
    r->req.aiocb = NULL;
116 117

    aio_context_acquire(blk_get_aio_context(s->conf.blk));
118
    scsi_command_complete_noio(r, ret);
119
    aio_context_release(blk_get_aio_context(s->conf.blk));
120 121
}

122
static int execute_command(BlockBackend *blk,
123
                           SCSIGenericReq *r, int direction,
124
                           BlockCompletionFunc *complete)
125 126 127 128 129
{
    r->io_header.interface_id = 'S';
    r->io_header.dxfer_direction = direction;
    r->io_header.dxferp = r->buf;
    r->io_header.dxfer_len = r->buflen;
130 131
    r->io_header.cmdp = r->req.cmd.buf;
    r->io_header.cmd_len = r->req.cmd.len;
132 133
    r->io_header.mx_sb_len = sizeof(r->req.sense);
    r->io_header.sbp = r->req.sense;
134 135 136 137
    r->io_header.timeout = MAX_UINT;
    r->io_header.usr_ptr = r;
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

138
    r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
139 140 141
    if (r->req.aiocb == NULL) {
        return -EIO;
    }
142 143 144 145 146 147

    return 0;
}

static void scsi_read_complete(void * opaque, int ret)
{
148
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
149
    SCSIDevice *s = r->req.dev;
150 151
    int len;

152
    assert(r->req.aiocb != NULL);
153
    r->req.aiocb = NULL;
154

155 156
    aio_context_acquire(blk_get_aio_context(s->conf.blk));

157
    if (ret || r->req.io_canceled) {
158
        scsi_command_complete_noio(r, ret);
159
        goto done;
160
    }
161

162
    len = r->io_header.dxfer_len - r->io_header.resid;
163
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
164 165

    r->len = -1;
166
    if (len == 0) {
167
        scsi_command_complete_noio(r, 0);
168
        goto done;
169
    }
170

171 172 173 174 175 176 177 178 179
    /* Snoop READ CAPACITY output to set the blocksize.  */
    if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
        (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
        s->blocksize = ldl_be_p(&r->buf[4]);
        s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
    } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
               (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
        s->blocksize = ldl_be_p(&r->buf[8]);
        s->max_lba = ldq_be_p(&r->buf[0]);
180
    }
181 182
    blk_set_guest_block_size(s->conf.blk, s->blocksize);

183 184 185 186 187 188 189 190 191 192 193 194 195 196
    /* Patch MODE SENSE device specific parameters if the BDS is opened
     * readonly.
     */
    if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) &&
        blk_is_read_only(s->conf.blk) &&
        (r->req.cmd.buf[0] == MODE_SENSE ||
         r->req.cmd.buf[0] == MODE_SENSE_10) &&
        (r->req.cmd.buf[1] & 0x8) == 0) {
        if (r->req.cmd.buf[0] == MODE_SENSE) {
            r->buf[2] |= 0x80;
        } else  {
            r->buf[3] |= 0x80;
        }
    }
197 198 199
    if (s->type == TYPE_DISK &&
        r->req.cmd.buf[0] == INQUIRY &&
        r->req.cmd.buf[2] == 0xb0) {
200 201
        uint32_t max_transfer =
            blk_get_max_transfer(s->conf.blk) / s->blocksize;
202

203 204
        assert(max_transfer);
        stl_be_p(&r->buf[8], max_transfer);
205
        /* Also take care of the opt xfer len. */
206 207
        stl_be_p(&r->buf[12],
                 MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
208
    }
209 210
    scsi_req_data(&r->req, len);
    scsi_req_unref(&r->req);
211 212 213

done:
    aio_context_release(blk_get_aio_context(s->conf.blk));
214 215 216
}

/* Read more data from scsi device into buffer.  */
217
static void scsi_read_data(SCSIRequest *req)
218
{
219
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
220
    SCSIDevice *s = r->req.dev;
221 222
    int ret;

223
    DPRINTF("scsi_read_data tag=0x%x\n", req->tag);
224 225 226

    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
227
    if (r->len == -1) {
228
        scsi_command_complete_noio(r, 0);
229 230 231
        return;
    }

232 233
    ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
                          scsi_read_complete);
234
    if (ret < 0) {
235
        scsi_command_complete_noio(r, ret);
236 237 238 239 240
    }
}

static void scsi_write_complete(void * opaque, int ret)
{
241
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
242
    SCSIDevice *s = r->req.dev;
243 244

    DPRINTF("scsi_write_complete() ret = %d\n", ret);
245 246

    assert(r->req.aiocb != NULL);
247
    r->req.aiocb = NULL;
248

249 250
    aio_context_acquire(blk_get_aio_context(s->conf.blk));

251
    if (ret || r->req.io_canceled) {
252
        scsi_command_complete_noio(r, ret);
253
        goto done;
254 255
    }

256
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
257 258 259
        s->type == TYPE_TAPE) {
        s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
        DPRINTF("block size %d\n", s->blocksize);
A
aurel32 已提交
260 261
    }

262
    scsi_command_complete_noio(r, ret);
263 264 265

done:
    aio_context_release(blk_get_aio_context(s->conf.blk));
266 267 268 269
}

/* Write data to a scsi device.  Returns nonzero on failure.
   The transfer may complete asynchronously.  */
270
static void scsi_write_data(SCSIRequest *req)
271
{
272
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
273
    SCSIDevice *s = r->req.dev;
274 275
    int ret;

276
    DPRINTF("scsi_write_data tag=0x%x\n", req->tag);
277 278
    if (r->len == 0) {
        r->len = r->buflen;
P
Paolo Bonzini 已提交
279
        scsi_req_data(&r->req, r->len);
280
        return;
281 282
    }

283 284
    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
285
    ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
286
    if (ret < 0) {
287
        scsi_command_complete_noio(r, ret);
288 289 290 291
    }
}

/* Return a pointer to the data buffer.  */
292
static uint8_t *scsi_get_buf(SCSIRequest *req)
293
{
294 295
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

296 297 298 299 300 301 302 303
    return r->buf;
}

/* Execute a scsi command.  Returns the length of the data expected by the
   command.  This will be Positive for data transfers from the device
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
   and zero if the command does not transfer any data.  */

304
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
305
{
306
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
307
    SCSIDevice *s = r->req.dev;
308 309
    int ret;

310
#ifdef DEBUG_SCSI
311
    DPRINTF("Command: data=0x%02x", cmd[0]);
312 313 314 315 316 317 318 319
    {
        int i;
        for (i = 1; i < r->req.cmd.len; i++) {
            printf(" 0x%02x", cmd[i]);
        }
        printf("\n");
    }
#endif
320

321
    if (r->req.cmd.xfer == 0) {
322
        g_free(r->buf);
323 324
        r->buflen = 0;
        r->buf = NULL;
325 326
        /* The request is used as the AIO opaque value, so add a ref.  */
        scsi_req_ref(&r->req);
327 328
        ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
                              scsi_command_complete);
329
        if (ret < 0) {
330
            scsi_command_complete_noio(r, ret);
331
            return 0;
332 333 334 335
        }
        return 0;
    }

336
    if (r->buflen != r->req.cmd.xfer) {
337
        g_free(r->buf);
338
        r->buf = g_malloc(r->req.cmd.xfer);
339
        r->buflen = r->req.cmd.xfer;
340 341 342
    }

    memset(r->buf, 0, r->buflen);
343
    r->len = r->req.cmd.xfer;
G
Gerd Hoffmann 已提交
344
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
345
        r->len = 0;
346
        return -r->req.cmd.xfer;
P
Paolo Bonzini 已提交
347
    } else {
348
        return r->req.cmd.xfer;
349 350 351
    }
}

352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
{
    int i;

    if ((p[1] & 0xF) == 3) {
        /* NAA designator type */
        if (p[3] != 8) {
            return -EINVAL;
        }
        *p_wwn = ldq_be_p(p + 4);
        return 0;
    }

    if ((p[1] & 0xF) == 8) {
        /* SCSI name string designator type */
        if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
            return -EINVAL;
        }
        if (p[3] > 20 && p[24] != ',') {
            return -EINVAL;
        }
        *p_wwn = 0;
        for (i = 8; i < 24; i++) {
375
            char c = qemu_toupper(p[i]);
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
            c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
            *p_wwn = (*p_wwn << 4) | c;
        }
        return 0;
    }

    return -EINVAL;
}

void scsi_generic_read_device_identification(SCSIDevice *s)
{
    uint8_t cmd[6];
    uint8_t buf[250];
    uint8_t sensebuf[8];
    sg_io_hdr_t io_header;
    int ret;
    int i, len;

    memset(cmd, 0, sizeof(cmd));
    memset(buf, 0, sizeof(buf));
    cmd[0] = INQUIRY;
    cmd[1] = 1;
    cmd[2] = 0x83;
    cmd[4] = sizeof(buf);

    memset(&io_header, 0, sizeof(io_header));
    io_header.interface_id = 'S';
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
    io_header.dxfer_len = sizeof(buf);
    io_header.dxferp = buf;
    io_header.cmdp = cmd;
    io_header.cmd_len = sizeof(cmd);
    io_header.mx_sb_len = sizeof(sensebuf);
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

    ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
        return;
    }

    len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
    for (i = 0; i + 3 <= len; ) {
        const uint8_t *p = &buf[i + 4];
        uint64_t wwn;

        if (i + (p[3] + 4) > len) {
            break;
        }

        if ((p[1] & 0x10) == 0) {
            /* Associated with the logical unit */
            if (read_naa_id(p, &wwn) == 0) {
                s->wwn = wwn;
            }
        } else if ((p[1] & 0x10) == 0x10) {
            /* Associated with the target port */
            if (read_naa_id(p, &wwn) == 0) {
                s->port_wwn = wwn;
            }
        }

        i += p[3] + 4;
    }
}

442
static int get_stream_blocksize(BlockBackend *blk)
A
aurel32 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
{
    uint8_t cmd[6];
    uint8_t buf[12];
    uint8_t sensebuf[8];
    sg_io_hdr_t io_header;
    int ret;

    memset(cmd, 0, sizeof(cmd));
    memset(buf, 0, sizeof(buf));
    cmd[0] = MODE_SENSE;
    cmd[4] = sizeof(buf);

    memset(&io_header, 0, sizeof(io_header));
    io_header.interface_id = 'S';
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
    io_header.dxfer_len = sizeof(buf);
    io_header.dxferp = buf;
    io_header.cmdp = cmd;
    io_header.cmd_len = sizeof(cmd);
    io_header.mx_sb_len = sizeof(sensebuf);
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

466
    ret = blk_ioctl(blk, SG_IO, &io_header);
467
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
A
aurel32 已提交
468
        return -1;
469
    }
A
aurel32 已提交
470 471 472
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
}

473 474
static void scsi_generic_reset(DeviceState *dev)
{
475
    SCSIDevice *s = SCSI_DEVICE(dev);
476

477
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
478 479
}

480
static void scsi_generic_realize(SCSIDevice *s, Error **errp)
481
{
482
    int rc;
483 484 485
    int sg_version;
    struct sg_scsi_id scsiid;

486
    if (!s->conf.blk) {
487 488
        error_setg(errp, "drive property not set");
        return;
489
    }
490

491
    if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
492 493
        error_setg(errp, "Device doesn't support drive option werror");
        return;
494
    }
495
    if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
496 497
        error_setg(errp, "Device doesn't support drive option rerror");
        return;
498 499
    }

500
    /* check we are using a driver managing SG_IO (version 3 and after */
501
    rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
502
    if (rc < 0) {
503 504 505 506
        error_setg_errno(errp, -rc, "cannot get SG_IO version number");
        if (rc != -EPERM) {
            error_append_hint(errp, "Is this a SCSI device?\n");
        }
507
        return;
508 509
    }
    if (sg_version < 30000) {
510 511
        error_setg(errp, "scsi generic interface too old");
        return;
512
    }
513 514

    /* get LUN of the /dev/sg? */
515
    if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
516 517
        error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
        return;
518
    }
519 520 521
    if (!blkconf_apply_backend_options(&s->conf,
                                       blk_is_read_only(s->conf.blk),
                                       true, errp)) {
F
Fam Zheng 已提交
522 523
        return;
    }
524 525

    /* define device state */
526 527
    s->type = scsiid.scsi_type;
    DPRINTF("device type %d\n", s->type);
P
Paolo Bonzini 已提交
528

529 530
    switch (s->type) {
    case TYPE_TAPE:
531
        s->blocksize = get_stream_blocksize(s->conf.blk);
532 533 534
        if (s->blocksize == -1) {
            s->blocksize = 0;
        }
535 536 537 538 539 540 541 542 543 544 545 546 547
        break;

        /* Make a guess for block devices, we'll fix it when the guest sends.
         * READ CAPACITY.  If they don't, they likely would assume these sizes
         * anyway. (TODO: they could also send MODE SENSE).
         */
    case TYPE_ROM:
    case TYPE_WORM:
        s->blocksize = 2048;
        break;
    default:
        s->blocksize = 512;
        break;
A
aurel32 已提交
548
    }
549 550

    DPRINTF("block size %d\n", s->blocksize);
551 552

    scsi_generic_read_device_identification(s);
553
}
554

P
Paolo Bonzini 已提交
555
const SCSIReqOps scsi_generic_req_ops = {
P
Paolo Bonzini 已提交
556
    .size         = sizeof(SCSIGenericReq),
557 558 559 560 561
    .free_req     = scsi_free_request,
    .send_command = scsi_send_command,
    .read_data    = scsi_read_data,
    .write_data   = scsi_write_data,
    .get_buf      = scsi_get_buf,
562 563
    .load_request = scsi_generic_load_request,
    .save_request = scsi_generic_save_request,
P
Paolo Bonzini 已提交
564 565 566
};

static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
P
Paolo Bonzini 已提交
567
                                     uint8_t *buf, void *hba_private)
P
Paolo Bonzini 已提交
568
{
569
    return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
P
Paolo Bonzini 已提交
570 571
}

572
static Property scsi_generic_properties[] = {
573
    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
F
Fam Zheng 已提交
574
    DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
575 576 577
    DEFINE_PROP_END_OF_LIST(),
};

578 579 580 581 582 583
static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
                                  uint8_t *buf, void *hba_private)
{
    return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
}

584 585
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
{
586
    DeviceClass *dc = DEVICE_CLASS(klass);
587 588
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);

589
    sc->realize      = scsi_generic_realize;
590
    sc->alloc_req    = scsi_new_request;
591
    sc->parse_cdb    = scsi_generic_parse_cdb;
592 593 594 595
    dc->fw_name = "disk";
    dc->desc = "pass through generic scsi device (/dev/sg*)";
    dc->reset = scsi_generic_reset;
    dc->props = scsi_generic_properties;
596
    dc->vmsd  = &vmstate_scsi_device;
597 598
}

599
static const TypeInfo scsi_generic_info = {
600 601 602 603
    .name          = "scsi-generic",
    .parent        = TYPE_SCSI_DEVICE,
    .instance_size = sizeof(SCSIDevice),
    .class_init    = scsi_generic_class_initfn,
604
};
605

A
Andreas Färber 已提交
606
static void scsi_generic_register_types(void)
607
{
608
    type_register_static(&scsi_generic_info);
609
}
A
Andreas Färber 已提交
610 611

type_init(scsi_generic_register_types)
612

613
#endif /* __linux__ */