scsi-generic.c 14.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 14
 *
 */

#include "qemu-common.h"
15
#include "qemu/error-report.h"
P
Paolo Bonzini 已提交
16
#include "hw/scsi/scsi.h"
17
#include "sysemu/blockdev.h"
18

19
#ifdef __linux__
20 21 22 23

//#define DEBUG_SCSI

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

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

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <scsi/sg.h>
P
Paolo Bonzini 已提交
38
#include "block/scsi.h"
39

P
Paolo Bonzini 已提交
40 41 42 43 44 45 46
#define SG_ERR_DRIVER_TIMEOUT  0x06
#define SG_ERR_DRIVER_SENSE    0x08

#define SG_ERR_DID_OK          0x00
#define SG_ERR_DID_NO_CONNECT  0x01
#define SG_ERR_DID_BUS_BUSY    0x02
#define SG_ERR_DID_TIME_OUT    0x03
47 48 49 50 51

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

52 53
typedef struct SCSIGenericReq {
    SCSIRequest req;
54 55 56 57
    uint8_t *buf;
    int buflen;
    int len;
    sg_io_hdr_t io_header;
58
} SCSIGenericReq;
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
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 已提交
82
static void scsi_free_request(SCSIRequest *req)
83
{
P
Paolo Bonzini 已提交
84 85
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

86
    g_free(r->buf);
87 88 89 90 91
}

/* Helper function for command completion.  */
static void scsi_command_complete(void *opaque, int ret)
{
92
    int status;
93
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
94

95
    r->req.aiocb = NULL;
P
Paolo Bonzini 已提交
96
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
97
        r->req.sense_len = r->io_header.sb_len_wr;
P
Paolo Bonzini 已提交
98
    }
A
aurel32 已提交
99

100 101
    if (ret != 0) {
        switch (ret) {
P
Paolo Bonzini 已提交
102
        case -EDOM:
103
            status = TASK_SET_FULL;
P
Paolo Bonzini 已提交
104
            break;
105
        case -ENOMEM:
106
            status = CHECK_CONDITION;
107
            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
108 109
            break;
        default:
110
            status = CHECK_CONDITION;
111
            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
112 113 114
            break;
        }
    } else {
P
Paolo Bonzini 已提交
115 116 117 118
        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
119
            status = BUSY;
120
            BADF("Driver Timeout\n");
P
Paolo Bonzini 已提交
121 122 123
        } else if (r->io_header.host_status) {
            status = CHECK_CONDITION;
            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
124 125
        } else if (r->io_header.status) {
            status = r->io_header.status;
126
        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
127 128 129 130
            status = CHECK_CONDITION;
        } else {
            status = GOOD;
        }
131
    }
A
aurel32 已提交
132
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
133
            r, r->req.tag, status);
G
Gerd Hoffmann 已提交
134

135
    scsi_req_complete(&r->req, status);
136 137 138
    if (!r->req.io_canceled) {
        scsi_req_unref(&r->req);
    }
139 140 141
}

/* Cancel a pending data transfer.  */
142
static void scsi_cancel_io(SCSIRequest *req)
143
{
144 145 146 147 148
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

    DPRINTF("Cancel tag=0x%x\n", req->tag);
    if (r->req.aiocb) {
        bdrv_aio_cancel(r->req.aiocb);
149 150 151 152 153

        /* This reference was left in by scsi_*_data.  We take ownership of
         * it independent of whether bdrv_aio_cancel completes the request
         * or not.  */
        scsi_req_unref(&r->req);
154
    }
155
    r->req.aiocb = NULL;
156 157 158
}

static int execute_command(BlockDriverState *bdrv,
159
                           SCSIGenericReq *r, int direction,
160 161 162 163 164 165
			   BlockDriverCompletionFunc *complete)
{
    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;
166 167
    r->io_header.cmdp = r->req.cmd.buf;
    r->io_header.cmd_len = r->req.cmd.len;
168 169
    r->io_header.mx_sb_len = sizeof(r->req.sense);
    r->io_header.sbp = r->req.sense;
170 171 172 173
    r->io_header.timeout = MAX_UINT;
    r->io_header.usr_ptr = r;
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

174
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
175 176 177
    if (r->req.aiocb == NULL) {
        return -EIO;
    }
178 179 180 181 182 183

    return 0;
}

