Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ b8c18e4c

History | View | Annotate | Download (19 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 2cc977e2 ths
#define DPRINTF(fmt, args...) \
32 2cc977e2 ths
do { printf("scsi-generic: " fmt , ##args); } while (0)
33 2cc977e2 ths
#else
34 2cc977e2 ths
#define DPRINTF(fmt, args...) do {} while(0)
35 2cc977e2 ths
#endif
36 2cc977e2 ths
37 2cc977e2 ths
#define BADF(fmt, args...) \
38 2cc977e2 ths
do { fprintf(stderr, "scsi-generic: " fmt , ##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 7d780669 aliguori
    int ret;
205 2cc977e2 ths
206 2cc977e2 ths
    r->io_header.interface_id = 'S';
207 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
208 2cc977e2 ths
    r->io_header.dxferp = r->buf;
209 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
210 2cc977e2 ths
    r->io_header.cmdp = r->cmd;
211 2cc977e2 ths
    r->io_header.cmd_len = r->cmdlen;
212 2cc977e2 ths
    r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
213 2cc977e2 ths
    r->io_header.sbp = r->dev->sensebuf;
214 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
215 2cc977e2 ths
    r->io_header.usr_ptr = r;
216 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
217 2cc977e2 ths
218 7d780669 aliguori
    ret = bdrv_sg_send_command(bdrv, &r->io_header, sizeof(r->io_header));
219 7d780669 aliguori
    if (ret < 0) {
220 2cc977e2 ths
        BADF("execute_command: write failed ! (%d)\n", errno);
221 2cc977e2 ths
        return -1;
222 2cc977e2 ths
    }
223 2cc977e2 ths
    if (complete == NULL) {
224 2cc977e2 ths
        int ret;
225 2cc977e2 ths
        r->aiocb = NULL;
226 7d780669 aliguori
        while ((ret = bdrv_sg_recv_response(bdrv, &r->io_header,
227 7d780669 aliguori
                                            sizeof(r->io_header))) < 0 &&
228 7d780669 aliguori
               ret == -EINTR)
229 7d780669 aliguori
            ;
230 7d780669 aliguori
        if (ret < 0) {
231 2cc977e2 ths
            BADF("execute_command: read failed !\n");
232 2cc977e2 ths
            return -1;
233 2cc977e2 ths
        }
234 2cc977e2 ths
        return 0;
235 2cc977e2 ths
    }
236 2cc977e2 ths
237 7d780669 aliguori
    r->aiocb = bdrv_sg_aio_read(bdrv, (uint8_t*)&r->io_header,
238 7d780669 aliguori
                                sizeof(r->io_header), complete, r);
239 2cc977e2 ths
    if (r->aiocb == NULL) {
240 2cc977e2 ths
        BADF("execute_command: read failed !\n");
241 2cc977e2 ths
        return -1;
242 2cc977e2 ths
    }
243 2cc977e2 ths
244 2cc977e2 ths
    return 0;
245 2cc977e2 ths
}
246 2cc977e2 ths
247 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
248 2cc977e2 ths
{
249 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
250 2cc977e2 ths
    SCSIDeviceState *s = r->dev;
251 2cc977e2 ths
    int len;
252 2cc977e2 ths
253 2cc977e2 ths
    if (ret) {
254 2cc977e2 ths
        DPRINTF("IO error\n");
255 2cc977e2 ths
        scsi_command_complete(r, ret);
256 2cc977e2 ths
        return;
257 2cc977e2 ths
    }
258 2cc977e2 ths
    len = r->io_header.dxfer_len - r->io_header.resid;
259 2cc977e2 ths
    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
260 2cc977e2 ths
261 2cc977e2 ths
    r->len = -1;
262 2cc977e2 ths
    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
263 89c0f643 aurel32
    if (len == 0)
264 89c0f643 aurel32
        scsi_command_complete(r, 0);
265 2cc977e2 ths
}
266 2cc977e2 ths
267 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
268 2cc977e2 ths
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
269 2cc977e2 ths
{
270 2cc977e2 ths
    SCSIDeviceState *s = d->state;
271 2cc977e2 ths
    SCSIRequest *r;
272 2cc977e2 ths
    int ret;
273 2cc977e2 ths
274 2cc977e2 ths
    DPRINTF("scsi_read_data 0x%x\n", tag);
275 2cc977e2 ths
    r = scsi_find_request(s, tag);
276 2cc977e2 ths
    if (!r) {
277 2cc977e2 ths
        BADF("Bad read tag 0x%x\n", tag);
278 2cc977e2 ths
        /* ??? This is the wrong error.  */
279 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
280 2cc977e2 ths
        return;
281 2cc977e2 ths
    }
282 2cc977e2 ths
283 2cc977e2 ths
    if (r->len == -1) {
284 2cc977e2 ths
        scsi_command_complete(r, 0);
285 2cc977e2 ths
        return;
286 2cc977e2 ths
    }
287 2cc977e2 ths
288 2cc977e2 ths
    if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
289 2cc977e2 ths
    {
290 89c0f643 aurel32
        s->senselen = MIN(r->len, s->senselen);
291 89c0f643 aurel32
        memcpy(r->buf, s->sensebuf, s->senselen);
292 2cc977e2 ths
        r->io_header.driver_status = 0;
293 89c0f643 aurel32
        r->io_header.status = 0;
294 89c0f643 aurel32
        r->io_header.dxfer_len  = s->senselen;
295 2cc977e2 ths
        r->len = -1;
296 89c0f643 aurel32
        DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, s->senselen);
297 a9dd6843 aliguori
        DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
298 a9dd6843 aliguori
                r->buf[0], r->buf[1], r->buf[2], r->buf[3],
299 a9dd6843 aliguori
                r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
300 89c0f643 aurel32
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, s->senselen);
301 2cc977e2 ths
        return;
302 2cc977e2 ths
    }
303 2cc977e2 ths
304 2cc977e2 ths
    ret = execute_command(s->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
305 2cc977e2 ths
    if (ret == -1) {
306 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
307 2cc977e2 ths
        return;
308 2cc977e2 ths
    }
309 2cc977e2 ths
}
310 2cc977e2 ths
311 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
312 2cc977e2 ths
{
313 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
314 2cc977e2 ths
315 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
316 2cc977e2 ths
    if (ret) {
317 2cc977e2 ths
        DPRINTF("IO error\n");
318 2cc977e2 ths
        scsi_command_complete(r, ret);
319 2cc977e2 ths
        return;
320 2cc977e2 ths
    }
321 2cc977e2 ths
322 89c0f643 aurel32
    if (r->cmd[0] == MODE_SELECT && r->cmd[4] == 12 &&
323 89c0f643 aurel32
        r->dev->type == TYPE_TAPE) {
324 89c0f643 aurel32
        r->dev->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
325 89c0f643 aurel32
        DPRINTF("block size %d\n", r->dev->blocksize);
326 89c0f643 aurel32
    }
327 89c0f643 aurel32
328 2cc977e2 ths
    scsi_command_complete(r, ret);
329 2cc977e2 ths
}
330 2cc977e2 ths
331 2cc977e2 ths
/* Write data to a scsi device.  Returns nonzero on failure.
332 2cc977e2 ths
   The transfer may complete asynchronously.  */
333 2cc977e2 ths
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
334 2cc977e2 ths
{
335 2cc977e2 ths
    SCSIDeviceState *s = d->state;
336 2cc977e2 ths
    SCSIRequest *r;
337 2cc977e2 ths
    int ret;
338 2cc977e2 ths
339 2cc977e2 ths
    DPRINTF("scsi_write_data 0x%x\n", tag);
340 2cc977e2 ths
    r = scsi_find_request(s, tag);
341 2cc977e2 ths
    if (!r) {
342 2cc977e2 ths
        BADF("Bad write tag 0x%x\n", tag);
343 2cc977e2 ths
        /* ??? This is the wrong error.  */
344 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
345 2cc977e2 ths
        return 0;
346 2cc977e2 ths
    }
347 2cc977e2 ths
348 2cc977e2 ths
    if (r->len == 0) {
349 2cc977e2 ths
        r->len = r->buflen;
350 2cc977e2 ths
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len);
351 2cc977e2 ths
        return 0;
352 2cc977e2 ths
    }
353 2cc977e2 ths
354 2cc977e2 ths
    ret = execute_command(s->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
355 2cc977e2 ths
    if (ret == -1) {
356 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
357 2cc977e2 ths
        return 1;
358 2cc977e2 ths
    }
359 2cc977e2 ths
360 2cc977e2 ths
    return 0;
361 2cc977e2 ths
}
362 2cc977e2 ths
363 2cc977e2 ths
/* Return a pointer to the data buffer.  */
364 2cc977e2 ths
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
365 2cc977e2 ths
{
366 2cc977e2 ths
    SCSIDeviceState *s = d->state;
367 2cc977e2 ths
    SCSIRequest *r;
368 2cc977e2 ths
    r = scsi_find_request(s, tag);
369 2cc977e2 ths
    if (!r) {
370 2cc977e2 ths
        BADF("Bad buffer tag 0x%x\n", tag);
371 2cc977e2 ths
        return NULL;
372 2cc977e2 ths
    }
373 2cc977e2 ths
    return r->buf;
374 2cc977e2 ths
}
375 2cc977e2 ths
376 2cc977e2 ths
static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
377 2cc977e2 ths
{
378 2cc977e2 ths
    switch (cmd[0] >> 5) {
379 2cc977e2 ths
    case 0:
380 2cc977e2 ths
        *len = cmd[4];
381 2cc977e2 ths
        *cmdlen = 6;
382 72ecb8d9 aliguori
        /* length 0 means 256 blocks */
383 72ecb8d9 aliguori
        if (*len == 0)
384 72ecb8d9 aliguori
            *len = 256;
385 2cc977e2 ths
        break;
386 2cc977e2 ths
    case 1:
387 2cc977e2 ths
    case 2:
388 2cc977e2 ths
        *len = cmd[8] | (cmd[7] << 8);
389 2cc977e2 ths
        *cmdlen = 10;
390 2cc977e2 ths
        break;
391 2cc977e2 ths
    case 4:
392 2cc977e2 ths
        *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
393 2cc977e2 ths
        *cmdlen = 16;
394 2cc977e2 ths
        break;
395 2cc977e2 ths
    case 5:
396 2cc977e2 ths
        *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
397 2cc977e2 ths
        *cmdlen = 12;
398 2cc977e2 ths
        break;
399 2cc977e2 ths
    default:
400 2cc977e2 ths
        return -1;
401 2cc977e2 ths
    }
402 2cc977e2 ths
403 2cc977e2 ths
    switch(cmd[0]) {
404 2cc977e2 ths
    case TEST_UNIT_READY:
405 2cc977e2 ths
    case REZERO_UNIT:
406 2cc977e2 ths
    case START_STOP:
407 2cc977e2 ths
    case SEEK_6:
408 2cc977e2 ths
    case WRITE_FILEMARKS:
409 2cc977e2 ths
    case SPACE:
410 2cc977e2 ths
    case ERASE:
411 2cc977e2 ths
    case ALLOW_MEDIUM_REMOVAL:
412 2cc977e2 ths
    case VERIFY:
413 2cc977e2 ths
    case SEEK_10:
414 2cc977e2 ths
    case SYNCHRONIZE_CACHE:
415 2cc977e2 ths
    case LOCK_UNLOCK_CACHE:
416 2cc977e2 ths
    case LOAD_UNLOAD:
417 2cc977e2 ths
    case SET_CD_SPEED:
418 2cc977e2 ths
    case SET_LIMITS:
419 2cc977e2 ths
    case WRITE_LONG:
420 2cc977e2 ths
    case MOVE_MEDIUM:
421 2cc977e2 ths
    case UPDATE_BLOCK:
422 2cc977e2 ths
        *len = 0;
423 2cc977e2 ths
        break;
424 2cc977e2 ths
    case MODE_SENSE:
425 2cc977e2 ths
        break;
426 2cc977e2 ths
    case WRITE_SAME:
427 2cc977e2 ths
        *len = 1;
428 2cc977e2 ths
        break;
429 2cc977e2 ths
    case READ_CAPACITY:
430 2cc977e2 ths
        *len = 8;
431 2cc977e2 ths
        break;
432 2cc977e2 ths
    case READ_BLOCK_LIMITS:
433 2cc977e2 ths
        *len = 6;
434 2cc977e2 ths
        break;
435 2cc977e2 ths
    case READ_POSITION:
436 2cc977e2 ths
        *len = 20;
437 2cc977e2 ths
        break;
438 2cc977e2 ths
    case SEND_VOLUME_TAG:
439 2cc977e2 ths
        *len *= 40;
440 2cc977e2 ths
        break;
441 2cc977e2 ths
    case MEDIUM_SCAN:
442 2cc977e2 ths
        *len *= 8;
443 2cc977e2 ths
        break;
444 2cc977e2 ths
    case WRITE_10:
445 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
446 2cc977e2 ths
    case WRITE_VERIFY:
447 2cc977e2 ths
    case WRITE_6:
448 2cc977e2 ths
    case WRITE_12:
449 2cc977e2 ths
    case WRITE_VERIFY_12:
450 2cc977e2 ths
        *len *= blocksize;
451 2cc977e2 ths
        break;
452 2cc977e2 ths
    case READ_10:
453 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
454 2cc977e2 ths
    case READ_6:
455 2cc977e2 ths
    case READ_REVERSE:
456 2cc977e2 ths
    case RECOVER_BUFFERED_DATA:
457 2cc977e2 ths
    case READ_12:
458 2cc977e2 ths
        *len *= blocksize;
459 2cc977e2 ths
        break;
460 89c0f643 aurel32
    case INQUIRY:
461 89c0f643 aurel32
        *len = cmd[4] | (cmd[3] << 8);
462 89c0f643 aurel32
        break;
463 2cc977e2 ths
    }
464 2cc977e2 ths
    return 0;
465 2cc977e2 ths
}
466 2cc977e2 ths
467 a9dd6843 aliguori
static int scsi_stream_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
468 a9dd6843 aliguori
{
469 a9dd6843 aliguori
    switch(cmd[0]) {
470 a9dd6843 aliguori
    /* stream commands */
471 a9dd6843 aliguori
    case READ_6:
472 a9dd6843 aliguori
    case READ_REVERSE:
473 a9dd6843 aliguori
    case RECOVER_BUFFERED_DATA:
474 a9dd6843 aliguori
    case WRITE_6:
475 a9dd6843 aliguori
        *cmdlen = 6;
476 a9dd6843 aliguori
        *len = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
477 a9dd6843 aliguori
        if (cmd[1] & 0x01) /* fixed */
478 a9dd6843 aliguori
            *len *= blocksize;
479 a9dd6843 aliguori
        break;
480 a9dd6843 aliguori
    case REWIND:
481 a9dd6843 aliguori
    case START_STOP:
482 a9dd6843 aliguori
        *cmdlen = 6;
483 a9dd6843 aliguori
        *len = 0;
484 a9dd6843 aliguori
        cmd[1] = 0x01;        /* force IMMED, otherwise qemu waits end of command */
485 a9dd6843 aliguori
        break;
486 a9dd6843 aliguori
    /* generic commands */
487 a9dd6843 aliguori
    default:
488 a9dd6843 aliguori
        return scsi_length(cmd, blocksize, cmdlen, len);
489 a9dd6843 aliguori
    }
490 a9dd6843 aliguori
    return 0;
491 a9dd6843 aliguori
}
492 a9dd6843 aliguori
493 2cc977e2 ths
static int is_write(int command)
494 2cc977e2 ths
{
495 2cc977e2 ths
    switch (command) {
496 2cc977e2 ths
    case COPY:
497 2cc977e2 ths
    case COPY_VERIFY:
498 2cc977e2 ths
    case COMPARE:
499 2cc977e2 ths
    case CHANGE_DEFINITION:
500 2cc977e2 ths
    case LOG_SELECT:
501 2cc977e2 ths
    case MODE_SELECT:
502 2cc977e2 ths
    case MODE_SELECT_10:
503 2cc977e2 ths
    case SEND_DIAGNOSTIC:
504 2cc977e2 ths
    case WRITE_BUFFER:
505 2cc977e2 ths
    case FORMAT_UNIT:
506 2cc977e2 ths
    case REASSIGN_BLOCKS:
507 2cc977e2 ths
    case RESERVE:
508 2cc977e2 ths
    case SEARCH_EQUAL:
509 2cc977e2 ths
    case SEARCH_HIGH:
510 2cc977e2 ths
    case SEARCH_LOW:
511 2cc977e2 ths
    case WRITE_6:
512 2cc977e2 ths
    case WRITE_10:
513 2cc977e2 ths
    case WRITE_VERIFY:
514 2cc977e2 ths
    case UPDATE_BLOCK:
515 2cc977e2 ths
    case WRITE_LONG:
516 2cc977e2 ths
    case WRITE_SAME:
517 2cc977e2 ths
    case SEARCH_HIGH_12:
518 2cc977e2 ths
    case SEARCH_EQUAL_12:
519 2cc977e2 ths
    case SEARCH_LOW_12:
520 2cc977e2 ths
    case WRITE_12:
521 2cc977e2 ths
    case WRITE_VERIFY_12:
522 2cc977e2 ths
    case SET_WINDOW:
523 2cc977e2 ths
    case MEDIUM_SCAN:
524 2cc977e2 ths
    case SEND_VOLUME_TAG:
525 2cc977e2 ths
    case WRITE_LONG_2:
526 2cc977e2 ths
        return 1;
527 2cc977e2 ths
    }
528 2cc977e2 ths
    return 0;
529 2cc977e2 ths
}
530 2cc977e2 ths
531 2cc977e2 ths
/* Execute a scsi command.  Returns the length of the data expected by the
532 2cc977e2 ths
   command.  This will be Positive for data transfers from the device
533 2cc977e2 ths
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
534 2cc977e2 ths
   and zero if the command does not transfer any data.  */
535 2cc977e2 ths
536 2cc977e2 ths
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
537 2cc977e2 ths
                                 uint8_t *cmd, int lun)
538 2cc977e2 ths
{
539 2cc977e2 ths
    SCSIDeviceState *s = d->state;
540 37e828b4 aurel32
    uint32_t len=0;
541 37e828b4 aurel32
    int cmdlen=0;
542 2cc977e2 ths
    SCSIRequest *r;
543 2cc977e2 ths
    int ret;
544 2cc977e2 ths
545 a9dd6843 aliguori
    if (s->type == TYPE_TAPE) {
546 a9dd6843 aliguori
        if (scsi_stream_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
547 a9dd6843 aliguori
            BADF("Unsupported command length, command %x\n", cmd[0]);
548 a9dd6843 aliguori
            return 0;
549 a9dd6843 aliguori
        }
550 a9dd6843 aliguori
     } else {
551 a9dd6843 aliguori
        if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
552 a9dd6843 aliguori
            BADF("Unsupported command length, command %x\n", cmd[0]);
553 a9dd6843 aliguori
            return 0;
554 a9dd6843 aliguori
        }
555 2cc977e2 ths
    }
556 2cc977e2 ths
557 2cc977e2 ths
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
558 2cc977e2 ths
            cmd[0], len);
559 2cc977e2 ths
560 89c0f643 aurel32
    if (cmd[0] != REQUEST_SENSE &&
561 89c0f643 aurel32
        (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
562 89c0f643 aurel32
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
563 89c0f643 aurel32
564 89c0f643 aurel32
        s->sensebuf[0] = 0x70;
565 89c0f643 aurel32
        s->sensebuf[1] = 0x00;
566 89c0f643 aurel32
        s->sensebuf[2] = ILLEGAL_REQUEST;
567 89c0f643 aurel32
        s->sensebuf[3] = 0x00;
568 89c0f643 aurel32
        s->sensebuf[4] = 0x00;
569 89c0f643 aurel32
        s->sensebuf[5] = 0x00;
570 89c0f643 aurel32
        s->sensebuf[6] = 0x00;
571 89c0f643 aurel32
        s->senselen = 7;
572 89c0f643 aurel32
        s->driver_status = SG_ERR_DRIVER_SENSE;
573 89c0f643 aurel32
        s->completion(s->opaque, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
574 89c0f643 aurel32
        return 0;
575 89c0f643 aurel32
    }
576 89c0f643 aurel32
577 2cc977e2 ths
    r = scsi_find_request(s, tag);
578 2cc977e2 ths
    if (r) {
579 2cc977e2 ths
        BADF("Tag 0x%x already in use %p\n", tag, r);
580 2cc977e2 ths
        scsi_cancel_io(d, tag);
581 2cc977e2 ths
    }
582 2cc977e2 ths
    r = scsi_new_request(s, tag);
583 2cc977e2 ths
584 2cc977e2 ths
    memcpy(r->cmd, cmd, cmdlen);
585 2cc977e2 ths
    r->cmdlen = cmdlen;
586 2cc977e2 ths
587 2cc977e2 ths
    if (len == 0) {
588 2cc977e2 ths
        if (r->buf != NULL)
589 2cc977e2 ths
            free(r->buf);
590 2cc977e2 ths
        r->buflen = 0;
591 2cc977e2 ths
        r->buf = NULL;
592 2cc977e2 ths
        ret = execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
593 2cc977e2 ths
        if (ret == -1) {
594 2cc977e2 ths
            scsi_command_complete(r, -EINVAL);
595 2cc977e2 ths
            return 0;
596 2cc977e2 ths
        }
597 2cc977e2 ths
        return 0;
598 2cc977e2 ths
    }
599 2cc977e2 ths
600 2cc977e2 ths
    if (r->buflen != len) {
601 2cc977e2 ths
        if (r->buf != NULL)
602 2cc977e2 ths
            free(r->buf);
603 2cc977e2 ths
        r->buf = qemu_malloc(len);
604 2cc977e2 ths
        r->buflen = len;
605 2cc977e2 ths
    }
606 2cc977e2 ths
607 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
608 2cc977e2 ths
    r->len = len;
609 2cc977e2 ths
    if (is_write(cmd[0])) {
610 2cc977e2 ths
        r->len = 0;
611 2cc977e2 ths
        return -len;
612 2cc977e2 ths
    }
613 2cc977e2 ths
614 2cc977e2 ths
    return len;
615 2cc977e2 ths
}
616 2cc977e2 ths
617 2cc977e2 ths
static int get_blocksize(BlockDriverState *bdrv)
618 2cc977e2 ths
{
619 2cc977e2 ths
    uint8_t cmd[10];
620 2cc977e2 ths
    uint8_t buf[8];
621 2cc977e2 ths
    uint8_t sensebuf[8];
622 2cc977e2 ths
    sg_io_hdr_t io_header;
623 2cc977e2 ths
    int ret;
624 2cc977e2 ths
625 4f26a486 aliguori
    memset(cmd, 0, sizeof(cmd));
626 4f26a486 aliguori
    memset(buf, 0, sizeof(buf));
627 2cc977e2 ths
    cmd[0] = READ_CAPACITY;
628 2cc977e2 ths
629 2cc977e2 ths
    memset(&io_header, 0, sizeof(io_header));
630 2cc977e2 ths
    io_header.interface_id = 'S';
631 2cc977e2 ths
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
632 2cc977e2 ths
    io_header.dxfer_len = sizeof(buf);
633 2cc977e2 ths
    io_header.dxferp = buf;
634 2cc977e2 ths
    io_header.cmdp = cmd;
635 2cc977e2 ths
    io_header.cmd_len = sizeof(cmd);
636 2cc977e2 ths
    io_header.mx_sb_len = sizeof(sensebuf);
637 2cc977e2 ths
    io_header.sbp = sensebuf;
638 2cc977e2 ths
    io_header.timeout = 6000; /* XXX */
639 2cc977e2 ths
640 7d780669 aliguori
    ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header));
641 7d780669 aliguori
    if (ret < 0)
642 2cc977e2 ths
        return -1;
643 2cc977e2 ths
644 7d780669 aliguori
    while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 &&
645 7d780669 aliguori
           ret == -EINTR)
