Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 94d3f98a

History | View | Annotate | Download (14.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 SCSIRequest *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 req;
75
}
76

    
77
static void scsi_free_request(SCSIRequest *req)
78
{
79
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
80

    
81
    qemu_free(r->buf);
82
}
83

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

    
90
    r->req.aiocb = NULL;
91
    s->driver_status = r->io_header.driver_status;
92
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
93
        s->senselen = r->io_header.sb_len_wr;
94

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

    
111
    scsi_req_complete(&r->req);
112
}
113

    
114
/* Cancel a pending data transfer.  */
115
static void scsi_cancel_io(SCSIRequest *req)
116
{
117
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
118

    
119
    DPRINTF("Cancel tag=0x%x\n", req->tag);
120
    if (r->req.aiocb) {
121
        bdrv_aio_cancel(r->req.aiocb);
122
    }
123
    r->req.aiocb = NULL;
124
}
125

    
126
static int execute_command(BlockDriverState *bdrv,
127
                           SCSIGenericReq *r, int direction,
128
                           BlockDriverCompletionFunc *complete)
129
{
130
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
131

    
132
    r->io_header.interface_id = 'S';
133
    r->io_header.dxfer_direction = direction;
134
    r->io_header.dxferp = r->buf;
135
    r->io_header.dxfer_len = r->buflen;
136
    r->io_header.cmdp = r->req.cmd.buf;
137
    r->io_header.cmd_len = r->req.cmd.len;
138
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
139
    r->io_header.sbp = s->sensebuf;
140
    r->io_header.timeout = MAX_UINT;
141
    r->io_header.usr_ptr = r;
142
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
143

    
144
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
145
    if (r->req.aiocb == NULL) {
146
        BADF("execute_command: read failed !\n");
147
        return -1;
148
    }
149

    
150
    return 0;
151
}
152

    
153
static void scsi_read_complete(void * opaque, int ret)
154
{
155
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
156
    int len;
157

    
158
    r->req.aiocb = NULL;
159
    if (ret) {
160
        DPRINTF("IO error ret %d\n", ret);
161
        scsi_command_complete(r, ret);
162
        return;
163
    }
164
    len = r->io_header.dxfer_len - r->io_header.resid;
165
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
166

    
167
    r->len = -1;
168
    if (len == 0) {
169
        scsi_command_complete(r, 0);
170
    } else {
171
        scsi_req_data(&r->req, len);
172
    }
173
}
174

    
175
/* Read more data from scsi device into buffer.  */
176
static void scsi_read_data(SCSIRequest *req)
177
{
178
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
179
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
180
    int ret;
181

    
182
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
183
    if (r->len == -1) {
184
        scsi_command_complete(r, 0);
185
        return;
186
    }
187

    
188
    if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
189
    {
190
        s->senselen = MIN(r->len, s->senselen);
191
        memcpy(r->buf, s->sensebuf, s->senselen);
192
        r->io_header.driver_status = 0;
193
        r->io_header.status = 0;
194
        r->io_header.dxfer_len  = s->senselen;
195
        r->len = -1;
196
        DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
197
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
198
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
199
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
200
        scsi_req_data(&r->req, s->senselen);
201
        return;
202
    }
203

    
204
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
205
    if (ret == -1) {
206
        scsi_command_complete(r, -EINVAL);
207
        return;
208
    }
209
}
210

    
211
static void scsi_write_complete(void * opaque, int ret)
212
{
213
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
214
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
215

    
216
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
217
    r->req.aiocb = NULL;
218
    if (ret) {
219
        DPRINTF("IO error\n");
220
        scsi_command_complete(r, ret);
221
        return;
222
    }
223

    
224
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
225
        s->qdev.type == TYPE_TAPE) {
226
        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
227
        DPRINTF("block size %d\n", s->qdev.blocksize);
228
    }
229

    
230
    scsi_command_complete(r, ret);
231
}
232

    
233
/* Write data to a scsi device.  Returns nonzero on failure.
234
   The transfer may complete asynchronously.  */
