Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 74382217

History | View | Annotate | Download (15.4 kB)

1 2cc977e2 ths
/*
2 2cc977e2 ths
 * Generic SCSI Device support
3 2cc977e2 ths
 *
4 2cc977e2 ths
 * Copyright (c) 2007 Bull S.A.S.
5 2cc977e2 ths
 * Based on code by Paul Brook
6 2cc977e2 ths
 * Based on code by Fabrice Bellard
7 2cc977e2 ths
 *
8 2cc977e2 ths
 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
9 2cc977e2 ths
 *
10 2cc977e2 ths
 * This code is licenced under the LGPL.
11 2cc977e2 ths
 *
12 2cc977e2 ths
 */
13 2cc977e2 ths
14 2cc977e2 ths
#include "qemu-common.h"
15 2f792016 Markus Armbruster
#include "qemu-error.h"
16 43b443b6 Gerd Hoffmann
#include "scsi.h"
17 2446333c Blue Swirl
#include "blockdev.h"
18 2cc977e2 ths
19 d52affa7 Gerd Hoffmann
#ifdef __linux__
20 2cc977e2 ths
21 2cc977e2 ths
//#define DEBUG_SCSI
22 2cc977e2 ths
23 2cc977e2 ths
#ifdef DEBUG_SCSI
24 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) \
25 001faf32 Blue Swirl
do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26 2cc977e2 ths
#else
27 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do {} while(0)
28 2cc977e2 ths
#endif
29 2cc977e2 ths
30 001faf32 Blue Swirl
#define BADF(fmt, ...) \
31 001faf32 Blue Swirl
do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
32 2cc977e2 ths
33 2cc977e2 ths
#include <stdio.h>
34 2cc977e2 ths
#include <sys/types.h>
35 2cc977e2 ths
#include <sys/stat.h>
36 2cc977e2 ths
#include <unistd.h>
37 2cc977e2 ths
#include <scsi/sg.h>
38 0d65e1f8 Gerd Hoffmann
#include "scsi-defs.h"
39 2cc977e2 ths
40 a9dd6843 aliguori
#define SCSI_SENSE_BUF_SIZE 96
41 2cc977e2 ths
42 2cc977e2 ths
#define SG_ERR_DRIVER_TIMEOUT 0x06
43 2cc977e2 ths
#define SG_ERR_DRIVER_SENSE 0x08
44 2cc977e2 ths
45 2cc977e2 ths
#ifndef MAX_UINT
46 2cc977e2 ths
#define MAX_UINT ((unsigned int)-1)
47 2cc977e2 ths
#endif
48 2cc977e2 ths
49 d52affa7 Gerd Hoffmann
typedef struct SCSIGenericState SCSIGenericState;
50 d52affa7 Gerd Hoffmann
51 4c41d2ef Gerd Hoffmann
typedef struct SCSIGenericReq {
52 4c41d2ef Gerd Hoffmann
    SCSIRequest req;
53 2cc977e2 ths
    uint8_t *buf;
54 2cc977e2 ths
    int buflen;
55 2cc977e2 ths
    int len;
56 2cc977e2 ths
    sg_io_hdr_t io_header;
57 4c41d2ef Gerd Hoffmann
} SCSIGenericReq;
58 2cc977e2 ths
59 d52affa7 Gerd Hoffmann
struct SCSIGenericState
60 2cc977e2 ths
{
61 d52affa7 Gerd Hoffmann
    SCSIDevice qdev;
62 428c149b Christoph Hellwig
    BlockDriverState *bs;
63 2cc977e2 ths
    int lun;
64 2cc977e2 ths
    int driver_status;
65 2cc977e2 ths
    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
66 89c0f643 aurel32
    uint8_t senselen;
67 2cc977e2 ths
};
68 2cc977e2 ths
69 a1f0cce2 Hannes Reinecke
static void scsi_set_sense(SCSIGenericState *s, SCSISense sense)
70 a1f0cce2 Hannes Reinecke
{
71 a1f0cce2 Hannes Reinecke
    s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0);
