Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ ad2d30f7

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