235
static int scsi_write_data(SCSIRequest *req)
236
{
237
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
238
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
239
    int ret;
240

    
241
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
242
    if (r->len == 0) {
243
        r->len = r->buflen;
244
        scsi_req_data(&r->req, r->len);
245
        return 0;
246
    }
247

    
248
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
249
    if (ret == -1) {
250
        scsi_command_complete(r, -EINVAL);
251
        return 1;
252
    }
253

    
254
    return 0;
255
}
256

    
257
/* Return a pointer to the data buffer.  */
258
static uint8_t *scsi_get_buf(SCSIRequest *req)
259
{
260
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
261

    
262
    return r->buf;
263
}
264

    
265
static void scsi_req_fixup(SCSIRequest *req)
266
{
267
    switch(req->cmd.buf[0]) {
268
    case WRITE_10:
269
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
270
        break;
271
    case READ_10:
272
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
273
        break;
274
    case REWIND:
275
    case START_STOP:
276
        if (req->dev->type == TYPE_TAPE) {
277
            /* force IMMED, otherwise qemu waits end of command */
278
            req->cmd.buf[1] = 0x01;
279
        }
280
        break;
281
    }
282
}
283

    
284
/* Execute a scsi command.  Returns the length of the data expected by the
285
   command.  This will be Positive for data transfers from the device
286
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
287
   and zero if the command does not transfer any data.  */
288

    
289
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
290
{
291
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
292
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
293
    SCSIBus *bus;
294
    int ret;
295

    
296
    scsi_req_enqueue(req);
297
    if (cmd[0] != REQUEST_SENSE &&
298
        (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
299
        DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
300

    
301
        s->sensebuf[0] = 0x70;
302
        s->sensebuf[1] = 0x00;
303
        s->sensebuf[2] = ILLEGAL_REQUEST;
304
        s->sensebuf[3] = 0x00;
305
        s->sensebuf[4] = 0x00;
306
        s->sensebuf[5] = 0x00;
307
        s->sensebuf[6] = 0x00;
308
        s->senselen = 7;
309
        s->driver_status = SG_ERR_DRIVER_SENSE;
310
        bus = scsi_bus_from_device(&s->qdev);
311
        bus->ops->complete(req, SCSI_REASON_DONE, CHECK_CONDITION);
312
        return 0;
313
    }
314

    
315
    if (-1 == scsi_req_parse(&r->req, cmd)) {
316
        BADF("Unsupported command length, command %x\n", cmd[0]);
317
        scsi_req_dequeue(&r->req);
318
        scsi_req_unref(&r->req);
319
        return 0;
320
    }
321
    scsi_req_fixup(&r->req);
322

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

    
326
#ifdef DEBUG_SCSI
327
    {
328
        int i;
329
        for (i = 1; i < r->req.cmd.len; i++) {
330
            printf(" 0x%02x", cmd[i]);
331
        }
332
        printf("\n");
333
    }
334
#endif
335

    
336
    if (r->req.cmd.xfer == 0) {
337
        if (r->buf != NULL)
338
            qemu_free(r->buf);
339
        r->buflen = 0;
340
        r->buf = NULL;
341
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
342
        if (ret == -1) {
343
            scsi_command_complete(r, -EINVAL);
344
        }
345
        return 0;
346
    }
347

    
348
    if (r->buflen != r->req.cmd.xfer) {
349
        if (r->buf != NULL)
350
            qemu_free(r->buf);
351
        r->buf = qemu_malloc(r->req.cmd.xfer);
352
        r->buflen = r->req.cmd.xfer;
353
    }
354

    
355
    memset(r->buf, 0, r->buflen);
356
    r->len = r->req.cmd.xfer;
357
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
358
        r->len = 0;
359
        return -r->req.cmd.xfer;
360
    } else {
361
        return r->req.cmd.xfer;
362
    }
363
}
364

    
365
static int get_blocksize(BlockDriverState *bdrv)
366
{
367
    uint8_t cmd[10];
368
    uint8_t buf[8];
369
    uint8_t sensebuf[8];
370
    sg_io_hdr_t io_header;
371
    int ret;
372

    
373
    memset(cmd, 0, sizeof(cmd));
374
    memset(buf, 0, sizeof(buf));
375
    cmd[0] = READ_CAPACITY;
376

    
377
    memset(&io_header, 0, sizeof(io_header));
378
    io_header.interface_id = 'S';
379
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
380
    io_header.dxfer_len = sizeof(buf);
381
    io_header.dxferp = buf;
382
    io_header.cmdp = cmd;
383
    io_header.cmd_len = sizeof(cmd);
384
    io_header.mx_sb_len = sizeof(sensebuf);
385
    io_header.sbp = sensebuf;
386
    io_header.timeout = 6000; /* XXX */
387

    
388
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
389
    if (ret < 0)
390
        return -1;
391

    
392
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
393
}
394

    
395
static int get_stream_blocksize(BlockDriverState *bdrv)
396
{
397
    uint8_t cmd[6];
398
    uint8_t buf[12];
399
    uint8_t sensebuf[8];
400
    sg_io_hdr_t io_header;
401
    int ret;
402

    
403
    memset(cmd, 0, sizeof(cmd));
404
    memset(buf, 0, sizeof(buf));
405
    cmd[0] = MODE_SENSE;
406
    cmd[4] = sizeof(buf);
407

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

    
419
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
420
    if (ret < 0)
421
        return -1;
422

    
423
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
424
}
425

    
426
static void scsi_generic_reset(DeviceState *dev)
427
{
428
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
429

    
430
    scsi_device_purge_requests(&s->qdev);
431
}
432

    
433
static void scsi_destroy(SCSIDevice *d)
434
{
435
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
436

    
437
    scsi_device_purge_requests(&s->qdev);
438
    blockdev_mark_auto_del(s->qdev.conf.bs);
439
}
440

    
441
static int scsi_generic_initfn(SCSIDevice *dev)
442
{
443
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
444
    int sg_version;
445
    struct sg_scsi_id scsiid;
446

    
447
    if (!s->qdev.conf.bs) {
448
        error_report("scsi-generic: drive property not set");
449
        return -1;
450
    }
451
    s->bs = s->qdev.conf.bs;
452

    
453
    /* check we are really using a /dev/sg* file */
454
    if (!bdrv_is_sg(s->bs)) {
455
        error_report("scsi-generic: not /dev/sg*");
456
        return -1;
457
    }
458

    
459
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
460
        error_report("Device doesn't support drive option werror");
461
        return -1;
462
    }
