Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 4b8f1c88

History | View | Annotate | Download (14.1 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 licensed 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
#define SG_ERR_DID_OK          0x00
46
#define SG_ERR_DID_NO_CONNECT  0x01
47
#define SG_ERR_DID_BUS_BUSY    0x02
48
#define SG_ERR_DID_TIME_OUT    0x03
49

    
50
#ifndef MAX_UINT
51
#define MAX_UINT ((unsigned int)-1)
52
#endif
53

    
54
typedef struct SCSIGenericReq {
55
    SCSIRequest req;
56
    uint8_t *buf;
57
    int buflen;
58
    int len;
59
    sg_io_hdr_t io_header;
60
} SCSIGenericReq;
61

    
62
static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
63
{
64
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
65

    
66
    qemu_put_sbe32s(f, &r->buflen);
67
    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
68
        assert(!r->req.sg);
69
        qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
70
    }
71
}
72

    
73
static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
74
{
75
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
76

    
77
    qemu_get_sbe32s(f, &r->buflen);
78
    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
79
        assert(!r->req.sg);
80
        qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
81
    }
82
}
83

    
84
static void scsi_free_request(SCSIRequest *req)
85
{
86
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
87

    
88
    g_free(r->buf);
89
}
90

    
91
/* Helper function for command completion.  */
92
static void scsi_command_complete(void *opaque, int ret)
93
{
94
    int status;
95
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
96

    
97
    r->req.aiocb = NULL;
98
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
99
        r->req.sense_len = r->io_header.sb_len_wr;
100
    }
101

    
102
    if (ret != 0) {
103
        switch (ret) {
104
        case -EDOM:
105
            status = TASK_SET_FULL;
106
            break;
107
        case -ENOMEM:
108
            status = CHECK_CONDITION;
109
            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
110
            break;
111
        default:
112
            status = CHECK_CONDITION;
113
            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
114
            break;
115
        }
116
    } else {
117
        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
118
            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
119
            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
120
            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
121
            status = BUSY;
122
            BADF("Driver Timeout\n");
123
        } else if (r->io_header.host_status) {
124
            status = CHECK_CONDITION;
125
            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
126
        } else if (r->io_header.status) {
127
            status = r->io_header.status;
128
        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
129
            status = CHECK_CONDITION;
130
        } else {
131
            status = GOOD;
132
        }
133
    }
134
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135
            r, r->req.tag, status);
136

    
137
    scsi_req_complete(&r->req, status);
138
    if (!r->req.io_canceled) {
139
        scsi_req_unref(&r->req);
140
    }
141
}
142

    
143
/* Cancel a pending data transfer.  */
144
static void scsi_cancel_io(SCSIRequest *req)
145
{
146
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
147

    
148
    DPRINTF("Cancel tag=0x%x\n", req->tag);
149
    if (r->req.aiocb) {
150
        bdrv_aio_cancel(r->req.aiocb);
151

    
152
        /* This reference was left in by scsi_*_data.  We take ownership of
153
         * it independent of whether bdrv_aio_cancel completes the request
154
         * or not.  */
155
        scsi_req_unref(&r->req);
156
    }
157
    r->req.aiocb = NULL;
158
}
159

    
160
static int execute_command(BlockDriverState *bdrv,
161
                           SCSIGenericReq *r, int direction,
162
                           BlockDriverCompletionFunc *complete)
163
{
164
    r->io_header.interface_id = 'S';
165
    r->io_header.dxfer_direction = direction;
166
    r->io_header.dxferp = r->buf;
167
    r->io_header.dxfer_len = r->buflen;
168
    r->io_header.cmdp = r->req.cmd.buf;
169
    r->io_header.cmd_len = r->req.cmd.len;
170
    r->io_header.mx_sb_len = sizeof(r->req.sense);
171
    r->io_header.sbp = r->req.sense;
172
    r->io_header.timeout = MAX_UINT;
173
    r->io_header.usr_ptr = r;
174
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
175

    
176
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
177

    
178
    return 0;
179
}
180

    
181
static void scsi_read_complete(void * opaque, int ret)
182
{
183
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
184
    SCSIDevice *s = r->req.dev;
185
    int len;
186

    
187
    r->req.aiocb = NULL;
188
    if (ret) {
189
        DPRINTF("IO error ret %d\n", ret);
190
        scsi_command_complete(r, ret);
191
        return;
192
    }
193
    len = r->io_header.dxfer_len - r->io_header.resid;
194
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
195

    
196
    r->len = -1;
197
    if (len == 0) {
198
        scsi_command_complete(r, 0);
199
    } else {
200
        /* Snoop READ CAPACITY output to set the blocksize.  */
201
        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
202
            s->blocksize = ldl_be_p(&r->buf[4]);
203
            s->max_lba = ldl_be_p(&r->buf[0]);
204
        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
205
                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
206
            s->blocksize = ldl_be_p(&r->buf[8]);
207
            s->max_lba = ldq_be_p(&r->buf[0]);
208
        }
209
        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
210

    
211
        scsi_req_data(&r->req, len);
212
        if (!r->req.io_canceled) {
213
            scsi_req_unref(&r->req);
214
        }
215
    }