72 a1f0cce2 Hannes Reinecke
    s->driver_status = SG_ERR_DRIVER_SENSE;
73 a1f0cce2 Hannes Reinecke
}
74 a1f0cce2 Hannes Reinecke
75 a1f0cce2 Hannes Reinecke
static void scsi_clear_sense(SCSIGenericState *s)
76 a1f0cce2 Hannes Reinecke
{
77 a1f0cce2 Hannes Reinecke
    memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE);
78 a1f0cce2 Hannes Reinecke
    s->senselen = 0;
79 a1f0cce2 Hannes Reinecke
    s->driver_status = 0;
80 a1f0cce2 Hannes Reinecke
}
81 a1f0cce2 Hannes Reinecke
82 74382217 Hannes Reinecke
static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
83 74382217 Hannes Reinecke
{
84 74382217 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
85 74382217 Hannes Reinecke
    int size = SCSI_SENSE_BUF_SIZE;
86 74382217 Hannes Reinecke
87 74382217 Hannes Reinecke
    if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) {
88 74382217 Hannes Reinecke
        size = scsi_build_sense(SENSE_CODE(NO_SENSE), s->sensebuf,
89 74382217 Hannes Reinecke
                                SCSI_SENSE_BUF_SIZE, 0);
90 74382217 Hannes Reinecke
    }
91 74382217 Hannes Reinecke
    if (size > len) {
92 74382217 Hannes Reinecke
        size = len;
93 74382217 Hannes Reinecke
    }
94 74382217 Hannes Reinecke
    memcpy(outbuf, s->sensebuf, size);
95 74382217 Hannes Reinecke
96 74382217 Hannes Reinecke
    return size;
97 74382217 Hannes Reinecke
}
98 74382217 Hannes Reinecke
99 5c6c0e51 Hannes Reinecke
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
100 2cc977e2 ths
{
101 89b08ae1 Gerd Hoffmann
    SCSIRequest *req;
102 2cc977e2 ths
103 89b08ae1 Gerd Hoffmann
    req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
104 5c6c0e51 Hannes Reinecke
    return req;
105 2cc977e2 ths
}
106 2cc977e2 ths
107 ad2d30f7 Paolo Bonzini
static void scsi_free_request(SCSIRequest *req)
108 2cc977e2 ths
{
109 ad2d30f7 Paolo Bonzini
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
110 ad2d30f7 Paolo Bonzini
111 9af99d98 Gerd Hoffmann
    qemu_free(r->buf);
112 2cc977e2 ths
}
113 2cc977e2 ths
114 2cc977e2 ths
/* Helper function for command completion.  */
115 2cc977e2 ths
static void scsi_command_complete(void *opaque, int ret)
116 2cc977e2 ths
{
117 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
118 4c41d2ef Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
119 2cc977e2 ths
120 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
121 2cc977e2 ths
    s->driver_status = r->io_header.driver_status;
122 89c0f643 aurel32
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
123 89c0f643 aurel32
        s->senselen = r->io_header.sb_len_wr;
124 89c0f643 aurel32
125 a1f0cce2 Hannes Reinecke
    if (ret != 0) {
126 a1f0cce2 Hannes Reinecke
        switch (ret) {
127 a1f0cce2 Hannes Reinecke
        case -EINVAL:
128 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
129 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
130 a1f0cce2 Hannes Reinecke
            break;
131 a1f0cce2 Hannes Reinecke
        case -ENOMEM:
132 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
133 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
134 a1f0cce2 Hannes Reinecke
            break;
135 a1f0cce2 Hannes Reinecke
        default:
136 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
137 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(IO_ERROR));
138 a1f0cce2 Hannes Reinecke
            break;
139 a1f0cce2 Hannes Reinecke
        }
140 a1f0cce2 Hannes Reinecke
    } else {
141 2cc977e2 ths
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
142 f0171327 Hannes Reinecke
            r->req.status = BUSY;
143 2cc977e2 ths
            BADF("Driver Timeout\n");
144 89c0f643 aurel32
        } else if (r->io_header.status)
