Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 6618f909

History | View | Annotate | Download (13.1 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 8e31bf38 Matthew Fernandez
 * This code is licensed 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 a3b16e71 Paolo Bonzini
#define SG_ERR_DRIVER_TIMEOUT  0x06
43 a3b16e71 Paolo Bonzini
#define SG_ERR_DRIVER_SENSE    0x08
44 a3b16e71 Paolo Bonzini
45 a3b16e71 Paolo Bonzini
#define SG_ERR_DID_OK          0x00
46 a3b16e71 Paolo Bonzini
#define SG_ERR_DID_NO_CONNECT  0x01
47 a3b16e71 Paolo Bonzini
#define SG_ERR_DID_BUS_BUSY    0x02
48 a3b16e71 Paolo Bonzini
#define SG_ERR_DID_TIME_OUT    0x03
49 2cc977e2 ths
50 2cc977e2 ths
#ifndef MAX_UINT
51 2cc977e2 ths
#define MAX_UINT ((unsigned int)-1)
52 2cc977e2 ths
#endif
53 2cc977e2 ths
54 4c41d2ef Gerd Hoffmann
typedef struct SCSIGenericReq {
55 4c41d2ef Gerd Hoffmann
    SCSIRequest req;
56 2cc977e2 ths
    uint8_t *buf;
57 2cc977e2 ths
    int buflen;
58 2cc977e2 ths
    int len;
59 2cc977e2 ths
    sg_io_hdr_t io_header;
60 4c41d2ef Gerd Hoffmann
} SCSIGenericReq;
61 2cc977e2 ths
62 ad2d30f7 Paolo Bonzini
static void scsi_free_request(SCSIRequest *req)
63 2cc977e2 ths
{
64 ad2d30f7 Paolo Bonzini
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
65 ad2d30f7 Paolo Bonzini
66 7267c094 Anthony Liguori
    g_free(r->buf);
67 2cc977e2 ths
}
68 2cc977e2 ths
69 2cc977e2 ths
/* Helper function for command completion.  */
70 2cc977e2 ths
static void scsi_command_complete(void *opaque, int ret)
71 2cc977e2 ths
{
72 682a9b21 Paolo Bonzini
    int status;
73 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
74 2cc977e2 ths
75 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
76 a3b16e71 Paolo Bonzini
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
77 b45ef674 Paolo Bonzini
        r->req.sense_len = r->io_header.sb_len_wr;
78 a3b16e71 Paolo Bonzini
    }
79 89c0f643 aurel32
80 a1f0cce2 Hannes Reinecke
    if (ret != 0) {
81 a1f0cce2 Hannes Reinecke
        switch (ret) {
82 2e7cc4d6 Paolo Bonzini
        case -EDOM:
83 682a9b21 Paolo Bonzini
            status = TASK_SET_FULL;
84 2e7cc4d6 Paolo Bonzini
            break;
85 a1f0cce2 Hannes Reinecke
        case -ENOMEM:
86 682a9b21 Paolo Bonzini
            status = CHECK_CONDITION;
87 b45ef674 Paolo Bonzini
            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
88 a1f0cce2 Hannes Reinecke
            break;
89 a1f0cce2 Hannes Reinecke
        default:
90 682a9b21 Paolo Bonzini
            status = CHECK_CONDITION;
91 b45ef674 Paolo Bonzini
            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
92 a1f0cce2 Hannes Reinecke
            break;
93 a1f0cce2 Hannes Reinecke
        }
94 a1f0cce2 Hannes Reinecke
    } else {
95 a3b16e71 Paolo Bonzini
        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
96 a3b16e71 Paolo Bonzini
            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
97 a3b16e71 Paolo Bonzini
            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
98 a3b16e71 Paolo Bonzini
            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
99 682a9b21 Paolo Bonzini
            status = BUSY;
100 2cc977e2 ths
            BADF("Driver Timeout\n");
101 a3b16e71 Paolo Bonzini
        } else if (r->io_header.host_status) {
102 a3b16e71 Paolo Bonzini
            status = CHECK_CONDITION;
103 a3b16e71 Paolo Bonzini
            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
104 682a9b21 Paolo Bonzini
        } else if (r->io_header.status) {
105 682a9b21 Paolo Bonzini
            status = r->io_header.status;
106 b45ef674 Paolo Bonzini
        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
107 682a9b21 Paolo Bonzini
            status = CHECK_CONDITION;
108 682a9b21 Paolo Bonzini
        } else {
109 682a9b21 Paolo Bonzini
            status = GOOD;
110 682a9b21 Paolo Bonzini
        }
111 2cc977e2 ths
    }
