Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ dc333cd6

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