Statistics
| Branch: | Revision:

root / hw / scsi-generic.c @ e927bb00

History | View | Annotate | Download (15.3 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 2cc977e2 ths
#define LOAD_UNLOAD 0xa6
48 2cc977e2 ths
#define SET_CD_SPEED 0xbb
49 2cc977e2 ths
#define BLANK 0xa1
50 2cc977e2 ths
51 2cc977e2 ths
#define SCSI_CMD_BUF_SIZE     16
52 2cc977e2 ths
#define SCSI_SENSE_BUF_SIZE 32
53 2cc977e2 ths
54 2cc977e2 ths
#define SG_ERR_DRIVER_TIMEOUT 0x06
55 2cc977e2 ths
#define SG_ERR_DRIVER_SENSE 0x08
56 2cc977e2 ths
57 2cc977e2 ths
#ifndef MAX_UINT
58 2cc977e2 ths
#define MAX_UINT ((unsigned int)-1)
59 2cc977e2 ths
#endif
60 2cc977e2 ths
61 2cc977e2 ths
typedef struct SCSIRequest {
62 2cc977e2 ths
    BlockDriverAIOCB *aiocb;
63 2cc977e2 ths
    struct SCSIRequest *next;
64 2cc977e2 ths
    SCSIDeviceState *dev;
65 2cc977e2 ths
    uint32_t tag;
66 2cc977e2 ths
    uint8_t cmd[SCSI_CMD_BUF_SIZE];
67 2cc977e2 ths
    int cmdlen;
68 2cc977e2 ths
    uint8_t *buf;
69 2cc977e2 ths
    int buflen;
70 2cc977e2 ths
    int len;
71 2cc977e2 ths
    sg_io_hdr_t io_header;
72 2cc977e2 ths
} SCSIRequest;
73 2cc977e2 ths
74 2cc977e2 ths
struct SCSIDeviceState
75 2cc977e2 ths
{
76 2cc977e2 ths
    SCSIRequest *requests;
77 2cc977e2 ths
    BlockDriverState *bdrv;
78 2cc977e2 ths
    int blocksize;
79 2cc977e2 ths
    int lun;
80 2cc977e2 ths
    scsi_completionfn completion;
81 2cc977e2 ths
    void *opaque;
82 2cc977e2 ths
    int driver_status;
83 2cc977e2 ths
    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
84 2cc977e2 ths
};
85 2cc977e2 ths
86 2cc977e2 ths
/* Global pool of SCSIRequest structures.  */
87 2cc977e2 ths
static SCSIRequest *free_requests = NULL;
88 2cc977e2 ths
89 2cc977e2 ths
static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
90 2cc977e2 ths
{
91 2cc977e2 ths
    SCSIRequest *r;
92 2cc977e2 ths
93 2cc977e2 ths
    if (free_requests) {
94 2cc977e2 ths
        r = free_requests;
95 2cc977e2 ths
        free_requests = r->next;
96 2cc977e2 ths
    } else {
97 2cc977e2 ths
        r = qemu_malloc(sizeof(SCSIRequest));
98 2cc977e2 ths
        r->buf = NULL;
99 2cc977e2 ths
        r->buflen = 0;
100 2cc977e2 ths
    }
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 2cc977e2 ths
    SCSIDeviceState *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 2cc977e2 ths
static SCSIRequest *scsi_find_request(SCSIDeviceState *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 2cc977e2 ths
    SCSIDeviceState *s = r->dev;
153 2cc977e2 ths
    uint32_t tag;
154 2cc977e2 ths
    int sense;
155 2cc977e2 ths
156 2cc977e2 ths
    s->driver_status = r->io_header.driver_status;
157 2cc977e2 ths
    if (ret != 0)
158 2cc977e2 ths
        sense = HARDWARE_ERROR;
159 2cc977e2 ths
    else {
160 2cc977e2 ths
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
161 2cc977e2 ths
            sense = HARDWARE_ERROR;
162 2cc977e2 ths
            BADF("Driver Timeout\n");
163 2cc977e2 ths
        } else if ((s->driver_status & SG_ERR_DRIVER_SENSE) == 0)
164 2cc977e2 ths
            sense = NO_SENSE;
165 2cc977e2 ths
        else
166 2cc977e2 ths
            sense = s->sensebuf[2] & 0x0f;
167 2cc977e2 ths
    }
168 2cc977e2 ths
169 2cc977e2 ths
    DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r, r->tag, sense);
170 2cc977e2 ths
    tag = r->tag;
171 2cc977e2 ths
    scsi_remove_request(r);
172 2cc977e2 ths
    s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
173 2cc977e2 ths
}
174 2cc977e2 ths
175 2cc977e2 ths
/* Cancel a pending data transfer.  */
176 2cc977e2 ths
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
177 2cc977e2 ths
{
178 2cc977e2 ths
    DPRINTF("scsi_cancel_io 0x%x\n", tag);
179 2cc977e2 ths
    SCSIDeviceState *s = d->state;
180 2cc977e2 ths
    SCSIRequest *r;
181 2cc977e2 ths
    DPRINTF("Cancel tag=0x%x\n", tag);
182 2cc977e2 ths
    r = scsi_find_request(s, tag);
183 2cc977e2 ths
    if (r) {
184 2cc977e2 ths
        if (r->aiocb)
185 2cc977e2 ths
            bdrv_aio_cancel(r->aiocb);
186 2cc977e2 ths
        r->aiocb = NULL;
187 2cc977e2 ths
        scsi_remove_request(r);
188 2cc977e2 ths
    }
189 2cc977e2 ths
}
190 2cc977e2 ths
191 2cc977e2 ths
static int execute_command(BlockDriverState *bdrv,
192 2cc977e2 ths
                           SCSIRequest *r, int direction,
193 2cc977e2 ths
                           BlockDriverCompletionFunc *complete)
