scsi-generic.c 14.3 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/block-backend.h"
18
#include "sysemu/blockdev.h"
19

20
#ifdef __linux__
21 22 23 24

//#define DEBUG_SCSI

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

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

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

P
Paolo Bonzini 已提交
41 42 43 44 45 46 47
#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
48 49 50 51 52

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

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

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

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

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

95 96
    assert(r->req.aiocb == NULL);

97
    if (r->req.io_canceled) {
98
        scsi_req_cancel_complete(&r->req);
99 100
        goto done;
    }
P
Paolo Bonzini 已提交
101
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
102
        r->req.sense_len = r->io_header.sb_len_wr;
P
Paolo Bonzini 已提交
103
    }
A
aurel32 已提交
104

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

140
    scsi_req_complete(&r->req, status);
141
done:
142
    scsi_req_unref(&r->req);
143 144
}

145 146 147 148 149 150 151 152 153
static void scsi_command_complete(void *opaque, int ret)
{
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;

    assert(r->req.aiocb != NULL);
    r->req.aiocb = NULL;
    scsi_command_complete_noio(r, ret);
}

154
static int execute_command(BlockBackend *blk,
155
                           SCSIGenericReq *r, int direction,
156
                           BlockCompletionFunc *complete)
157 158 159 160 161
{
    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;
162 163
    r->io_header.cmdp = r->req.cmd.buf;
    r->io_header.cmd_len = r->req.cmd.len;
164 165
    r->io_header.mx_sb_len = sizeof(r->req.sense);
    r->io_header.sbp = r->req.sense;
166 167 168 169
    r->io_header.timeout = MAX_UINT;
    r->io_header.usr_ptr = r;
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

170
    r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
171 172 173
    if (r->req.aiocb == NULL) {
        return -EIO;
    }
174 175 176 177 178 179

    return 0;
}

static void scsi_read_complete(void * opaque, int ret)
{
180
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
181
    SCSIDevice *s = r->req.dev;
182 183
    int len;

184
    assert(r->req.aiocb != NULL);
185
    r->req.aiocb = NULL;
186

187
    if (ret || r->req.io_canceled) {
188
        scsi_command_complete_noio(r, ret);
189 190
        return;
    }
191

192
    len = r->io_header.dxfer_len - r->io_header.resid;
193
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
194 195

    r->len = -1;
196
    if (len == 0) {
197 198 199
        scsi_command_complete_noio(r, 0);
        return;
    }
200

201 202 203 204 205 206 207 208 209
    /* 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]);
210
    }
211 212
    blk_set_guest_block_size(s->conf.blk, s->blocksize);

213 214 215 216 217 218 219 220 221 222 223 224 225 226
    /* 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;
        }
    }
227 228
    scsi_req_data(&r->req, len);
    scsi_req_unref(&r->req);
229 230 231
}

/* Read more data from scsi device into buffer.  */
232
static void scsi_read_data(SCSIRequest *req)
233
{
234
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
235
    SCSIDevice *s = r->req.dev;
236 237
    int ret;

238
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
239 240 241

    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
242
    if (r->len == -1) {
243
        scsi_command_complete_noio(r, 0);
244 245 246
        return;
    }

247 248
    ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
                          scsi_read_complete);
249
    if (ret < 0) {
250
        scsi_command_complete_noio(r, ret);
251 252 253 254 255
    }
}

static void scsi_write_complete(void * opaque, int ret)
{
256
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
257
    SCSIDevice *s = r->req.dev;
258 259

    DPRINTF("scsi_write_complete() ret = %d\n", ret);
260 261

    assert(r->req.aiocb != NULL);
262
    r->req.aiocb = NULL;
263

264
    if (ret || r->req.io_canceled) {
265
        scsi_command_complete_noio(r, ret);
266 267 268
        return;
    }

269
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
270 271 272
        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 已提交
273 274
    }

275
    scsi_command_complete_noio(r, ret);
276 277 278 279
}

/* Write data to a scsi device.  Returns nonzero on failure.
   The transfer may complete asynchronously.  */