static void scsi_read_complete(void * opaque, int ret)
{
184
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
185
    SCSIDevice *s = r->req.dev;
186 187
    int len;

188
    r->req.aiocb = NULL;
189
    if (ret) {
190
        DPRINTF("IO error ret %d\n", ret);
191 192 193 194
        scsi_command_complete(r, ret);
        return;
    }
    len = r->io_header.dxfer_len - r->io_header.resid;
195
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
196 197

    r->len = -1;
198
    if (len == 0) {
A
aurel32 已提交
199
        scsi_command_complete(r, 0);
200
    } else {
201
        /* Snoop READ CAPACITY output to set the blocksize.  */
202 203
        if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
            (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
204
            s->blocksize = ldl_be_p(&r->buf[4]);
205
            s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
206 207 208
        } 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]);
P
Paolo Bonzini 已提交
209
            s->max_lba = ldq_be_p(&r->buf[0]);
210
        }
211
        bdrv_set_guest_block_size(s->conf.bs, s->blocksize);
212

P
Paolo Bonzini 已提交
213
        scsi_req_data(&r->req, len);
214 215 216
        if (!r->req.io_canceled) {
            scsi_req_unref(&r->req);
        }
217
    }
218 219 220
}

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

227
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
228 229 230

    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
231 232 233 234 235
    if (r->len == -1) {
        scsi_command_complete(r, 0);
        return;
    }

236
    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
237 238
    if (ret < 0) {
        scsi_command_complete(r, ret);
239 240 241 242 243
    }
}

static void scsi_write_complete(void * opaque, int ret)
{
244
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
245
    SCSIDevice *s = r->req.dev;
246 247

    DPRINTF("scsi_write_complete() ret = %d\n", ret);
248
    r->req.aiocb = NULL;
249 250 251 252 253 254
    if (ret) {
        DPRINTF("IO error\n");
        scsi_command_complete(r, ret);
        return;
    }

255
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
256 257 258
        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 已提交
259 260
    }

261 262 263 264 265
    scsi_command_complete(r, ret);
}

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

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

279 280
    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
281
    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
282 283
    if (ret < 0) {
        scsi_command_complete(r, ret);
284 285 286 287
    }
}

/* Return a pointer to the data buffer.  */
288
static uint8_t *scsi_get_buf(SCSIRequest *req)
289
{
290 291
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

292 293 294 295 296 297 298 299
    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.  */

300
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
301
{
302
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
303
    SCSIDevice *s = r->req.dev;
304 305
    int ret;

306 307 308 309 310 311 312 313 314
#ifdef DEBUG_SCSI
    {
        int i;
        for (i = 1; i < r->req.cmd.len; i++) {
            printf(" 0x%02x", cmd[i]);
        }
        printf("\n");
    }
#endif
315

316
    if (r->req.cmd.xfer == 0) {
317
        if (r->buf != NULL)
318
            g_free(r->buf);
319 320
        r->buflen = 0;
        r->buf = NULL;
321 322
        /* The request is used as the AIO opaque value, so add a ref.  */
        scsi_req_ref(&r->req);
323
        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
324 325 326
        if (ret < 0) {
            scsi_command_complete(r, ret);
            return 0;
327 328 329 330
        }
        return 0;
    }

331
    if (r->buflen != r->req.cmd.xfer) {
332
        if (r->buf != NULL)
333 334
            g_free(r->buf);
        r->buf = g_malloc(r->req.cmd.xfer);
335
        r->buflen = r->req.cmd.xfer;
336 337 338
    }

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

A
aurel32 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
static int get_stream_blocksize(BlockDriverState *bdrv)
{
    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 */

372
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
373
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
A
aurel32 已提交
374
        return -1;
375
    }
A
aurel32 已提交
376 377 378
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
}

379 380
static void scsi_generic_reset(DeviceState *dev)
{
381
    SCSIDevice *s = SCSI_DEVICE(dev);
382

383
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
384 385
}

386
static void scsi_unrealize(SCSIDevice *s, Error **errp)
387
{
388 389
    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
    blockdev_mark_auto_del(s->conf.bs);
390 391
}

392
static void scsi_generic_realize(SCSIDevice *s, Error **errp)
393
{
394
    int rc;
395 396 397
    int sg_version;
    struct sg_scsi_id scsiid;

398
    if (!s->conf.bs) {
399 400
        error_setg(errp, "drive property not set");
        return;
401
    }
402

403
    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
404 405
        error_setg(errp, "Device doesn't support drive option werror");
        return;
406
    }
407
    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
408 409
        error_setg(errp, "Device doesn't support drive option rerror");
        return;
410 411
    }