194 2cc977e2 ths
{
195 2cc977e2 ths
196 2cc977e2 ths
    r->io_header.interface_id = 'S';
197 2cc977e2 ths
    r->io_header.dxfer_direction = direction;
198 2cc977e2 ths
    r->io_header.dxferp = r->buf;
199 2cc977e2 ths
    r->io_header.dxfer_len = r->buflen;
200 2cc977e2 ths
    r->io_header.cmdp = r->cmd;
201 2cc977e2 ths
    r->io_header.cmd_len = r->cmdlen;
202 2cc977e2 ths
    r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
203 2cc977e2 ths
    r->io_header.sbp = r->dev->sensebuf;
204 2cc977e2 ths
    r->io_header.timeout = MAX_UINT;
205 2cc977e2 ths
    r->io_header.usr_ptr = r;
206 2cc977e2 ths
    r->io_header.flags |= SG_FLAG_DIRECT_IO;
207 2cc977e2 ths
208 2cc977e2 ths
    if (bdrv_pwrite(bdrv, -1, &r->io_header, sizeof(r->io_header)) == -1) {
209 2cc977e2 ths
        BADF("execute_command: write failed ! (%d)\n", errno);
210 2cc977e2 ths
        return -1;
211 2cc977e2 ths
    }
212 2cc977e2 ths
    if (complete == NULL) {
213 2cc977e2 ths
        int ret;
214 2cc977e2 ths
        r->aiocb = NULL;
215 2cc977e2 ths
        while ((ret = bdrv_pread(bdrv, -1, &r->io_header,
216 2cc977e2 ths
                                           sizeof(r->io_header))) == -1 &&
217 2cc977e2 ths
                      errno == EINTR);
218 2cc977e2 ths
        if (ret == -1) {
219 2cc977e2 ths
            BADF("execute_command: read failed !\n");
220 2cc977e2 ths
            return -1;
221 2cc977e2 ths
        }
222 2cc977e2 ths
        return 0;
223 2cc977e2 ths
    }
224 2cc977e2 ths
225 2cc977e2 ths
    r->aiocb = bdrv_aio_read(bdrv, 0, (uint8_t*)&r->io_header,
226 2cc977e2 ths
                          -(int64_t)sizeof(r->io_header), complete, r);
227 2cc977e2 ths
    if (r->aiocb == NULL) {
228 2cc977e2 ths
        BADF("execute_command: read failed !\n");
229 2cc977e2 ths
        return -1;
230 2cc977e2 ths
    }
231 2cc977e2 ths
232 2cc977e2 ths
    return 0;
233 2cc977e2 ths
}
234 2cc977e2 ths
235 2cc977e2 ths
static void scsi_read_complete(void * opaque, int ret)
236 2cc977e2 ths
{
237 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
238 2cc977e2 ths
    SCSIDeviceState *s = r->dev;
239 2cc977e2 ths
    int len;
240 2cc977e2 ths
241 2cc977e2 ths
    if (ret) {
242 2cc977e2 ths
        DPRINTF("IO error\n");
243 2cc977e2 ths
        scsi_command_complete(r, ret);
244 2cc977e2 ths
        return;
245 2cc977e2 ths
    }
246 2cc977e2 ths
    len = r->io_header.dxfer_len - r->io_header.resid;
247 2cc977e2 ths
    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
248 2cc977e2 ths
249 2cc977e2 ths
    r->len = -1;
250 2cc977e2 ths
    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
251 2cc977e2 ths
}
252 2cc977e2 ths
253 2cc977e2 ths
/* Read more data from scsi device into buffer.  */
254 2cc977e2 ths
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
255 2cc977e2 ths
{
256 2cc977e2 ths
    SCSIDeviceState *s = d->state;
257 2cc977e2 ths
    SCSIRequest *r;
258 2cc977e2 ths
    int ret;
259 2cc977e2 ths
260 2cc977e2 ths
    DPRINTF("scsi_read_data 0x%x\n", tag);
261 2cc977e2 ths
    r = scsi_find_request(s, tag);
262 2cc977e2 ths
    if (!r) {
263 2cc977e2 ths
        BADF("Bad read tag 0x%x\n", tag);
264 2cc977e2 ths
        /* ??? This is the wrong error.  */
265 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
266 2cc977e2 ths
        return;
267 2cc977e2 ths
    }
268 2cc977e2 ths
269 2cc977e2 ths
    if (r->len == -1) {
270 2cc977e2 ths
        scsi_command_complete(r, 0);
271 2cc977e2 ths
        return;
272 2cc977e2 ths
    }
273 2cc977e2 ths
274 2cc977e2 ths
    if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
275 2cc977e2 ths
    {
276 2cc977e2 ths
        memcpy(r->buf, s->sensebuf, 16);
277 2cc977e2 ths
        r->io_header.driver_status = 0;
278 2cc977e2 ths
        r->len = -1;
279 2cc977e2 ths
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16);
280 2cc977e2 ths
        return;
281 2cc977e2 ths
    }
