Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 74382217

History | View | Annotate | Download (15.4 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 licenced under the LGPL.
11
 *
12
 */
13

    
14
#include "qemu-common.h"
15
#include "qemu-error.h"
16
#include "scsi.h"
17
#include "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
#ifndef MAX_UINT
46
#define MAX_UINT ((unsigned int)-1)
47
#endif
48

    
49
typedef struct SCSIGenericState SCSIGenericState;
50

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

    
59
struct SCSIGenericState
60
{
61
    SCSIDevice qdev;
62
    BlockDriverState *bs;
63
    int lun;
64
    int driver_status;
65
    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
66
    uint8_t senselen;
67
};
68

    
69
static void scsi_set_sense(SCSIGenericState *s, SCSISense sense)
70
{
71
    s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0);
72
    s->driver_status = SG_ERR_DRIVER_SENSE;
73
}
74

    
75
static void scsi_clear_sense(SCSIGenericState *s)
76
{
77
    memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE);
78
    s->senselen = 0;
79
    s->driver_status = 0;
80
}
81

    
82
static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
83
{
84
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
85
    int size = SCSI_SENSE_BUF_SIZE;
86

    
87
    if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) {
88
        size = scsi_build_sense(SENSE_CODE(NO_SENSE), s->sensebuf,
89
                                SCSI_SENSE_BUF_SIZE, 0);
90
    }
91
    if (size > len) {
92
        size = len;
93
    }
94
    memcpy(outbuf, s->sensebuf, size);
95

    
96
    return size;
97
}
98

    
99
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
100
{
101
    SCSIRequest *req;
102

    
103
    req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
104
    return req;
105
}
106

    
107
static void scsi_free_request(SCSIRequest *req)
108
{
109
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
110

    
111
    qemu_free(r->buf);
112
}
113

    
114
/* Helper function for command completion.  */
115
static void scsi_command_complete(void *opaque, int ret)
116
{
117
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
118
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
119

    
120
    r->req.aiocb = NULL;
121
    s->driver_status = r->io_header.driver_status;
122
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
123
        s->senselen = r->io_header.sb_len_wr;
124

    
125
    if (ret != 0) {
126
        switch (ret) {
127
        case -EINVAL:
128
            r->req.status = CHECK_CONDITION;
129
            scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
130
            break;
131
        case -ENOMEM:
132
            r->req.status = CHECK_CONDITION;
133
            scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
134
            break;
135
        default:
136
            r->req.status = CHECK_CONDITION;
137
            scsi_set_sense(s, SENSE_CODE(IO_ERROR));
138
            break;
139
        }
140
    } else {
141
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
142
            r->req.status = BUSY;
143
            BADF("Driver Timeout\n");
144
        } else if (r->io_header.status)
145
            r->req.status = r->io_header.status;
146
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
147
            r->req.status = CHECK_CONDITION;
148
        else
149
            r->req.status = GOOD;
150
    }
151
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
152
            r, r->req.tag, r->req.status);
153

    
154
    scsi_req_complete(&r->req);
155
}
156

    
157
/* Cancel a pending data transfer.  */
158
static void scsi_cancel_io(SCSIRequest *req)
159
{
160
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
161

    
162
    DPRINTF("Cancel tag=0x%x\n", req->tag);
163
    if (r->req.aiocb) {
164
        bdrv_aio_cancel(r->req.aiocb);
165
    }
166
    r->req.aiocb = NULL;
167
}
168

    
169
static int execute_command(BlockDriverState *bdrv,
170
                           SCSIGenericReq *r, int direction,
171
                           BlockDriverCompletionFunc *complete)
