Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ be62a2eb

History | View | Annotate | Download (13.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_free_request(SCSIRequest *req)
63
{
64
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
65

    
66
    g_free(r->buf);
67
}
68

    
69
/* Helper function for command completion.  */
70
static void scsi_command_complete(void *opaque, int ret)
71
{
72
    int status;
73
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
74

    
75
    r->req.aiocb = NULL;
76
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
77
        r->req.sense_len = r->io_header.sb_len_wr;
78
    }
79

    
80
    if (ret != 0) {
81
        switch (ret) {
82
        case -EDOM:
83
            status = TASK_SET_FULL;
84
            break;
85
        case -ENOMEM:
86
            status = CHECK_CONDITION;
87
            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
88
            break;
89
        default:
90
            status = CHECK_CONDITION;
91
            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
92
            break;
93
        }
94
    } else {
95
        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
96
            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
97
            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
98
            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
99
            status = BUSY;
100
            BADF("Driver Timeout\n");
101
        } else if (r->io_header.host_status) {
102
            status = CHECK_CONDITION;
103
            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
104
        } else if (r->io_header.status) {
105
            status = r->io_header.status;
106
        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
107
            status = CHECK_CONDITION;
108
        } else {
109
            status = GOOD;
110
        }
111
    }
112
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113
            r, r->req.tag, status);
114

    
115
    scsi_req_complete(&r->req, status);
116
    if (!r->req.io_canceled) {
117
        scsi_req_unref(&r->req);
118
    }
119
}
120

    
121
/* Cancel a pending data transfer.  */
122
static void scsi_cancel_io(SCSIRequest *req)
123
{
124
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
125

    
126
    DPRINTF("Cancel tag=0x%x\n", req->tag);
127
    if (r->req.aiocb) {
128
        bdrv_aio_cancel(r->req.aiocb);
129

    
130
        /* This reference was left in by scsi_*_data.  We take ownership of
131
         * it independent of whether bdrv_aio_cancel completes the request
132
         * or not.  */
133
        scsi_req_unref(&r->req);
134
    }
135
    r->req.aiocb = NULL;
136
}
137

    
138
static int execute_command(BlockDriverState *bdrv,
139
                           SCSIGenericReq *r, int direction,
140
                           BlockDriverCompletionFunc *complete)
141
{
142
    r->io_header.interface_id = 'S';
143
    r->io_header.dxfer_direction = direction;
144
    r->io_header.dxferp = r->buf;
145
    r->io_header.dxfer_len = r->buflen;
146
    r->io_header.cmdp = r->req.cmd.buf;
147
    r->io_header.cmd_len = r->req.cmd.len;
148
    r->io_header.mx_sb_len = sizeof(r->req.sense);
149
    r->io_header.sbp = r->req.sense;
150
    r->io_header.timeout = MAX_UINT;
151
    r->io_header.usr_ptr = r;
152
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
153

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

    
156
    return 0;
157
}
158

    
159
static void scsi_read_complete(void * opaque, int ret)
160
{
161
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
162
    SCSIDevice *s = r->req.dev;
163
    int len;
164

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

    
174
    r->len = -1;
175
    if (len == 0) {
176
        scsi_command_complete(r, 0);
177
    } else {
178
        /* Snoop READ CAPACITY output to set the blocksize.  */
179
        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
180
            s->blocksize = ldl_be_p(&r->buf[4]);
181
            s->max_lba = ldl_be_p(&r->buf[0]);
182
        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
183
                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
184
            s->blocksize = ldl_be_p(&r->buf[8]);
185
            s->max_lba = ldq_be_p(&r->buf[0]);
186
        }
187
        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
188

    
189
        scsi_req_data(&r->req, len);
190
        if (!r->req.io_canceled) {
191
            scsi_req_unref(&r->req);
192
        }
193
    }
