Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ 57a46d05

History | View | Annotate | Download (18.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 2cc977e2 ths
#include <scsi/scsi.h>
38 2cc977e2 ths
39 a9dd6843 aliguori
#define REWIND 0x01
40 a9dd6843 aliguori
#define REPORT_DENSITY_SUPPORT 0x44
41 2cc977e2 ths
#define LOAD_UNLOAD 0xa6
42 2cc977e2 ths
#define SET_CD_SPEED 0xbb
43 2cc977e2 ths
#define BLANK 0xa1
44 2cc977e2 ths
45 2cc977e2 ths
#define SCSI_CMD_BUF_SIZE     16
46 a9dd6843 aliguori
#define SCSI_SENSE_BUF_SIZE 96
47 2cc977e2 ths
48 2cc977e2 ths
#define SG_ERR_DRIVER_TIMEOUT 0x06
49 2cc977e2 ths
#define SG_ERR_DRIVER_SENSE 0x08
50 2cc977e2 ths
51 2cc977e2 ths
#ifndef MAX_UINT
52 2cc977e2 ths
#define MAX_UINT ((unsigned int)-1)
53 2cc977e2 ths
#endif
54 2cc977e2 ths
55 d52affa7 Gerd Hoffmann
typedef struct SCSIGenericState SCSIGenericState;
56 d52affa7 Gerd Hoffmann
57 2cc977e2 ths
typedef struct SCSIRequest {
58 2cc977e2 ths
    BlockDriverAIOCB *aiocb;
59 2cc977e2 ths
    struct SCSIRequest *next;
60 d52affa7 Gerd Hoffmann
    SCSIBus *bus;
61 d52affa7 Gerd Hoffmann
    SCSIGenericState *dev;
62 2cc977e2 ths
    uint32_t tag;
63 2cc977e2 ths
    uint8_t cmd[SCSI_CMD_BUF_SIZE];
64 2cc977e2 ths
    int cmdlen;
65 2cc977e2 ths
    uint8_t *buf;
66 2cc977e2 ths
    int buflen;
67 2cc977e2 ths
    int len;
68 2cc977e2 ths
    sg_io_hdr_t io_header;
69 2cc977e2 ths
} SCSIRequest;
70 2cc977e2 ths
71 d52affa7 Gerd Hoffmann
struct SCSIGenericState
72 2cc977e2 ths
{
73 d52affa7 Gerd Hoffmann
    SCSIDevice qdev;
74 2cc977e2 ths
    SCSIRequest *requests;
75 d52affa7 Gerd Hoffmann
    DriveInfo *dinfo;
76 a9dd6843 aliguori
    int type;
77 2cc977e2 ths
    int blocksize;
78 2cc977e2 ths
    int lun;
79 2cc977e2 ths
    int driver_status;
80 2cc977e2 ths
    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
81 89c0f643 aurel32
    uint8_t senselen;
82 2cc977e2 ths
};
83 2cc977e2 ths
84 2cc977e2 ths
/* Global pool of SCSIRequest structures.  */
85 2cc977e2 ths
static SCSIRequest *free_requests = NULL;
86 2cc977e2 ths
87 d52affa7 Gerd Hoffmann
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
88 2cc977e2 ths
{
89 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
90 2cc977e2 ths
    SCSIRequest *r;
91 2cc977e2 ths
92 2cc977e2 ths
    if (free_requests) {
93 2cc977e2 ths
        r = free_requests;
94 2cc977e2 ths
        free_requests = r->next;
95 2cc977e2 ths
    } else {
96 2cc977e2 ths
        r = qemu_malloc(sizeof(SCSIRequest));
97 2cc977e2 ths
        r->buf = NULL;
98 2cc977e2 ths
        r->buflen = 0;
99 2cc977e2 ths
    }
100 d52affa7 Gerd Hoffmann
    r->bus = scsi_bus_from_device(d);
101 2cc977e2 ths
    r->dev = s;
102 2cc977e2 ths
    r->tag = tag;
103 2cc977e2 ths
    memset(r->cmd, 0, sizeof(r->cmd));
104 2cc977e2 ths
    memset(&r->io_header, 0, sizeof(r->io_header));
105 2cc977e2 ths
    r->cmdlen = 0;
106 2cc977e2 ths
    r->len = 0;
107 2cc977e2 ths
    r->aiocb = NULL;
108 2cc977e2 ths
109 2cc977e2 ths
    /* link */
110 2cc977e2 ths
111 2cc977e2 ths
    r->next = s->requests;
112 2cc977e2 ths
    s->requests = r;
113 2cc977e2 ths
    return r;
114 2cc977e2 ths
}
115 2cc977e2 ths
116 2cc977e2 ths
static void scsi_remove_request(SCSIRequest *r)
117 2cc977e2 ths
{
118 2cc977e2 ths
    SCSIRequest *last;
119 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = r->dev;
120 2cc977e2 ths
121 2cc977e2 ths
    if (s->requests == r) {
122 2cc977e2 ths
        s->requests = r->next;
123 2cc977e2 ths
    } else {
124 2cc977e2 ths
        last = s->requests;
125 2cc977e2 ths
        while (last && last->next != r)
126 2cc977e2 ths
            last = last->next;
127 2cc977e2 ths
        if (last) {
128 2cc977e2 ths
            last->next = r->next;
129 2cc977e2 ths
        } else {
130 2cc977e2 ths
            BADF("Orphaned request\n");
131 2cc977e2 ths
        }
132 2cc977e2 ths
    }
133 2cc977e2 ths
    r->next = free_requests;
134 2cc977e2 ths
    free_requests = r;
135 2cc977e2 ths
}
136 2cc977e2 ths
137 d52affa7 Gerd Hoffmann
static SCSIRequest *scsi_find_request(SCSIGenericState *s, uint32_t tag)
138 2cc977e2 ths
{
139 2cc977e2 ths
    SCSIRequest *r;
140 2cc977e2 ths
141 2cc977e2 ths
    r = s->requests;
142 2cc977e2 ths
    while (r && r->tag != tag)
143 2cc977e2 ths
        r = r->next;
144 2cc977e2 ths
145 2cc977e2 ths
    return r;
146 2cc977e2 ths
}
147 2cc977e2 ths
148 2cc977e2 ths
/* Helper function for command completion.  */
149 2cc977e2 ths
static void scsi_command_complete(void *opaque, int ret)
150 2cc977e2 ths
{
151 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
152 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = r->dev;
153 2cc977e2 ths
    uint32_t tag;
154 89c0f643 aurel32
    int status;
155 2cc977e2 ths
156 2cc977e2 ths
    s->driver_status = r->io_header.driver_status;
157 89c0f643 aurel32
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
158 89c0f643 aurel32
        s->senselen = r->io_header.sb_len_wr;
159 89c0f643 aurel32
160 2cc977e2 ths
    if (ret != 0)
161 89c0f643 aurel32
        status = BUSY << 1;
162 2cc977e2 ths
    else {
163 2cc977e2 ths
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
164 89c0f643 aurel32
            status = BUSY << 1;
165 2cc977e2 ths
            BADF("Driver Timeout\n");
166 89c0f643 aurel32
        } else if (r->io_header.status)
167 89c0f643 aurel32
            status = r->io_header.status;
168 89c0f643 aurel32
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
169 89c0f643 aurel32
            status = CHECK_CONDITION << 1;
170 2cc977e2 ths
        else
171 89c0f643 aurel32
            status = GOOD << 1;
172 2cc977e2 ths
    }
173 89c0f643 aurel32
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
174 89c0f643 aurel32
            r, r->tag, status);
