Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 290a5c60

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 2e7cc4d6 Paolo Bonzini
        case -EDOM:
128 2e7cc4d6 Paolo Bonzini
            r->req.status = TASK_SET_FULL;
129 2e7cc4d6 Paolo Bonzini
            break;
130 a1f0cce2 Hannes Reinecke
        case -EINVAL:
131 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
132 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
133 a1f0cce2 Hannes Reinecke
            break;
134 a1f0cce2 Hannes Reinecke
        case -ENOMEM:
135 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
136 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
137 a1f0cce2 Hannes Reinecke
            break;
138 a1f0cce2 Hannes Reinecke
        default:
139 a1f0cce2 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
140 a1f0cce2 Hannes Reinecke
            scsi_set_sense(s, SENSE_CODE(IO_ERROR));
141 a1f0cce2 Hannes Reinecke
            break;
142 a1f0cce2 Hannes Reinecke
        }
143 a1f0cce2 Hannes Reinecke
    } else {
144 2cc977e2 ths
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
145 f0171327 Hannes Reinecke
            r->req.status = BUSY;
146 2cc977e2 ths
            BADF("Driver Timeout\n");
147 89c0f643 aurel32
        } else if (r->io_header.status)
148 ed3a34a3 Gerd Hoffmann
            r->req.status = r->io_header.status;
149 89c0f643 aurel32
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
150 f0171327 Hannes Reinecke
            r->req.status = CHECK_CONDITION;
151 2cc977e2 ths
        else
152 f0171327 Hannes Reinecke
            r->req.status = GOOD;
153 2cc977e2 ths
    }
154 89c0f643 aurel32
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
155 ed3a34a3 Gerd Hoffmann
            r, r->req.tag, r->req.status);
156 ed3a34a3 Gerd Hoffmann
157 ed3a34a3 Gerd Hoffmann
    scsi_req_complete(&r->req);
158 2cc977e2 ths
}
159 2cc977e2 ths
160 2cc977e2 ths
/* Cancel a pending data transfer.  */
161 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
162 2cc977e2 ths
{
163 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
164 5c6c0e51 Hannes Reinecke
165 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
166 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
167 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
168 2cc977e2 ths
    }
169 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
170 2cc977e2 ths
}
171 2cc977e2 ths
172 2cc977e2 ths
static int execute_command(BlockDriverState *bdrv,
173 4c41d2ef Gerd Hoffmann
                           SCSIGenericReq *r, int direction,
174 2cc977e2 ths
                           BlockDriverCompletionFunc *complete)
175 2cc977e2 ths
{
176 4c41d2ef Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
177 4c41d2ef Gerd Hoffmann
178 2cc977e2 ths
    r->io_header.interface_id = 'S';
179 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
180 2cc977e2 ths
    r->io_header.dxferp = r->buf;
181 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
182 29362ebe Gerd Hoffmann
    r->io_header.cmdp = r->req.cmd.buf;
183 29362ebe Gerd Hoffmann
    r->io_header.cmd_len = r->req.cmd.len;
184 4c41d2ef Gerd Hoffmann
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
185 4c41d2ef Gerd Hoffmann
    r->io_header.sbp = s->sensebuf;
186 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
187 2cc977e2 ths
    r->io_header.usr_ptr = r;
188 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
189 2cc977e2 ths
190 4c41d2ef Gerd Hoffmann
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
191 4c41d2ef Gerd Hoffmann
    if (r->req.aiocb == NULL) {
192 2cc977e2 ths
        BADF("execute_command: read failed !\n");
193 a1f0cce2 Hannes Reinecke
        return -ENOMEM;
194 2cc977e2 ths
    }
195 2cc977e2 ths
196 2cc977e2 ths
    return 0;
197 2cc977e2 ths
}
198 2cc977e2 ths
199 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
200 2cc977e2 ths
{
201 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
202 2cc977e2 ths
    int len;
203 2cc977e2 ths
204 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
205 2cc977e2 ths
    if (ret) {
206 aa2b1e89 Bernhard Kohl
        DPRINTF("IO error ret %d\n", ret);
207 2cc977e2 ths
        scsi_command_complete(r, ret);
208 2cc977e2 ths
        return;
209 2cc977e2 ths
    }
210 2cc977e2 ths
    len = r->io_header.dxfer_len - r->io_header.resid;
211 4c41d2ef Gerd Hoffmann
    DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
212 2cc977e2 ths
213 2cc977e2 ths
    r->len = -1;
214 40f16dd1 Paolo Bonzini
    if (len == 0) {
215 89c0f643 aurel32
        scsi_command_complete(r, 0);
216 40f16dd1 Paolo Bonzini
    } else {
217 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, len);
218 40f16dd1 Paolo Bonzini
    }