282 2cc977e2 ths
283 2cc977e2 ths
    ret = execute_command(s->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
284 2cc977e2 ths
    if (ret == -1) {
285 2cc977e2 ths
        scsi_command_complete(r, -EINVAL);
286 2cc977e2 ths
        return;
287 2cc977e2 ths
    }
288 2cc977e2 ths
}
289 2cc977e2 ths
290 2cc977e2 ths
static void scsi_write_complete(void * opaque, int ret)
291 2cc977e2 ths
{
292 2cc977e2 ths
    SCSIRequest *r = (SCSIRequest *)opaque;
293 2cc977e2 ths
294 2cc977e2 ths
    DPRINTF("scsi_write_complete() ret = %d\n", ret);
295 2cc977e2 ths
    if (ret) {
296 2cc977e2 ths
        DPRINTF("IO error\n");
297 2cc977e2 ths
        scsi_command_complete(r, ret);
298 2cc977e2 ths
        return;
299 2cc977e2 ths
    }
300 2cc977e2 ths
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 2cc977e2 ths
    SCSIDeviceState *s = d->state;
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 2cc977e2 ths
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len);
324 2cc977e2 ths
        return 0;
325 2cc977e2 ths
    }
326 2cc977e2 ths
327 2cc977e2 ths
    ret = execute_command(s->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 2cc977e2 ths
    SCSIDeviceState *s = d->state;
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 2cc977e2 ths
        break;
356 2cc977e2 ths
    case 1:
357 2cc977e2 ths
    case 2:
358 2cc977e2 ths
        *len = cmd[8] | (cmd[7] << 8);
359 2cc977e2 ths
        *cmdlen = 10;
360 2cc977e2 ths
        break;
361 2cc977e2 ths
    case 4:
362 2cc977e2 ths
        *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
363 2cc977e2 ths
        *cmdlen = 16;
364 2cc977e2 ths
        break;
365 2cc977e2 ths
    case 5:
366 2cc977e2 ths
        *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
367 2cc977e2 ths
        *cmdlen = 12;
368 2cc977e2 ths
        break;
369 2cc977e2 ths
    default:
370 2cc977e2 ths
        return -1;
371 2cc977e2 ths
    }