175 2cc977e2 ths
    tag = r->tag;
176 2cc977e2 ths
    scsi_remove_request(r);
177 d52affa7 Gerd Hoffmann
    r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
178 2cc977e2 ths
}
179 2cc977e2 ths
180 2cc977e2 ths
/* Cancel a pending data transfer.  */
181 2cc977e2 ths
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
182 2cc977e2 ths
{
183 2cc977e2 ths
    DPRINTF("scsi_cancel_io 0x%x\n", tag);
184 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
185 2cc977e2 ths
    SCSIRequest *r;
186 2cc977e2 ths
    DPRINTF("Cancel tag=0x%x\n", tag);
187 2cc977e2 ths
    r = scsi_find_request(s, tag);
188 2cc977e2 ths
    if (r) {
189 2cc977e2 ths
        if (r->aiocb)
190 2cc977e2 ths
            bdrv_aio_cancel(r->aiocb);
191 2cc977e2 ths
        r->aiocb = NULL;
192 2cc977e2 ths
        scsi_remove_request(r);
193 2cc977e2 ths
    }
194 2cc977e2 ths
}
195 2cc977e2 ths
196 2cc977e2 ths
static int execute_command(BlockDriverState *bdrv,
197 2cc977e2 ths
                           SCSIRequest *r, int direction,
198 2cc977e2 ths
                           BlockDriverCompletionFunc *complete)