145 ed3a34a3 Gerd Hoffmann
            r->req.status = r->io_header.status;
146 89c0f643 aurel32
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
147 f0171327 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
148 2cc977e2 ths
        else
149 f0171327 Hannes Reinecke
            r->req.status = GOOD;
150 2cc977e2 ths
    }
151 89c0f643 aurel32
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
152 ed3a34a3 Gerd Hoffmann
            r, r->req.tag, r->req.status);
153 ed3a34a3 Gerd Hoffmann
154 ed3a34a3 Gerd Hoffmann
    scsi_req_complete(&r->req);
155 2cc977e2 ths
}
156 2cc977e2 ths
157 2cc977e2 ths
/* Cancel a pending data transfer.  */
158 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
159 2cc977e2 ths
{
160 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
161 5c6c0e51 Hannes Reinecke
162 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
163 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
164 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
165 2cc977e2 ths
    }
166 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
167 2cc977e2 ths
}
168 2cc977e2 ths
169 2cc977e2 ths
static int execute_command(BlockDriverState *bdrv,
170 4c41d2ef Gerd Hoffmann
                           SCSIGenericReq *r, int direction,
171 2cc977e2 ths
                           BlockDriverCompletionFunc *complete)
172 2cc977e2 ths
{
173 4c41d2ef Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
174 4c41d2ef Gerd Hoffmann
175 2cc977e2 ths
    r->io_header.interface_id = 'S';
176 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
177 2cc977e2 ths
    r->io_header.dxferp = r->buf;
178 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
179 29362ebe Gerd Hoffmann
    r->io_header.cmdp = r->req.cmd.buf;
180 29362ebe Gerd Hoffmann
    r->io_header.cmd_len = r->req.cmd.len;
181 4c41d2ef Gerd Hoffmann
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
182 4c41d2ef Gerd Hoffmann
    r->io_header.sbp = s->sensebuf;
183 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
184 2cc977e2 ths
    r->io_header.usr_ptr = r;
185 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
186 2cc977e2 ths
187 4c41d2ef Gerd Hoffmann
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
188 4c41d2ef Gerd Hoffmann
    if (r->req.aiocb == NULL) {
189 2cc977e2 ths
        BADF("execute_command: read failed !\n");
190 a1f0cce2 Hannes Reinecke
        return -ENOMEM;
191 2cc977e2 ths
    }
192 2cc977e2 ths
193 2cc977e2 ths
    return 0;
194 2cc977e2 ths
}
195 2cc977e2 ths
196 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
197 2cc977e2 ths
{
198 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
199 2cc977e2 ths
    int len;
200 2cc977e2 ths
201 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
202 2cc977e2 ths
    if (ret) {
203 aa2b1e89 Bernhard Kohl
        DPRINTF("IO error ret %d\n", ret);
204 2cc977e2 ths
        scsi_command_complete(r, ret);
205 2cc977e2 ths
        return;
206 2cc977e2 ths
    }
207 2cc977e2 ths
    len = r->io_header.dxfer_len - r->io_header.resid;
208 4c41d2ef Gerd Hoffmann
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
209 2cc977e2 ths
210 2cc977e2 ths
    r->len = -1;
211 40f16dd1 Paolo Bonzini
    if (len == 0) {
212 89c0f643 aurel32
        scsi_command_complete(r, 0);
213 40f16dd1 Paolo Bonzini
    } else {
214 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, len);
215 40f16dd1 Paolo Bonzini
    }