172
{
173
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
174

    
175
    r->io_header.interface_id = 'S';
176
    r->io_header.dxfer_direction = direction;
177
    r->io_header.dxferp = r->buf;
178
    r->io_header.dxfer_len = r->buflen;
179
    r->io_header.cmdp = r->req.cmd.buf;
180
    r->io_header.cmd_len = r->req.cmd.len;
181
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
182
    r->io_header.sbp = s->sensebuf;
183
    r->io_header.timeout = MAX_UINT;
184
    r->io_header.usr_ptr = r;
185
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
186

    
187
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
188
    if (r->req.aiocb == NULL) {
189
        BADF("execute_command: read failed !\n");
190
        return -ENOMEM;
191
    }
192

    
193
    return 0;
194
}
195

    
196
static void scsi_read_complete(void * opaque, int ret)
197
{
198
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
199
    int len;
200

    
201
    r->req.aiocb = NULL;
202
    if (ret) {
203
        DPRINTF("IO error ret %d\n", ret);
204
        scsi_command_complete(r, ret);
205
        return;
206
    }
207
    len = r->io_header.dxfer_len - r->io_header.resid;
208
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
209

    
210
    r->len = -1;
211
    if (len == 0) {
212
        scsi_command_complete(r, 0);
213
    } else {
214
        scsi_req_data(&r->req, len);
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
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
223
    int ret;
224

    
225
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
226
    if (r->len == -1) {
227
        scsi_command_complete(r, 0);
228
        return;
229
    }
230

    
231
    if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
232
    {
233
        s->senselen = MIN(r->len, s->senselen);
234
        memcpy(r->buf, s->sensebuf, s->senselen);
235
        r->io_header.driver_status = 0;
236
        r->io_header.status = 0;
237
        r->io_header.dxfer_len  = s->senselen;
238
        r->len = -1;
239
        DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
240
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
241
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
242
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
243
        scsi_req_data(&r->req, s->senselen);
244
        /* Clear sensebuf after REQUEST_SENSE */
245
        scsi_clear_sense(s);
246
        return;
247
    }
248

    
249
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
250
    if (ret < 0) {
251
        scsi_command_complete(r, ret);
252
        return;
253
    }
254
}
255

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

    
261
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
262
    r->req.aiocb = NULL;
263
    if (ret) {
264
        DPRINTF("IO error\n");
265
        scsi_command_complete(r, ret);
266
        return;
267
    }
268

    
269
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
270
        s->qdev.type == TYPE_TAPE) {
271
        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
272
        DPRINTF("block size %d\n", s->qdev.blocksize);
273
    }
274

    
275
    scsi_command_complete(r, ret);
276
}
277

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

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

    
293
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
294
    if (ret < 0) {
295
        scsi_command_complete(r, ret);
296
        return 1;
297
    }
298

    
299
    return 0;
300
}
301

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

    
307
    return r->buf;
308
}
309

    
310
static void scsi_req_fixup(SCSIRequest *req)
311
{
312
    switch(req->cmd.buf[0]) {
313
    case WRITE_10:
314
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
315
        break;
316
    case READ_10:
317
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
318
        break;
319
    case REWIND:
320
    case START_STOP:
321
        if (req->dev->type == TYPE_TAPE) {
322
            /* force IMMED, otherwise qemu waits end of command */
323
            req->cmd.buf[1] = 0x01;
324
        }
325
        break;
326
    }
327
}
328

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

    
334
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
335
{
336
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
337
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
338
    int ret;
339

    
340
    if (cmd[0] != REQUEST_SENSE &&
341
        (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
342
        DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
343
        scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
344
        r->req.status = CHECK_CONDITION;
345
        scsi_req_complete(&r->req);
346
        return 0;
347
    }
348

    
349
    if (-1 == scsi_req_parse(&r->req, cmd)) {
350
        BADF("Unsupported command length, command %x\n", cmd[0]);
351
        scsi_command_complete(r, -EINVAL);
352
        return 0;
353
    }
354
    scsi_req_fixup(&r->req);
355

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

    
359
#ifdef DEBUG_SCSI
360
    {
361
        int i;
362
        for (i = 1; i < r->req.cmd.len; i++) {
363
            printf(" 0x%02x", cmd[i]);
364
        }
365
        printf("\n");
366
    }
367
#endif
368

    
369
    if (r->req.cmd.xfer == 0) {
370
        if (r->buf != NULL)
371
            qemu_free(r->buf);
372
        r->buflen = 0;
373
        r->buf = NULL;
374
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
375
        if (ret < 0) {
376
            scsi_command_complete(r, ret);
377
            return 0;
378
        }
379
        return 0;
380
    }
381

    
382
    if (r->buflen != r->req.cmd.xfer) {
383
        if (r->buf != NULL)
384
            qemu_free(r->buf);
385
        r->buf = qemu_malloc(r->req.cmd.xfer);
386
        r->buflen = r->req.cmd.xfer;
387
    }
388

    
389
    memset(r->buf, 0, r->buflen);
390
    r->len = r->req.cmd.xfer;
391
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
392
        r->len = 0;
393
        return -r->req.cmd.xfer;
394
    } else {
395
        return r->req.cmd.xfer;
396
    }
397
}
398

    
399
static int get_blocksize(BlockDriverState *bdrv)
400
{
401
    uint8_t cmd[10];
402
    uint8_t buf[8];
403
    uint8_t sensebuf[8];
404
    sg_io_hdr_t io_header;
405
    int ret;
406

    
407
    memset(cmd, 0, sizeof(cmd));
408
    memset(buf, 0, sizeof(buf));
409
    cmd[0] = READ_CAPACITY;
410

    
411
    memset(&io_header, 0, sizeof(io_header));
412
    io_header.interface_id = 'S';
413
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
414
    io_header.dxfer_len = sizeof(buf);
415
    io_header.dxferp = buf;
416
    io_header.cmdp = cmd;
417
    io_header.cmd_len = sizeof(cmd);
418
    io_header.mx_sb_len = sizeof(sensebuf);
419
    io_header.sbp = sensebuf;
420
    io_header.timeout = 6000; /* XXX */
421

    
422
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
423
    if (ret < 0)
424
        return -1;
425

    
426
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
427
}
428

    
429
static int get_stream_blocksize(BlockDriverState *bdrv)
430
{
431
    uint8_t cmd[6];
432
    uint8_t buf[12];
433
    uint8_t sensebuf[8];
434
    sg_io_hdr_t io_header;
435
    int ret;
436

    
437
    memset(cmd, 0, sizeof(cmd));
438
    memset(buf, 0, sizeof(buf));
439
    cmd[0] = MODE_SENSE;
440
    cmd[4] = sizeof(buf);
441

    
442
    memset(&io_header, 0, sizeof(io_header));
443
    io_header.interface_id = 'S';
444
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
445
    io_header.dxfer_len = sizeof(buf);
446
    io_header.dxferp = buf;
447
    io_header.cmdp = cmd;
448
    io_header.cmd_len = sizeof(cmd);
449
    io_header.mx_sb_len = sizeof(sensebuf);
450
    io_header.sbp = sensebuf;
451
    io_header.timeout = 6000; /* XXX */
452

    
453
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
454
    if (ret < 0)
455
        return -1;
456

    
457
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
458
}
459

    
460
static void scsi_generic_reset(DeviceState *dev)
461
{
462
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
463

    
464
    scsi_device_purge_requests(&s->qdev);
465
}
466

    
467
static void scsi_destroy(SCSIDevice *d)
468
{
469
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
470

    
471
    scsi_device_purge_requests(&s->qdev);
472
    blockdev_mark_auto_del(s->qdev.conf.bs);
473
}
474

    
475
static int scsi_generic_initfn(SCSIDevice *dev)
476
{
477
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
478
    int sg_version;
479
    struct sg_scsi_id scsiid;
480

    
481
    if (!s->qdev.conf.bs) {
482
        error_report("scsi-generic: drive property not set");
483
        return -1;
484
    }
485
    s->bs = s->qdev.conf.bs;
486

    
487
    /* check we are really using a /dev/sg* file */
488
    if (!bdrv_is_sg(s->bs)) {
489
        error_report("scsi-generic: not /dev/sg*");
490
        return -1;
491
    }
492

    
493
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
494
        error_report("Device doesn't support drive option werror");
495
        return -1;
496
    }