216
}
217

    
218
/* Read more data from scsi device into buffer.  */
219
static void scsi_read_data(SCSIRequest *req)
220
{
221
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
222
    SCSIDevice *s = r->req.dev;
223
    int ret;
224

    
225
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
226

    
227
    /* The request is used as the AIO opaque value, so add a ref.  */
228
    scsi_req_ref(&r->req);
229
    if (r->len == -1) {
230
        scsi_command_complete(r, 0);
231
        return;
232
    }
233

    
234
    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
235
    if (ret < 0) {
236
        scsi_command_complete(r, ret);
237
    }
238
}
239

    
240
static void scsi_write_complete(void * opaque, int ret)
241
{
242
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
243
    SCSIDevice *s = r->req.dev;
244

    
245
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
246
    r->req.aiocb = NULL;
247
    if (ret) {
248
        DPRINTF("IO error\n");
249
        scsi_command_complete(r, ret);
250
        return;
251
    }
252

    
253
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
254
        s->type == TYPE_TAPE) {
255
        s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
256
        DPRINTF("block size %d\n", s->blocksize);
257
    }
258

    
259
    scsi_command_complete(r, ret);
260
}
261

    
262
/* Write data to a scsi device.  Returns nonzero on failure.
263
   The transfer may complete asynchronously.  */
264
static void scsi_write_data(SCSIRequest *req)
265
{
266
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267
    SCSIDevice *s = r->req.dev;
268
    int ret;
269

    
270
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
271
    if (r->len == 0) {
272
        r->len = r->buflen;
273
        scsi_req_data(&r->req, r->len);
274
        return;
275
    }
276

    
277
    /* The request is used as the AIO opaque value, so add a ref.  */
278
    scsi_req_ref(&r->req);
279
    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
280
    if (ret < 0) {
281
        scsi_command_complete(r, ret);
282
    }
283
}
284

    
285
/* Return a pointer to the data buffer.  */
286
static uint8_t *scsi_get_buf(SCSIRequest *req)
287
{
288
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
289

    
290
    return r->buf;
291
}
292

    
293
/* Execute a scsi command.  Returns the length of the data expected by the
294
   command.  This will be Positive for data transfers from the device
295
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
296
   and zero if the command does not transfer any data.  */
297

    
298
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
299
{
300
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
301
    SCSIDevice *s = r->req.dev;
302
    int ret;
303

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

    
307
#ifdef DEBUG_SCSI
308
    {
309
        int i;
310
        for (i = 1; i < r->req.cmd.len; i++) {
311
            printf(" 0x%02x", cmd[i]);
312
        }
313
        printf("\n");
314
    }
315
#endif
316

    
317
    if (r->req.cmd.xfer == 0) {
318
        if (r->buf != NULL)
319
            g_free(r->buf);
320
        r->buflen = 0;
321
        r->buf = NULL;
322
        /* The request is used as the AIO opaque value, so add a ref.  */
323
        scsi_req_ref(&r->req);
324
        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
325
        if (ret < 0) {
326
            scsi_command_complete(r, ret);
327
            return 0;
328
        }
329
        return 0;
330
    }
331

    
332
    if (r->buflen != r->req.cmd.xfer) {
333
        if (r->buf != NULL)
334
            g_free(r->buf);
335
        r->buf = g_malloc(r->req.cmd.xfer);
336
        r->buflen = r->req.cmd.xfer;
337
    }
338

    
339
    memset(r->buf, 0, r->buflen);
340
    r->len = r->req.cmd.xfer;
341
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
342
        r->len = 0;
343
        return -r->req.cmd.xfer;
344
    } else {
345
        return r->req.cmd.xfer;
346
    }
347
}
348

    
349
static int get_stream_blocksize(BlockDriverState *bdrv)
350
{
351
    uint8_t cmd[6];
352
    uint8_t buf[12];
353
    uint8_t sensebuf[8];
354
    sg_io_hdr_t io_header;
355
    int ret;
356

    
357
    memset(cmd, 0, sizeof(cmd));
358
    memset(buf, 0, sizeof(buf));
359
    cmd[0] = MODE_SENSE;
360
    cmd[4] = sizeof(buf);
361

    
362
    memset(&io_header, 0, sizeof(io_header));
363
    io_header.interface_id = 'S';
364
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
365
    io_header.dxfer_len = sizeof(buf);
366
    io_header.dxferp = buf;
367
    io_header.cmdp = cmd;
368
    io_header.cmd_len = sizeof(cmd);
369
    io_header.mx_sb_len = sizeof(sensebuf);
370
    io_header.sbp = sensebuf;
371
    io_header.timeout = 6000; /* XXX */
372

    
373
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
374
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
375
        return -1;
376
    }