646 7d780669 aliguori
        ;
647 2cc977e2 ths
648 7d780669 aliguori
    if (ret < 0)
649 2cc977e2 ths
        return -1;
650 2cc977e2 ths
651 2cc977e2 ths
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
652 2cc977e2 ths
}
653 2cc977e2 ths
654 89c0f643 aurel32
static int get_stream_blocksize(BlockDriverState *bdrv)
655 89c0f643 aurel32
{
656 89c0f643 aurel32
    uint8_t cmd[6];
657 89c0f643 aurel32
    uint8_t buf[12];
658 89c0f643 aurel32
    uint8_t sensebuf[8];
659 89c0f643 aurel32
    sg_io_hdr_t io_header;
660 89c0f643 aurel32
    int ret;
661 89c0f643 aurel32
662 89c0f643 aurel32
    memset(cmd, 0, sizeof(cmd));
663 89c0f643 aurel32
    memset(buf, 0, sizeof(buf));
664 89c0f643 aurel32
    cmd[0] = MODE_SENSE;
665 89c0f643 aurel32
    cmd[4] = sizeof(buf);
666 89c0f643 aurel32
667 89c0f643 aurel32
    memset(&io_header, 0, sizeof(io_header));
668 89c0f643 aurel32
    io_header.interface_id = 'S';
669 89c0f643 aurel32
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
670 89c0f643 aurel32
    io_header.dxfer_len = sizeof(buf);
671 89c0f643 aurel32
    io_header.dxferp = buf;
672 89c0f643 aurel32
    io_header.cmdp = cmd;
673 89c0f643 aurel32
    io_header.cmd_len = sizeof(cmd);
674 89c0f643 aurel32
    io_header.mx_sb_len = sizeof(sensebuf);
675 89c0f643 aurel32
    io_header.sbp = sensebuf;
676 89c0f643 aurel32
    io_header.timeout = 6000; /* XXX */
677 89c0f643 aurel32
678 7d780669 aliguori
    ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header));