372 2cc977e2 ths
373 2cc977e2 ths
    switch(cmd[0]) {
374 2cc977e2 ths
    case TEST_UNIT_READY:
375 2cc977e2 ths
    case REZERO_UNIT:
376 2cc977e2 ths
    case START_STOP:
377 2cc977e2 ths
    case SEEK_6:
378 2cc977e2 ths
    case WRITE_FILEMARKS:
379 2cc977e2 ths
    case SPACE:
380 2cc977e2 ths
    case ERASE:
381 2cc977e2 ths
    case ALLOW_MEDIUM_REMOVAL:
382 2cc977e2 ths
    case VERIFY:
383 2cc977e2 ths
    case SEEK_10:
384 2cc977e2 ths
    case SYNCHRONIZE_CACHE:
385 2cc977e2 ths
    case LOCK_UNLOCK_CACHE:
386 2cc977e2 ths
    case LOAD_UNLOAD:
387 2cc977e2 ths
    case SET_CD_SPEED:
388 2cc977e2 ths
    case SET_LIMITS:
389 2cc977e2 ths
    case WRITE_LONG:
390 2cc977e2 ths
    case MOVE_MEDIUM:
391 2cc977e2 ths
    case UPDATE_BLOCK:
392 2cc977e2 ths
        *len = 0;
393 2cc977e2 ths
        break;
394 2cc977e2 ths
    case MODE_SENSE:
395 2cc977e2 ths
        break;
396 2cc977e2 ths
    case WRITE_SAME:
397 2cc977e2 ths
        *len = 1;
398 2cc977e2 ths
        break;
399 2cc977e2 ths
    case READ_CAPACITY:
400 2cc977e2 ths
        *len = 8;
401 2cc977e2 ths
        break;
402 2cc977e2 ths
    case READ_BLOCK_LIMITS:
403 2cc977e2 ths
        *len = 6;
404 2cc977e2 ths
        break;
405 2cc977e2 ths
    case READ_POSITION:
406 2cc977e2 ths
        *len = 20;
407 2cc977e2 ths
        break;
408 2cc977e2 ths
    case SEND_VOLUME_TAG:
409 2cc977e2 ths
        *len *= 40;
410 2cc977e2 ths
        break;
411 2cc977e2 ths
    case MEDIUM_SCAN:
412 2cc977e2 ths
        *len *= 8;
413 2cc977e2 ths
        break;
414 2cc977e2 ths
    case WRITE_10:
415 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
416 2cc977e2 ths
    case WRITE_VERIFY:
417 2cc977e2 ths
    case WRITE_6:
418 2cc977e2 ths
    case WRITE_12:
419 2cc977e2 ths
    case WRITE_VERIFY_12:
420 2cc977e2 ths
        *len *= blocksize;
421 2cc977e2 ths
        break;
422 2cc977e2 ths
    case READ_10:
423 2cc977e2 ths
        cmd[1] &= ~0x08;        /* disable FUA */
424 2cc977e2 ths
    case READ_6:
425 2cc977e2 ths
    case READ_REVERSE:
426 2cc977e2 ths
    case RECOVER_BUFFERED_DATA:
427 2cc977e2 ths
    case READ_12:
428 2cc977e2 ths
        *len *= blocksize;
429 2cc977e2 ths
        break;
430 2cc977e2 ths
    }