112 89c0f643 aurel32
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113 682a9b21 Paolo Bonzini
            r, r->req.tag, status);
114 ed3a34a3 Gerd Hoffmann
115 682a9b21 Paolo Bonzini
    scsi_req_complete(&r->req, status);
116 c9501c95 Paolo Bonzini
    if (!r->req.io_canceled) {
117 c9501c95 Paolo Bonzini
        scsi_req_unref(&r->req);
118 c9501c95 Paolo Bonzini
    }
119 2cc977e2 ths
}
120 2cc977e2 ths
121 2cc977e2 ths
/* Cancel a pending data transfer.  */
122 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
123 2cc977e2 ths
{
124 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
125 5c6c0e51 Hannes Reinecke
126 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
127 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
128 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
129 c9501c95 Paolo Bonzini
130 c9501c95 Paolo Bonzini
        /* This reference was left in by scsi_*_data.  We take ownership of
131 c9501c95 Paolo Bonzini
         * it independent of whether bdrv_aio_cancel completes the request
132 c9501c95 Paolo Bonzini
         * or not.  */
133 c9501c95 Paolo Bonzini
        scsi_req_unref(&r->req);
134 2cc977e2 ths
    }
135 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
136 2cc977e2 ths
}
137 2cc977e2 ths
138 2cc977e2 ths
static int execute_command(BlockDriverState *bdrv,
139 4c41d2ef Gerd Hoffmann
                           SCSIGenericReq *r, int direction,
140 2cc977e2 ths
                           BlockDriverCompletionFunc *complete)
141 2cc977e2 ths
{
142 2cc977e2 ths
    r->io_header.interface_id = 'S';
143 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
144 2cc977e2 ths
    r->io_header.dxferp = r->buf;
145 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
146 29362ebe Gerd Hoffmann
    r->io_header.cmdp = r->req.cmd.buf;
147 29362ebe Gerd Hoffmann
    r->io_header.cmd_len = r->req.cmd.len;
148 b45ef674 Paolo Bonzini
    r->io_header.mx_sb_len = sizeof(r->req.sense);
149 b45ef674 Paolo Bonzini
    r->io_header.sbp = r->req.sense;
150 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
151 2cc977e2 ths
    r->io_header.usr_ptr = r;
152 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
153 2cc977e2 ths
154 4c41d2ef Gerd Hoffmann
    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
155 2cc977e2 ths
156 2cc977e2 ths
    return 0;
157 2cc977e2 ths
}
158 2cc977e2 ths
159 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
160 2cc977e2 ths
{
161 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
162 9b6eef8a Paolo Bonzini
    SCSIDevice *s = r->req.dev;
163 2cc977e2 ths
    int len;
164 2cc977e2 ths
165 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
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 9b6eef8a Paolo Bonzini
        /* Snoop READ CAPACITY output to set the blocksize.  */
179 9b6eef8a Paolo Bonzini
        if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
180 9b6eef8a Paolo Bonzini
            s->blocksize = ldl_be_p(&r->buf[4]);
181 7877903a Paolo Bonzini
            s->max_lba = ldl_be_p(&r->buf[0]);
182 9b6eef8a Paolo Bonzini
        } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
183 9b6eef8a Paolo Bonzini
                   (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
184 9b6eef8a Paolo Bonzini
            s->blocksize = ldl_be_p(&r->buf[8]);
185 7877903a Paolo Bonzini
            s->max_lba = ldq_be_p(&r->buf[0]);
186 9b6eef8a Paolo Bonzini
        }
187 9b6eef8a Paolo Bonzini
        bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
188 9b6eef8a Paolo Bonzini
189 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, len);
190 c9501c95 Paolo Bonzini
        if (!r->req.io_canceled) {
191 c9501c95 Paolo Bonzini
            scsi_req_unref(&r->req);
192 c9501c95 Paolo Bonzini
        }
193 40f16dd1 Paolo Bonzini
    }