219 2cc977e2 ths
}
220 2cc977e2 ths
221 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
222 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
223 2cc977e2 ths
{
224 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
225 5c6c0e51 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
226 2cc977e2 ths
    int ret;
227 2cc977e2 ths
228 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
229 2cc977e2 ths
    if (r->len == -1) {
230 2cc977e2 ths
        scsi_command_complete(r, 0);
231 2cc977e2 ths
        return;
232 2cc977e2 ths
    }
233 2cc977e2 ths
234 29362ebe Gerd Hoffmann
    if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
235 2cc977e2 ths
    {
236 89c0f643 aurel32
        s->senselen = MIN(r->len, s->senselen);
237 89c0f643 aurel32
        memcpy(r->buf, s->sensebuf, s->senselen);
238 2cc977e2 ths
        r->io_header.driver_status = 0;
239 89c0f643 aurel32
        r->io_header.status = 0;
240 89c0f643 aurel32
        r->io_header.dxfer_len  = s->senselen;
241 2cc977e2 ths
        r->len = -1;
242 4c41d2ef Gerd Hoffmann
        DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
243 a9dd6843 aliguori
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
244 a9dd6843 aliguori
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
245 a9dd6843 aliguori
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
246 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, s->senselen);
247 a1f0cce2 Hannes Reinecke
        /* Clear sensebuf after REQUEST_SENSE */
248 a1f0cce2 Hannes Reinecke
        scsi_clear_sense(s);
249 2cc977e2 ths
        return;
250 2cc977e2 ths
    }
251 2cc977e2 ths
252 428c149b Christoph Hellwig
    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
253 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
254 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
255 2cc977e2 ths
        return;
256 2cc977e2 ths
    }
257 2cc977e2 ths
}
258 2cc977e2 ths
259 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
260 2cc977e2 ths
{
261 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
262 4c41d2ef Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
263 2cc977e2 ths
264 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
265 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
266 2cc977e2 ths
    if (ret) {
267 2cc977e2 ths
        DPRINTF("IO error\n");
268 2cc977e2 ths
        scsi_command_complete(r, ret);
269 2cc977e2 ths
        return;
270 2cc977e2 ths
    }
271 2cc977e2 ths
272 29362ebe Gerd Hoffmann
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
273 91376656 Gerd Hoffmann
        s->qdev.type == TYPE_TAPE) {
274 b07995e3 Gerd Hoffmann
        s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
275 aa2b1e89 Bernhard Kohl
        DPRINTF("block size %d\n", s->qdev.blocksize);
276 89c0f643 aurel32
    }
277 89c0f643 aurel32
278 2cc977e2 ths
    scsi_command_complete(r, ret);
279 2cc977e2 ths
}
280 2cc977e2 ths
281 2cc977e2 ths
/* Write data to a scsi device.  Returns nonzero on failure.
282 2cc977e2 ths
   The transfer may complete asynchronously.  */
283 42741212 Paolo Bonzini
static void scsi_write_data(SCSIRequest *req)
284 2cc977e2 ths
{
285 5c6c0e51 Hannes Reinecke
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
286 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
287 2cc977e2 ths
    int ret;
288 2cc977e2 ths
289 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
290 2cc977e2 ths
    if (r->len == 0) {
291 2cc977e2 ths
        r->len = r->buflen;
292 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, r->len);
293 42741212 Paolo Bonzini
        return;
294 2cc977e2 ths
    }
295 2cc977e2 ths
296 428c149b Christoph Hellwig
    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
297 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
298 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
299 2cc977e2 ths
    }
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 1455084e Paolo Bonzini
    if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
341 1455084e Paolo Bonzini
        DPRINTF("Unimplemented LUN %d\n", req->lun);
342 a1f0cce2 Hannes Reinecke
        scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
343 2b8b3bb9 Paolo Bonzini
        r->req.status = CHECK_CONDITION;
344 2b8b3bb9 Paolo Bonzini
        scsi_req_complete(&r->req);
345 89c0f643 aurel32
        return 0;
346 89c0f643 aurel32
    }
347 89c0f643 aurel32
348 2ec749cb Gerd Hoffmann
    if (-1 == scsi_req_parse(&r->req, cmd)) {
349 2ec749cb Gerd Hoffmann
        BADF("Unsupported command length, command %x\n", cmd[0]);
350 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, -EINVAL);
351 2ec749cb Gerd Hoffmann
        return 0;
