Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ cfdc1bb0

History | View | Annotate | Download (15.5 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 SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
70
{
71
    SCSIRequest *req;
72

    
73
    req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
74
    return DO_UPCAST(SCSIGenericReq, req, req);
75
}
76

    
77
static void scsi_remove_request(SCSIGenericReq *r)
78
{
79
    qemu_free(r->buf);
80
    scsi_req_free(&r->req);
81
}
82

    
83
static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
84
{
85
    return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag));
86
}
87

    
88
/* Helper function for command completion.  */
89
static void scsi_command_complete(void *opaque, int ret)
90
{
91
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
92
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
93

    
94
    s->driver_status = r->io_header.driver_status;
95
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
96
        s->senselen = r->io_header.sb_len_wr;
97

    
98
    if (ret != 0)
99
        r->req.status = BUSY;
100
    else {
101
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
102
            r->req.status = BUSY;
103
            BADF("Driver Timeout\n");
104
        } else if (r->io_header.status)
105
            r->req.status = r->io_header.status;
106
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
107
            r->req.status = CHECK_CONDITION;
108
        else
109
            r->req.status = GOOD;
110
    }
111
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
112
            r, r->req.tag, r->req.status);
113

    
114
    scsi_req_complete(&r->req);
115
    scsi_remove_request(r);
116
}
117

    
118
/* Cancel a pending data transfer.  */
119
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
120
{
121
    DPRINTF("scsi_cancel_io 0x%x\n", tag);
122
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
123
    SCSIGenericReq *r;
124
    DPRINTF("Cancel tag=0x%x\n", tag);
125
    r = scsi_find_request(s, tag);
126
    if (r) {
127
        if (r->req.aiocb)
128
            bdrv_aio_cancel(r->req.aiocb);
129
        r->req.aiocb = NULL;
130
        scsi_remove_request(r);
131
    }
132
}
133

    
134
static int execute_command(BlockDriverState *bdrv,
135
                           SCSIGenericReq *r, int direction,
136
                           BlockDriverCompletionFunc *complete)
137
{
138
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
139

    
140
    r->io_header.interface_id = 'S';
141
    r->io_header.dxfer_direction = direction;
142
    r->io_header.dxferp = r->buf;
143
    r->io_header.dxfer_len = r->buflen;
144
    r->io_header.cmdp = r->req.cmd.buf;
145
    r->io_header.cmd_len = r->req.cmd.len;
146
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
147
    r->io_header.sbp = s->sensebuf;
148
    r->io_header.timeout = MAX_UINT;
149
    r->io_header.usr_ptr = r;
150
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
151

    
152
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
153
    if (r->req.aiocb == NULL) {
154
        BADF("execute_command: read failed !\n");
155
        return -1;
156
    }
157

    
158
    return 0;
159
}
160

    
161
static void scsi_read_complete(void * opaque, int ret)
162
{
163
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
164
    int len;
165

    
166
    if (ret) {
167
        DPRINTF("IO error ret %d\n", ret);
168
        scsi_command_complete(r, ret);
169
        return;
170
    }
171
    len = r->io_header.dxfer_len - r->io_header.resid;
172
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
173

    
174
    r->len = -1;
175
    if (len == 0) {
176
        scsi_command_complete(r, 0);
177
    } else {
178
        scsi_req_data(&r->req, len);
179
    }
180
}
181

    
182
/* Read more data from scsi device into buffer.  */
183
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
184
{
185
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
186
    SCSIGenericReq *r;
187
    int ret;
188

    
189
    DPRINTF("scsi_read_data 0x%x\n", tag);
190
    r = scsi_find_request(s, tag);
191
    if (!r) {
192
        BADF("Bad read tag 0x%x\n", tag);
193
        /* ??? This is the wrong error.  */
194
        scsi_command_complete(r, -EINVAL);
195
        return;
196
    }
197

    
198
    if (r->len == -1) {
199
        scsi_command_complete(r, 0);
200
        return;
201
    }
202

    
203
    if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
204
    {
205
        s->senselen = MIN(r->len, s->senselen);
206
        memcpy(r->buf, s->sensebuf, s->senselen);
207
        r->io_header.driver_status = 0;
208
        r->io_header.status = 0;
209
        r->io_header.dxfer_len  = s->senselen;
210
        r->len = -1;
211
        DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
212
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
213
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
214
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
215
        scsi_req_data(&r->req, s->senselen);
216
        return;
217
    }
218

    
219
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
220
    if (ret == -1) {
221
        scsi_command_complete(r, -EINVAL);
222
        return;
223
    }
224
}
225

    
226
static void scsi_write_complete(void * opaque, int ret)
227
{
228
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
229
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
230

    
231
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
232
    if (ret) {
233
        DPRINTF("IO error\n");
234
        scsi_command_complete(r, ret);
235
        return;
236
    }
237

    
238
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
239
        s->qdev.type == TYPE_TAPE) {
240
        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
241
        DPRINTF("block size %d\n", s->qdev.blocksize);
242
    }