194 2cc977e2 ths
}
195 2cc977e2 ths
196 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
197 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
198 2cc977e2 ths
{
199 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
200 8869e103 Paolo Bonzini
    SCSIDevice *s = r->req.dev;
201 2cc977e2 ths
    int ret;
202 2cc977e2 ths
203 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_read_data 0x%x\n", req->tag);
204 c9501c95 Paolo Bonzini
205 c9501c95 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
206 c9501c95 Paolo Bonzini
    scsi_req_ref(&r->req);
207 2cc977e2 ths
    if (r->len == -1) {
208 2cc977e2 ths
        scsi_command_complete(r, 0);
209 2cc977e2 ths
        return;
210 2cc977e2 ths
    }
211 2cc977e2 ths
212 8869e103 Paolo Bonzini
    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
213 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
214 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
215 2cc977e2 ths
    }
216 2cc977e2 ths
}
217 2cc977e2 ths
218 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
219 2cc977e2 ths
{
220 4c41d2ef Gerd Hoffmann
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
221 8869e103 Paolo Bonzini
    SCSIDevice *s = r->req.dev;
222 2cc977e2 ths
223 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
224 d33e0ce2 Paolo Bonzini
    r->req.aiocb = NULL;
225 2cc977e2 ths
    if (ret) {
226 2cc977e2 ths
        DPRINTF("IO error\n");
227 2cc977e2 ths
        scsi_command_complete(r, ret);
228 2cc977e2 ths
        return;
229 2cc977e2 ths
    }
230 2cc977e2 ths
231 29362ebe Gerd Hoffmann
    if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
232 8869e103 Paolo Bonzini
        s->type == TYPE_TAPE) {
233 8869e103 Paolo Bonzini
        s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
234 8869e103 Paolo Bonzini
        DPRINTF("block size %d\n", s->blocksize);
235 89c0f643 aurel32
    }
236 89c0f643 aurel32
237 2cc977e2 ths
    scsi_command_complete(r, ret);
238 2cc977e2 ths
}
239 2cc977e2 ths
240 2cc977e2 ths
/* Write data to a scsi device.  Returns nonzero on failure.
241 2cc977e2 ths
   The transfer may complete asynchronously.  */
242 42741212 Paolo Bonzini
static void scsi_write_data(SCSIRequest *req)
243 2cc977e2 ths
{
244 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
245 8869e103 Paolo Bonzini
    SCSIDevice *s = r->req.dev;
246 2cc977e2 ths
    int ret;
247 2cc977e2 ths
248 5c6c0e51 Hannes Reinecke
    DPRINTF("scsi_write_data 0x%x\n", req->tag);
249 2cc977e2 ths
    if (r->len == 0) {
250 2cc977e2 ths
        r->len = r->buflen;
251 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, r->len);
252 42741212 Paolo Bonzini
        return;
253 2cc977e2 ths
    }
254 2cc977e2 ths
255 c9501c95 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
256 c9501c95 Paolo Bonzini
    scsi_req_ref(&r->req);
257 8869e103 Paolo Bonzini
    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
258 a1f0cce2 Hannes Reinecke
    if (ret < 0) {
259 a1f0cce2 Hannes Reinecke
        scsi_command_complete(r, ret);
260 2cc977e2 ths
    }
261 2cc977e2 ths
}
262 2cc977e2 ths
263 2cc977e2 ths
/* Return a pointer to the data buffer.  */
264 5c6c0e51 Hannes Reinecke
static uint8_t *scsi_get_buf(SCSIRequest *req)
265 2cc977e2 ths
{
266 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267 5c6c0e51 Hannes Reinecke
268 2cc977e2 ths
    return r->buf;
269 2cc977e2 ths
}
270 2cc977e2 ths
271 2cc977e2 ths
/* Execute a scsi command.  Returns the length of the data expected by the
272 2cc977e2 ths
   command.  This will be Positive for data transfers from the device
273 2cc977e2 ths
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
274 2cc977e2 ths
   and zero if the command does not transfer any data.  */
275 2cc977e2 ths
276 5c6c0e51 Hannes Reinecke
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
277 2cc977e2 ths
{
278 5c6c0e51 Hannes Reinecke
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
279 8869e103 Paolo Bonzini
    SCSIDevice *s = r->req.dev;
280 2cc977e2 ths
    int ret;
281 2cc977e2 ths
282 aa2b1e89 Bernhard Kohl
    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
283 aa2b1e89 Bernhard Kohl
            r->req.cmd.xfer, cmd[0]);