216 2cc977e2 ths
}
217 2cc977e2 ths
218 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
219 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
220 2cc977e2 ths
{
221 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
222 5c6c0e51 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
223 2cc977e2 ths
    int ret;
224 2cc977e2 ths
225 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
226 2cc977e2 ths
    if (r->len == -1) {
227 2cc977e2 ths
        scsi_command_complete(r, 0);
228 2cc977e2 ths
        return;
229 2cc977e2 ths
    }
230 2cc977e2 ths
231 29362ebe Gerd Hoffmann
    if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
232 2cc977e2 ths
    {
233 89c0f643 aurel32
        s->senselen = MIN(r->len, s->senselen);
234 89c0f643 aurel32
        memcpy(r->buf, s->sensebuf, s->senselen);
235 2cc977e2 ths
        r->io_header.driver_status = 0;
236 89c0f643 aurel32
        r->io_header.status = 0;
237 89c0f643 aurel32
        r->io_header.dxfer_len  = s->senselen;
238 2cc977e2 ths
        r->len = -1;
239 4c41d2ef Gerd Hoffmann
        DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
240 a9dd6843 aliguori
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
241 a9dd6843 aliguori
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
242 a9dd6843 aliguori
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
243 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, s->senselen);
244 a1f0cce2 Hannes Reinecke
        /* Clear sensebuf after REQUEST_SENSE */
245 a1f0cce2 Hannes Reinecke
        scsi_clear_sense(s);
246 2cc977e2 ths
        return;
247 2cc977e2 ths
    }
248 2cc977e2 ths
249 428c149b Christoph Hellwig
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
250 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
251 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
252 2cc977e2 ths
        return;
253 2cc977e2 ths
    }
254 2cc977e2 ths
}
255 2cc977e2 ths
256 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
257 2cc977e2 ths
{
258 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
259 4c41d2ef Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
260 2cc977e2 ths
261 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
262 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
263 2cc977e2 ths
    if (ret) {
264 2cc977e2 ths
        DPRINTF("IO error\n");
265 2cc977e2 ths
        scsi_command_complete(r, ret);
266 2cc977e2 ths
        return;
267 2cc977e2 ths
    }
268 2cc977e2 ths
269 29362ebe Gerd Hoffmann
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
270 91376656 Gerd Hoffmann
        s->qdev.type == TYPE_TAPE) {
271 b07995e3 Gerd Hoffmann
        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
272 aa2b1e89 Bernhard Kohl
        DPRINTF("block size %d\n", s->qdev.blocksize);
273 89c0f643 aurel32
    }
274 89c0f643 aurel32
275 2cc977e2 ths
    scsi_command_complete(r, ret);
276 2cc977e2 ths
}
277 2cc977e2 ths
278 2cc977e2 ths
/* Write data to a scsi device.  Returns nonzero on failure.
279 2cc977e2 ths
   The transfer may complete asynchronously.  */
280 5c6c0e51 Hannes Reinecke
static int scsi_write_data(SCSIRequest *req)
281 2cc977e2 ths
{
282 5c6c0e51 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
283 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
284 2cc977e2 ths
    int ret;
285 2cc977e2 ths
286 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
287 2cc977e2 ths
    if (r->len == 0) {
288 2cc977e2 ths
        r->len = r->buflen;
289 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, r->len);
290 2cc977e2 ths
        return 0;
291 2cc977e2 ths
    }
292 2cc977e2 ths
293 428c149b Christoph Hellwig
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
294 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
295 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
296 2cc977e2 ths
        return 1;
297 2cc977e2 ths
    }
298 2cc977e2 ths
299 2cc977e2 ths
    return 0;
