Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ f65ed4c1

History | View | Annotate | Download (26 kB)

1 2e5d83bb pbrook
/*
2 2e5d83bb pbrook
 * SCSI Device emulation
3 2e5d83bb pbrook
 *
4 2e5d83bb pbrook
 * Copyright (c) 2006 CodeSourcery.
5 2e5d83bb pbrook
 * Based on code by Fabrice Bellard
6 2e5d83bb pbrook
 *
7 2e5d83bb pbrook
 * Written by Paul Brook
8 2e5d83bb pbrook
 *
9 2e5d83bb pbrook
 * This code is licenced under the LGPL.
10 a917d384 pbrook
 *
11 a917d384 pbrook
 * Note that this file only handles the SCSI architecture model and device
12 1d4db89c balrog
 * commands.  Emulation of interface/link layer protocols is handled by
13 1d4db89c balrog
 * the host adapter emulator.
14 2e5d83bb pbrook
 */
15 2e5d83bb pbrook
16 2e5d83bb pbrook
//#define DEBUG_SCSI
17 2e5d83bb pbrook
18 2e5d83bb pbrook
#ifdef DEBUG_SCSI
19 2e5d83bb pbrook
#define DPRINTF(fmt, args...) \
20 2e5d83bb pbrook
do { printf("scsi-disk: " fmt , ##args); } while (0)
21 2e5d83bb pbrook
#else
22 2e5d83bb pbrook
#define DPRINTF(fmt, args...) do {} while(0)
23 2e5d83bb pbrook
#endif
24 2e5d83bb pbrook
25 2e5d83bb pbrook
#define BADF(fmt, args...) \
26 2e5d83bb pbrook
do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
27 2e5d83bb pbrook
28 87ecb68b pbrook
#include "qemu-common.h"
29 87ecb68b pbrook
#include "block.h"
30 87ecb68b pbrook
#include "scsi-disk.h"
31 2e5d83bb pbrook
32 2e5d83bb pbrook
#define SENSE_NO_SENSE        0
33 1aacf348 pbrook
#define SENSE_NOT_READY       2
34 4d611c9a pbrook
#define SENSE_HARDWARE_ERROR  4
35 2e5d83bb pbrook
#define SENSE_ILLEGAL_REQUEST 5
36 2e5d83bb pbrook
37 22864256 blueswir1
#define STATUS_GOOD            0
38 22864256 blueswir1
#define STATUS_CHECK_CONDITION 2
39 22864256 blueswir1
40 f0f72ffe aurel32
#define SCSI_DMA_BUF_SIZE    131072
41 57575058 balrog
#define SCSI_MAX_INQUIRY_LEN 256
42 a917d384 pbrook
43 a917d384 pbrook
typedef struct SCSIRequest {
44 8ccc2ace ths
    SCSIDeviceState *dev;
45 2e5d83bb pbrook
    uint32_t tag;
46 2e5d83bb pbrook
    /* ??? We should probably keep track of whether the data trasfer is
47 2e5d83bb pbrook
       a read or a write.  Currently we rely on the host getting it right.  */
48 a917d384 pbrook
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
49 2e5d83bb pbrook
    int sector;
50 2e5d83bb pbrook
    int sector_count;
51 a917d384 pbrook
    /* The amounnt of data in the buffer.  */
52 2e5d83bb pbrook
    int buf_len;
53 33f00271 balrog
    uint8_t *dma_buf;
54 4d611c9a pbrook
    BlockDriverAIOCB *aiocb;
55 a917d384 pbrook
    struct SCSIRequest *next;
56 a917d384 pbrook
} SCSIRequest;
57 a917d384 pbrook
58 8ccc2ace ths
struct SCSIDeviceState
59 a917d384 pbrook
{
60 a917d384 pbrook
    BlockDriverState *bdrv;
61 a917d384 pbrook
    SCSIRequest *requests;
62 a917d384 pbrook
    /* The qemu block layer uses a fixed 512 byte sector size.
63 a917d384 pbrook
       This is the number of 512 byte blocks in a single scsi sector.  */
64 a917d384 pbrook
    int cluster_size;
65 a917d384 pbrook
    int sense;
66 a917d384 pbrook
    int tcq;
67 4d611c9a pbrook
    /* Completion functions may be called from either scsi_{read,write}_data
68 4d611c9a pbrook
       or from the AIO completion routines.  */
69 2e5d83bb pbrook
    scsi_completionfn completion;
70 2e5d83bb pbrook
    void *opaque;
71 2e5d83bb pbrook
};
72 2e5d83bb pbrook
73 a917d384 pbrook
/* Global pool of SCSIRequest structures.  */
74 a917d384 pbrook
static SCSIRequest *free_requests = NULL;
75 a917d384 pbrook
76 8ccc2ace ths
static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
77 2e5d83bb pbrook
{
78 a917d384 pbrook
    SCSIRequest *r;
79 a917d384 pbrook
80 a917d384 pbrook
    if (free_requests) {
81 a917d384 pbrook
        r = free_requests;
82 a917d384 pbrook
        free_requests = r->next;
83 a917d384 pbrook
    } else {
84 a917d384 pbrook
        r = qemu_malloc(sizeof(SCSIRequest));
85 33f00271 balrog
        r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
86 a917d384 pbrook
    }
87 a917d384 pbrook
    r->dev = s;
88 a917d384 pbrook
    r->tag = tag;
89 a917d384 pbrook
    r->sector_count = 0;
90 a917d384 pbrook
    r->buf_len = 0;
91 a917d384 pbrook
    r->aiocb = NULL;
92 a917d384 pbrook
93 a917d384 pbrook
    r->next = s->requests;
94 a917d384 pbrook
    s->requests = r;
95 a917d384 pbrook
    return r;
96 2e5d83bb pbrook
}
97 2e5d83bb pbrook
98 a917d384 pbrook
static void scsi_remove_request(SCSIRequest *r)
99 4d611c9a pbrook
{
100 a917d384 pbrook
    SCSIRequest *last;
101 8ccc2ace ths
    SCSIDeviceState *s = r->dev;
102 a917d384 pbrook
103 a917d384 pbrook
    if (s->requests == r) {
104 a917d384 pbrook
        s->requests = r->next;
105 a917d384 pbrook
    } else {
106 a917d384 pbrook
        last = s->requests;
107 a917d384 pbrook
        while (last && last->next != r)
108 a917d384 pbrook
            last = last->next;
109 a917d384 pbrook
        if (last) {
110 a917d384 pbrook
            last->next = r->next;
111 a917d384 pbrook
        } else {
112 a917d384 pbrook
            BADF("Orphaned request\n");
113 a917d384 pbrook
        }
114 a917d384 pbrook
    }
115 a917d384 pbrook
    r->next = free_requests;
116 a917d384 pbrook
    free_requests = r;
117 4d611c9a pbrook
}
118 4d611c9a pbrook
119 8ccc2ace ths
static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
120 4d611c9a pbrook
{
121 a917d384 pbrook
    SCSIRequest *r;
122 4d611c9a pbrook
123 a917d384 pbrook
    r = s->requests;
124 a917d384 pbrook
    while (r && r->tag != tag)
125 a917d384 pbrook
        r = r->next;
126 4d611c9a pbrook
127 a917d384 pbrook
    return r;
128 a917d384 pbrook
}
129 a917d384 pbrook
130 a917d384 pbrook
/* Helper function for command completion.  */
131 22864256 blueswir1
static void scsi_command_complete(SCSIRequest *r, int status, int sense)
132 a917d384 pbrook
{
133 8ccc2ace ths
    SCSIDeviceState *s = r->dev;
134 a917d384 pbrook
    uint32_t tag;
135 22864256 blueswir1
    DPRINTF("Command complete tag=0x%x status=%d sense=%d\n", r->tag, status, sense);
136 a917d384 pbrook
    s->sense = sense;
137 a917d384 pbrook
    tag = r->tag;
138 a917d384 pbrook
    scsi_remove_request(r);
139 22864256 blueswir1
    s->completion(s->opaque, SCSI_REASON_DONE, tag, status);
140 4d611c9a pbrook
}
141 4d611c9a pbrook
142 4d611c9a pbrook
/* Cancel a pending data transfer.  */
143 8ccc2ace ths
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
144 4d611c9a pbrook
{
145 8ccc2ace ths
    SCSIDeviceState *s = d->state;
146 a917d384 pbrook
    SCSIRequest *r;
147 a917d384 pbrook
    DPRINTF("Cancel tag=0x%x\n", tag);
148 a917d384 pbrook
    r = scsi_find_request(s, tag);
149 a917d384 pbrook
    if (r) {
150 a917d384 pbrook
        if (r->aiocb)
151 a917d384 pbrook
            bdrv_aio_cancel(r->aiocb);
152 a917d384 pbrook
        r->aiocb = NULL;
153 a917d384 pbrook
        scsi_remove_request(r);
154 a917d384 pbrook
    }
155 a917d384 pbrook
}
156 a917d384 pbrook
157 a917d384 pbrook
static void scsi_read_complete(void * opaque, int ret)
158 a917d384 pbrook
{
159 a917d384 pbrook
    SCSIRequest *r = (SCSIRequest *)opaque;
160 8ccc2ace ths
    SCSIDeviceState *s = r->dev;
161 a917d384 pbrook
162 a917d384 pbrook
    if (ret) {
163 a917d384 pbrook
        DPRINTF("IO error\n");
164 22864256 blueswir1
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 0);
165 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
166 4d611c9a pbrook
        return;
167 4d611c9a pbrook
    }
168 a917d384 pbrook
    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
169 a917d384 pbrook
170 a917d384 pbrook
    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
171 4d611c9a pbrook
}
172 4d611c9a pbrook
173 a917d384 pbrook
/* Read more data from scsi device into buffer.  */
174 8ccc2ace ths
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
175 2e5d83bb pbrook
{
176 8ccc2ace ths
    SCSIDeviceState *s = d->state;
177 a917d384 pbrook
    SCSIRequest *r;
178 2e5d83bb pbrook
    uint32_t n;
179 2e5d83bb pbrook
180 a917d384 pbrook
    r = scsi_find_request(s, tag);
181 a917d384 pbrook
    if (!r) {
182 a917d384 pbrook
        BADF("Bad read tag 0x%x\n", tag);
183 b1fa7164 blueswir1
        /* ??? This is the wrong error.  */
184 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
185 a917d384 pbrook
        return;
186 2e5d83bb pbrook
    }
187 a917d384 pbrook
    if (r->sector_count == (uint32_t)-1) {
188 a917d384 pbrook
        DPRINTF("Read buf_len=%d\n", r->buf_len);
189 a917d384 pbrook
        r->sector_count = 0;
190 a917d384 pbrook
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
191 a917d384 pbrook
        return;
192 2e5d83bb pbrook
    }
193 a917d384 pbrook
    DPRINTF("Read sector_count=%d\n", r->sector_count);
194 a917d384 pbrook
    if (r->sector_count == 0) {
195 22864256 blueswir1
        scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
196 a917d384 pbrook
        return;
197 2e5d83bb pbrook
    }
198 2e5d83bb pbrook
199 a917d384 pbrook
    n = r->sector_count;
200 a917d384 pbrook
    if (n > SCSI_DMA_BUF_SIZE / 512)
201 a917d384 pbrook
        n = SCSI_DMA_BUF_SIZE / 512;
202 a917d384 pbrook
203 a917d384 pbrook
    r->buf_len = n * 512;
204 a917d384 pbrook
    r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
205 a917d384 pbrook
                             scsi_read_complete, r);
206 a917d384 pbrook
    if (r->aiocb == NULL)
207 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
208 a917d384 pbrook
    r->sector += n;
209 a917d384 pbrook
    r->sector_count -= n;
210 2e5d83bb pbrook
}
211 2e5d83bb pbrook
212 4d611c9a pbrook
static void scsi_write_complete(void * opaque, int ret)
213 4d611c9a pbrook
{
214 a917d384 pbrook
    SCSIRequest *r = (SCSIRequest *)opaque;
215 8ccc2ace ths
    SCSIDeviceState *s = r->dev;
216 a917d384 pbrook
    uint32_t len;
217 4d611c9a pbrook
218 4d611c9a pbrook
    if (ret) {
219 4d611c9a pbrook
        fprintf(stderr, "scsi-disc: IO write error\n");
220 4d611c9a pbrook
        exit(1);
221 4d611c9a pbrook
    }
222 4d611c9a pbrook
223 a917d384 pbrook
    r->aiocb = NULL;
224 a917d384 pbrook
    if (r->sector_count == 0) {
225 22864256 blueswir1
        scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
226 a917d384 pbrook
    } else {
227 a917d384 pbrook
        len = r->sector_count * 512;
228 a917d384 pbrook
        if (len > SCSI_DMA_BUF_SIZE) {
229 a917d384 pbrook
            len = SCSI_DMA_BUF_SIZE;
230 a917d384 pbrook
        }
231 a917d384 pbrook
        r->buf_len = len;
232 a917d384 pbrook
        DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
233 a917d384 pbrook
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
234 4d611c9a pbrook
    }
235 4d611c9a pbrook
}
236 4d611c9a pbrook
237 4d611c9a pbrook
/* Write data to a scsi device.  Returns nonzero on failure.
238 4d611c9a pbrook
   The transfer may complete asynchronously.  */