431 2cc977e2 ths
    return 0;
432 2cc977e2 ths
}
433 2cc977e2 ths
434 2cc977e2 ths
static int is_write(int command)
435 2cc977e2 ths
{
436 2cc977e2 ths
    switch (command) {
437 2cc977e2 ths
    case COPY:
438 2cc977e2 ths
    case COPY_VERIFY:
439 2cc977e2 ths
    case COMPARE:
440 2cc977e2 ths
    case CHANGE_DEFINITION:
441 2cc977e2 ths
    case LOG_SELECT:
442 2cc977e2 ths
    case MODE_SELECT:
443 2cc977e2 ths
    case MODE_SELECT_10:
444 2cc977e2 ths
    case SEND_DIAGNOSTIC:
445 2cc977e2 ths
    case WRITE_BUFFER:
446 2cc977e2 ths
    case FORMAT_UNIT:
447 2cc977e2 ths
    case REASSIGN_BLOCKS:
448 2cc977e2 ths
    case RESERVE:
449 2cc977e2 ths
    case SEARCH_EQUAL:
450 2cc977e2 ths
    case SEARCH_HIGH:
451 2cc977e2 ths
    case SEARCH_LOW:
452 2cc977e2 ths
    case WRITE_6:
453 2cc977e2 ths
    case WRITE_10:
454 2cc977e2 ths
    case WRITE_VERIFY:
455 2cc977e2 ths
    case UPDATE_BLOCK:
456 2cc977e2 ths
    case WRITE_LONG:
457 2cc977e2 ths
    case WRITE_SAME:
458 2cc977e2 ths
    case SEARCH_HIGH_12:
459 2cc977e2 ths
    case SEARCH_EQUAL_12:
460 2cc977e2 ths
    case SEARCH_LOW_12:
461 2cc977e2 ths
    case WRITE_12:
462 2cc977e2 ths
    case WRITE_VERIFY_12:
463 2cc977e2 ths
    case SET_WINDOW:
464 2cc977e2 ths
    case MEDIUM_SCAN:
465 2cc977e2 ths
    case SEND_VOLUME_TAG:
466 2cc977e2 ths
    case WRITE_LONG_2:
467 2cc977e2 ths
        return 1;
468 2cc977e2 ths
    }
469 2cc977e2 ths
    return 0;
470 2cc977e2 ths
}
471 2cc977e2 ths
472 2cc977e2 ths
/* Execute a scsi command.  Returns the length of the data expected by the
473 2cc977e2 ths
   command.  This will be Positive for data transfers from the device
474 2cc977e2 ths
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
475 2cc977e2 ths
   and zero if the command does not transfer any data.  */
476 2cc977e2 ths
477 2cc977e2 ths
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
478 2cc977e2 ths
                                 uint8_t *cmd, int lun)
479 2cc977e2 ths
{
480 2cc977e2 ths
    SCSIDeviceState *s = d->state;
481 2cc977e2 ths
    uint32_t len;
482 2cc977e2 ths
    int cmdlen;
483 2cc977e2 ths
    SCSIRequest *r;
484 2cc977e2 ths
    int ret;
485 2cc977e2 ths
486 2cc977e2 ths
    /* ??? Tags are not unique for different luns.  We only implement a
487 2cc977e2 ths
       single lun, so this should not matter.  */
488 2cc977e2 ths
489 2cc977e2 ths
    if (lun != s->lun || (cmd[1] >> 5) != s->lun) {
490 2cc977e2 ths
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
491 2cc977e2 ths
        s->completion(s->opaque, SCSI_REASON_DONE, tag, ILLEGAL_REQUEST);
492 2cc977e2 ths
        return 0;
493 2cc977e2 ths
    }
494 2cc977e2 ths
495 2cc977e2 ths
    if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
496 2cc977e2 ths
        BADF("Unsupported command length, command %x\n", cmd[0]);
497 2cc977e2 ths
        return 0;
498 2cc977e2 ths
    }
499 2cc977e2 ths
500 2cc977e2 ths
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
501 2cc977e2 ths
            cmd[0], len);