497
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
498
        error_report("Device doesn't support drive option rerror");
499
        return -1;
500
    }
501

    
502
    /* check we are using a driver managing SG_IO (version 3 and after */
503
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
504
        sg_version < 30000) {
505
        error_report("scsi-generic: scsi generic interface too old");
506
        return -1;
507
    }
508

    
509
    /* get LUN of the /dev/sg? */
510
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
511
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
512
        return -1;
513
    }
514

    
515
    /* define device state */
516
    s->lun = scsiid.lun;
517
    DPRINTF("LUN %d\n", s->lun);
518
    s->qdev.type = scsiid.scsi_type;
519
    DPRINTF("device type %d\n", s->qdev.type);
520
    if (s->qdev.type == TYPE_TAPE) {
521
        s->qdev.blocksize = get_stream_blocksize(s->bs);
522
        if (s->qdev.blocksize == -1)
523
            s->qdev.blocksize = 0;
524
    } else {
525
        s->qdev.blocksize = get_blocksize(s->bs);
526
        /* removable media returns 0 if not present */
527
        if (s->qdev.blocksize <= 0) {
528
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
529
                s->qdev.blocksize = 2048;
530
            else
531
                s->qdev.blocksize = 512;
532
        }
533
    }
534
    DPRINTF("block size %d\n", s->qdev.blocksize);
535
    s->driver_status = 0;
536
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
537
    bdrv_set_removable(s->bs, 0);
538
    return 0;
539
}
540

    
541
static SCSIDeviceInfo scsi_generic_info = {
542
    .qdev.name    = "scsi-generic",
543
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
544
    .qdev.size    = sizeof(SCSIGenericState),
545
    .qdev.reset   = scsi_generic_reset,
546
    .init         = scsi_generic_initfn,
547
    .destroy      = scsi_destroy,
548
    .alloc_req    = scsi_new_request,
549
    .free_req     = scsi_free_request,
550
    .send_command = scsi_send_command,
551
    .read_data    = scsi_read_data,
552
    .write_data   = scsi_write_data,
553
    .cancel_io    = scsi_cancel_io,
554
    .get_buf      = scsi_get_buf,
555
    .get_sense    = scsi_get_sense,
556
    .qdev.props   = (Property[]) {
557
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
558
        DEFINE_PROP_END_OF_LIST(),
559
    },
560
};
561

    
562
static void scsi_generic_register_devices(void)
563
{
564
    scsi_qdev_register(&scsi_generic_info);
565
}
566
device_init(scsi_generic_register_devices)
567

    
568
#endif /* __linux__ */