Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 18ebcc86

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
    if (r->req.aiocb == NULL) {
156
        BADF("execute_command: read failed !\n");
157
        return -ENOMEM;
158
    }
159

    
160
    return 0;
161
}
162

    
163
static void scsi_read_complete(void * opaque, int ret)
164
{
165
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
166
    SCSIDevice *s = r->req.dev;
167
    int len;
168

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

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

    
193
        scsi_req_data(&r->req, len);
194
        if (!r->req.io_canceled) {
195
            scsi_req_unref(&r->req);
196
        }
197
    }
198
}
199

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

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

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

    
216
    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
217
    if (ret < 0) {
218
        scsi_command_complete(r, ret);
219
    }
220
}
221

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

    
227
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
228
    r->req.aiocb = NULL;
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->type == TYPE_TAPE) {
237
        s->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 void scsi_write_data(SCSIRequest *req)
247
{
248
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
249
    SCSIDevice *s = r->req.dev;
250
    int ret;
251

    
252
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
253
    if (r->len == 0) {
254
        r->len = r->buflen;
255
        scsi_req_data(&r->req, r->len);
256
        return;
257
    }
258

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

    
267
/* Return a pointer to the data buffer.  */
268
static uint8_t *scsi_get_buf(SCSIRequest *req)
269
{
270
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271

    
272
    return r->buf;
273
}
274

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

    
280
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
281
{
282
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
283
    SCSIDevice *s = r->req.dev;
284
    int ret;
285

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

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

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

    
314
    if (r->buflen != r->req.cmd.xfer) {
315
        if (r->buf != NULL)
316
            g_free(r->buf);
317
        r->buf = g_malloc(r->req.cmd.xfer);
318
        r->buflen = r->req.cmd.xfer;
319
    }
320

    
321
    memset(r->buf, 0, r->buflen);
322
    r->len = r->req.cmd.xfer;
323
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
324
        r->len = 0;
325
        return -r->req.cmd.xfer;
326
    } else {
327
        return r->req.cmd.xfer;
328
    }
329
}
330

    
331
static int get_stream_blocksize(BlockDriverState *bdrv)
332
{
333
    uint8_t cmd[6];
334
    uint8_t buf[12];
335
    uint8_t sensebuf[8];
336
    sg_io_hdr_t io_header;
337
    int ret;
338

    
339
    memset(cmd, 0, sizeof(cmd));
340
    memset(buf, 0, sizeof(buf));
341
    cmd[0] = MODE_SENSE;
342
    cmd[4] = sizeof(buf);
343

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

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

    
362
static void scsi_generic_reset(DeviceState *dev)
363
{
364
    SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
365

    
366
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
367
}
368

    
369
static void scsi_destroy(SCSIDevice *s)
370
{
371
    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
372
    blockdev_mark_auto_del(s->conf.bs);
373
}
374

    
375
static int scsi_generic_initfn(SCSIDevice *s)
376
{
377
    int sg_version;
378
    struct sg_scsi_id scsiid;
379

    
380
    if (!s->conf.bs) {
381
        error_report("scsi-generic: drive property not set");
382
        return -1;
383
    }
384

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

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

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

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

    
413
    /* define device state */
414
    s->type = scsiid.scsi_type;
415
    DPRINTF("device type %d\n", s->type);
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.desc    = "pass through generic scsi device (/dev/sg*)",
463
    .qdev.size    = sizeof(SCSIDevice),
464
    .qdev.reset   = scsi_generic_reset,
465
    .init         = scsi_generic_initfn,
466
    .destroy      = scsi_destroy,
467
    .alloc_req    = scsi_new_request,
468
    .qdev.props   = (Property[]) {
469
        DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
470
        DEFINE_PROP_END_OF_LIST(),
471
    },
472
};
473

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

    
480
#endif /* __linux__ */