Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 14bafc54

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 "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
    BlockDriverState *bs;
62
    int lun;
63
    int driver_status;
64
    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
65
    uint8_t senselen;
66
};
67

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

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

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

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

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

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

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

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

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

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

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

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

    
157
    return 0;
158
}
159

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

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

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

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

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

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

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

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

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

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

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

    
241
    scsi_command_complete(r, ret);
242
}
243

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

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

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

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

    
273
    return 0;
274
}
275

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
484
    /* get LUN of the /dev/sg? */
485
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
486
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
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->bs);
497
        if (s->qdev.blocksize == -1)
498
            s->qdev.blocksize = 0;
499
    } else {
500
        s->qdev.blocksize = get_blocksize(s->bs);
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_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
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__ */