239 8ccc2ace ths
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
240 2e5d83bb pbrook
{
241 8ccc2ace ths
    SCSIDeviceState *s = d->state;
242 a917d384 pbrook
    SCSIRequest *r;
243 2e5d83bb pbrook
    uint32_t n;
244 2e5d83bb pbrook
245 a917d384 pbrook
    DPRINTF("Write data tag=0x%x\n", tag);
246 a917d384 pbrook
    r = scsi_find_request(s, tag);
247 a917d384 pbrook
    if (!r) {
248 a917d384 pbrook
        BADF("Bad write tag 0x%x\n", tag);
249 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
250 2e5d83bb pbrook
        return 1;
251 2e5d83bb pbrook
    }
252 a917d384 pbrook
    if (r->aiocb)
253 a917d384 pbrook
        BADF("Data transfer already in progress\n");
254 a917d384 pbrook
    n = r->buf_len / 512;
255 a917d384 pbrook
    if (n) {
256 a917d384 pbrook
        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
257 a917d384 pbrook
                                  scsi_write_complete, r);
258 a917d384 pbrook
        if (r->aiocb == NULL)
259 22864256 blueswir1
            scsi_command_complete(r, STATUS_CHECK_CONDITION,
260 22864256 blueswir1
                                  SENSE_HARDWARE_ERROR);
261 a917d384 pbrook
        r->sector += n;
262 a917d384 pbrook
        r->sector_count -= n;
263 a917d384 pbrook
    } else {
264 a917d384 pbrook
        /* Invoke completion routine to fetch data from host.  */
265 a917d384 pbrook
        scsi_write_complete(r, 0);
266 2e5d83bb pbrook
    }
