Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ c9a33054

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