300 2cc977e2 ths
}
301 2cc977e2 ths
302 2cc977e2 ths
/* Return a pointer to the data buffer.  */
303 5c6c0e51 Hannes Reinecke
static uint8_t *scsi_get_buf(SCSIRequest *req)
304 2cc977e2 ths
{
305 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
306 5c6c0e51 Hannes Reinecke
307 2cc977e2 ths
    return r->buf;
308 2cc977e2 ths
}
309 2cc977e2 ths
310 2ec749cb Gerd Hoffmann
static void scsi_req_fixup(SCSIRequest *req)
311 2cc977e2 ths
{
312 2ec749cb Gerd Hoffmann
    switch(req->cmd.buf[0]) {
313 2cc977e2 ths
    case WRITE_10:
314 2ec749cb Gerd Hoffmann
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
315 2cc977e2 ths
        break;
316 2cc977e2 ths
    case READ_10:
317 2ec749cb Gerd Hoffmann
        req->cmd.buf[1] &= ~0x08;        /* disable FUA */
318 a9dd6843 aliguori
        break;
319 a9dd6843 aliguori
    case REWIND:
320 a9dd6843 aliguori
    case START_STOP:
321 2ec749cb Gerd Hoffmann
        if (req->dev->type == TYPE_TAPE) {
322 2ec749cb Gerd Hoffmann
            /* force IMMED, otherwise qemu waits end of command */
323 2ec749cb Gerd Hoffmann
            req->cmd.buf[1] = 0x01;
324 2ec749cb Gerd Hoffmann
        }
325 a9dd6843 aliguori
        break;
326 a9dd6843 aliguori
    }
327 a9dd6843 aliguori
}
328 a9dd6843 aliguori
329 2cc977e2 ths
/* Execute a scsi command.  Returns the length of the data expected by the
330 2cc977e2 ths
   command.  This will be Positive for data transfers from the device
331 2cc977e2 ths
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
332 2cc977e2 ths
   and zero if the command does not transfer any data.  */
333 2cc977e2 ths
334 5c6c0e51 Hannes Reinecke
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
335 2cc977e2 ths
{
336 5c6c0e51 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
337 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
338 2cc977e2 ths
    int ret;
339 2cc977e2 ths
340 89c0f643 aurel32
    if (cmd[0] != REQUEST_SENSE &&
341 5c6c0e51 Hannes Reinecke
        (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
342 5c6c0e51 Hannes Reinecke
        DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
343 a1f0cce2 Hannes Reinecke
        scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
344 2b8b3bb9 Paolo Bonzini
        r->req.status = CHECK_CONDITION;
345 2b8b3bb9 Paolo Bonzini
        scsi_req_complete(&r->req);
346 89c0f643 aurel32
        return 0;
347 89c0f643 aurel32
    }
348 89c0f643 aurel32
349 2ec749cb Gerd Hoffmann
    if (-1 == scsi_req_parse(&r->req, cmd)) {
350 2ec749cb Gerd Hoffmann
        BADF("Unsupported command length, command %x\n", cmd[0]);
351 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, -EINVAL);
352 2ec749cb Gerd Hoffmann
        return 0;
353 2ec749cb Gerd Hoffmann
    }
354 2ec749cb Gerd Hoffmann
    scsi_req_fixup(&r->req);
355 2ec749cb Gerd Hoffmann
356 aa2b1e89 Bernhard Kohl
    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
357 aa2b1e89 Bernhard Kohl
            r->req.cmd.xfer, cmd[0]);
358 aa2b1e89 Bernhard Kohl
359 aa2b1e89 Bernhard Kohl
#ifdef DEBUG_SCSI
360 aa2b1e89 Bernhard Kohl
    {
361 aa2b1e89 Bernhard Kohl
        int i;
362 aa2b1e89 Bernhard Kohl
        for (i = 1; i < r->req.cmd.len; i++) {
363 aa2b1e89 Bernhard Kohl
            printf(" 0x%02x", cmd[i]);
364 aa2b1e89 Bernhard Kohl
        }
365 aa2b1e89 Bernhard Kohl
        printf("\n");
366 aa2b1e89 Bernhard Kohl
    }
367 aa2b1e89 Bernhard Kohl
#endif
368 2cc977e2 ths
369 2ec749cb Gerd Hoffmann
    if (r->req.cmd.xfer == 0) {
370 2cc977e2 ths
        if (r->buf != NULL)
371 e3c916e6 Jean-Christophe DUBOIS
            qemu_free(r->buf);
372 2cc977e2 ths
        r->buflen = 0;
373 2cc977e2 ths
        r->buf = NULL;
374 428c149b Christoph Hellwig
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
375 a1f0cce2 Hannes Reinecke
        if (ret < 0) {
376 a1f0cce2 Hannes Reinecke
            scsi_command_complete(r, ret);
377 a1f0cce2 Hannes Reinecke
            return 0;
378 2cc977e2 ths
        }
379 2cc977e2 ths
        return 0;
380 2cc977e2 ths
    }