267 2e5d83bb pbrook
268 a917d384 pbrook
    return 0;
269 a917d384 pbrook
}
270 2e5d83bb pbrook
271 a917d384 pbrook
/* Return a pointer to the data buffer.  */
272 8ccc2ace ths
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
273 a917d384 pbrook
{
274 8ccc2ace ths
    SCSIDeviceState *s = d->state;
275 a917d384 pbrook
    SCSIRequest *r;
276 2e5d83bb pbrook
277 a917d384 pbrook
    r = scsi_find_request(s, tag);
278 a917d384 pbrook
    if (!r) {
279 a917d384 pbrook
        BADF("Bad buffer tag 0x%x\n", tag);
280 a917d384 pbrook
        return NULL;
281 4d611c9a pbrook
    }
282 a917d384 pbrook
    return r->dma_buf;
283 2e5d83bb pbrook
}
284 2e5d83bb pbrook
285 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
286 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
287 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
288 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
289 2e5d83bb pbrook
290 8ccc2ace ths
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
291 8ccc2ace ths
                                 uint8_t *buf, int lun)
292 2e5d83bb pbrook
{
293 8ccc2ace ths
    SCSIDeviceState *s = d->state;
294 96b8f136 ths
    uint64_t nb_sectors;
295 2e5d83bb pbrook
    uint32_t lba;
296 2e5d83bb pbrook
    uint32_t len;
297 2e5d83bb pbrook
    int cmdlen;
298 2e5d83bb pbrook
    int is_write;
299 a917d384 pbrook
    uint8_t command;
300 a917d384 pbrook
    uint8_t *outbuf;
301 a917d384 pbrook
    SCSIRequest *r;
302 a917d384 pbrook
303 a917d384 pbrook
    command = buf[0];
304 a917d384 pbrook
    r = scsi_find_request(s, tag);
305 a917d384 pbrook
    if (r) {
306 a917d384 pbrook
        BADF("Tag 0x%x already in use\n", tag);
307 8ccc2ace ths
        scsi_cancel_io(d, tag);
308 a917d384 pbrook
    }
309 a917d384 pbrook
    /* ??? Tags are not unique for different luns.  We only implement a
310 a917d384 pbrook
       single lun, so this should not matter.  */
311 a917d384 pbrook
    r = scsi_new_request(s, tag);
312 a917d384 pbrook
    outbuf = r->dma_buf;
313 2e5d83bb pbrook
    is_write = 0;
314 a917d384 pbrook
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
315 a917d384 pbrook
    switch (command >> 5) {
316 2e5d83bb pbrook
    case 0:
317 2e5d83bb pbrook
        lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
318 2e5d83bb pbrook
        len = buf[4];
319 2e5d83bb pbrook
        cmdlen = 6;
320 2e5d83bb pbrook
        break;
321 2e5d83bb pbrook
    case 1:
322 2e5d83bb pbrook
    case 2:
323 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
324 2e5d83bb pbrook
        len = buf[8] | (buf[7] << 8);
325 2e5d83bb pbrook
        cmdlen = 10;
326 2e5d83bb pbrook
        break;
327 2e5d83bb pbrook
    case 4:
328 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
329 2e5d83bb pbrook
        len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
330 2e5d83bb pbrook
        cmdlen = 16;
331 2e5d83bb pbrook
        break;
332 2e5d83bb pbrook
    case 5:
333 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
334 2e5d83bb pbrook
        len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
335 2e5d83bb pbrook
        cmdlen = 12;
336 2e5d83bb pbrook
        break;
337 2e5d83bb pbrook
    default:
338 a917d384 pbrook
        BADF("Unsupported command length, command %x\n", command);
339 2e5d83bb pbrook
        goto fail;
340 2e5d83bb pbrook
    }
341 2e5d83bb pbrook
#ifdef DEBUG_SCSI
342 2e5d83bb pbrook
    {
343 2e5d83bb pbrook
        int i;
344 2e5d83bb pbrook
        for (i = 1; i < cmdlen; i++) {
345 2e5d83bb pbrook
            printf(" 0x%02x", buf[i]);
346 2e5d83bb pbrook
        }
347 2e5d83bb pbrook
        printf("\n");
348 2e5d83bb pbrook
    }
349 2e5d83bb pbrook
#endif
350 0fc5c15a pbrook
    if (lun || buf[1] >> 5) {
351 2e5d83bb pbrook
        /* Only LUN 0 supported.  */
352 0fc5c15a pbrook
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
353 22864256 blueswir1
        if (command != 0x03 && command != 0x12) /* REQUEST SENSE and INQUIRY */
354 22864256 blueswir1
            goto fail;
355 2e5d83bb pbrook
    }
356 a917d384 pbrook
    switch (command) {
357 2e5d83bb pbrook
    case 0x0:
358 2e5d83bb pbrook
        DPRINTF("Test Unit Ready\n");
359 2e5d83bb pbrook
        break;
360 2e5d83bb pbrook
    case 0x03:
361 2e5d83bb pbrook
        DPRINTF("Request Sense (len %d)\n", len);
362 2e5d83bb pbrook
        if (len < 4)
363 2e5d83bb pbrook
            goto fail;
364 67cd24a8 ths
        memset(outbuf, 0, 4);
365 a917d384 pbrook
        outbuf[0] = 0xf0;
366 a917d384 pbrook
        outbuf[1] = 0;
367 a917d384 pbrook
        outbuf[2] = s->sense;
368 a917d384 pbrook
        r->buf_len = 4;
369 2e5d83bb pbrook
        break;
370 2e5d83bb pbrook
    case 0x12:
371 7d8406be pbrook
        DPRINTF("Inquiry (len %d)\n", len);
372 1d4db89c balrog
        if (buf[1] & 0x2) {
373 1d4db89c balrog
            /* Command support data - optional, not implemented */
374 1d4db89c balrog
            BADF("optional INQUIRY command support request not implemented\n");
375 1d4db89c balrog
            goto fail;
376 1d4db89c balrog
        }
377 1d4db89c balrog
        else if (buf[1] & 0x1) {
378 1d4db89c balrog
            /* Vital product data */
379 1d4db89c balrog
            uint8_t page_code = buf[2];
380 1d4db89c balrog
            if (len < 4) {
381 1d4db89c balrog
                BADF("Error: Inquiry (EVPD[%02X]) buffer size %d is "
382 1d4db89c balrog
                     "less than 4\n", page_code, len);
383 1d4db89c balrog
                goto fail;
384 1d4db89c balrog
            }
385 1d4db89c balrog
386 1d4db89c balrog
            switch (page_code) {
387 1d4db89c balrog
                case 0x00:
388 1d4db89c balrog
                    {
389 1d4db89c balrog
                        /* Supported page codes, mandatory */
390 1d4db89c balrog
                        DPRINTF("Inquiry EVPD[Supported pages] "
391 1d4db89c balrog
                                "buffer size %d\n", len);
392 1d4db89c balrog
393 1d4db89c balrog
                        r->buf_len = 0;
394 1d4db89c balrog
395 1d4db89c balrog
                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
396 1d4db89c balrog
                            outbuf[r->buf_len++] = 5;
397 1d4db89c balrog
                        } else {
398 1d4db89c balrog
                            outbuf[r->buf_len++] = 0;
399 1d4db89c balrog
                        }
400 1d4db89c balrog
401 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x00; // this page
402 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x00;
403 1d4db89c balrog
                        outbuf[r->buf_len++] = 3;    // number of pages
404 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x00; // list of supported pages (this page)
405 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x80; // unit serial number
406 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x83; // device identification
407 1d4db89c balrog
                    }
408 1d4db89c balrog
                    break;
409 1d4db89c balrog
                case 0x80:
410 1d4db89c balrog
                    {
411 1d4db89c balrog
                        /* Device serial number, optional */
412 1d4db89c balrog
                        if (len < 4) {
413 1d4db89c balrog
                            BADF("Error: EVPD[Serial number] Inquiry buffer "
414 1d4db89c balrog
                                 "size %d too small, %d needed\n", len, 4);
415 1d4db89c balrog
                            goto fail;
416 1d4db89c balrog
                        }
417 1d4db89c balrog
418 1d4db89c balrog
                        DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
419 1d4db89c balrog
420 1d4db89c balrog
                        r->buf_len = 0;
421 1d4db89c balrog
422 1d4db89c balrog
                        /* Supported page codes */
423 1d4db89c balrog
                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
424 1d4db89c balrog
                            outbuf[r->buf_len++] = 5;
425 1d4db89c balrog
                        } else {
426 1d4db89c balrog
                            outbuf[r->buf_len++] = 0;
427 1d4db89c balrog
                        }
428 1d4db89c balrog
429 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x80; // this page
430 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x00;
431 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x01; // 1 byte data follow
432 1d4db89c balrog
433 1d4db89c balrog
                        outbuf[r->buf_len++] = '0';  // 1 byte data follow 
434 1d4db89c balrog
                    }
435 1d4db89c balrog
436 1d4db89c balrog
                    break;
437 1d4db89c balrog
                case 0x83:
438 1d4db89c balrog
                    {
439 1d4db89c balrog
                        /* Device identification page, mandatory */
440 1d4db89c balrog
                        int max_len = 255 - 8;
441 1d4db89c balrog
                        int id_len = strlen(bdrv_get_device_name(s->bdrv));
442 1d4db89c balrog
                        if (id_len > max_len)
443 1d4db89c balrog
                            id_len = max_len;
444 1d4db89c balrog
445 1d4db89c balrog
                        DPRINTF("Inquiry EVPD[Device identification] "
446 1d4db89c balrog
                                "buffer size %d\n", len);
447 1d4db89c balrog
                        r->buf_len = 0;
448 1d4db89c balrog
                        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
449 1d4db89c balrog
                            outbuf[r->buf_len++] = 5;
450 1d4db89c balrog
                        } else {
451 1d4db89c balrog
                            outbuf[r->buf_len++] = 0;
452 1d4db89c balrog
                        }
453 1d4db89c balrog
454 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x83; // this page
455 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x00;
456 1d4db89c balrog
                        outbuf[r->buf_len++] = 3 + id_len;
457 1d4db89c balrog
458 1d4db89c balrog
                        outbuf[r->buf_len++] = 0x2; // ASCII
459 1d4db89c balrog
                        outbuf[r->buf_len++] = 0;   // not officially assigned
460 1d4db89c balrog
                        outbuf[r->buf_len++] = 0;   // reserved
461 1d4db89c balrog
                        outbuf[r->buf_len++] = id_len; // length of data following
462 1d4db89c balrog
463 1d4db89c balrog
                        memcpy(&outbuf[r->buf_len],
464 1d4db89c balrog
                               bdrv_get_device_name(s->bdrv), id_len);
465 1d4db89c balrog
                        r->buf_len += id_len;
466 1d4db89c balrog
                    }
467 1d4db89c balrog
                    break;
468 1d4db89c balrog
                default:
469 1d4db89c balrog
                    BADF("Error: unsupported Inquiry (EVPD[%02X]) "
470 1d4db89c balrog
                         "buffer size %d\n", page_code, len);
471 1d4db89c balrog
                    goto fail;
472 1d4db89c balrog
            }