243

    
244
    scsi_command_complete(r, ret);
245
}
246

    
247
/* Write data to a scsi device.  Returns nonzero on failure.
248
   The transfer may complete asynchronously.  */
249
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
250
{
251
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
252
    SCSIGenericReq *r;
253
    int ret;
254

    
255
    DPRINTF("scsi_write_data 0x%x\n", tag);
256
    r = scsi_find_request(s, tag);
257
    if (!r) {
258
        BADF("Bad write tag 0x%x\n", tag);
259
        /* ??? This is the wrong error.  */
260
        scsi_command_complete(r, -EINVAL);
261
        return 0;
262
    }
263

    
264
    if (r->len == 0) {
265
        r->len = r->buflen;
266
        scsi_req_data(&r->req, r->len);
267
        return 0;
268
    }
269

    
270
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
271
    if (ret == -1) {
272
        scsi_command_complete(r, -EINVAL);
273
        return 1;
274
    }
275

    
276
    return 0;
277
}
278

    
279
/* Return a pointer to the data buffer.  */
280
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
281
{
282
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
283
    SCSIGenericReq *r;
284
    r = scsi_find_request(s, tag);
285
    if (!r) {
286
        BADF("Bad buffer tag 0x%x\n", tag);
287
        return NULL;
288
    }
289
    return r->buf;
290
}
291

    
292
static void scsi_req_fixup(SCSIRequest *req)
293
{
294
    switch(req->cmd.buf[0]) {
295
    case WRITE_10:
296
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
297
        break;
298
    case READ_10:
299
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
300
        break;
301
    case REWIND:
302
    case START_STOP:
303
        if (req->dev->type == TYPE_TAPE) {
304
            /* force IMMED, otherwise qemu waits end of command */
305
            req->cmd.buf[1] = 0x01;
306
        }
307
        break;
308
    }
309
}
310

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

    
316
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
317
                                 uint8_t *cmd, int lun)