199 2cc977e2 ths
{
200 2cc977e2 ths
    r->io_header.interface_id = 'S';
201 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
202 2cc977e2 ths
    r->io_header.dxferp = r->buf;
203 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
204 2cc977e2 ths
    r->io_header.cmdp = r->cmd;
205 2cc977e2 ths
    r->io_header.cmd_len = r->cmdlen;
206 2cc977e2 ths
    r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
207 2cc977e2 ths
    r->io_header.sbp = r->dev->sensebuf;
208 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
209 2cc977e2 ths
    r->io_header.usr_ptr = r;
210 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
211 2cc977e2 ths
212 221f715d aliguori
    r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
213 2cc977e2 ths
    if (r->aiocb == NULL) {
214 2cc977e2 ths
        BADF("execute_command: read failed !\n");
215 2cc977e2 ths
        return -1;
216 2cc977e2 ths
    }
217 2cc977e2 ths
218 2cc977e2 ths
    return 0;
219 2cc977e2 ths
}
220 2cc977e2 ths
221 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
222 2cc977e2 ths
{
223 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
224 2cc977e2 ths
    int len;
225 2cc977e2 ths
226 2cc977e2 ths
    if (ret) {
227 2cc977e2 ths
        DPRINTF("IO error\n");
228 2cc977e2 ths
        scsi_command_complete(r, ret);
229 2cc977e2 ths
        return;
230 2cc977e2 ths
    }
231 2cc977e2 ths
    len = r->io_header.dxfer_len - r->io_header.resid;
232 2cc977e2 ths
    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
233 2cc977e2 ths
234 2cc977e2 ths
    r->len = -1;
235 d52affa7 Gerd Hoffmann
    r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
236 89c0f643 aurel32
    if (len == 0)
237 89c0f643 aurel32
        scsi_command_complete(r, 0);
238 2cc977e2 ths
}
239 2cc977e2 ths
240 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
241 2cc977e2 ths
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
242 2cc977e2 ths
{
243 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
244 2cc977e2 ths
    SCSIRequest *r;
245 2cc977e2 ths
    int ret;
246 2cc977e2 ths
247 2cc977e2 ths
    DPRINTF("scsi_read_data 0x%x\n", tag);
248 2cc977e2 ths
    r = scsi_find_request(s, tag);
249 2cc977e2 ths
    if (!r) {
250 2cc977e2 ths
        BADF("Bad read tag 0x%x\n", tag);
251 2cc977e2 ths
        /* ??? This is the wrong error.  */
252 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
253 2cc977e2 ths
        return;
254 2cc977e2 ths
    }
255 2cc977e2 ths
256 2cc977e2 ths
    if (r->len == -1) {
257 2cc977e2 ths
        scsi_command_complete(r, 0);
258 2cc977e2 ths
        return;
259 2cc977e2 ths
    }
260 2cc977e2 ths
261 2cc977e2 ths
    if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
262 2cc977e2 ths
    {
263 89c0f643 aurel32
        s->senselen = MIN(r->len, s->senselen);
264 89c0f643 aurel32
        memcpy(r->buf, s->sensebuf, s->senselen);
265 2cc977e2 ths
        r->io_header.driver_status = 0;
266 89c0f643 aurel32
        r->io_header.status = 0;
267 89c0f643 aurel32
        r->io_header.dxfer_len  = s->senselen;
268 2cc977e2 ths
        r->len = -1;
269 89c0f643 aurel32
        DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, s->senselen);
270 a9dd6843 aliguori
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
271 a9dd6843 aliguori
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
272 a9dd6843 aliguori
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
273 d52affa7 Gerd Hoffmann
        r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, s->senselen);
274 2cc977e2 ths
        return;
275 2cc977e2 ths
    }
276 2cc977e2 ths
277 d52affa7 Gerd Hoffmann
    ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
278 2cc977e2 ths
    if (ret == -1) {
279 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
280 2cc977e2 ths
        return;
281 2cc977e2 ths
    }
282 2cc977e2 ths
}
283 2cc977e2 ths
284 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
285 2cc977e2 ths
{
286 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
287 2cc977e2 ths
288 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
289 2cc977e2 ths
    if (ret) {
290 2cc977e2 ths
        DPRINTF("IO error\n");
291 2cc977e2 ths
        scsi_command_complete(r, ret);
292 2cc977e2 ths
        return;
293 2cc977e2 ths
    }
294 2cc977e2 ths
295 89c0f643 aurel32
    if (r->cmd[0] == MODE_SELECT && r->cmd[4] == 12 &&
296 89c0f643 aurel32
        r->dev->type == TYPE_TAPE) {
297 89c0f643 aurel32
        r->dev->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
298 89c0f643 aurel32
        DPRINTF("block size %d\n", r->dev->blocksize);
299 89c0f643 aurel32
    }
300 89c0f643 aurel32
301 2cc977e2 ths
    scsi_command_complete(r, ret);
302 2cc977e2 ths
}
303 2cc977e2 ths
304 2cc977e2 ths
/* Write data to a scsi device.  Returns nonzero on failure.
305 2cc977e2 ths
   The transfer may complete asynchronously.  */
306 2cc977e2 ths
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
307 2cc977e2 ths
{
308 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
309 2cc977e2 ths
    SCSIRequest *r;
310 2cc977e2 ths
    int ret;
311 2cc977e2 ths
312 2cc977e2 ths
    DPRINTF("scsi_write_data 0x%x\n", tag);
313 2cc977e2 ths
    r = scsi_find_request(s, tag);
314 2cc977e2 ths
    if (!r) {
315 2cc977e2 ths
        BADF("Bad write tag 0x%x\n", tag);
316 2cc977e2 ths
        /* ??? This is the wrong error.  */
317 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
318 2cc977e2 ths
        return 0;
319 2cc977e2 ths
    }
320 2cc977e2 ths
321 2cc977e2 ths
    if (r->len == 0) {
322 2cc977e2 ths
        r->len = r->buflen;
323 d52affa7 Gerd Hoffmann
        r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->len);
324 2cc977e2 ths
        return 0;
325 2cc977e2 ths
    }