194
}
195

    
196
/* Read more data from scsi device into buffer.  */
197
static void scsi_read_data(SCSIRequest *req)
198
{
199
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
200
    SCSIDevice *s = r->req.dev;
201
    int ret;
202

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

    
205
    /* The request is used as the AIO opaque value, so add a ref.  */
206
    scsi_req_ref(&r->req);
207
    if (r->len == -1) {
208
        scsi_command_complete(r, 0);
209
        return;
210
    }
211

    
212
    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
213
    if (ret < 0) {
214
        scsi_command_complete(r, ret);
215
    }
216
}
217

    
218
static void scsi_write_complete(void * opaque, int ret)
219
{
220
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
221
    SCSIDevice *s = r->req.dev;
222

    
223
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
224
    r->req.aiocb = NULL;
225
    if (ret) {
226
        DPRINTF("IO error\n");
227
        scsi_command_complete(r, ret);
228
        return;
229
    }
230

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

    
237
    scsi_command_complete(r, ret);
238
}
239

    
240
/* Write data to a scsi device.  Returns nonzero on failure.
241
   The transfer may complete asynchronously.  */
242
static void scsi_write_data(SCSIRequest *req)
243
{
244
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
245
    SCSIDevice *s = r->req.dev;
246
    int ret;
247

    
248
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
249
    if (r->len == 0) {
250
        r->len = r->buflen;
251
        scsi_req_data(&r->req, r->len);
252
        return;
253
    }
254

    
255
    /* The request is used as the AIO opaque value, so add a ref.  */
256
    scsi_req_ref(&r->req);
257
    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
258
    if (ret < 0) {
259
        scsi_command_complete(r, ret);
260
    }
261
}
262

    
263
/* Return a pointer to the data buffer.  */
264
static uint8_t *scsi_get_buf(SCSIRequest *req)
265
{
266
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267

    
268
    return r->buf;
269
}
270

    
271
/* Execute a scsi command.  Returns the length of the data expected by the
272
   command.  This will be Positive for data transfers from the device
273
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
274
   and zero if the command does not transfer any data.  */
275

    
276
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
277
{
278
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
279
    SCSIDevice *s = r->req.dev;
280
    int ret;
281

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

    
285
#ifdef DEBUG_SCSI
286
    {
287
        int i;
288
        for (i = 1; i < r->req.cmd.len; i++) {
289
            printf(" 0x%02x", cmd[i]);
290
        }
291
        printf("\n");
292
    }
293
#endif
294

    
295
    if (r->req.cmd.xfer == 0) {
296
        if (r->buf != NULL)
297
            g_free(r->buf);
298
        r->buflen = 0;
299
        r->buf = NULL;
300
        /* The request is used as the AIO opaque value, so add a ref.  */
301
        scsi_req_ref(&r->req);
302
        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
303
        if (ret < 0) {
304
            scsi_command_complete(r, ret);
305
            return 0;
306
        }
307
        return 0;
308
    }
309

    
310
    if (r->buflen != r->req.cmd.xfer) {
311
        if (r->buf != NULL)
312
            g_free(r->buf);
313
        r->buf = g_malloc(r->req.cmd.xfer);
314
        r->buflen = r->req.cmd.xfer;
315
    }
316

    
317
    memset(r->buf, 0, r->buflen);
318
    r->len = r->req.cmd.xfer;
319
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
320
        r->len = 0;
321
        return -r->req.cmd.xfer;
322
    } else {
323
        return r->req.cmd.xfer;
324
    }
325
}
326

    
327
static int get_stream_blocksize(BlockDriverState *bdrv)
328
{
329
    uint8_t cmd[6];
330
    uint8_t buf[12];
331
    uint8_t sensebuf[8];
332
    sg_io_hdr_t io_header;
333
    int ret;
334

    
335
    memset(cmd, 0, sizeof(cmd));
336
    memset(buf, 0, sizeof(buf));
337
    cmd[0] = MODE_SENSE;
338
    cmd[4] = sizeof(buf);
339

    
340
    memset(&io_header, 0, sizeof(io_header));
341
    io_header.interface_id = 'S';
342
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
343
    io_header.dxfer_len = sizeof(buf);
344
    io_header.dxferp = buf;
345
    io_header.cmdp = cmd;
346
    io_header.cmd_len = sizeof(cmd);
347
    io_header.mx_sb_len = sizeof(sensebuf);
348
    io_header.sbp = sensebuf;
349
    io_header.timeout = 6000; /* XXX */
350

    
351
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
352
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
353
        return -1;
354
    }