679 7d780669 aliguori
    if (ret < 0)
680 89c0f643 aurel32
        return -1;
681 89c0f643 aurel32
682 7d780669 aliguori
    while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 &&
683 7d780669 aliguori
           ret == -EINTR)
684 7d780669 aliguori
        ;
685 89c0f643 aurel32
686 7d780669 aliguori
    if (ret < 0)
687 89c0f643 aurel32
        return -1;
688 89c0f643 aurel32
689 89c0f643 aurel32
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
690 89c0f643 aurel32
}
691 89c0f643 aurel32
692 2cc977e2 ths
static void scsi_destroy(SCSIDevice *d)
693 2cc977e2 ths
{
694 2cc977e2 ths
    SCSIRequest *r, *n;
695 2cc977e2 ths
696 2cc977e2 ths
    r = d->state->requests;
697 2cc977e2 ths
    while (r) {
698 2cc977e2 ths
        n = r->next;
699 2cc977e2 ths
        qemu_free(r);
700 2cc977e2 ths
        r = n;
701 2cc977e2 ths
    }
702 2cc977e2 ths
703 2cc977e2 ths
    r = free_requests;
704 2cc977e2 ths
    while (r) {
705 2cc977e2 ths
        n = r->next;
706 2cc977e2 ths
        qemu_free(r);
707 2cc977e2 ths
        r = n;
708 2cc977e2 ths
    }
709 2cc977e2 ths
710 2cc977e2 ths
    qemu_free(d->state);
711 2cc977e2 ths
    qemu_free(d);
712 2cc977e2 ths
}
713 2cc977e2 ths
714 2cc977e2 ths
SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
715 2cc977e2 ths
                              scsi_completionfn completion, void *opaque)