377
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
378
}
379

    
380
static void scsi_generic_reset(DeviceState *dev)
381
{
382
    SCSIDevice *s = SCSI_DEVICE(dev);
383

    
384
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
385
}
386

    
387
static void scsi_destroy(SCSIDevice *s)
388
{
389
    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
390
    blockdev_mark_auto_del(s->conf.bs);
391
}
392

    
393
static int scsi_generic_initfn(SCSIDevice *s)
394
{
395
    int sg_version;
396
    struct sg_scsi_id scsiid;
397

    
398
    if (!s->conf.bs) {
399
        error_report("drive property not set");
400
        return -1;
401
    }
402

    
403
    /* check we are really using a /dev/sg* file */
404
    if (!bdrv_is_sg(s->conf.bs)) {
405
        error_report("not /dev/sg*");
406
        return -1;
407
    }
408

    
409
    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
410
        error_report("Device doesn't support drive option werror");
411
        return -1;
412
    }
413
    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
414
        error_report("Device doesn't support drive option rerror");
415
        return -1;
416
    }
417

    
418
    /* check we are using a driver managing SG_IO (version 3 and after */
419
    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
420
        sg_version < 30000) {
421
        error_report("scsi generic interface too old");
422
        return -1;
423
    }
424

    
425
    /* get LUN of the /dev/sg? */
426
    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
427
        error_report("SG_GET_SCSI_ID ioctl failed");
428
        return -1;
429
    }
430

    
431
    /* define device state */
432
    s->type = scsiid.scsi_type;
433
    DPRINTF("device type %d\n", s->type);
434
    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
435
        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
436
    }
437

    
438
    switch (s->type) {
439
    case TYPE_TAPE:
440
        s->blocksize = get_stream_blocksize(s->conf.bs);
441
        if (s->blocksize == -1) {
442
            s->blocksize = 0;
443
        }
444
        break;
445

    
446
        /* Make a guess for block devices, we'll fix it when the guest sends.
447
         * READ CAPACITY.  If they don't, they likely would assume these sizes
448
         * anyway. (TODO: they could also send MODE SENSE).
449
         */
450
    case TYPE_ROM:
451
    case TYPE_WORM:
452
        s->blocksize = 2048;
453
        break;
454
    default:
455
        s->blocksize = 512;
456
        break;
457
    }
458

    
459
    DPRINTF("block size %d\n", s->blocksize);
460
    return 0;
461
}
462

    
463
const SCSIReqOps scsi_generic_req_ops = {
464
    .size         = sizeof(SCSIGenericReq),
465
    .free_req     = scsi_free_request,
466
    .send_command = scsi_send_command,
467
    .read_data    = scsi_read_data,
468
    .write_data   = scsi_write_data,
469
    .cancel_io    = scsi_cancel_io,
470
    .get_buf      = scsi_get_buf,
471
    .load_request = scsi_generic_load_request,
472
    .save_request = scsi_generic_save_request,
473
};
474

    
475
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
476
                                     uint8_t *buf, void *hba_private)
477
{
478
    SCSIRequest *req;
479

    
480
    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
481
    return req;
482
}
483

    
484
static Property scsi_generic_properties[] = {
485
    DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
486
    DEFINE_PROP_END_OF_LIST(),
487
};
488

    
489
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
490
{
491
    DeviceClass *dc = DEVICE_CLASS(klass);
492
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
493

    
494
    sc->init         = scsi_generic_initfn;
495
    sc->destroy      = scsi_destroy;
496
    sc->alloc_req    = scsi_new_request;
497
    dc->fw_name = "disk";
498
    dc->desc = "pass through generic scsi device (/dev/sg*)";
499
    dc->reset = scsi_generic_reset;
500
    dc->props = scsi_generic_properties;
501
    dc->vmsd  = &vmstate_scsi_device;
502
}
503

    
504
static TypeInfo scsi_generic_info = {
505
    .name          = "scsi-generic",
506
    .parent        = TYPE_SCSI_DEVICE,
507
    .instance_size = sizeof(SCSIDevice),
508
    .class_init    = scsi_generic_class_initfn,
509
};
510

    
511
static void scsi_generic_register_types(void)
512
{
513
    type_register_static(&scsi_generic_info);
514
}
515

    
516
type_init(scsi_generic_register_types)
517

    
518
#endif /* __linux__ */