352 2ec749cb Gerd Hoffmann
    }
353 2ec749cb Gerd Hoffmann
    scsi_req_fixup(&r->req);
354 2ec749cb Gerd Hoffmann
355 aa2b1e89 Bernhard Kohl
    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
356 aa2b1e89 Bernhard Kohl
            r->req.cmd.xfer, cmd[0]);
357 aa2b1e89 Bernhard Kohl
358 aa2b1e89 Bernhard Kohl
#ifdef DEBUG_SCSI
359 aa2b1e89 Bernhard Kohl
    {
360 aa2b1e89 Bernhard Kohl
        int i;
361 aa2b1e89 Bernhard Kohl
        for (i = 1; i < r->req.cmd.len; i++) {
362 aa2b1e89 Bernhard Kohl
            printf(" 0x%02x", cmd[i]);
363 aa2b1e89 Bernhard Kohl
        }
364 aa2b1e89 Bernhard Kohl
        printf("\n");
365 aa2b1e89 Bernhard Kohl
    }
366 aa2b1e89 Bernhard Kohl
#endif
367 2cc977e2 ths
368 2ec749cb Gerd Hoffmann
    if (r->req.cmd.xfer == 0) {
369 2cc977e2 ths
        if (r->buf != NULL)
370 e3c916e6 Jean-Christophe DUBOIS
            qemu_free(r->buf);
371 2cc977e2 ths
        r->buflen = 0;
372 2cc977e2 ths
        r->buf = NULL;
373 428c149b Christoph Hellwig
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
374 a1f0cce2 Hannes Reinecke
        if (ret < 0) {
375 a1f0cce2 Hannes Reinecke
            scsi_command_complete(r, ret);
376 a1f0cce2 Hannes Reinecke
            return 0;
377 2cc977e2 ths
        }
378 2cc977e2 ths
        return 0;
379 2cc977e2 ths
    }
380 2cc977e2 ths
381 2ec749cb Gerd Hoffmann
    if (r->buflen != r->req.cmd.xfer) {
382 2cc977e2 ths
        if (r->buf != NULL)
383 e3c916e6 Jean-Christophe DUBOIS
            qemu_free(r->buf);
384 2ec749cb Gerd Hoffmann
        r->buf = qemu_malloc(r->req.cmd.xfer);
385 2ec749cb Gerd Hoffmann
        r->buflen = r->req.cmd.xfer;
386 2cc977e2 ths
    }
387 2cc977e2 ths
388 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
389 2ec749cb Gerd Hoffmann
    r->len = r->req.cmd.xfer;
390 97a06435 Gerd Hoffmann
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
391 2cc977e2 ths
        r->len = 0;
392 5c6c0e51 Hannes Reinecke
        return -r->req.cmd.xfer;
393 ad2d30f7 Paolo Bonzini
    } else {
394 5c6c0e51 Hannes Reinecke
        return r->req.cmd.xfer;
395 2cc977e2 ths
    }