326 2cc977e2 ths
327 d52affa7 Gerd Hoffmann
    ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
328 2cc977e2 ths
    if (ret == -1) {
329 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
330 2cc977e2 ths
        return 1;
331 2cc977e2 ths
    }
332 2cc977e2 ths
333 2cc977e2 ths
    return 0;
334 2cc977e2 ths
}
335 2cc977e2 ths
336 2cc977e2 ths
/* Return a pointer to the data buffer.  */
337 2cc977e2 ths
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
338 2cc977e2 ths
{
339 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
340 2cc977e2 ths
    SCSIRequest *r;
341 2cc977e2 ths
    r = scsi_find_request(s, tag);
342 2cc977e2 ths
    if (!r) {
343 2cc977e2 ths
        BADF("Bad buffer tag 0x%x\n", tag);
344 2cc977e2 ths
        return NULL;
345 2cc977e2 ths
    }
346 2cc977e2 ths
    return r->buf;
347 2cc977e2 ths
}
348 2cc977e2 ths
349 2cc977e2 ths
static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
350 2cc977e2 ths
{
351 2cc977e2 ths
    switch (cmd[0] >> 5) {
352 2cc977e2 ths
    case 0:
353 2cc977e2 ths
        *len = cmd[4];
354 2cc977e2 ths
        *cmdlen = 6;
355 72ecb8d9 aliguori
        /* length 0 means 256 blocks */
356 72ecb8d9 aliguori
        if (*len == 0)
357 72ecb8d9 aliguori
            *len = 256;
358 2cc977e2 ths
        break;
359 2cc977e2 ths
    case 1:
360 2cc977e2 ths
    case 2:
361 2cc977e2 ths
        *len = cmd[8] | (cmd[7] << 8);
362 2cc977e2 ths
        *cmdlen = 10;
363 2cc977e2 ths
        break;
364 2cc977e2 ths
    case 4:
365 2cc977e2 ths
        *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
366 2cc977e2 ths
        *cmdlen = 16;
367 2cc977e2 ths
        break;
368 2cc977e2 ths
    case 5:
369 2cc977e2 ths
        *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
370 2cc977e2 ths
        *cmdlen = 12;
371 2cc977e2 ths
        break;
372 2cc977e2 ths
    default:
373 2cc977e2 ths
        return -1;
374 2cc977e2 ths
    }
375 2cc977e2 ths
376 2cc977e2 ths
    switch(cmd[0]) {
377 2cc977e2 ths
    case TEST_UNIT_READY:
378 2cc977e2 ths
    case REZERO_UNIT:
379 2cc977e2 ths
    case START_STOP:
380 2cc977e2 ths
    case SEEK_6:
381 2cc977e2 ths
    case WRITE_FILEMARKS:
382 2cc977e2 ths
    case SPACE:
383 2cc977e2 ths
    case ERASE:
384 2cc977e2 ths
    case ALLOW_MEDIUM_REMOVAL:
385 2cc977e2 ths
    case VERIFY:
386 2cc977e2 ths
    case SEEK_10:
387 2cc977e2 ths
    case SYNCHRONIZE_CACHE:
388 2cc977e2 ths
    case LOCK_UNLOCK_CACHE:
389 2cc977e2 ths
    case LOAD_UNLOAD:
390 2cc977e2 ths
    case SET_CD_SPEED:
391 2cc977e2 ths
    case SET_LIMITS:
392 2cc977e2 ths
    case WRITE_LONG:
393 2cc977e2 ths
    case MOVE_MEDIUM:
394 2cc977e2 ths
    case UPDATE_BLOCK:
395 2cc977e2 ths
        *len = 0;
396 2cc977e2 ths
        break;
397 2cc977e2 ths
    case MODE_SENSE:
398 2cc977e2 ths
        break;
399 2cc977e2 ths
    case WRITE_SAME:
400 2cc977e2 ths
        *len = 1;
401 2cc977e2 ths
        break;
402 2cc977e2 ths
    case READ_CAPACITY:
403 2cc977e2 ths
        *len = 8;
404 2cc977e2 ths
        break;
405 2cc977e2 ths
    case READ_BLOCK_LIMITS:
406 2cc977e2 ths
        *len = 6;
407 2cc977e2 ths
        break;
408 2cc977e2 ths
    case READ_POSITION:
409 2cc977e2 ths
        *len = 20;
410 2cc977e2 ths
        break;
411 2cc977e2 ths
    case SEND_VOLUME_TAG:
412 2cc977e2 ths
        *len *= 40;
413 2cc977e2 ths
        break;
414 2cc977e2 ths
    case MEDIUM_SCAN:
415 2cc977e2 ths
        *len *= 8;
416 2cc977e2 ths
        break;
417 2cc977e2 ths
    case WRITE_10:
418 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
419 2cc977e2 ths
    case WRITE_VERIFY:
420 2cc977e2 ths
    case WRITE_6:
421 2cc977e2 ths
    case WRITE_12:
422 2cc977e2 ths
    case WRITE_VERIFY_12:
423 2cc977e2 ths
        *len *= blocksize;
424 2cc977e2 ths
        break;
425 2cc977e2 ths
    case READ_10:
426 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
427 2cc977e2 ths
    case READ_6:
428 2cc977e2 ths
    case READ_REVERSE:
429 2cc977e2 ths
    case RECOVER_BUFFERED_DATA:
430 2cc977e2 ths
    case READ_12:
431 2cc977e2 ths
        *len *= blocksize;
432 2cc977e2 ths
        break;
433 89c0f643 aurel32
    case INQUIRY:
434 89c0f643 aurel32
        *len = cmd[4] | (cmd[3] << 8);
435 89c0f643 aurel32
        break;
436 2cc977e2 ths
    }
437 2cc977e2 ths
    return 0;
438 2cc977e2 ths
}
439 2cc977e2 ths
440 a9dd6843 aliguori
static int scsi_stream_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
441 a9dd6843 aliguori
{
442 a9dd6843 aliguori
    switch(cmd[0]) {
443 a9dd6843 aliguori
    /* stream commands */
444 a9dd6843 aliguori
    case READ_6:
445 a9dd6843 aliguori
    case READ_REVERSE:
446 a9dd6843 aliguori
    case RECOVER_BUFFERED_DATA:
447 a9dd6843 aliguori
    case WRITE_6:
448 a9dd6843 aliguori
        *cmdlen = 6;
449 a9dd6843 aliguori
        *len = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
450 a9dd6843 aliguori
        if (cmd[1] & 0x01) /* fixed */
451 a9dd6843 aliguori
            *len *= blocksize;
452 a9dd6843 aliguori
        break;
453 a9dd6843 aliguori
    case REWIND:
454 a9dd6843 aliguori
    case START_STOP:
455 a9dd6843 aliguori
        *cmdlen = 6;
456 a9dd6843 aliguori
        *len = 0;
457 a9dd6843 aliguori
        cmd[1] = 0x01;        /* force IMMED, otherwise qemu waits end of command */
458 a9dd6843 aliguori
        break;
459 a9dd6843 aliguori
    /* generic commands */
460 a9dd6843 aliguori
    default:
461 a9dd6843 aliguori
        return scsi_length(cmd, blocksize, cmdlen, len);
462 a9dd6843 aliguori
    }
463 a9dd6843 aliguori
    return 0;
464 a9dd6843 aliguori
}
465 a9dd6843 aliguori
466 2cc977e2 ths
static int is_write(int command)
467 2cc977e2 ths
{
468 2cc977e2 ths
    switch (command) {
469 2cc977e2 ths
    case COPY:
470 2cc977e2 ths
    case COPY_VERIFY:
471 2cc977e2 ths
    case COMPARE:
472 2cc977e2 ths
    case CHANGE_DEFINITION:
473 2cc977e2 ths
    case LOG_SELECT:
474 2cc977e2 ths
    case MODE_SELECT:
475 2cc977e2 ths
    case MODE_SELECT_10:
476 2cc977e2 ths
    case SEND_DIAGNOSTIC:
477 2cc977e2 ths
    case WRITE_BUFFER:
478 2cc977e2 ths
    case FORMAT_UNIT:
479 2cc977e2 ths
    case REASSIGN_BLOCKS:
480 2cc977e2 ths
    case RESERVE:
481 2cc977e2 ths
    case SEARCH_EQUAL:
482 2cc977e2 ths
    case SEARCH_HIGH:
483 2cc977e2 ths
    case SEARCH_LOW:
484 2cc977e2 ths
    case WRITE_6:
485 2cc977e2 ths
    case WRITE_10:
486 2cc977e2 ths
    case WRITE_VERIFY:
487 2cc977e2 ths
    case UPDATE_BLOCK:
488 2cc977e2 ths
    case WRITE_LONG:
489 2cc977e2 ths
    case WRITE_SAME:
490 2cc977e2 ths
    case SEARCH_HIGH_12:
491 2cc977e2 ths
    case SEARCH_EQUAL_12:
492 2cc977e2 ths
    case SEARCH_LOW_12:
493 2cc977e2 ths
    case WRITE_12:
494 2cc977e2 ths
    case WRITE_VERIFY_12:
495 2cc977e2 ths
    case SET_WINDOW:
496 2cc977e2 ths
    case MEDIUM_SCAN:
497 2cc977e2 ths
    case SEND_VOLUME_TAG:
498 2cc977e2 ths
    case WRITE_LONG_2:
499 2cc977e2 ths
        return 1;
500 2cc977e2 ths
    }
501 2cc977e2 ths
    return 0;
502 2cc977e2 ths
}
503 2cc977e2 ths
504 2cc977e2 ths
/* Execute a scsi command.  Returns the length of the data expected by the
505 2cc977e2 ths
   command.  This will be Positive for data transfers from the device
506 2cc977e2 ths
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
507 2cc977e2 ths
   and zero if the command does not transfer any data.  */