463
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
464
        error_report("Device doesn't support drive option rerror");
465
        return -1;
466
    }
467

    
468
    /* check we are using a driver managing SG_IO (version 3 and after */
469
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
470
        sg_version < 30000) {
471
        error_report("scsi-generic: scsi generic interface too old");
472
        return -1;
473
    }
474

    
475
    /* get LUN of the /dev/sg? */
476
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
477
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
478
        return -1;
479
    }
480

    
481
    /* define device state */
482
    s->lun = scsiid.lun;
483
    DPRINTF("LUN %d\n", s->lun);
484
    s->qdev.type = scsiid.scsi_type;
485
    DPRINTF("device type %d\n", s->qdev.type);
486
    if (s->qdev.type == TYPE_TAPE) {
487
        s->qdev.blocksize = get_stream_blocksize(s->bs);
488
        if (s->qdev.blocksize == -1)
489
            s->qdev.blocksize = 0;
490
    } else {
491
        s->qdev.blocksize = get_blocksize(s->bs);
492
        /* removable media returns 0 if not present */
493
        if (s->qdev.blocksize <= 0) {
494
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
495
                s->qdev.blocksize = 2048;
496
            else
497
                s->qdev.blocksize = 512;
498
        }
499
    }
500
    DPRINTF("block size %d\n", s->qdev.blocksize);
501
    s->driver_status = 0;
502
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
503
    bdrv_set_removable(s->bs, 0);
504
    return 0;
505
}
506

    
507
static SCSIDeviceInfo scsi_generic_info = {
508
    .qdev.name    = "scsi-generic",
509
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
510
    .qdev.size    = sizeof(SCSIGenericState),
511
    .qdev.reset   = scsi_generic_reset,
512
    .init         = scsi_generic_initfn,
513
    .destroy      = scsi_destroy,
514
    .alloc_req    = scsi_new_request,
515
    .free_req     = scsi_free_request,
516
    .send_command = scsi_send_command,
517
    .read_data    = scsi_read_data,
518
    .write_data   = scsi_write_data,
519
    .cancel_io    = scsi_cancel_io,
520
    .get_buf      = scsi_get_buf,
521
    .qdev.props   = (Property[]) {
522
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
523
        DEFINE_PROP_END_OF_LIST(),
524
    },
525
};
526

    
527
static void scsi_generic_register_devices(void)
528
{
529
    scsi_qdev_register(&scsi_generic_info);
530
}
531
device_init(scsi_generic_register_devices)
532

    
533
#endif /* __linux__ */