396 2cc977e2 ths
}
397 2cc977e2 ths
398 2cc977e2 ths
static int get_blocksize(BlockDriverState *bdrv)
399 2cc977e2 ths
{
400 2cc977e2 ths
    uint8_t cmd[10];
401 2cc977e2 ths
    uint8_t buf[8];
402 2cc977e2 ths
    uint8_t sensebuf[8];
403 2cc977e2 ths
    sg_io_hdr_t io_header;
404 2cc977e2 ths
    int ret;
405 2cc977e2 ths
406 4f26a486 aliguori
    memset(cmd, 0, sizeof(cmd));
407 4f26a486 aliguori
    memset(buf, 0, sizeof(buf));
408 2cc977e2 ths
    cmd[0] = READ_CAPACITY;
409 2cc977e2 ths
410 2cc977e2 ths
    memset(&io_header, 0, sizeof(io_header));
411 2cc977e2 ths
    io_header.interface_id = 'S';
412 2cc977e2 ths
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
413 2cc977e2 ths
    io_header.dxfer_len = sizeof(buf);
414 2cc977e2 ths
    io_header.dxferp = buf;
415 2cc977e2 ths
    io_header.cmdp = cmd;
416 2cc977e2 ths
    io_header.cmd_len = sizeof(cmd);
417 2cc977e2 ths
    io_header.mx_sb_len = sizeof(sensebuf);
418 2cc977e2 ths
    io_header.sbp = sensebuf;
419 2cc977e2 ths
    io_header.timeout = 6000; /* XXX */
420 2cc977e2 ths
421 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
422 7d780669 aliguori
    if (ret < 0)
423 2cc977e2 ths
        return -1;
424 2cc977e2 ths
425 2cc977e2 ths
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
426 2cc977e2 ths
}
427 2cc977e2 ths
428 89c0f643 aurel32
static int get_stream_blocksize(BlockDriverState *bdrv)
429 89c0f643 aurel32
{
430 89c0f643 aurel32
    uint8_t cmd[6];
431 89c0f643 aurel32
    uint8_t buf[12];
432 89c0f643 aurel32
    uint8_t sensebuf[8];
433 89c0f643 aurel32
    sg_io_hdr_t io_header;
434 89c0f643 aurel32
    int ret;
435 89c0f643 aurel32
436 89c0f643 aurel32
    memset(cmd, 0, sizeof(cmd));
437 89c0f643 aurel32
    memset(buf, 0, sizeof(buf));
438 89c0f643 aurel32
    cmd[0] = MODE_SENSE;
439 89c0f643 aurel32
    cmd[4] = sizeof(buf);
440 89c0f643 aurel32
441 89c0f643 aurel32
    memset(&io_header, 0, sizeof(io_header));
442 89c0f643 aurel32
    io_header.interface_id = 'S';
443 89c0f643 aurel32
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
444 89c0f643 aurel32
    io_header.dxfer_len = sizeof(buf);
445 89c0f643 aurel32
    io_header.dxferp = buf;
446 89c0f643 aurel32
    io_header.cmdp = cmd;
447 89c0f643 aurel32
    io_header.cmd_len = sizeof(cmd);
448 89c0f643 aurel32
    io_header.mx_sb_len = sizeof(sensebuf);
449 89c0f643 aurel32
    io_header.sbp = sensebuf;
450 89c0f643 aurel32
    io_header.timeout = 6000; /* XXX */
451 89c0f643 aurel32
452 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
453 7d780669 aliguori
    if (ret < 0)
454 89c0f643 aurel32
        return -1;
455 89c0f643 aurel32
456 89c0f643 aurel32
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
457 89c0f643 aurel32
}
458 89c0f643 aurel32
459 f8b6d672 Bernhard Kohl
static void scsi_generic_reset(DeviceState *dev)
460 f8b6d672 Bernhard Kohl
{
461 f8b6d672 Bernhard Kohl
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
462 f8b6d672 Bernhard Kohl
463 c557e889 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev);
464 f8b6d672 Bernhard Kohl
}
465 f8b6d672 Bernhard Kohl
466 f8b6d672 Bernhard Kohl
static void scsi_destroy(SCSIDevice *d)
467 f8b6d672 Bernhard Kohl
{
468 f8b6d672 Bernhard Kohl
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
469 f8b6d672 Bernhard Kohl
470 c557e889 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev);
471 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
472 2cc977e2 ths
}
473 2cc977e2 ths
474 d52affa7 Gerd Hoffmann
static int scsi_generic_initfn(SCSIDevice *dev)
475 2cc977e2 ths
{
476 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
477 2cc977e2 ths
    int sg_version;
478 2cc977e2 ths
    struct sg_scsi_id scsiid;
479 2cc977e2 ths
480 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
481 1ecda02b Markus Armbruster
        error_report("scsi-generic: drive property not set");
482 d52affa7 Gerd Hoffmann
        return -1;
483 d52affa7 Gerd Hoffmann
    }
484 f8b6cc00 Markus Armbruster
    s->bs = s->qdev.conf.bs;
485 2cc977e2 ths
486 d52affa7 Gerd Hoffmann
    /* check we are really using a /dev/sg* file */
487 428c149b Christoph Hellwig
    if (!bdrv_is_sg(s->bs)) {
488 1ecda02b Markus Armbruster
        error_report("scsi-generic: not /dev/sg*");
489 d52affa7 Gerd Hoffmann
        return -1;
490 d52affa7 Gerd Hoffmann
    }
491 2cc977e2 ths
492 620f862e Markus Armbruster
    if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
493 620f862e Markus Armbruster
        error_report("Device doesn't support drive option werror");
494 620f862e Markus Armbruster
        return -1;
495 620f862e Markus Armbruster
    }
496 620f862e Markus Armbruster
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
497 620f862e Markus Armbruster
        error_report("Device doesn't support drive option rerror");
498 620f862e Markus Armbruster
        return -1;
499 620f862e Markus Armbruster
    }
500 620f862e Markus Armbruster
501 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
502 428c149b Christoph Hellwig
    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