280
static void scsi_write_data(SCSIRequest *req)
281
{
282
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
283
    SCSIDevice *s = r->req.dev;
284 285
    int ret;

286
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
287 288
    if (r->len == 0) {
        r->len = r->buflen;
P
Paolo Bonzini 已提交
289
        scsi_req_data(&r->req, r->len);
290
        return;
291 292
    }

293 294
    /* The request is used as the AIO opaque value, so add a ref.  */
    scsi_req_ref(&r->req);
295
    ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
296
    if (ret < 0) {
297
        scsi_command_complete_noio(r, ret);
298 299 300 301
    }
}

/* Return a pointer to the data buffer.  */
302
static uint8_t *scsi_get_buf(SCSIRequest *req)
303
{
304 305
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);

306 307 308 309 310 311 312 313
    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.  */

314
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
315
{
316
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
317
    SCSIDevice *s = r->req.dev;
318 319
    int ret;

320 321 322 323 324 325 326 327 328
#ifdef DEBUG_SCSI
    {
        int i;
        for (i = 1; i < r->req.cmd.len; i++) {
            printf(" 0x%02x", cmd[i]);
        }
        printf("\n");
    }
#endif
329

330
    if (r->req.cmd.xfer == 0) {
331
        g_free(r->buf);
332 333
        r->buflen = 0;
        r->buf = NULL;
334 335
        /* The request is used as the AIO opaque value, so add a ref.  */
        scsi_req_ref(&r->req);
336 337
        ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
                              scsi_command_complete);
338
        if (ret < 0) {
339
            scsi_command_complete_noio(r, ret);
340
            return 0;
341 342 343 344
        }
        return 0;
    }

345
    if (r->buflen != r->req.cmd.xfer) {
346
        g_free(r->buf);
347
        r->buf = g_malloc(r->req.cmd.xfer);
348
        r->buflen = r->req.cmd.xfer;
349 350 351
    }

    memset(r->buf, 0, r->buflen);
352
    r->len = r->req.cmd.xfer;
G
Gerd Hoffmann 已提交
353
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
354
        r->len = 0;
355
        return -r->req.cmd.xfer;
P
Paolo Bonzini 已提交
356
    } else {
357
        return r->req.cmd.xfer;
358 359 360
    }
}

361
static int get_stream_blocksize(BlockBackend *blk)
A
aurel32 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
{
    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 */

385
    ret = blk_ioctl(blk, SG_IO, &io_header);
386
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
A
aurel32 已提交
387
        return -1;
388
    }
A
aurel32 已提交
389 390 391
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
}

392 393
static void scsi_generic_reset(DeviceState *dev)
{
394
    SCSIDevice *s = SCSI_DEVICE(dev);
395

396
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
397 398
}

399
static void scsi_generic_realize(SCSIDevice *s, Error **errp)
400
{
401
    int rc;
402 403 404
    int sg_version;
    struct sg_scsi_id scsiid;

405
    if (!s->conf.blk) {
406 407
        error_setg(errp, "drive property not set");
        return;
408
    }
409

410
    if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
411 412
        error_setg(errp, "Device doesn't support drive option werror");
        return;
413
    }
414
    if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
415 416
        error_setg(errp, "Device doesn't support drive option rerror");
        return;
417 418
    }

419
    /* check we are using a driver managing SG_IO (version 3 and after */
420
    rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
421
    if (rc < 0) {
422 423 424 425
        error_setg(errp, "cannot get SG_IO version number: %s.  "
                         "Is this a SCSI device?",
                         strerror(-rc));
        return;
426 427
    }
    if (sg_version < 30000) {
428 429
        error_setg(errp, "scsi generic interface too old");
        return;
430
    }
431 432

    /* get LUN of the /dev/sg? */
433
    if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
434 435
        error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
        return;
436
    }
437 438

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

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

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

P
Paolo Bonzini 已提交
466
const SCSIReqOps scsi_generic_req_ops = {
P
Paolo Bonzini 已提交
467
    .size         = sizeof(SCSIGenericReq),
468 469 470 471 472
    .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,
473 474
    .load_request = scsi_generic_load_request,
    .save_request = scsi_generic_save_request,
P
Paolo Bonzini 已提交
475 476 477
};

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

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

486
static Property scsi_generic_properties[] = {
487
    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
488 489 490
    DEFINE_PROP_END_OF_LIST(),
};

491 492 493 494 495 496
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);
}

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

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

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

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

type_init(scsi_generic_register_types)
525

526
#endif /* __linux__ */