284 aa2b1e89 Bernhard Kohl
285 aa2b1e89 Bernhard Kohl
#ifdef DEBUG_SCSI
286 aa2b1e89 Bernhard Kohl
    {
287 aa2b1e89 Bernhard Kohl
        int i;
288 aa2b1e89 Bernhard Kohl
        for (i = 1; i < r->req.cmd.len; i++) {
289 aa2b1e89 Bernhard Kohl
            printf(" 0x%02x", cmd[i]);
290 aa2b1e89 Bernhard Kohl
        }
291 aa2b1e89 Bernhard Kohl
        printf("\n");
292 aa2b1e89 Bernhard Kohl
    }
293 aa2b1e89 Bernhard Kohl
#endif
294 2cc977e2 ths
295 2ec749cb Gerd Hoffmann
    if (r->req.cmd.xfer == 0) {
296 2cc977e2 ths
        if (r->buf != NULL)
297 7267c094 Anthony Liguori
            g_free(r->buf);
298 2cc977e2 ths
        r->buflen = 0;
299 2cc977e2 ths
        r->buf = NULL;
300 c9501c95 Paolo Bonzini
        /* The request is used as the AIO opaque value, so add a ref.  */
301 c9501c95 Paolo Bonzini
        scsi_req_ref(&r->req);
302 8869e103 Paolo Bonzini
        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
303 a1f0cce2 Hannes Reinecke
        if (ret < 0) {
304 a1f0cce2 Hannes Reinecke
            scsi_command_complete(r, ret);
305 a1f0cce2 Hannes Reinecke
            return 0;
306 2cc977e2 ths
        }
307 2cc977e2 ths
        return 0;
308 2cc977e2 ths
    }
309 2cc977e2 ths
310 2ec749cb Gerd Hoffmann
    if (r->buflen != r->req.cmd.xfer) {
311 2cc977e2 ths
        if (r->buf != NULL)
312 7267c094 Anthony Liguori
            g_free(r->buf);
313 7267c094 Anthony Liguori
        r->buf = g_malloc(r->req.cmd.xfer);
314 2ec749cb Gerd Hoffmann
        r->buflen = r->req.cmd.xfer;
315 2cc977e2 ths
    }
316 2cc977e2 ths
317 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
318 2ec749cb Gerd Hoffmann
    r->len = r->req.cmd.xfer;
319 97a06435 Gerd Hoffmann
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
320 2cc977e2 ths
        r->len = 0;
321 5c6c0e51 Hannes Reinecke
        return -r->req.cmd.xfer;
322 ad2d30f7 Paolo Bonzini
    } else {
323 5c6c0e51 Hannes Reinecke
        return r->req.cmd.xfer;
324 2cc977e2 ths
    }
325 2cc977e2 ths
}
326 2cc977e2 ths
327 89c0f643 aurel32
static int get_stream_blocksize(BlockDriverState *bdrv)
328 89c0f643 aurel32
{
329 89c0f643 aurel32
    uint8_t cmd[6];
330 89c0f643 aurel32
    uint8_t buf[12];
331 89c0f643 aurel32
    uint8_t sensebuf[8];
332 89c0f643 aurel32
    sg_io_hdr_t io_header;
333 89c0f643 aurel32
    int ret;
334 89c0f643 aurel32
335 89c0f643 aurel32
    memset(cmd, 0, sizeof(cmd));
336 89c0f643 aurel32
    memset(buf, 0, sizeof(buf));
337 89c0f643 aurel32
    cmd[0] = MODE_SENSE;
338 89c0f643 aurel32
    cmd[4] = sizeof(buf);
339 89c0f643 aurel32
340 89c0f643 aurel32
    memset(&io_header, 0, sizeof(io_header));
341 89c0f643 aurel32
    io_header.interface_id = 'S';
342 89c0f643 aurel32
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
343 89c0f643 aurel32
    io_header.dxfer_len = sizeof(buf);
344 89c0f643 aurel32
    io_header.dxferp = buf;
345 89c0f643 aurel32
    io_header.cmdp = cmd;
346 89c0f643 aurel32
    io_header.cmd_len = sizeof(cmd);
347 89c0f643 aurel32
    io_header.mx_sb_len = sizeof(sensebuf);
348 89c0f643 aurel32
    io_header.sbp = sensebuf;
349 89c0f643 aurel32
    io_header.timeout = 6000; /* XXX */
350 89c0f643 aurel32
351 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
352 fe0ed712 Paolo Bonzini
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
353 89c0f643 aurel32
        return -1;
354 fe0ed712 Paolo Bonzini
    }