508 2cc977e2 ths
509 2cc977e2 ths
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
510 2cc977e2 ths
                                 uint8_t *cmd, int lun)
511 2cc977e2 ths
{
512 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
513 37e828b4 aurel32
    uint32_t len=0;
514 37e828b4 aurel32
    int cmdlen=0;
515 2cc977e2 ths
    SCSIRequest *r;
516 d52affa7 Gerd Hoffmann
    SCSIBus *bus;
517 2cc977e2 ths
    int ret;
518 2cc977e2 ths
519 a9dd6843 aliguori
    if (s->type == TYPE_TAPE) {
520 a9dd6843 aliguori
        if (scsi_stream_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
521 a9dd6843 aliguori
            BADF("Unsupported command length, command %x\n", cmd[0]);
522 a9dd6843 aliguori
            return 0;
523 a9dd6843 aliguori
        }
524 a9dd6843 aliguori
     } else {
525 a9dd6843 aliguori
        if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
526 a9dd6843 aliguori
            BADF("Unsupported command length, command %x\n", cmd[0]);
527 a9dd6843 aliguori
            return 0;
528 a9dd6843 aliguori
        }
529 2cc977e2 ths
    }
530 2cc977e2 ths
531 2cc977e2 ths
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
532 2cc977e2 ths
            cmd[0], len);
