Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 40f16dd1

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