473 1d4db89c balrog
            /* done with EVPD */
474 1d4db89c balrog
            break;
475 1d4db89c balrog
        }
476 1d4db89c balrog
        else {
477 1d4db89c balrog
            /* Standard INQUIRY data */
478 1d4db89c balrog
            if (buf[2] != 0) {
479 1d4db89c balrog
                BADF("Error: Inquiry (STANDARD) page or code "
480 1d4db89c balrog
                     "is non-zero [%02X]\n", buf[2]);
481 1d4db89c balrog
                goto fail;
482 1d4db89c balrog
            }
483 1d4db89c balrog
484 1d4db89c balrog
            /* PAGE CODE == 0 */
485 1d4db89c balrog
            if (len < 5) {
486 1d4db89c balrog
                BADF("Error: Inquiry (STANDARD) buffer size %d "
487 1d4db89c balrog
                     "is less than 5\n", len);
488 1d4db89c balrog
                goto fail;
489 1d4db89c balrog
            }
490 1d4db89c balrog
491 1d4db89c balrog
            if (len < 36) {
492 1d4db89c balrog
                BADF("Error: Inquiry (STANDARD) buffer size %d "
493 1d4db89c balrog
                     "is less than 36 (TODO: only 5 required)\n", len);
494 1d4db89c balrog
            }
495 2e5d83bb pbrook
        }