533 2cc977e2 ths
534 89c0f643 aurel32
    if (cmd[0] != REQUEST_SENSE &&
535 89c0f643 aurel32
        (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
536 89c0f643 aurel32
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
537 89c0f643 aurel32
538 89c0f643 aurel32
        s->sensebuf[0] = 0x70;
539 89c0f643 aurel32
        s->sensebuf[1] = 0x00;
540 89c0f643 aurel32
        s->sensebuf[2] = ILLEGAL_REQUEST;
541 89c0f643 aurel32
        s->sensebuf[3] = 0x00;
542 89c0f643 aurel32
        s->sensebuf[4] = 0x00;
543 89c0f643 aurel32
        s->sensebuf[5] = 0x00;
544 89c0f643 aurel32
        s->sensebuf[6] = 0x00;
545 89c0f643 aurel32
        s->senselen = 7;
546 89c0f643 aurel32
        s->driver_status = SG_ERR_DRIVER_SENSE;
547 d52affa7 Gerd Hoffmann
        bus = scsi_bus_from_device(d);
548 d52affa7 Gerd Hoffmann
        bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
549 89c0f643 aurel32
        return 0;
550 89c0f643 aurel32
    }
551 89c0f643 aurel32
552 2cc977e2 ths
    r = scsi_find_request(s, tag);
553 2cc977e2 ths
    if (r) {
554 2cc977e2 ths
        BADF("Tag 0x%x already in use %p\n", tag, r);
555 2cc977e2 ths
        scsi_cancel_io(d, tag);
556 2cc977e2 ths
    }
557 d52affa7 Gerd Hoffmann
    r = scsi_new_request(d, tag);
558 2cc977e2 ths
559 2cc977e2 ths
    memcpy(r->cmd, cmd, cmdlen);
560 2cc977e2 ths
    r->cmdlen = cmdlen;
561 2cc977e2 ths
562 2cc977e2 ths
    if (len == 0) {
563 2cc977e2 ths
        if (r->buf != NULL)
564 2cc977e2 ths
            free(r->buf);
565 2cc977e2 ths
        r->buflen = 0;
566 2cc977e2 ths
        r->buf = NULL;
567 d52affa7 Gerd Hoffmann
        ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
568 2cc977e2 ths
        if (ret == -1) {
569 2cc977e2 ths
            scsi_command_complete(r, -EINVAL);
570 2cc977e2 ths
            return 0;
571 2cc977e2 ths
        }
572 2cc977e2 ths
        return 0;
573 2cc977e2 ths
    }
574 2cc977e2 ths
575 2cc977e2 ths
    if (r->buflen != len) {
576 2cc977e2 ths
        if (r->buf != NULL)
577 2cc977e2 ths
            free(r->buf);
578 2cc977e2 ths
        r->buf = qemu_malloc(len);
579 2cc977e2 ths
        r->buflen = len;
580 2cc977e2 ths
    }
581 2cc977e2 ths
582 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
583 2cc977e2 ths
    r->len = len;
584 2cc977e2 ths
    if (is_write(cmd[0])) {
585 2cc977e2 ths
        r->len = 0;
586 2cc977e2 ths
        return -len;
587 2cc977e2 ths
    }
588 2cc977e2 ths
589 2cc977e2 ths
    return len;
590 2cc977e2 ths
}
591 2cc977e2 ths
592 2cc977e2 ths
static int get_blocksize(BlockDriverState *bdrv)
593 2cc977e2 ths
{
594 2cc977e2 ths
    uint8_t cmd[10];
595 2cc977e2 ths
    uint8_t buf[8];
596 2cc977e2 ths
    uint8_t sensebuf[8];
597 2cc977e2 ths
    sg_io_hdr_t io_header;
598 2cc977e2 ths
    int ret;
599 2cc977e2 ths
600 4f26a486 aliguori
    memset(cmd, 0, sizeof(cmd));
601 4f26a486 aliguori
    memset(buf, 0, sizeof(buf));
602 2cc977e2 ths
    cmd[0] = READ_CAPACITY;
603 2cc977e2 ths
604 2cc977e2 ths
    memset(&io_header, 0, sizeof(io_header));
605 2cc977e2 ths
    io_header.interface_id = 'S';
606 2cc977e2 ths
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
607 2cc977e2 ths
    io_header.dxfer_len = sizeof(buf);
608 2cc977e2 ths
    io_header.dxferp = buf;
609 2cc977e2 ths
    io_header.cmdp = cmd;
610 2cc977e2 ths
    io_header.cmd_len = sizeof(cmd);
611 2cc977e2 ths
    io_header.mx_sb_len = sizeof(sensebuf);
612 2cc977e2 ths
    io_header.sbp = sensebuf;
613 2cc977e2 ths
    io_header.timeout = 6000; /* XXX */
614 2cc977e2 ths
615 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
616 7d780669 aliguori
    if (ret < 0)
617 2cc977e2 ths
        return -1;
618 2cc977e2 ths
619 2cc977e2 ths
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
620 2cc977e2 ths
}
621 2cc977e2 ths
622 89c0f643 aurel32
static int get_stream_blocksize(BlockDriverState *bdrv)
623 89c0f643 aurel32
{
624 89c0f643 aurel32
    uint8_t cmd[6];
625 89c0f643 aurel32
    uint8_t buf[12];
626 89c0f643 aurel32
    uint8_t sensebuf[8];
627 89c0f643 aurel32
    sg_io_hdr_t io_header;
628 89c0f643 aurel32
    int ret;
629 89c0f643 aurel32
630 89c0f643 aurel32
    memset(cmd, 0, sizeof(cmd));
631 89c0f643 aurel32
    memset(buf, 0, sizeof(buf));
632 89c0f643 aurel32
    cmd[0] = MODE_SENSE;
633 89c0f643 aurel32
    cmd[4] = sizeof(buf);
634 89c0f643 aurel32
635 89c0f643 aurel32
    memset(&io_header, 0, sizeof(io_header));
636 89c0f643 aurel32
    io_header.interface_id = 'S';
637 89c0f643 aurel32
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
638 89c0f643 aurel32
    io_header.dxfer_len = sizeof(buf);
639 89c0f643 aurel32
    io_header.dxferp = buf;
640 89c0f643 aurel32
    io_header.cmdp = cmd;
641 89c0f643 aurel32
    io_header.cmd_len = sizeof(cmd);
642 89c0f643 aurel32
    io_header.mx_sb_len = sizeof(sensebuf);
643 89c0f643 aurel32
    io_header.sbp = sensebuf;
644 89c0f643 aurel32
    io_header.timeout = 6000; /* XXX */
645 89c0f643 aurel32
646 221f715d aliguori
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
647 7d780669 aliguori
    if (ret < 0)
648 89c0f643 aurel32
        return -1;
649 89c0f643 aurel32
650 89c0f643 aurel32
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
651 89c0f643 aurel32
}
652 89c0f643 aurel32
653 2cc977e2 ths
static void scsi_destroy(SCSIDevice *d)
654 2cc977e2 ths
{
655 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
656 2cc977e2 ths
    SCSIRequest *r, *n;
657 2cc977e2 ths
658 d52affa7 Gerd Hoffmann
    r = s->requests;
659 2cc977e2 ths
    while (r) {
660 2cc977e2 ths
        n = r->next;
661 2cc977e2 ths
        qemu_free(r);
662 2cc977e2 ths
        r = n;
663 2cc977e2 ths
    }
664 2cc977e2 ths
665 2cc977e2 ths
    r = free_requests;
666 2cc977e2 ths
    while (r) {
667 2cc977e2 ths
        n = r->next;
668 2cc977e2 ths
        qemu_free(r);
669 2cc977e2 ths
        r = n;
670 2cc977e2 ths
    }
671 56a14938 Gerd Hoffmann
672 56a14938 Gerd Hoffmann
    drive_uninit(s->dinfo);
673 2cc977e2 ths
}
674 2cc977e2 ths
675 d52affa7 Gerd Hoffmann
static int scsi_generic_initfn(SCSIDevice *dev)
676 2cc977e2 ths
{
677 d52affa7 Gerd Hoffmann
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
678 2cc977e2 ths
    int sg_version;
679 2cc977e2 ths
    struct sg_scsi_id scsiid;
680 2cc977e2 ths
681 d52affa7 Gerd Hoffmann
    if (!s->dinfo || !s->dinfo->bdrv) {
682 d52affa7 Gerd Hoffmann
        qemu_error("scsi-generic: drive property not set\n");
683 d52affa7 Gerd Hoffmann
        return -1;
684 d52affa7 Gerd Hoffmann
    }
685 2cc977e2 ths
686 d52affa7 Gerd Hoffmann
    /* check we are really using a /dev/sg* file */
687 d52affa7 Gerd Hoffmann
    if (!bdrv_is_sg(s->dinfo->bdrv)) {
688 d52affa7 Gerd Hoffmann
        qemu_error("scsi-generic: not /dev/sg*\n");
689 d52affa7 Gerd Hoffmann
        return -1;
690 d52affa7 Gerd Hoffmann
    }
691 2cc977e2 ths
692 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
693 d52affa7 Gerd Hoffmann
    if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
694 d52affa7 Gerd Hoffmann
        sg_version < 30000) {
695 d52affa7 Gerd Hoffmann
        qemu_error("scsi-generic: scsi generic interface too old\n");
696 d52affa7 Gerd Hoffmann
        return -1;
697 d52affa7 Gerd Hoffmann
    }