502 2cc977e2 ths
503 2cc977e2 ths
    r = scsi_find_request(s, tag);
504 2cc977e2 ths
    if (r) {
505 2cc977e2 ths
        BADF("Tag 0x%x already in use %p\n", tag, r);
506 2cc977e2 ths
        scsi_cancel_io(d, tag);
507 2cc977e2 ths
    }
508 2cc977e2 ths
    r = scsi_new_request(s, tag);
509 2cc977e2 ths
510 2cc977e2 ths
    memcpy(r->cmd, cmd, cmdlen);
511 2cc977e2 ths
    r->cmdlen = cmdlen;
512 2cc977e2 ths
513 2cc977e2 ths
    if (len == 0) {
514 2cc977e2 ths
        if (r->buf != NULL)
515 2cc977e2 ths
            free(r->buf);
516 2cc977e2 ths
        r->buflen = 0;
517 2cc977e2 ths
        r->buf = NULL;
518 2cc977e2 ths
        ret = execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
519 2cc977e2 ths
        if (ret == -1) {
520 2cc977e2 ths
            scsi_command_complete(r, -EINVAL);
521 2cc977e2 ths
            return 0;
522 2cc977e2 ths
        }
523 2cc977e2 ths
        return 0;
524 2cc977e2 ths
    }
525 2cc977e2 ths
526 2cc977e2 ths
    if (r->buflen != len) {
527 2cc977e2 ths
        if (r->buf != NULL)
528 2cc977e2 ths
            free(r->buf);
529 2cc977e2 ths
        r->buf = qemu_malloc(len);
530 2cc977e2 ths
        r->buflen = len;
531 2cc977e2 ths
    }
532 2cc977e2 ths
533 2cc977e2 ths
    memset(r->buf, 0, r->buflen);
534 2cc977e2 ths
    r->len = len;
535 2cc977e2 ths
    if (is_write(cmd[0])) {
536 2cc977e2 ths
        r->len = 0;
537 2cc977e2 ths
        return -len;
538 2cc977e2 ths
    }
539 2cc977e2 ths
540 2cc977e2 ths
    return len;
541 2cc977e2 ths
}
542 2cc977e2 ths
543 2cc977e2 ths
static int get_blocksize(BlockDriverState *bdrv)
544 2cc977e2 ths
{
545 2cc977e2 ths
    uint8_t cmd[10];
546 2cc977e2 ths
    uint8_t buf[8];
547 2cc977e2 ths
    uint8_t sensebuf[8];
548 2cc977e2 ths
    sg_io_hdr_t io_header;
549 2cc977e2 ths
    int ret;
550 2cc977e2 ths
551 2cc977e2 ths
    memset(cmd, sizeof(cmd), 0);
552 2cc977e2 ths
    memset(buf, sizeof(buf), 0);
553 2cc977e2 ths
    cmd[0] = READ_CAPACITY;
554 2cc977e2 ths
555 2cc977e2 ths
    memset(&io_header, 0, sizeof(io_header));
556 2cc977e2 ths
    io_header.interface_id = 'S';
557 2cc977e2 ths
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
558 2cc977e2 ths
    io_header.dxfer_len = sizeof(buf);
559 2cc977e2 ths
    io_header.dxferp = buf;
560 2cc977e2 ths
    io_header.cmdp = cmd;
561 2cc977e2 ths
    io_header.cmd_len = sizeof(cmd);
562 2cc977e2 ths
    io_header.mx_sb_len = sizeof(sensebuf);
563 2cc977e2 ths
    io_header.sbp = sensebuf;
564 2cc977e2 ths
    io_header.timeout = 6000; /* XXX */
565 2cc977e2 ths
566 2cc977e2 ths
    ret = bdrv_pwrite(bdrv, -1, &io_header, sizeof(io_header));
567 2cc977e2 ths
    if (ret == -1)
568 2cc977e2 ths
        return -1;
569 2cc977e2 ths
570 2cc977e2 ths
    while ((ret = bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) == -1 &&
571 2cc977e2 ths
           errno == EINTR);
572 2cc977e2 ths
573 2cc977e2 ths
    if (ret == -1)
574 2cc977e2 ths
        return -1;
575 2cc977e2 ths
576 2cc977e2 ths
    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
577 2cc977e2 ths
}
578 2cc977e2 ths
579 2cc977e2 ths
static void scsi_destroy(SCSIDevice *d)
580 2cc977e2 ths
{
581 2cc977e2 ths
    SCSIRequest *r, *n;
582 2cc977e2 ths
583 2cc977e2 ths
    r = d->state->requests;
584 2cc977e2 ths
    while (r) {
585 2cc977e2 ths
        n = r->next;
586 2cc977e2 ths
        qemu_free(r);
587 2cc977e2 ths
        r = n;
588 2cc977e2 ths
    }
589 2cc977e2 ths
590 2cc977e2 ths
    r = free_requests;
591 2cc977e2 ths
    while (r) {
592 2cc977e2 ths
        n = r->next;
593 2cc977e2 ths
        qemu_free(r);
594 2cc977e2 ths
        r = n;
595 2cc977e2 ths
    }
596 2cc977e2 ths
597 2cc977e2 ths
    qemu_free(d->state);
598 2cc977e2 ths
    qemu_free(d);
599 2cc977e2 ths
}
600 2cc977e2 ths
601 2cc977e2 ths
SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
602 2cc977e2 ths
                              scsi_completionfn completion, void *opaque)
