Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 5c6c0e51

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 "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
    scsi_req_dequeue(&r->req);
125
}
126

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

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

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

    
151
    return 0;
152
}
153

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

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

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

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

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

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

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

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

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

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

    
231
    scsi_command_complete(r, ret);
232
}
233

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

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

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

    
255
    return 0;
256
}
257

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

    
263
    return r->buf;
264
}
265

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
427
static void scsi_generic_purge_requests(SCSIGenericState *s)
428
{
429
    SCSIGenericReq *r;
430

    
431
    while (!QTAILQ_EMPTY(&s->qdev.requests)) {
432
        r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
433
        if (r->req.aiocb) {
434
            bdrv_aio_cancel(r->req.aiocb);
435
        }
436
        scsi_req_dequeue(&r->req);
437
        scsi_req_unref(&r->req);
438
    }
439
}
440

    
441
static void scsi_generic_reset(DeviceState *dev)
442
{
443
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
444

    
445
    scsi_generic_purge_requests(s);
446
}
447

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

    
452
    scsi_generic_purge_requests(s);
453
    blockdev_mark_auto_del(s->qdev.conf.bs);
454
}
455

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

    
462
    if (!s->qdev.conf.bs) {
463
        error_report("scsi-generic: drive property not set");
464
        return -1;
465
    }
466
    s->bs = s->qdev.conf.bs;
467

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

    
474
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
475
        error_report("Device doesn't support drive option werror");
476
        return -1;
477
    }
478
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
479
        error_report("Device doesn't support drive option rerror");
480
        return -1;
481
    }
482

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

    
490
    /* get LUN of the /dev/sg? */
491
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
492
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
493
        return -1;
494
    }
495

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

    
522
static SCSIDeviceInfo scsi_generic_info = {
523
    .qdev.name    = "scsi-generic",
524
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
525
    .qdev.size    = sizeof(SCSIGenericState),
526
    .qdev.reset   = scsi_generic_reset,
527
    .init         = scsi_generic_initfn,
528
    .destroy      = scsi_destroy,
529
    .alloc_req    = scsi_new_request,
530
    .free_req     = scsi_free_request,
531
    .send_command = scsi_send_command,
532
    .read_data    = scsi_read_data,
533
    .write_data   = scsi_write_data,
534
    .cancel_io    = scsi_cancel_io,
535
    .get_buf      = scsi_get_buf,
536
    .qdev.props   = (Property[]) {
537
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
538
        DEFINE_PROP_END_OF_LIST(),
539
    },
540
};
541

    
542
static void scsi_generic_register_devices(void)
543
{
544
    scsi_qdev_register(&scsi_generic_info);
545
}
546
device_init(scsi_generic_register_devices)
547

    
548
#endif /* __linux__ */