716 2cc977e2 ths
{
717 2cc977e2 ths
    int sg_version;
718 2cc977e2 ths
    SCSIDevice *d;
719 2cc977e2 ths
    SCSIDeviceState *s;
720 2cc977e2 ths
    struct sg_scsi_id scsiid;
721 2cc977e2 ths
722 2cc977e2 ths
    /* check we are really using a /dev/sg* file */
723 2cc977e2 ths
724 2cc977e2 ths
    if (!bdrv_is_sg(bdrv))
725 2cc977e2 ths
        return NULL;
726 2cc977e2 ths
727 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
728 2cc977e2 ths
729 2cc977e2 ths
    if (bdrv_ioctl(bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
730 2cc977e2 ths
        sg_version < 30000)
731 2cc977e2 ths
        return NULL;
732 2cc977e2 ths
733 2cc977e2 ths
    /* get LUN of the /dev/sg? */
734 2cc977e2 ths
735 2cc977e2 ths
    if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid))
736 2cc977e2 ths
        return NULL;
737 2cc977e2 ths
738 2cc977e2 ths
    /* define device state */
739 2cc977e2 ths
740 2cc977e2 ths
    s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
741 2cc977e2 ths
    s->bdrv = bdrv;
742 2cc977e2 ths
    s->requests = NULL;