355
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
356
}
357

    
358
static void scsi_generic_reset(DeviceState *dev)
359
{
360
    SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
361

    
362
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
363
}
364

    
365
static void scsi_destroy(SCSIDevice *s)
366
{
367
    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
368
    blockdev_mark_auto_del(s->conf.bs);
369
}
370

    
371
static int scsi_generic_initfn(SCSIDevice *s)
372
{
373
    int sg_version;
374
    struct sg_scsi_id scsiid;
375

    
376
    if (!s->conf.bs) {
377
        error_report("scsi-generic: drive property not set");
378
        return -1;
379
    }
380

    
381
    /* check we are really using a /dev/sg* file */
382
    if (!bdrv_is_sg(s->conf.bs)) {
383
        error_report("scsi-generic: not /dev/sg*");
384
        return -1;
385
    }
386

    
387
    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
388
        error_report("Device doesn't support drive option werror");
389
        return -1;
390
    }
391
    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
392
        error_report("Device doesn't support drive option rerror");
393
        return -1;
394
    }
395

    
396
    /* check we are using a driver managing SG_IO (version 3 and after */
397
    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
398
        sg_version < 30000) {
399
        error_report("scsi-generic: scsi generic interface too old");
400
        return -1;
401
    }
402

    
403
    /* get LUN of the /dev/sg? */
404
    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
405
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
406
        return -1;
407
    }
408

    
409
    /* define device state */
410
    s->type = scsiid.scsi_type;
411
    DPRINTF("device type %d\n", s->type);
412
    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
413
        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
414
    }
415

    
416
    switch (s->type) {
417
    case TYPE_TAPE:
418
        s->blocksize = get_stream_blocksize(s->conf.bs);
419
        if (s->blocksize == -1) {
420
            s->blocksize = 0;
421
        }
422
        break;
423

    
424
        /* Make a guess for block devices, we'll fix it when the guest sends.
425
         * READ CAPACITY.  If they don't, they likely would assume these sizes
426
         * anyway. (TODO: they could also send MODE SENSE).
427
         */
428
    case TYPE_ROM:
429
    case TYPE_WORM:
430
        s->blocksize = 2048;
431
        break;
432
    default:
433
        s->blocksize = 512;
434
        break;
435
    }
436

    
437
    DPRINTF("block size %d\n", s->blocksize);
438
    return 0;
439
}
440

    
441
const SCSIReqOps scsi_generic_req_ops = {
442
    .size         = sizeof(SCSIGenericReq),
443
    .free_req     = scsi_free_request,
444
    .send_command = scsi_send_command,
445
    .read_data    = scsi_read_data,
446
    .write_data   = scsi_write_data,
447
    .cancel_io    = scsi_cancel_io,
448
    .get_buf      = scsi_get_buf,
449
};
450

    
451
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
452
                                     uint8_t *buf, void *hba_private)
453
{
454
    SCSIRequest *req;
455

    
456
    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
457
    return req;
458
}
459

    
460
static SCSIDeviceInfo scsi_generic_info = {
461
    .qdev.name    = "scsi-generic",
462
    .qdev.fw_name = "disk",
463
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
464
    .qdev.size    = sizeof(SCSIDevice),
465
    .qdev.reset   = scsi_generic_reset,
466
    .init         = scsi_generic_initfn,
467
    .destroy      = scsi_destroy,
468
    .alloc_req    = scsi_new_request,
469
    .qdev.props   = (Property[]) {
470
        DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
471
        DEFINE_PROP_END_OF_LIST(),
472
    },
473
};
474

    
475
static void scsi_generic_register_devices(void)
476
{
477
    scsi_qdev_register(&scsi_generic_info);
478
}
479
device_init(scsi_generic_register_devices)
480

    
481
#endif /* __linux__ */