496 57575058 balrog
497 57575058 balrog
        if(len > SCSI_MAX_INQUIRY_LEN)
498 57575058 balrog
            len = SCSI_MAX_INQUIRY_LEN;
499 57575058 balrog
500 57575058 balrog
        memset(outbuf, 0, len);
501 22864256 blueswir1
502 22864256 blueswir1
        if (lun || buf[1] >> 5) {
503 22864256 blueswir1
            outbuf[0] = 0x7f;        /* LUN not supported */
504 22864256 blueswir1
        } else if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
505 a917d384 pbrook
            outbuf[0] = 5;
506 a917d384 pbrook
            outbuf[1] = 0x80;
507 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU CD-ROM    ", 16);
508 2e5d83bb pbrook
        } else {
509 a917d384 pbrook
            outbuf[0] = 0;
510 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU HARDDISK  ", 16);
511 2e5d83bb pbrook
        }
512 a917d384 pbrook
        memcpy(&outbuf[8], "QEMU   ", 8);
513 a917d384 pbrook
        memcpy(&outbuf[32], QEMU_VERSION, 4);
514 17acfe32 pbrook
        /* Identify device as SCSI-3 rev 1.
515 17acfe32 pbrook
           Some later commands are also implemented. */
516 a917d384 pbrook
        outbuf[2] = 3;
517 a917d384 pbrook
        outbuf[3] = 2; /* Format 2 */
518 57575058 balrog
        outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
519 a917d384 pbrook
        /* Sync data transfer and TCQ.  */
520 a917d384 pbrook
        outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
521 57575058 balrog
        r->buf_len = len;
522 2e5d83bb pbrook
        break;
523 2e5d83bb pbrook
    case 0x16:
524 2e5d83bb pbrook
        DPRINTF("Reserve(6)\n");
525 2e5d83bb pbrook
        if (buf[1] & 1)
526 2e5d83bb pbrook
            goto fail;
527 2e5d83bb pbrook
        break;
528 2e5d83bb pbrook
    case 0x17:
529 2e5d83bb pbrook
        DPRINTF("Release(6)\n");
530 2e5d83bb pbrook
        if (buf[1] & 1)
531 2e5d83bb pbrook
            goto fail;
532 2e5d83bb pbrook
        break;
533 2e5d83bb pbrook
    case 0x1a:
534 7d8406be pbrook
    case 0x5a:
535 17acfe32 pbrook
        {
536 a917d384 pbrook
            uint8_t *p;
537 17acfe32 pbrook
            int page;
538 17acfe32 pbrook
539 17acfe32 pbrook
            page = buf[2] & 0x3f;
540 17acfe32 pbrook
            DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
541 a917d384 pbrook
            p = outbuf;
542 17acfe32 pbrook
            memset(p, 0, 4);
543 a917d384 pbrook
            outbuf[1] = 0; /* Default media type.  */
544 a917d384 pbrook
            outbuf[3] = 0; /* Block descriptor length.  */
545 17acfe32 pbrook
            if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
546 a917d384 pbrook
                outbuf[2] = 0x80; /* Readonly.  */
547 17acfe32 pbrook
            }
548 17acfe32 pbrook
            p += 4;
549 5e65a310 blueswir1
            if (page == 4) {
550 5e65a310 blueswir1
                int cylinders, heads, secs;
551 5e65a310 blueswir1
552 5e65a310 blueswir1
                /* Rigid disk device geometry page. */
553 5e65a310 blueswir1
                p[0] = 4;
554 5e65a310 blueswir1
                p[1] = 0x16;
555 5e65a310 blueswir1
                /* if a geometry hint is available, use it */
556 5e65a310 blueswir1
                bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs);
557 5e65a310 blueswir1
                p[2] = (cylinders >> 16) & 0xff;
558 5e65a310 blueswir1
                p[3] = (cylinders >> 8) & 0xff;
559 5e65a310 blueswir1
                p[4] = cylinders & 0xff;
560 5e65a310 blueswir1
                p[5] = heads & 0xff;
561 5e65a310 blueswir1
                /* Write precomp start cylinder, disabled */
562 5e65a310 blueswir1
                p[6] = (cylinders >> 16) & 0xff;
563 5e65a310 blueswir1
                p[7] = (cylinders >> 8) & 0xff;
564 5e65a310 blueswir1
                p[8] = cylinders & 0xff;
565 5e65a310 blueswir1
                /* Reduced current start cylinder, disabled */
566 5e65a310 blueswir1
                p[9] = (cylinders >> 16) & 0xff;
567 5e65a310 blueswir1
                p[10] = (cylinders >> 8) & 0xff;
568 5e65a310 blueswir1
                p[11] = cylinders & 0xff;
569 5e65a310 blueswir1
                /* Device step rate [ns], 200ns */
570 5e65a310 blueswir1
                p[12] = 0;
571 5e65a310 blueswir1
                p[13] = 200;
572 5e65a310 blueswir1
                /* Landing zone cylinder */
573 5e65a310 blueswir1
                p[14] = 0xff;
574 5e65a310 blueswir1
                p[15] =  0xff;
575 5e65a310 blueswir1
                p[16] = 0xff;
576 5e65a310 blueswir1
                /* Medium rotation rate [rpm], 5400 rpm */
577 5e65a310 blueswir1
                p[20] = (5400 >> 8) & 0xff;
578 5e65a310 blueswir1
                p[21] = 5400 & 0xff;
579 5e65a310 blueswir1
                p += 0x16;
580 5e65a310 blueswir1
            } else if (page == 5) {
581 5e65a310 blueswir1
                int cylinders, heads, secs;
582 5e65a310 blueswir1
583 5e65a310 blueswir1
                /* Flexible disk device geometry page. */
584 5e65a310 blueswir1
                p[0] = 5;
585 5e65a310 blueswir1
                p[1] = 0x1e;
586 5e65a310 blueswir1
                /* Transfer rate [kbit/s], 5Mbit/s */
587 5e65a310 blueswir1
                p[2] = 5000 >> 8;
588 5e65a310 blueswir1
                p[3] = 5000 & 0xff;
589 5e65a310 blueswir1
                /* if a geometry hint is available, use it */
590 5e65a310 blueswir1
                bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs);
591 5e65a310 blueswir1
                p[4] = heads & 0xff;
592 5e65a310 blueswir1
                p[5] = secs & 0xff;
593 5e65a310 blueswir1
                p[6] = s->cluster_size * 2;
594 5e65a310 blueswir1
                p[8] = (cylinders >> 8) & 0xff;
595 5e65a310 blueswir1
                p[9] = cylinders & 0xff;
596 5e65a310 blueswir1
                /* Write precomp start cylinder, disabled */
597 5e65a310 blueswir1
                p[10] = (cylinders >> 8) & 0xff;
598 5e65a310 blueswir1
                p[11] = cylinders & 0xff;
599 5e65a310 blueswir1
                /* Reduced current start cylinder, disabled */
600 5e65a310 blueswir1
                p[12] = (cylinders >> 8) & 0xff;
601 5e65a310 blueswir1
                p[13] = cylinders & 0xff;
602 5e65a310 blueswir1
                /* Device step rate [100us], 100us */
603 5e65a310 blueswir1
                p[14] = 0;
604 5e65a310 blueswir1
                p[15] = 1;
605 5e65a310 blueswir1
                /* Device step pulse width [us], 1us */
606 5e65a310 blueswir1
                p[16] = 1;
607 5e65a310 blueswir1
                /* Device head settle delay [100us], 100us */
608 5e65a310 blueswir1
                p[17] = 0;
609 5e65a310 blueswir1
                p[18] = 1;
610 5e65a310 blueswir1
                /* Motor on delay [0.1s], 0.1s */
611 5e65a310 blueswir1
                p[19] = 1;
612 5e65a310 blueswir1
                /* Motor off delay [0.1s], 0.1s */
613 5e65a310 blueswir1
                p[20] = 1;
614 5e65a310 blueswir1
                /* Medium rotation rate [rpm], 5400 rpm */
615 5e65a310 blueswir1
                p[28] = (5400 >> 8) & 0xff;
616 5e65a310 blueswir1
                p[29] = 5400 & 0xff;
617 5e65a310 blueswir1
                p += 0x1e;
618 5e65a310 blueswir1
            } else if ((page == 8 || page == 0x3f)) {
619 17acfe32 pbrook
                /* Caching page.  */
620 67cd24a8 ths
                memset(p,0,20);
621 17acfe32 pbrook
                p[0] = 8;
622 17acfe32 pbrook
                p[1] = 0x12;
623 17acfe32 pbrook
                p[2] = 4; /* WCE */
624 67cd24a8 ths
                p += 20;
625 17acfe32 pbrook
            }