318
{
319
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
320
    SCSIGenericReq *r;
321
    SCSIBus *bus;
322
    int ret;
323

    
324
    if (cmd[0] != REQUEST_SENSE &&
325
        (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
326
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
327

    
328
        s->sensebuf[0] = 0x70;
329
        s->sensebuf[1] = 0x00;
330
        s->sensebuf[2] = ILLEGAL_REQUEST;
331
        s->sensebuf[3] = 0x00;
332
        s->sensebuf[4] = 0x00;
333
        s->sensebuf[5] = 0x00;
334
        s->sensebuf[6] = 0x00;
335
        s->senselen = 7;
336
        s->driver_status = SG_ERR_DRIVER_SENSE;
337
        bus = scsi_bus_from_device(d);
338
        bus->ops->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
339
        return 0;
340
    }
341

    
342
    r = scsi_find_request(s, tag);
343
    if (r) {
344
        BADF("Tag 0x%x already in use %p\n", tag, r);
345
        scsi_cancel_io(d, tag);
346
    }
347
    r = scsi_new_request(d, tag, lun);
348

    
349
    if (-1 == scsi_req_parse(&r->req, cmd)) {
350
        BADF("Unsupported command length, command %x\n", cmd[0]);
351
        scsi_remove_request(r);
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 == -1) {
376
            scsi_command_complete(r, -EINVAL);
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
    }
395

    
396
    return r->req.cmd.xfer;
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_purge_requests(SCSIGenericState *s)
461
{
462
    SCSIGenericReq *r;
463

    
464
    while (!QTAILQ_EMPTY(&s->qdev.requests)) {
465
        r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
466
        if (r->req.aiocb) {
467
            bdrv_aio_cancel(r->req.aiocb);
468
        }
469
        scsi_remove_request(r);
470
    }
471
}
472

    
473
static void scsi_generic_reset(DeviceState *dev)
474
{
475
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
476

    
477
    scsi_generic_purge_requests(s);
478
}
479

    
480
static void scsi_destroy(SCSIDevice *d)
481
{
482
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
483

    
484
    scsi_generic_purge_requests(s);
485
    blockdev_mark_auto_del(s->qdev.conf.bs);
486
}
487

    
488
static int scsi_generic_initfn(SCSIDevice *dev)
489
{
490
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
491
    int sg_version;
492
    struct sg_scsi_id scsiid;
493

    
494
    if (!s->qdev.conf.bs) {
495
        error_report("scsi-generic: drive property not set");
496
        return -1;
497
    }
498
    s->bs = s->qdev.conf.bs;
499

    
500
    /* check we are really using a /dev/sg* file */
501
    if (!bdrv_is_sg(s->bs)) {
502
        error_report("scsi-generic: not /dev/sg*");
503
        return -1;
504
    }
505

    
506
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
507
        error_report("Device doesn't support drive option werror");
508
        return -1;
509
    }
510
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
511
        error_report("Device doesn't support drive option rerror");
512
        return -1;
513
    }
514

    
515
    /* check we are using a driver managing SG_IO (version 3 and after */
516
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
517
        sg_version < 30000) {
518
        error_report("scsi-generic: scsi generic interface too old");
519
        return -1;
520
    }
521

    
522
    /* get LUN of the /dev/sg? */
523
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
524
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
525
        return -1;
526
    }
527

    
528
    /* define device state */
529
    s->lun = scsiid.lun;
530
    DPRINTF("LUN %d\n", s->lun);
531
    s->qdev.type = scsiid.scsi_type;
532
    DPRINTF("device type %d\n", s->qdev.type);
533
    if (s->qdev.type == TYPE_TAPE) {
534
        s->qdev.blocksize = get_stream_blocksize(s->bs);
535
        if (s->qdev.blocksize == -1)
536
            s->qdev.blocksize = 0;
537
    } else {
538
        s->qdev.blocksize = get_blocksize(s->bs);
539
        /* removable media returns 0 if not present */
540
        if (s->qdev.blocksize <= 0) {
541
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
542
                s->qdev.blocksize = 2048;
543
            else
544
                s->qdev.blocksize = 512;
545
        }
546
    }
547
    DPRINTF("block size %d\n", s->qdev.blocksize);
548
    s->driver_status = 0;
549
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
550
    bdrv_set_removable(s->bs, 0);
551
    return 0;
552
}
553

    
554
static SCSIDeviceInfo scsi_generic_info = {
555
    .qdev.name    = "scsi-generic",
556
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
557
    .qdev.size    = sizeof(SCSIGenericState),
558
    .qdev.reset   = scsi_generic_reset,
559
    .init         = scsi_generic_initfn,
560
    .destroy      = scsi_destroy,
561
    .send_command = scsi_send_command,
562
    .read_data    = scsi_read_data,
563
    .write_data   = scsi_write_data,
564
    .cancel_io    = scsi_cancel_io,
565
    .get_buf      = scsi_get_buf,
566
    .qdev.props   = (Property[]) {
567
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
568
        DEFINE_PROP_END_OF_LIST(),
569
    },
570
};
571

    
572
static void scsi_generic_register_devices(void)
573
{
574
    scsi_qdev_register(&scsi_generic_info);
575
}
576
device_init(scsi_generic_register_devices)
577

    
578
#endif /* __linux__ */