Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 1ecda02b

History | View | Annotate | Download (14.7 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 "block.h"
17
#include "scsi.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 << 1;
100
    else {
101
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
102
            r->req.status = BUSY << 1;
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 << 1;
108
        else
109
            r->req.status = GOOD << 1;
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\n");
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
    r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
176
    if (len == 0)
177
        scsi_command_complete(r, 0);
178
}
179

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

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

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

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

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

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

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

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

    
242
    scsi_command_complete(r, ret);
243
}
244

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

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

    
262
    if (r->len == 0) {
263
        r->len = r->buflen;
264
        r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
265
        return 0;
266
    }
267

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

    
274
    return 0;
275
}
276

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

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

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

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

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

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

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

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

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

    
357
    if (r->req.cmd.xfer == 0) {
358
        if (r->buf != NULL)
359
            qemu_free(r->buf);
360
        r->buflen = 0;
361
        r->buf = NULL;
362
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
363
        if (ret == -1) {
364
            scsi_command_complete(r, -EINVAL);
365
            return 0;
366
        }
367
        return 0;
368
    }
369

    
370
    if (r->buflen != r->req.cmd.xfer) {
371
        if (r->buf != NULL)
372
            qemu_free(r->buf);
373
        r->buf = qemu_malloc(r->req.cmd.xfer);
374
        r->buflen = r->req.cmd.xfer;
375
    }
376

    
377
    memset(r->buf, 0, r->buflen);
378
    r->len = r->req.cmd.xfer;
379
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
380
        r->len = 0;
381
        return -r->req.cmd.xfer;
382
    }
383

    
384
    return r->req.cmd.xfer;
385
}
386

    
387
static int get_blocksize(BlockDriverState *bdrv)
388
{
389
    uint8_t cmd[10];
390
    uint8_t buf[8];
391
    uint8_t sensebuf[8];
392
    sg_io_hdr_t io_header;
393
    int ret;
394

    
395
    memset(cmd, 0, sizeof(cmd));
396
    memset(buf, 0, sizeof(buf));
397
    cmd[0] = READ_CAPACITY;
398

    
399
    memset(&io_header, 0, sizeof(io_header));
400
    io_header.interface_id = 'S';
401
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
402
    io_header.dxfer_len = sizeof(buf);
403
    io_header.dxferp = buf;
404
    io_header.cmdp = cmd;
405
    io_header.cmd_len = sizeof(cmd);
406
    io_header.mx_sb_len = sizeof(sensebuf);
407
    io_header.sbp = sensebuf;
408
    io_header.timeout = 6000; /* XXX */
409

    
410
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
411
    if (ret < 0)
412
        return -1;
413

    
414
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
415
}
416

    
417
static int get_stream_blocksize(BlockDriverState *bdrv)
418
{
419
    uint8_t cmd[6];
420
    uint8_t buf[12];
421
    uint8_t sensebuf[8];
422
    sg_io_hdr_t io_header;
423
    int ret;
424

    
425
    memset(cmd, 0, sizeof(cmd));
426
    memset(buf, 0, sizeof(buf));
427
    cmd[0] = MODE_SENSE;
428
    cmd[4] = sizeof(buf);
429

    
430
    memset(&io_header, 0, sizeof(io_header));
431
    io_header.interface_id = 'S';
432
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
433
    io_header.dxfer_len = sizeof(buf);
434
    io_header.dxferp = buf;
435
    io_header.cmdp = cmd;
436
    io_header.cmd_len = sizeof(cmd);
437
    io_header.mx_sb_len = sizeof(sensebuf);
438
    io_header.sbp = sensebuf;
439
    io_header.timeout = 6000; /* XXX */
440

    
441
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
442
    if (ret < 0)
443
        return -1;
444

    
445
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
446
}
447

    
448
static void scsi_destroy(SCSIDevice *d)
449
{
450
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
451
    SCSIGenericReq *r;
452

    
453
    while (!QTAILQ_EMPTY(&s->qdev.requests)) {
454
        r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
455
        scsi_remove_request(r);
456
    }
457
    drive_uninit(s->qdev.conf.dinfo);
458
}
459

    
460
static int scsi_generic_initfn(SCSIDevice *dev)
461
{
462
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
463
    int sg_version;
464
    struct sg_scsi_id scsiid;
465

    
466
    if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
467
        error_report("scsi-generic: drive property not set");
468
        return -1;
469
    }
470
    s->bs = s->qdev.conf.dinfo->bdrv;
471

    
472
    /* check we are really using a /dev/sg* file */
473
    if (!bdrv_is_sg(s->bs)) {
474
        error_report("scsi-generic: not /dev/sg*");
475
        return -1;
476
    }
477

    
478
    /* check we are using a driver managing SG_IO (version 3 and after */
479
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
480
        sg_version < 30000) {
481
        error_report("scsi-generic: scsi generic interface too old");
482
        return -1;
483
    }
484

    
485
    /* get LUN of the /dev/sg? */
486
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
487
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
488
        return -1;
489
    }
490

    
491
    /* define device state */
492
    s->lun = scsiid.lun;
493
    DPRINTF("LUN %d\n", s->lun);
494
    s->qdev.type = scsiid.scsi_type;
495
    DPRINTF("device type %d\n", s->qdev.type);
496
    if (s->qdev.type == TYPE_TAPE) {
497
        s->qdev.blocksize = get_stream_blocksize(s->bs);
498
        if (s->qdev.blocksize == -1)
499
            s->qdev.blocksize = 0;
500
    } else {
501
        s->qdev.blocksize = get_blocksize(s->bs);
502
        /* removable media returns 0 if not present */
503
        if (s->qdev.blocksize <= 0) {
504
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
505
                s->qdev.blocksize = 2048;
506
            else
507
                s->qdev.blocksize = 512;
508
        }
509
    }
510
    DPRINTF("block size %d\n", s->qdev.blocksize);
511
    s->driver_status = 0;
512
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
513
    return 0;
514
}
515

    
516
static SCSIDeviceInfo scsi_generic_info = {
517
    .qdev.name    = "scsi-generic",
518
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
519
    .qdev.size    = sizeof(SCSIGenericState),
520
    .init         = scsi_generic_initfn,
521
    .destroy      = scsi_destroy,
522
    .send_command = scsi_send_command,
523
    .read_data    = scsi_read_data,
524
    .write_data   = scsi_write_data,
525
    .cancel_io    = scsi_cancel_io,
526
    .get_buf      = scsi_get_buf,
527
    .qdev.props   = (Property[]) {
528
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
529
        DEFINE_PROP_END_OF_LIST(),
530
    },
531
};
532

    
533
static void scsi_generic_register_devices(void)
534
{
535
    scsi_qdev_register(&scsi_generic_info);
536
}
537
device_init(scsi_generic_register_devices)
538

    
539
#endif /* __linux__ */