743 2cc977e2 ths
    s->completion = completion;
744 2cc977e2 ths
    s->opaque = opaque;
745 2cc977e2 ths
    s->lun = scsiid.lun;
746 89c0f643 aurel32
    DPRINTF("LUN %d\n", s->lun);
747 a9dd6843 aliguori
    s->type = scsiid.scsi_type;
748 89c0f643 aurel32
    DPRINTF("device type %d\n", s->type);
749 89c0f643 aurel32
    if (s->type == TYPE_TAPE) {
750 89c0f643 aurel32
        s->blocksize = get_stream_blocksize(s->bdrv);
751 89c0f643 aurel32
        if (s->blocksize == -1)
752 89c0f643 aurel32
            s->blocksize = 0;
753 89c0f643 aurel32
    } else {
754 89c0f643 aurel32
        s->blocksize = get_blocksize(s->bdrv);
755 89c0f643 aurel32
        /* removable media returns 0 if not present */
756 89c0f643 aurel32
        if (s->blocksize <= 0) {
757 89c0f643 aurel32
            if (s->type == TYPE_ROM || s->type  == TYPE_WORM)
758 89c0f643 aurel32
                s->blocksize = 2048;
759 89c0f643 aurel32
            else
760 89c0f643 aurel32
                s->blocksize = 512;
761 89c0f643 aurel32
        }
762 89c0f643 aurel32
    }
763 89c0f643 aurel32
    DPRINTF("block size %d\n", s->blocksize);
764 2cc977e2 ths
    s->driver_status = 0;
765 2cc977e2 ths
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
766 2cc977e2 ths
767 2cc977e2 ths
    /* define function to manage device */
768 2cc977e2 ths
769 2cc977e2 ths
    d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
770 2cc977e2 ths
    d->state = s;
771 2cc977e2 ths
    d->destroy = scsi_destroy;
772 2cc977e2 ths
    d->send_command = scsi_send_command;
773 2cc977e2 ths
    d->read_data = scsi_read_data;
774 2cc977e2 ths
    d->write_data = scsi_write_data;
775 2cc977e2 ths
    d->cancel_io = scsi_cancel_io;
776 2cc977e2 ths
    d->get_buf = scsi_get_buf;
777 2cc977e2 ths
778 2cc977e2 ths
    return d;
779 2cc977e2 ths
}
780 2cc977e2 ths
#endif /* __linux__ */