Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ c9f398e5

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 "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

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

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

    
112
    scsi_req_complete(&r->req);
113
    scsi_remove_request(r);
114
}
115

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

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

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

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

    
156
    return 0;
157
}
158

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

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

    
172
    r->len = -1;
173
    r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
174
    if (len == 0)
175
        scsi_command_complete(r, 0);
176
}
177

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

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

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

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

    
215
    ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
216
    if (ret == -1) {
217
        scsi_command_complete(r, -EINVAL);
218
        return;
219
    }
220
}
221

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

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

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

    
240
    scsi_command_complete(r, ret);
241
}
242

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

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

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

    
266
    ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
267
    if (ret == -1) {
268
        scsi_command_complete(r, -EINVAL);
269
        return 1;
270
    }
271

    
272
    return 0;
273
}
274

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

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

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

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

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

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

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

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

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

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

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

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

    
382
    return r->req.cmd.xfer;
383
}
384

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

    
393
    memset(cmd, 0, sizeof(cmd));
394
    memset(buf, 0, sizeof(buf));
395
    cmd[0] = READ_CAPACITY;
396

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

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

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

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

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

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

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

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

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

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

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

    
464
    if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
465
        qemu_error("scsi-generic: drive property not set\n");
466
        return -1;
467
    }
468

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

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

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

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

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

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

    
536
#endif /* __linux__ */