698 2cc977e2 ths
699 2cc977e2 ths
    /* get LUN of the /dev/sg? */
700 d52affa7 Gerd Hoffmann
    if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
701 d52affa7 Gerd Hoffmann
        qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
702 d52affa7 Gerd Hoffmann
        return -1;
703 d52affa7 Gerd Hoffmann
    }
704 2cc977e2 ths
705 2cc977e2 ths
    /* define device state */
706 2cc977e2 ths
    s->lun = scsiid.lun;
707 89c0f643 aurel32
    DPRINTF("LUN %d\n", s->lun);
708 a9dd6843 aliguori
    s->type = scsiid.scsi_type;
709 89c0f643 aurel32
    DPRINTF("device type %d\n", s->type);
710 89c0f643 aurel32
    if (s->type == TYPE_TAPE) {
711 d52affa7 Gerd Hoffmann
        s->blocksize = get_stream_blocksize(s->dinfo->bdrv);
712 89c0f643 aurel32
        if (s->blocksize == -1)
713 89c0f643 aurel32
            s->blocksize = 0;
714 89c0f643 aurel32
    } else {
715 d52affa7 Gerd Hoffmann
        s->blocksize = get_blocksize(s->dinfo->bdrv);
716 89c0f643 aurel32
        /* removable media returns 0 if not present */
717 89c0f643 aurel32
        if (s->blocksize <= 0) {
718 89c0f643 aurel32
            if (s->type == TYPE_ROM || s->type  == TYPE_WORM)
719 89c0f643 aurel32
                s->blocksize = 2048;
720 89c0f643 aurel32
            else
721 89c0f643 aurel32
                s->blocksize = 512;
722 89c0f643 aurel32
        }
723 89c0f643 aurel32
    }
