Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ fc4f0754

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