355 89c0f643 aurel32
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
356 89c0f643 aurel32
}
357 89c0f643 aurel32
358 f8b6d672 Bernhard Kohl
static void scsi_generic_reset(DeviceState *dev)
359 f8b6d672 Bernhard Kohl
{
360 8869e103 Paolo Bonzini
    SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
361 f8b6d672 Bernhard Kohl
362 8869e103 Paolo Bonzini
    scsi_device_purge_requests(s, SENSE_CODE(RESET));
363 f8b6d672 Bernhard Kohl
}
364 f8b6d672 Bernhard Kohl
365 8869e103 Paolo Bonzini
static void scsi_destroy(SCSIDevice *s)
366 f8b6d672 Bernhard Kohl
{
367 8869e103 Paolo Bonzini
    scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
368 8869e103 Paolo Bonzini
    blockdev_mark_auto_del(s->conf.bs);
369 2cc977e2 ths
}
370 2cc977e2 ths
371 8869e103 Paolo Bonzini
static int scsi_generic_initfn(SCSIDevice *s)
372 2cc977e2 ths
{
373 2cc977e2 ths
    int sg_version;
374 2cc977e2 ths
    struct sg_scsi_id scsiid;
375 2cc977e2 ths
376 8869e103 Paolo Bonzini
    if (!s->conf.bs) {
377 6a84cb1f Markus Armbruster
        error_report("drive property not set");
378 d52affa7 Gerd Hoffmann
        return -1;
379 d52affa7 Gerd Hoffmann
    }
380 2cc977e2 ths
381 d52affa7 Gerd Hoffmann
    /* check we are really using a /dev/sg* file */
382 8869e103 Paolo Bonzini
    if (!bdrv_is_sg(s->conf.bs)) {
383 6a84cb1f Markus Armbruster
        error_report("not /dev/sg*");
384 d52affa7 Gerd Hoffmann
        return -1;
385 d52affa7 Gerd Hoffmann
    }
386 2cc977e2 ths
387 8869e103 Paolo Bonzini
    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
388 620f862e Markus Armbruster
        error_report("Device doesn't support drive option werror");
389 620f862e Markus Armbruster
        return -1;
390 620f862e Markus Armbruster
    }
391 8869e103 Paolo Bonzini
    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
392 620f862e Markus Armbruster
        error_report("Device doesn't support drive option rerror");
393 620f862e Markus Armbruster
        return -1;
394 620f862e Markus Armbruster
    }
395 620f862e Markus Armbruster
396 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
397 8869e103 Paolo Bonzini
    if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
398 d52affa7 Gerd Hoffmann
        sg_version < 30000) {
399 6a84cb1f Markus Armbruster
        error_report("scsi generic interface too old");
400 d52affa7 Gerd Hoffmann
        return -1;
401 d52affa7 Gerd Hoffmann
    }
402 2cc977e2 ths
403 2cc977e2 ths
    /* get LUN of the /dev/sg? */
404 8869e103 Paolo Bonzini
    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
405 6a84cb1f Markus Armbruster
        error_report("SG_GET_SCSI_ID ioctl failed");
406 d52affa7 Gerd Hoffmann
        return -1;
407 d52affa7 Gerd Hoffmann
    }
408 2cc977e2 ths
409 2cc977e2 ths
    /* define device state */
410 8869e103 Paolo Bonzini
    s->type = scsiid.scsi_type;
411 8869e103 Paolo Bonzini
    DPRINTF("device type %d\n", s->type);
412 28b77657 Paolo Bonzini
    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
413 28b77657 Paolo Bonzini
        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
414 28b77657 Paolo Bonzini
    }