381 2cc977e2 ths
382 2ec749cb Gerd Hoffmann
    if (r->buflen != r->req.cmd.xfer) {
383 2cc977e2 ths
        if (r->buf != NULL)
384 e3c916e6 Jean-Christophe DUBOIS
            qemu_free(r->buf);
385 2ec749cb Gerd Hoffmann
        r->buf = qemu_malloc(r->req.cmd.xfer);
386 2ec749cb Gerd Hoffmann
        r->buflen = r->req.cmd.xfer;
387 2cc977e2 ths
    }
388 2cc977e2 ths
389 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
390 2ec749cb Gerd Hoffmann
    r->len = r->req.cmd.xfer;
391 97a06435 Gerd Hoffmann
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
392 2cc977e2 ths
        r->len = 0;
393 5c6c0e51 Hannes Reinecke
        return -r->req.cmd.xfer;
394 ad2d30f7 Paolo Bonzini
    } else {
395 5c6c0e51 Hannes Reinecke
        return r->req.cmd.xfer;
396 2cc977e2 ths
    }
397 2cc977e2 ths
}
398 2cc977e2 ths
399 2cc977e2 ths
static int get_blocksize(BlockDriverState *bdrv)
400 2cc977e2 ths
{
401 2cc977e2 ths
    uint8_t cmd[10];
402 2cc977e2 ths
    uint8_t buf[8];
403 2cc977e2 ths
    uint8_t sensebuf[8];
404 2cc977e2 ths
    sg_io_hdr_t io_header;
405 2cc977e2 ths
    int ret;
406 2cc977e2 ths
407 4f26a486 aliguori
    memset(cmd, 0, sizeof(cmd));
408 4f26a486 aliguori
    memset(buf, 0, sizeof(buf));
409 2cc977e2 ths
    cmd[0] = READ_CAPACITY;
410 2cc977e2 ths
411 2cc977e2 ths
    memset(&io_header, 0, sizeof(io_header));
412 2cc977e2 ths
    io_header.interface_id = 'S';
413 2cc977e2 ths
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
414 2cc977e2 ths
    io_header.dxfer_len = sizeof(buf);
415 2cc977e2 ths
    io_header.dxferp = buf;
416 2cc977e2 ths
    io_header.cmdp = cmd;
417 2cc977e2 ths
    io_header.cmd_len = sizeof(cmd);
418 2cc977e2 ths
    io_header.mx_sb_len = sizeof(sensebuf);
419 2cc977e2 ths
    io_header.sbp = sensebuf;
420 2cc977e2 ths
    io_header.timeout = 6000; /* XXX */
421 2cc977e2 ths
422 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
423 7d780669 aliguori
    if (ret < 0)
424 2cc977e2 ths
        return -1;
425 2cc977e2 ths
426 2cc977e2 ths
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
427 2cc977e2 ths
}
428 2cc977e2 ths
429 89c0f643 aurel32
static int get_stream_blocksize(BlockDriverState *bdrv)
430 89c0f643 aurel32
{
431 89c0f643 aurel32
    uint8_t cmd[6];
432 89c0f643 aurel32
    uint8_t buf[12];
433 89c0f643 aurel32
    uint8_t sensebuf[8];
434 89c0f643 aurel32
    sg_io_hdr_t io_header;
435 89c0f643 aurel32
    int ret;
436 89c0f643 aurel32
437 89c0f643 aurel32
    memset(cmd, 0, sizeof(cmd));
438 89c0f643 aurel32
    memset(buf, 0, sizeof(buf));
439 89c0f643 aurel32
    cmd[0] = MODE_SENSE;
440 89c0f643 aurel32
    cmd[4] = sizeof(buf);
441 89c0f643 aurel32
442 89c0f643 aurel32
    memset(&io_header, 0, sizeof(io_header));
443 89c0f643 aurel32
    io_header.interface_id = 'S';
444 89c0f643 aurel32
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
445 89c0f643 aurel32
    io_header.dxfer_len = sizeof(buf);
446 89c0f643 aurel32
    io_header.dxferp = buf;
447 89c0f643 aurel32
    io_header.cmdp = cmd;
448 89c0f643 aurel32
    io_header.cmd_len = sizeof(cmd);
449 89c0f643 aurel32
    io_header.mx_sb_len = sizeof(sensebuf);
450 89c0f643 aurel32
    io_header.sbp = sensebuf;
451 89c0f643 aurel32
    io_header.timeout = 6000; /* XXX */
452 89c0f643 aurel32
453 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
454 7d780669 aliguori
    if (ret < 0)
455 89c0f643 aurel32
        return -1;
456 89c0f643 aurel32
457 89c0f643 aurel32
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
458 89c0f643 aurel32
}
459 89c0f643 aurel32
460 f8b6d672 Bernhard Kohl
static void scsi_generic_reset(DeviceState *dev)
461 f8b6d672 Bernhard Kohl
{
462 f8b6d672 Bernhard Kohl
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
463 f8b6d672 Bernhard Kohl
464 c557e889 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev);
465 f8b6d672 Bernhard Kohl
}
466 f8b6d672 Bernhard Kohl
467 f8b6d672 Bernhard Kohl
static void scsi_destroy(SCSIDevice *d)
468 f8b6d672 Bernhard Kohl
{
469 f8b6d672 Bernhard Kohl
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
470 f8b6d672 Bernhard Kohl
471 c557e889 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev);
472 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
473 2cc977e2 ths
}
474 2cc977e2 ths
475 d52affa7 Gerd Hoffmann
static int scsi_generic_initfn(SCSIDevice *dev)
476 2cc977e2 ths
{
477 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
478 2cc977e2 ths
    int sg_version;
479 2cc977e2 ths
    struct sg_scsi_id scsiid;
480 2cc977e2 ths
481 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
482 1ecda02b Markus Armbruster
        error_report("scsi-generic: drive property not set");
483 d52affa7 Gerd Hoffmann
        return -1;
484 d52affa7 Gerd Hoffmann
    }
