Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ c557e889

History | View | Annotate | Download (14.4 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_reset(DeviceState *dev)
428
{
429
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
430

    
431
    scsi_device_purge_requests(&s->qdev);
432
}
433

    
434
static void scsi_destroy(SCSIDevice *d)
435
{
436
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
437

    
438
    scsi_device_purge_requests(&s->qdev);
439
    blockdev_mark_auto_del(s->qdev.conf.bs);
440
}
441

    
442
static int scsi_generic_initfn(SCSIDevice *dev)
443
{
444
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
445
    int sg_version;
446
    struct sg_scsi_id scsiid;
447

    
448
    if (!s->qdev.conf.bs) {
449
        error_report("scsi-generic: drive property not set");
450
        return -1;
451
    }
452
    s->bs = s->qdev.conf.bs;
453

    
454
    /* check we are really using a /dev/sg* file */
455
    if (!bdrv_is_sg(s->bs)) {
456
        error_report("scsi-generic: not /dev/sg*");
457
        return -1;
458
    }
459

    
460
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
461
        error_report("Device doesn't support drive option werror");
462
        return -1;
463
    }
464
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
465
        error_report("Device doesn't support drive option rerror");
466
        return -1;
467
    }
468

    
469
    /* check we are using a driver managing SG_IO (version 3 and after */
470
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
471
        sg_version < 30000) {
472
        error_report("scsi-generic: scsi generic interface too old");
473
        return -1;
474
    }
475

    
476
    /* get LUN of the /dev/sg? */
477
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
478
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
479
        return -1;
480
    }
481

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

    
508
static SCSIDeviceInfo scsi_generic_info = {
509
    .qdev.name    = "scsi-generic",
510
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
511
    .qdev.size    = sizeof(SCSIGenericState),
512
    .qdev.reset   = scsi_generic_reset,
513
    .init         = scsi_generic_initfn,
514
    .destroy      = scsi_destroy,
515
    .alloc_req    = scsi_new_request,
516
    .free_req     = scsi_free_request,
517
    .send_command = scsi_send_command,
518
    .read_data    = scsi_read_data,
519
    .write_data   = scsi_write_data,
520
    .cancel_io    = scsi_cancel_io,
521
    .get_buf      = scsi_get_buf,
522
    .qdev.props   = (Property[]) {
523
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
524
        DEFINE_PROP_END_OF_LIST(),
525
    },
526
};
527

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

    
534
#endif /* __linux__ */