415 28b77657 Paolo Bonzini
416 9b6eef8a Paolo Bonzini
    switch (s->type) {
417 9b6eef8a Paolo Bonzini
    case TYPE_TAPE:
418 8869e103 Paolo Bonzini
        s->blocksize = get_stream_blocksize(s->conf.bs);
419 8869e103 Paolo Bonzini
        if (s->blocksize == -1) {
420 8869e103 Paolo Bonzini
            s->blocksize = 0;
421 8869e103 Paolo Bonzini
        }
422 9b6eef8a Paolo Bonzini
        break;
423 9b6eef8a Paolo Bonzini
424 9b6eef8a Paolo Bonzini
        /* Make a guess for block devices, we'll fix it when the guest sends.
425 9b6eef8a Paolo Bonzini
         * READ CAPACITY.  If they don't, they likely would assume these sizes
426 9b6eef8a Paolo Bonzini
         * anyway. (TODO: they could also send MODE SENSE).
427 9b6eef8a Paolo Bonzini
         */
428 9b6eef8a Paolo Bonzini
    case TYPE_ROM:
429 9b6eef8a Paolo Bonzini
    case TYPE_WORM:
430 9b6eef8a Paolo Bonzini
        s->blocksize = 2048;
431 9b6eef8a Paolo Bonzini
        break;
432 9b6eef8a Paolo Bonzini
    default:
433 9b6eef8a Paolo Bonzini
        s->blocksize = 512;
434 9b6eef8a Paolo Bonzini
        break;
435 89c0f643 aurel32
    }
436 8869e103 Paolo Bonzini
437 8869e103 Paolo Bonzini
    DPRINTF("block size %d\n", s->blocksize);
438 d52affa7 Gerd Hoffmann
    return 0;
439 d52affa7 Gerd Hoffmann
}
440 2cc977e2 ths
441 765d1525 Paolo Bonzini
const SCSIReqOps scsi_generic_req_ops = {
442 8dbd4574 Paolo Bonzini
    .size         = sizeof(SCSIGenericReq),
443 12010e7b Paolo Bonzini
    .free_req     = scsi_free_request,
444 12010e7b Paolo Bonzini
    .send_command = scsi_send_command,
445 12010e7b Paolo Bonzini
    .read_data    = scsi_read_data,
446 12010e7b Paolo Bonzini
    .write_data   = scsi_write_data,
447 12010e7b Paolo Bonzini
    .cancel_io    = scsi_cancel_io,
448 12010e7b Paolo Bonzini
    .get_buf      = scsi_get_buf,
449 8dbd4574 Paolo Bonzini
};
450 8dbd4574 Paolo Bonzini
451 8dbd4574 Paolo Bonzini
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
452 63db0f0e Paolo Bonzini
                                     uint8_t *buf, void *hba_private)
453 8dbd4574 Paolo Bonzini
{
454 8dbd4574 Paolo Bonzini
    SCSIRequest *req;
455 8dbd4574 Paolo Bonzini
456 8dbd4574 Paolo Bonzini
    req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
457 8dbd4574 Paolo Bonzini
    return req;
458 8dbd4574 Paolo Bonzini
}
459 8dbd4574 Paolo Bonzini
460 d52affa7 Gerd Hoffmann
static SCSIDeviceInfo scsi_generic_info = {
461 d52affa7 Gerd Hoffmann
    .qdev.name    = "scsi-generic",
462 28b77657 Paolo Bonzini
    .qdev.fw_name = "disk",
463 d52affa7 Gerd Hoffmann
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
464 8869e103 Paolo Bonzini
    .qdev.size    = sizeof(SCSIDevice),
465 f8b6d672 Bernhard Kohl
    .qdev.reset   = scsi_generic_reset,
466 d52affa7 Gerd Hoffmann
    .init         = scsi_generic_initfn,
467 d52affa7 Gerd Hoffmann
    .destroy      = scsi_destroy,
468 5c6c0e51 Hannes Reinecke
    .alloc_req    = scsi_new_request,
469 d52affa7 Gerd Hoffmann
    .qdev.props   = (Property[]) {
470 8869e103 Paolo Bonzini
        DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
471 d52affa7 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
472 d52affa7 Gerd Hoffmann
    },
473 d52affa7 Gerd Hoffmann
};
474 2cc977e2 ths
475 d52affa7 Gerd Hoffmann
static void scsi_generic_register_devices(void)
476 d52affa7 Gerd Hoffmann
{
477 d52affa7 Gerd Hoffmann
    scsi_qdev_register(&scsi_generic_info);
478 2cc977e2 ths
}
479 d52affa7 Gerd Hoffmann
device_init(scsi_generic_register_devices)
480 d52affa7 Gerd Hoffmann
481 2cc977e2 ths
#endif /* __linux__ */