485 f8b6cc00 Markus Armbruster
    s->bs = s->qdev.conf.bs;
486 2cc977e2 ths
487 d52affa7 Gerd Hoffmann
    /* check we are really using a /dev/sg* file */
488 428c149b Christoph Hellwig
    if (!bdrv_is_sg(s->bs)) {
489 1ecda02b Markus Armbruster
        error_report("scsi-generic: not /dev/sg*");
490 d52affa7 Gerd Hoffmann
        return -1;
491 d52affa7 Gerd Hoffmann
    }
492 2cc977e2 ths
493 620f862e Markus Armbruster
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
494 620f862e Markus Armbruster
        error_report("Device doesn't support drive option werror");
495 620f862e Markus Armbruster
        return -1;
496 620f862e Markus Armbruster
    }
497 620f862e Markus Armbruster
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
498 620f862e Markus Armbruster
        error_report("Device doesn't support drive option rerror");
499 620f862e Markus Armbruster
        return -1;
500 620f862e Markus Armbruster
    }
501 620f862e Markus Armbruster
502 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
503 428c149b Christoph Hellwig
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
504 d52affa7 Gerd Hoffmann
        sg_version < 30000) {
505 1ecda02b Markus Armbruster
        error_report("scsi-generic: scsi generic interface too old");
506 d52affa7 Gerd Hoffmann
        return -1;
507 d52affa7 Gerd Hoffmann
    }
508 2cc977e2 ths
509 2cc977e2 ths
    /* get LUN of the /dev/sg? */
510 428c149b Christoph Hellwig
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
511 1ecda02b Markus Armbruster
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
512 d52affa7 Gerd Hoffmann
        return -1;
513 d52affa7 Gerd Hoffmann
    }
514 2cc977e2 ths
515 2cc977e2 ths
    /* define device state */