603 2cc977e2 ths
{
604 2cc977e2 ths
    int sg_version;
605 2cc977e2 ths
    SCSIDevice *d;
606 2cc977e2 ths
    SCSIDeviceState *s;
607 2cc977e2 ths
    struct sg_scsi_id scsiid;
608 2cc977e2 ths
609 2cc977e2 ths
    /* check we are really using a /dev/sg* file */
610 2cc977e2 ths
611 2cc977e2 ths
    if (!bdrv_is_sg(bdrv))
612 2cc977e2 ths
        return NULL;
613 2cc977e2 ths
614 2cc977e2 ths
    /* check we are using a driver managing SG_IO (version 3 and after */
615 2cc977e2 ths
616 2cc977e2 ths
    if (bdrv_ioctl(bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
617 2cc977e2 ths
        sg_version < 30000)
618 2cc977e2 ths
        return NULL;
619 2cc977e2 ths
620 2cc977e2 ths
    /* get LUN of the /dev/sg? */
621 2cc977e2 ths
622 2cc977e2 ths
    if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid))
623 2cc977e2 ths
        return NULL;
624 2cc977e2 ths
625 2cc977e2 ths
    /* define device state */
626 2cc977e2 ths
627 2cc977e2 ths
    s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
628 2cc977e2 ths
    s->bdrv = bdrv;
629 2cc977e2 ths
    s->requests = NULL;
630 2cc977e2 ths
    s->completion = completion;
631 2cc977e2 ths
    s->opaque = opaque;
632 2cc977e2 ths
    s->lun = scsiid.lun;
633 2cc977e2 ths
    s->blocksize = get_blocksize(s->bdrv);
634 2cc977e2 ths
    s->driver_status = 0;
635 2cc977e2 ths
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
636 2cc977e2 ths
    /* removable media returns 0 if not present */
637 2cc977e2 ths
    if (s->blocksize <= 0)
638 2cc977e2 ths
        s->blocksize = 2048;
639 2cc977e2 ths
640 2cc977e2 ths
    /* define function to manage device */
641 2cc977e2 ths
642 2cc977e2 ths
    d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
643 2cc977e2 ths
    d->state = s;
644 2cc977e2 ths
    d->destroy = scsi_destroy;
645 2cc977e2 ths
    d->send_command = scsi_send_command;
646 2cc977e2 ths
    d->read_data = scsi_read_data;
647 2cc977e2 ths
    d->write_data = scsi_write_data;
648 2cc977e2 ths
    d->cancel_io = scsi_cancel_io;
649 2cc977e2 ths
    d->get_buf = scsi_get_buf;
650 2cc977e2 ths
651 2cc977e2 ths
    return d;
652 2cc977e2 ths
}
653 2cc977e2 ths
#endif /* __linux__ */