Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ df97b920

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