516 2cc977e2 ths
    s->lun = scsiid.lun;
517 89c0f643 aurel32
    DPRINTF("LUN %d\n", s->lun);
518 91376656 Gerd Hoffmann
    s->qdev.type = scsiid.scsi_type;
519 91376656 Gerd Hoffmann
    DPRINTF("device type %d\n", s->qdev.type);
520 91376656 Gerd Hoffmann
    if (s->qdev.type == TYPE_TAPE) {
521 428c149b Christoph Hellwig
        s->qdev.blocksize = get_stream_blocksize(s->bs);
522 b07995e3 Gerd Hoffmann
        if (s->qdev.blocksize == -1)
523 b07995e3 Gerd Hoffmann
            s->qdev.blocksize = 0;
524 89c0f643 aurel32
    } else {
525 428c149b Christoph Hellwig
        s->qdev.blocksize = get_blocksize(s->bs);
526 89c0f643 aurel32
        /* removable media returns 0 if not present */
527 b07995e3 Gerd Hoffmann
        if (s->qdev.blocksize <= 0) {
528 91376656 Gerd Hoffmann
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
529 b07995e3 Gerd Hoffmann
                s->qdev.blocksize = 2048;
530 89c0f643 aurel32
            else
531 b07995e3 Gerd Hoffmann
                s->qdev.blocksize = 512;
532 89c0f643 aurel32
        }
533 89c0f643 aurel32
    }
534 b07995e3 Gerd Hoffmann
    DPRINTF("block size %d\n", s->qdev.blocksize);
535 2cc977e2 ths
    s->driver_status = 0;
536 2cc977e2 ths
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
537 7d0d6950 Markus Armbruster
    bdrv_set_removable(s->bs, 0);
538 d52affa7 Gerd Hoffmann
    return 0;
539 d52affa7 Gerd Hoffmann
}
540 2cc977e2 ths
541 d52affa7 Gerd Hoffmann
static SCSIDeviceInfo scsi_generic_info = {
542 d52affa7 Gerd Hoffmann
    .qdev.name    = "scsi-generic",
543 d52affa7 Gerd Hoffmann
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
544 d52affa7 Gerd Hoffmann
    .qdev.size    = sizeof(SCSIGenericState),
545 f8b6d672 Bernhard Kohl
    .qdev.reset   = scsi_generic_reset,
546 d52affa7 Gerd Hoffmann
    .init         = scsi_generic_initfn,
547 d52affa7 Gerd Hoffmann
    .destroy      = scsi_destroy,
548 5c6c0e51 Hannes Reinecke
    .alloc_req    = scsi_new_request,
549 ad2d30f7 Paolo Bonzini
    .free_req     = scsi_free_request,
550 d52affa7 Gerd Hoffmann
    .send_command = scsi_send_command,
551 d52affa7 Gerd Hoffmann
    .read_data    = scsi_read_data,
552 d52affa7 Gerd Hoffmann
    .write_data   = scsi_write_data,
553 d52affa7 Gerd Hoffmann
    .cancel_io    = scsi_cancel_io,
554 d52affa7 Gerd Hoffmann
    .get_buf      = scsi_get_buf,
555 74382217 Hannes Reinecke
    .get_sense    = scsi_get_sense,
556 d52affa7 Gerd Hoffmann
    .qdev.props   = (Property[]) {
557 428c149b Christoph Hellwig
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
558 d52affa7 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
559 d52affa7 Gerd Hoffmann
    },
560 d52affa7 Gerd Hoffmann
};
561 2cc977e2 ths
562 d52affa7 Gerd Hoffmann
static void scsi_generic_register_devices(void)
563 d52affa7 Gerd Hoffmann
{
564 d52affa7 Gerd Hoffmann
    scsi_qdev_register(&scsi_generic_info);
565 2cc977e2 ths
}
566 d52affa7 Gerd Hoffmann
device_init(scsi_generic_register_devices)
567 d52affa7 Gerd Hoffmann
568 2cc977e2 ths
#endif /* __linux__ */