Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 9c17d615

History | View | Annotate | Download (14.1 kB)

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 "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, ...) \
25
do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26
#else
27
#define DPRINTF(fmt, ...) do {} while(0)
28
#endif
29

    
30
#define BADF(fmt, ...) \
31
do { 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 "scsi-defs.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

    
54
typedef 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

    
62
static 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

    
73
static 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

    
84
static 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.  */
92
static 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.  */
144
static 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

    
160
static 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

    
178
    return 0;
179
}
180

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

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

    
196
    r->len = -1;
197
    if (len == 0) {
198
        scsi_command_complete(r, 0);
199
    } else {
200
        /* Snoop READ CAPACITY output to set the blocksize.  */
201
        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
202
            s->blocksize = ldl_be_p(&r->buf[4]);
203
            s->max_lba = ldl_be_p(&r->buf[0]);
204
        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
205
                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
206
            s->blocksize = ldl_be_p(&r->buf[8]);
207
            s->max_lba = ldq_be_p(&r->buf[0]);
208
        }
209
        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
210

    
211
        scsi_req_data(&r->req, len);
212
        if (!r->req.io_canceled) {
213
            scsi_req_unref(&r->req);
214
        }
215
    }
216
}
217

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

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

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

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

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

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

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

    
259
    scsi_command_complete(r, ret);
260
}
261

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

    
270
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
271
    if (r->len == 0) {
272
        r->len = r->buflen;
273
        scsi_req_data(&r->req, r->len);
274
        return;
275
    }
276

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

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

    
290
    return r->buf;
291
}
292

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

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

    
304
    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
305
            r->req.cmd.xfer, cmd[0]);
306

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

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

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

    
339
    memset(r->buf, 0, r->buflen);
340
    r->len = r->req.cmd.xfer;
341
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
342
        r->len = 0;
343
        return -r->req.cmd.xfer;
344
    } else {
345
        return r->req.cmd.xfer;
346
    }
347
}
348

    
349
static int get_stream_blocksize(BlockDriverState *bdrv)
350
{
351
    uint8_t cmd[6];
352
    uint8_t buf[12];
353
    uint8_t sensebuf[8];
354
    sg_io_hdr_t io_header;
355
    int ret;
356

    
357
    memset(cmd, 0, sizeof(cmd));
358
    memset(buf, 0, sizeof(buf));
359
    cmd[0] = MODE_SENSE;
360
    cmd[4] = sizeof(buf);
361

    
362
    memset(&io_header, 0, sizeof(io_header));
363
    io_header.interface_id = 'S';
364
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
365
    io_header.dxfer_len = sizeof(buf);
366
    io_header.dxferp = buf;
367
    io_header.cmdp = cmd;
368
    io_header.cmd_len = sizeof(cmd);
369
    io_header.mx_sb_len = sizeof(sensebuf);
370
    io_header.sbp = sensebuf;
371
    io_header.timeout = 6000; /* XXX */
372

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

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

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

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

    
393
static int scsi_generic_initfn(SCSIDevice *s)
394
{
395
    int sg_version;
396
    struct sg_scsi_id scsiid;
397

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

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

    
412
    /* check we are using a driver managing SG_IO (version 3 and after */
413
    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
414
        error_report("scsi generic interface not supported");
415
        return -1;
416
    }
417
    if (sg_version < 30000) {
418
        error_report("scsi generic interface too old");
419
        return -1;
420
    }
421

    
422
    /* get LUN of the /dev/sg? */
423
    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
424
        error_report("SG_GET_SCSI_ID ioctl failed");
425
        return -1;
426
    }
427

    
428
    /* define device state */
429
    s->type = scsiid.scsi_type;
430
    DPRINTF("device type %d\n", s->type);
431
    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
432
        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
433
    }
434

    
435
    switch (s->type) {
436
    case TYPE_TAPE:
437
        s->blocksize = get_stream_blocksize(s->conf.bs);
438
        if (s->blocksize == -1) {
439
            s->blocksize = 0;
440
        }
441
        break;
442

    
443
        /* Make a guess for block devices, we'll fix it when the guest sends.
444
         * READ CAPACITY.  If they don't, they likely would assume these sizes
445
         * anyway. (TODO: they could also send MODE SENSE).
446
         */
447
    case TYPE_ROM:
448
    case TYPE_WORM:
449
        s->blocksize = 2048;
450
        break;
451
    default:
452
        s->blocksize = 512;
453
        break;
454
    }
455

    
456
    DPRINTF("block size %d\n", s->blocksize);
457
    return 0;
458
}
459

    
460
const SCSIReqOps scsi_generic_req_ops = {
461
    .size         = sizeof(SCSIGenericReq),
462
    .free_req     = scsi_free_request,
463
    .send_command = scsi_send_command,
464
    .read_data    = scsi_read_data,
465
    .write_data   = scsi_write_data,
466
    .cancel_io    = scsi_cancel_io,
467
    .get_buf      = scsi_get_buf,
468
    .load_request = scsi_generic_load_request,
469
    .save_request = scsi_generic_save_request,
470
};
471

    
472
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
473
                                     uint8_t *buf, void *hba_private)
474
{
475
    SCSIRequest *req;
476

    
477
    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
478
    return req;
479
}
480

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

    
487
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
488
{
489
    DeviceClass *dc = DEVICE_CLASS(klass);
490
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
491

    
492
    sc->init         = scsi_generic_initfn;
493
    sc->destroy      = scsi_destroy;
494
    sc->alloc_req    = scsi_new_request;
495
    dc->fw_name = "disk";
496
    dc->desc = "pass through generic scsi device (/dev/sg*)";
497
    dc->reset = scsi_generic_reset;
498
    dc->props = scsi_generic_properties;
499
    dc->vmsd  = &vmstate_scsi_device;
500
}
501

    
502
static TypeInfo scsi_generic_info = {
503
    .name          = "scsi-generic",
504
    .parent        = TYPE_SCSI_DEVICE,
505
    .instance_size = sizeof(SCSIDevice),
506
    .class_init    = scsi_generic_class_initfn,
507
};
508

    
509
static void scsi_generic_register_types(void)
510
{
511
    type_register_static(&scsi_generic_info);
512
}
513

    
514
type_init(scsi_generic_register_types)
515

    
516
#endif /* __linux__ */