412
    /* check we are using a driver managing SG_IO (version 3 and after */
413 414
    rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version);
    if (rc < 0) {
415 416 417 418
        error_setg(errp, "cannot get SG_IO version number: %s.  "
                         "Is this a SCSI device?",
                         strerror(-rc));
        return;
419 420
    }
    if (sg_version < 30000) {
421 422
        error_setg(errp, "scsi generic interface too old");
        return;
423
    }
424 425

    /* get LUN of the /dev/sg? */
426
    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
427 428
        error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
        return;
429
    }
430 431

    /* define device state */
432 433
    s->type = scsiid.scsi_type;
    DPRINTF("device type %d\n", s->type);
P
Paolo Bonzini 已提交
434 435 436 437
    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
    }

438 439
    switch (s->type) {
    case TYPE_TAPE:
440 441 442 443
        s->blocksize = get_stream_blocksize(s->conf.bs);
        if (s->blocksize == -1) {
            s->blocksize = 0;
        }
444 445 446 447 448 449 450 451 452 453 454 455 456
        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 已提交
457
    }
458 459

    DPRINTF("block size %d\n", s->blocksize);
460
}
461

P
Paolo Bonzini 已提交
462
const SCSIReqOps scsi_generic_req_ops = {
P
Paolo Bonzini 已提交
463
    .size         = sizeof(SCSIGenericReq),
464 465 466 467 468 469
    .free_req     = scsi_free_request,
    .send_command = scsi_send_command,
    .read_data    = scsi_read_data,
    .write_data   = scsi_write_data,
    .cancel_io    = scsi_cancel_io,
    .get_buf      = scsi_get_buf,
470 471
    .load_request = scsi_generic_load_request,
    .save_request = scsi_generic_save_request,
P
Paolo Bonzini 已提交
472 473 474
};

static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
P
Paolo Bonzini 已提交
475
                                     uint8_t *buf, void *hba_private)
P
Paolo Bonzini 已提交
476 477 478 479 480 481 482
{
    SCSIRequest *req;

    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
    return req;
}

483
static Property scsi_generic_properties[] = {
484 485
    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
    DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
486 487 488
    DEFINE_PROP_END_OF_LIST(),
};

489 490 491 492 493 494
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);
}

495 496
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
{
497
    DeviceClass *dc = DEVICE_CLASS(klass);
498 499
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);

500 501
    sc->realize      = scsi_generic_realize;
    sc->unrealize    = scsi_unrealize;
502
    sc->alloc_req    = scsi_new_request;
503
    sc->parse_cdb    = scsi_generic_parse_cdb;
504 505 506 507
    dc->fw_name = "disk";
    dc->desc = "pass through generic scsi device (/dev/sg*)";
    dc->reset = scsi_generic_reset;
    dc->props = scsi_generic_properties;
508
    dc->vmsd  = &vmstate_scsi_device;
509 510
}

511
static const TypeInfo scsi_generic_info = {
512 513 514 515
    .name          = "scsi-generic",
    .parent        = TYPE_SCSI_DEVICE,
    .instance_size = sizeof(SCSIDevice),
    .class_init    = scsi_generic_class_initfn,
516
};
517

A
Andreas Färber 已提交
518
static void scsi_generic_register_types(void)
519
{
520
    type_register_static(&scsi_generic_info);
521
}
A
Andreas Färber 已提交
522 523

type_init(scsi_generic_register_types)
524

525
#endif /* __linux__ */