626 17acfe32 pbrook
            if ((page == 0x3f || page == 0x2a)
627 17acfe32 pbrook
                    && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
628 17acfe32 pbrook
                /* CD Capabilities and Mechanical Status page. */
629 17acfe32 pbrook
                p[0] = 0x2a;
630 17acfe32 pbrook
                p[1] = 0x14;
631 17acfe32 pbrook
                p[2] = 3; // CD-R & CD-RW read
632 17acfe32 pbrook
                p[3] = 0; // Writing not supported
633 17acfe32 pbrook
                p[4] = 0x7f; /* Audio, composite, digital out,
634 17acfe32 pbrook
                                         mode 2 form 1&2, multi session */
635 17acfe32 pbrook
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
636 17acfe32 pbrook
                                         RW corrected, C2 errors, ISRC,
637 17acfe32 pbrook
                                         UPC, Bar code */
638 17acfe32 pbrook
                p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
639 17acfe32 pbrook
                /* Locking supported, jumper present, eject, tray */
640 17acfe32 pbrook
                p[7] = 0; /* no volume & mute control, no
641 17acfe32 pbrook
                                      changer */
642 17acfe32 pbrook
                p[8] = (50 * 176) >> 8; // 50x read speed
643 17acfe32 pbrook
                p[9] = (50 * 176) & 0xff;
644 17acfe32 pbrook
                p[10] = 0 >> 8; // No volume
645 17acfe32 pbrook
                p[11] = 0 & 0xff;
646 17acfe32 pbrook
                p[12] = 2048 >> 8; // 2M buffer
647 17acfe32 pbrook
                p[13] = 2048 & 0xff;
648 17acfe32 pbrook
                p[14] = (16 * 176) >> 8; // 16x read speed current
649 17acfe32 pbrook
                p[15] = (16 * 176) & 0xff;
650 17acfe32 pbrook
                p[18] = (16 * 176) >> 8; // 16x write speed
651 17acfe32 pbrook
                p[19] = (16 * 176) & 0xff;
652 17acfe32 pbrook
                p[20] = (16 * 176) >> 8; // 16x write speed current
653 17acfe32 pbrook
                p[21] = (16 * 176) & 0xff;
654 67cd24a8 ths
                p += 22;
655 17acfe32 pbrook
            }
656 a917d384 pbrook
            r->buf_len = p - outbuf;
657 a917d384 pbrook
            outbuf[0] = r->buf_len - 4;
658 a917d384 pbrook
            if (r->buf_len > len)
659 a917d384 pbrook
                r->buf_len = len;
660 7d8406be pbrook
        }
661 17acfe32 pbrook
        break;
662 17acfe32 pbrook
    case 0x1b:
663 17acfe32 pbrook
        DPRINTF("Start Stop Unit\n");
664 17acfe32 pbrook
        break;
665 17acfe32 pbrook
    case 0x1e:
666 17acfe32 pbrook
        DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
667 17acfe32 pbrook
        bdrv_set_locked(s->bdrv, buf[4] & 1);
668 2e5d83bb pbrook
        break;
669 2e5d83bb pbrook
    case 0x25:
670 2e5d83bb pbrook
        DPRINTF("Read Capacity\n");
671 2e5d83bb pbrook
        /* The normal LEN field for this command is zero.  */
672 a917d384 pbrook
        memset(outbuf, 0, 8);
673 2e5d83bb pbrook
        bdrv_get_geometry(s->bdrv, &nb_sectors);
674 51c1ebb1 pbrook
        /* Returned value is the address of the last sector.  */
675 51c1ebb1 pbrook
        if (nb_sectors) {
676 51c1ebb1 pbrook
            nb_sectors--;
677 a917d384 pbrook
            outbuf[0] = (nb_sectors >> 24) & 0xff;
678 a917d384 pbrook
            outbuf[1] = (nb_sectors >> 16) & 0xff;
679 a917d384 pbrook
            outbuf[2] = (nb_sectors >> 8) & 0xff;
680 a917d384 pbrook
            outbuf[3] = nb_sectors & 0xff;
681 a917d384 pbrook
            outbuf[4] = 0;
682 a917d384 pbrook
            outbuf[5] = 0;
683 a917d384 pbrook
            outbuf[6] = s->cluster_size * 2;
684 a917d384 pbrook
            outbuf[7] = 0;
685 a917d384 pbrook
            r->buf_len = 8;
686 51c1ebb1 pbrook
        } else {
687 22864256 blueswir1
            scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
688 35f1df84 pbrook
            return 0;
689 51c1ebb1 pbrook
        }
690 2e5d83bb pbrook
        break;
691 2e5d83bb pbrook
    case 0x08:
692 2e5d83bb pbrook
    case 0x28:
693 2e5d83bb pbrook
        DPRINTF("Read (sector %d, count %d)\n", lba, len);
694 a917d384 pbrook
        r->sector = lba * s->cluster_size;
695 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
696 2e5d83bb pbrook
        break;
697 2e5d83bb pbrook
    case 0x0a:
698 2e5d83bb pbrook
    case 0x2a:
699 2e5d83bb pbrook
        DPRINTF("Write (sector %d, count %d)\n", lba, len);
700 a917d384 pbrook
        r->sector = lba * s->cluster_size;
701 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
702 2e5d83bb pbrook
        is_write = 1;
703 2e5d83bb pbrook
        break;
704 7d8406be pbrook
    case 0x35:
705 e91c8a77 ths
        DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len);
706 7a6cba61 pbrook
        bdrv_flush(s->bdrv);
707 7d8406be pbrook
        break;
708 2e5d83bb pbrook
    case 0x43:
709 2e5d83bb pbrook
        {
710 7c22dd52 pbrook
            int start_track, format, msf, toclen;
711 2e5d83bb pbrook
712 2e5d83bb pbrook
            msf = buf[1] & 2;
713 2e5d83bb pbrook
            format = buf[2] & 0xf;
714 2e5d83bb pbrook
            start_track = buf[6];
715 2e5d83bb pbrook
            bdrv_get_geometry(s->bdrv, &nb_sectors);
716 2e5d83bb pbrook
            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
717 2e5d83bb pbrook
            switch(format) {
718 2e5d83bb pbrook
            case 0:
719 a917d384 pbrook
                toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
720 2e5d83bb pbrook
                break;
721 2e5d83bb pbrook
            case 1:
722 2e5d83bb pbrook
                /* multi session : only a single session defined */
723 7c22dd52 pbrook
                toclen = 12;
724 a917d384 pbrook
                memset(outbuf, 0, 12);
725 a917d384 pbrook
                outbuf[1] = 0x0a;
726 a917d384 pbrook
                outbuf[2] = 0x01;
727 a917d384 pbrook
                outbuf[3] = 0x01;
728 2e5d83bb pbrook
                break;
729 2e5d83bb pbrook
            case 2:
730 a917d384 pbrook
                toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
731 2e5d83bb pbrook
                break;
732 2e5d83bb pbrook
            default:
733 7c22dd52 pbrook
                goto error_cmd;
734 7c22dd52 pbrook
            }
735 7c22dd52 pbrook
            if (toclen > 0) {
736 7c22dd52 pbrook
                if (len > toclen)
737 7c22dd52 pbrook
                  len = toclen;
738 a917d384 pbrook
                r->buf_len = len;
739 7c22dd52 pbrook
                break;
740 2e5d83bb pbrook
            }
741 7c22dd52 pbrook
        error_cmd:
742 7c22dd52 pbrook
            DPRINTF("Read TOC error\n");
743 7c22dd52 pbrook
            goto fail;
744 2e5d83bb pbrook
        }
745 17acfe32 pbrook
    case 0x46:
746 17acfe32 pbrook
        DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
747 a917d384 pbrook
        memset(outbuf, 0, 8);
748 1235fc06 ths
        /* ??? This should probably return much more information.  For now
749 17acfe32 pbrook
           just return the basic header indicating the CD-ROM profile.  */
750 a917d384 pbrook
        outbuf[7] = 8; // CD-ROM
751 a917d384 pbrook
        r->buf_len = 8;
752 17acfe32 pbrook
        break;
753 2e5d83bb pbrook
    case 0x56:
754 2e5d83bb pbrook
        DPRINTF("Reserve(10)\n");
755 2e5d83bb pbrook
        if (buf[1] & 3)
756 2e5d83bb pbrook
            goto fail;
757 2e5d83bb pbrook
        break;
758 2e5d83bb pbrook
    case 0x57:
759 2e5d83bb pbrook
        DPRINTF("Release(10)\n");
760 2e5d83bb pbrook
        if (buf[1] & 3)
761 2e5d83bb pbrook
            goto fail;
762 2e5d83bb pbrook
        break;
763 2e5d83bb pbrook
    case 0xa0:
764 2e5d83bb pbrook
        DPRINTF("Report LUNs (len %d)\n", len);
765 2e5d83bb pbrook
        if (len < 16)
766 2e5d83bb pbrook
            goto fail;
767 a917d384 pbrook
        memset(outbuf, 0, 16);
768 a917d384 pbrook
        outbuf[3] = 8;
769 a917d384 pbrook
        r->buf_len = 16;
770 2e5d83bb pbrook
        break;
771 22864256 blueswir1
    case 0x2f:
772 22864256 blueswir1
        DPRINTF("Verify (sector %d, count %d)\n", lba, len);
773 22864256 blueswir1
        break;
774 2e5d83bb pbrook
    default:
775 2e5d83bb pbrook
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
776 2e5d83bb pbrook
    fail:
777 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST);
778 2e5d83bb pbrook
        return 0;
779 2e5d83bb pbrook
    }
780 a917d384 pbrook
    if (r->sector_count == 0 && r->buf_len == 0) {
781 22864256 blueswir1
        scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
782 a917d384 pbrook
    }
783 a917d384 pbrook
    len = r->sector_count * 512 + r->buf_len;
784 a917d384 pbrook
    if (is_write) {
785 a917d384 pbrook
        return -len;
786 a917d384 pbrook
    } else {
787 a917d384 pbrook
        if (!r->sector_count)
788 a917d384 pbrook
            r->sector_count = -1;
789 a917d384 pbrook
        return len;
790 2e5d83bb pbrook
    }
791 2e5d83bb pbrook
}
792 2e5d83bb pbrook
793 8ccc2ace ths
static void scsi_destroy(SCSIDevice *d)
794 2e5d83bb pbrook
{
795 8ccc2ace ths
    qemu_free(d->state);
796 8ccc2ace ths
    qemu_free(d);
797 2e5d83bb pbrook
}
798 2e5d83bb pbrook
799 8ccc2ace ths
SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
800 8ccc2ace ths
                           scsi_completionfn completion, void *opaque)
801 2e5d83bb pbrook
{
802 8ccc2ace ths
    SCSIDevice *d;
803 8ccc2ace ths
    SCSIDeviceState *s;
804 2e5d83bb pbrook
805 8ccc2ace ths
    s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
806 2e5d83bb pbrook
    s->bdrv = bdrv;
807 a917d384 pbrook
    s->tcq = tcq;
808 2e5d83bb pbrook
    s->completion = completion;
809 2e5d83bb pbrook
    s->opaque = opaque;
810 2e5d83bb pbrook
    if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
811 7c22dd52 pbrook
        s->cluster_size = 4;
812 2e5d83bb pbrook
    } else {
813 7c22dd52 pbrook
        s->cluster_size = 1;
814 2e5d83bb pbrook
    }
815 2e5d83bb pbrook
816 8ccc2ace ths
    d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
817 8ccc2ace ths
    d->state = s;
818 8ccc2ace ths
    d->destroy = scsi_destroy;
819 8ccc2ace ths
    d->send_command = scsi_send_command;
820 8ccc2ace ths
    d->read_data = scsi_read_data;
821 8ccc2ace ths
    d->write_data = scsi_write_data;
822 8ccc2ace ths
    d->cancel_io = scsi_cancel_io;
823 8ccc2ace ths
    d->get_buf = scsi_get_buf;
824 2e5d83bb pbrook
825 8ccc2ace ths
    return d;
826 8ccc2ace ths
}