Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 251882b7

History | View | Annotate | Download (14.8 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 "block.h"
16
#include "scsi.h"
17

    
18
#ifdef __linux__
19

    
20
//#define DEBUG_SCSI
21

    
22
#ifdef DEBUG_SCSI
23
#define DPRINTF(fmt, ...) \
24
do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
25
#else
26
#define DPRINTF(fmt, ...) do {} while(0)
27
#endif
28

    
29
#define BADF(fmt, ...) \
30
do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
31

    
32
#include <stdio.h>
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <unistd.h>
36
#include <scsi/sg.h>
37
#include "scsi-defs.h"
38

    
39
#define SCSI_SENSE_BUF_SIZE 96
40

    
41
#define SG_ERR_DRIVER_TIMEOUT 0x06
42
#define SG_ERR_DRIVER_SENSE 0x08
43

    
44
#ifndef MAX_UINT
45
#define MAX_UINT ((unsigned int)-1)
46
#endif
47

    
48
typedef struct SCSIGenericState SCSIGenericState;
49

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

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

    
67
static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
68
{
69
    SCSIRequest *req;
70

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

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

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

    
86
/* Helper function for command completion.  */
87
static void scsi_command_complete(void *opaque, int ret)
88
{
89
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
90
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
91
    uint32_t tag;
92
    int status;
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
        status = BUSY << 1;
100
    else {
101
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
102
            status = BUSY << 1;
103
            BADF("Driver Timeout\n");
104
        } else if (r->io_header.status)
105
            status = r->io_header.status;
106
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
107
            status = CHECK_CONDITION << 1;
108
        else
109
            status = GOOD << 1;
110
    }
111
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
112
            r, r->req.tag, status);
113
    tag = r->req.tag;
114
    r->req.bus->complete(r->req.bus, SCSI_REASON_DONE, tag, status);
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->qdev.dinfo->bdrv, 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->qdev.dinfo->bdrv, 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->qdev.dinfo->bdrv, 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.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.dinfo || !s->qdev.dinfo->bdrv) {
467
        qemu_error("scsi-generic: drive property not set\n");
468
        return -1;
469
    }
470

    
471
    /* check we are really using a /dev/sg* file */
472
    if (!bdrv_is_sg(s->qdev.dinfo->bdrv)) {
473
        qemu_error("scsi-generic: not /dev/sg*\n");
474
        return -1;
475
    }
476

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

    
484
    /* get LUN of the /dev/sg? */
485
    if (bdrv_ioctl(s->qdev.dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
486
        qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
487
        return -1;
488
    }
489

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

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

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

    
538
#endif /* __linux__ */