503 d52affa7 Gerd Hoffmann
        sg_version < 30000) {
504 1ecda02b Markus Armbruster
        error_report("scsi-generic: scsi generic interface too old");
505 d52affa7 Gerd Hoffmann
        return -1;
506 d52affa7 Gerd Hoffmann
    }
507 2cc977e2 ths
508 2cc977e2 ths
    /* get LUN of the /dev/sg? */
509 428c149b Christoph Hellwig
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
510 1ecda02b Markus Armbruster
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
511 d52affa7 Gerd Hoffmann
        return -1;
512 d52affa7 Gerd Hoffmann
    }
513 2cc977e2 ths
514 2cc977e2 ths
    /* define device state */
515 2cc977e2 ths
    s->lun = scsiid.lun;
516 89c0f643 aurel32
    DPRINTF("LUN %d\n", s->lun);
517 91376656 Gerd Hoffmann
    s->qdev.type = scsiid.scsi_type;
518 91376656 Gerd Hoffmann
    DPRINTF("device type %d\n", s->qdev.type);
519 91376656 Gerd Hoffmann
    if (s->qdev.type == TYPE_TAPE) {
520 428c149b Christoph Hellwig
        s->qdev.blocksize = get_stream_blocksize(s->bs);
521 b07995e3 Gerd Hoffmann
        if (s->qdev.blocksize == -1)
522 b07995e3 Gerd Hoffmann
            s->qdev.blocksize = 0;
523 89c0f643 aurel32
    } else {
524 428c149b Christoph Hellwig
        s->qdev.blocksize = get_blocksize(s->bs);
525 89c0f643 aurel32
        /* removable media returns 0 if not present */
526 b07995e3 Gerd Hoffmann
        if (s->qdev.blocksize <= 0) {
527 91376656 Gerd Hoffmann
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
528 b07995e3 Gerd Hoffmann
                s->qdev.blocksize = 2048;
529 89c0f643 aurel32
            else
530 b07995e3 Gerd Hoffmann
                s->qdev.blocksize = 512;
531 89c0f643 aurel32
        }
532 89c0f643 aurel32
    }
533 b07995e3 Gerd Hoffmann
    DPRINTF("block size %d\n", s->qdev.blocksize);
534 2cc977e2 ths
    s->driver_status = 0;
535 2cc977e2 ths
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
536 7d0d6950 Markus Armbruster
    bdrv_set_removable(s->bs, 0);
537 d52affa7 Gerd Hoffmann
    return 0;
538 d52affa7 Gerd Hoffmann
}
539 2cc977e2 ths
540 d52affa7 Gerd Hoffmann
static SCSIDeviceInfo scsi_generic_info = {
541 d52affa7 Gerd Hoffmann
    .qdev.name    = "scsi-generic",
542 d52affa7 Gerd Hoffmann
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
543 d52affa7 Gerd Hoffmann
    .qdev.size    = sizeof(SCSIGenericState),
544 f8b6d672 Bernhard Kohl
    .qdev.reset   = scsi_generic_reset,
545 d52affa7 Gerd Hoffmann
    .init         = scsi_generic_initfn,
546 d52affa7 Gerd Hoffmann
    .destroy      = scsi_destroy,
547 5c6c0e51 Hannes Reinecke
    .alloc_req    = scsi_new_request,
548 ad2d30f7 Paolo Bonzini
    .free_req     = scsi_free_request,
549 d52affa7 Gerd Hoffmann
    .send_command = scsi_send_command,
550 d52affa7 Gerd Hoffmann
    .read_data    = scsi_read_data,
551 d52affa7 Gerd Hoffmann
    .write_data   = scsi_write_data,
552 d52affa7 Gerd Hoffmann
    .cancel_io    = scsi_cancel_io,
553 d52affa7 Gerd Hoffmann
    .get_buf      = scsi_get_buf,
554 74382217 Hannes Reinecke
    .get_sense    = scsi_get_sense,
555 d52affa7 Gerd Hoffmann
    .qdev.props   = (Property[]) {
556 428c149b Christoph Hellwig
        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
557 d52affa7 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
558 d52affa7 Gerd Hoffmann
    },
559 d52affa7 Gerd Hoffmann
};
560 2cc977e2 ths
561 d52affa7 Gerd Hoffmann
static void scsi_generic_register_devices(void)
562 d52affa7 Gerd Hoffmann
{
563 d52affa7 Gerd Hoffmann
    scsi_qdev_register(&scsi_generic_info);
564 2cc977e2 ths
}
565 d52affa7 Gerd Hoffmann
device_init(scsi_generic_register_devices)
566 d52affa7 Gerd Hoffmann
567 2cc977e2 ths
#endif /* __linux__ */