724 89c0f643 aurel32
    DPRINTF("block size %d\n", s->blocksize);
725 2cc977e2 ths
    s->driver_status = 0;
726 2cc977e2 ths
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
727 d52affa7 Gerd Hoffmann
    return 0;
728 d52affa7 Gerd Hoffmann
}
729 2cc977e2 ths
730 d52affa7 Gerd Hoffmann
static SCSIDeviceInfo scsi_generic_info = {
731 d52affa7 Gerd Hoffmann
    .qdev.name    = "scsi-generic",
732 d52affa7 Gerd Hoffmann
    .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
733 d52affa7 Gerd Hoffmann
    .qdev.size    = sizeof(SCSIGenericState),
734 d52affa7 Gerd Hoffmann
    .init         = scsi_generic_initfn,
735 d52affa7 Gerd Hoffmann
    .destroy      = scsi_destroy,
736 d52affa7 Gerd Hoffmann
    .send_command = scsi_send_command,
737 d52affa7 Gerd Hoffmann
    .read_data    = scsi_read_data,
738 d52affa7 Gerd Hoffmann
    .write_data   = scsi_write_data,
739 d52affa7 Gerd Hoffmann
    .cancel_io    = scsi_cancel_io,
740 d52affa7 Gerd Hoffmann
    .get_buf      = scsi_get_buf,
741 d52affa7 Gerd Hoffmann
    .qdev.props   = (Property[]) {
742 d52affa7 Gerd Hoffmann
        DEFINE_PROP_DRIVE("drive", SCSIGenericState, dinfo),
743 d52affa7 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
744 d52affa7 Gerd Hoffmann
    },
745 d52affa7 Gerd Hoffmann
};
746 2cc977e2 ths
747 d52affa7 Gerd Hoffmann
static void scsi_generic_register_devices(void)
748 d52affa7 Gerd Hoffmann
{
749 d52affa7 Gerd Hoffmann
    scsi_qdev_register(&scsi_generic_info);
750 2cc977e2 ths
}
751 d52affa7 Gerd Hoffmann
device_init(scsi_generic_register_devices)
752 d52affa7 Gerd Hoffmann
753 2cc977e2 ths
#endif /* __linux__ */