Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ b94ec3ec

History | View | Annotate | Download (17.5 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 a917d384 pbrook
 * commands.  Emultion of interface/link layer protocols is handled by
13 a917d384 pbrook
 * the host adapter emulation.
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 a917d384 pbrook
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 a917d384 pbrook
    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 a917d384 pbrook
        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 a917d384 pbrook
        /* ??? This is the wrong error.  */
179 a917d384 pbrook
        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 a917d384 pbrook
        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 a917d384 pbrook
        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 a917d384 pbrook
        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 a917d384 pbrook
        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 a917d384 pbrook
            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 2e5d83bb pbrook
        if (len < 36) {
366 2e5d83bb pbrook
            BADF("Inquiry buffer too small (%d)\n", len);
367 2e5d83bb pbrook
        }
368 a917d384 pbrook
        memset(outbuf, 0, 36);
369 2e5d83bb pbrook
        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
370 a917d384 pbrook
            outbuf[0] = 5;
371 a917d384 pbrook
            outbuf[1] = 0x80;
372 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU CD-ROM    ", 16);
373 2e5d83bb pbrook
        } else {
374 a917d384 pbrook
            outbuf[0] = 0;
375 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU HARDDISK  ", 16);
376 2e5d83bb pbrook
        }
377 a917d384 pbrook
        memcpy(&outbuf[8], "QEMU   ", 8);
378 a917d384 pbrook
        memcpy(&outbuf[32], QEMU_VERSION, 4);
379 17acfe32 pbrook
        /* Identify device as SCSI-3 rev 1.
380 17acfe32 pbrook
           Some later commands are also implemented. */
381 a917d384 pbrook
        outbuf[2] = 3;
382 a917d384 pbrook
        outbuf[3] = 2; /* Format 2 */
383 67cd24a8 ths
        outbuf[4] = 31;
384 a917d384 pbrook
        /* Sync data transfer and TCQ.  */
385 a917d384 pbrook
        outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
386 a917d384 pbrook
        r->buf_len = 36;
387 2e5d83bb pbrook
        break;
388 2e5d83bb pbrook
    case 0x16:
389 2e5d83bb pbrook
        DPRINTF("Reserve(6)\n");
390 2e5d83bb pbrook
        if (buf[1] & 1)
391 2e5d83bb pbrook
            goto fail;
392 2e5d83bb pbrook
        break;
393 2e5d83bb pbrook
    case 0x17:
394 2e5d83bb pbrook
        DPRINTF("Release(6)\n");
395 2e5d83bb pbrook
        if (buf[1] & 1)
396 2e5d83bb pbrook
            goto fail;
397 2e5d83bb pbrook
        break;
398 2e5d83bb pbrook
    case 0x1a:
399 7d8406be pbrook
    case 0x5a:
400 17acfe32 pbrook
        {
401 a917d384 pbrook
            uint8_t *p;
402 17acfe32 pbrook
            int page;
403 17acfe32 pbrook
404 17acfe32 pbrook
            page = buf[2] & 0x3f;
405 17acfe32 pbrook
            DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
406 a917d384 pbrook
            p = outbuf;
407 17acfe32 pbrook
            memset(p, 0, 4);
408 a917d384 pbrook
            outbuf[1] = 0; /* Default media type.  */
409 a917d384 pbrook
            outbuf[3] = 0; /* Block descriptor length.  */
410 17acfe32 pbrook
            if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
411 a917d384 pbrook
                outbuf[2] = 0x80; /* Readonly.  */
412 17acfe32 pbrook
            }
413 17acfe32 pbrook
            p += 4;
414 17acfe32 pbrook
            if ((page == 8 || page == 0x3f)) {
415 17acfe32 pbrook
                /* Caching page.  */
416 67cd24a8 ths
                memset(p,0,20);
417 17acfe32 pbrook
                p[0] = 8;
418 17acfe32 pbrook
                p[1] = 0x12;
419 17acfe32 pbrook
                p[2] = 4; /* WCE */
420 67cd24a8 ths
                p += 20;
421 17acfe32 pbrook
            }
422 17acfe32 pbrook
            if ((page == 0x3f || page == 0x2a)
423 17acfe32 pbrook
                    && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
424 17acfe32 pbrook
                /* CD Capabilities and Mechanical Status page. */
425 17acfe32 pbrook
                p[0] = 0x2a;
426 17acfe32 pbrook
                p[1] = 0x14;
427 17acfe32 pbrook
                p[2] = 3; // CD-R & CD-RW read
428 17acfe32 pbrook
                p[3] = 0; // Writing not supported
429 17acfe32 pbrook
                p[4] = 0x7f; /* Audio, composite, digital out,
430 17acfe32 pbrook
                                         mode 2 form 1&2, multi session */
431 17acfe32 pbrook
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
432 17acfe32 pbrook
                                         RW corrected, C2 errors, ISRC,
433 17acfe32 pbrook
                                         UPC, Bar code */
434 17acfe32 pbrook
                p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
435 17acfe32 pbrook
                /* Locking supported, jumper present, eject, tray */
436 17acfe32 pbrook
                p[7] = 0; /* no volume & mute control, no
437 17acfe32 pbrook
                                      changer */
438 17acfe32 pbrook
                p[8] = (50 * 176) >> 8; // 50x read speed
439 17acfe32 pbrook
                p[9] = (50 * 176) & 0xff;
440 17acfe32 pbrook
                p[10] = 0 >> 8; // No volume
441 17acfe32 pbrook
                p[11] = 0 & 0xff;
442 17acfe32 pbrook
                p[12] = 2048 >> 8; // 2M buffer
443 17acfe32 pbrook
                p[13] = 2048 & 0xff;
444 17acfe32 pbrook
                p[14] = (16 * 176) >> 8; // 16x read speed current
445 17acfe32 pbrook
                p[15] = (16 * 176) & 0xff;
446 17acfe32 pbrook
                p[18] = (16 * 176) >> 8; // 16x write speed
447 17acfe32 pbrook
                p[19] = (16 * 176) & 0xff;
448 17acfe32 pbrook
                p[20] = (16 * 176) >> 8; // 16x write speed current
449 17acfe32 pbrook
                p[21] = (16 * 176) & 0xff;
450 67cd24a8 ths
                p += 22;
451 17acfe32 pbrook
            }
452 a917d384 pbrook
            r->buf_len = p - outbuf;
453 a917d384 pbrook
            outbuf[0] = r->buf_len - 4;
454 a917d384 pbrook
            if (r->buf_len > len)
455 a917d384 pbrook
                r->buf_len = len;
456 7d8406be pbrook
        }
457 17acfe32 pbrook
        break;
458 17acfe32 pbrook
    case 0x1b:
459 17acfe32 pbrook
        DPRINTF("Start Stop Unit\n");
460 17acfe32 pbrook
        break;
461 17acfe32 pbrook
    case 0x1e:
462 17acfe32 pbrook
        DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
463 17acfe32 pbrook
        bdrv_set_locked(s->bdrv, buf[4] & 1);
464 2e5d83bb pbrook
        break;
465 2e5d83bb pbrook
    case 0x25:
466 2e5d83bb pbrook
        DPRINTF("Read Capacity\n");
467 2e5d83bb pbrook
        /* The normal LEN field for this command is zero.  */
468 a917d384 pbrook
        memset(outbuf, 0, 8);
469 2e5d83bb pbrook
        bdrv_get_geometry(s->bdrv, &nb_sectors);
470 51c1ebb1 pbrook
        /* Returned value is the address of the last sector.  */
471 51c1ebb1 pbrook
        if (nb_sectors) {
472 51c1ebb1 pbrook
            nb_sectors--;
473 a917d384 pbrook
            outbuf[0] = (nb_sectors >> 24) & 0xff;
474 a917d384 pbrook
            outbuf[1] = (nb_sectors >> 16) & 0xff;
475 a917d384 pbrook
            outbuf[2] = (nb_sectors >> 8) & 0xff;
476 a917d384 pbrook
            outbuf[3] = nb_sectors & 0xff;
477 a917d384 pbrook
            outbuf[4] = 0;
478 a917d384 pbrook
            outbuf[5] = 0;
479 a917d384 pbrook
            outbuf[6] = s->cluster_size * 2;
480 a917d384 pbrook
            outbuf[7] = 0;
481 a917d384 pbrook
            r->buf_len = 8;
482 51c1ebb1 pbrook
        } else {
483 a917d384 pbrook
            scsi_command_complete(r, SENSE_NOT_READY);
484 35f1df84 pbrook
            return 0;
485 51c1ebb1 pbrook
        }
486 2e5d83bb pbrook
        break;
487 2e5d83bb pbrook
    case 0x08:
488 2e5d83bb pbrook
    case 0x28:
489 2e5d83bb pbrook
        DPRINTF("Read (sector %d, count %d)\n", lba, len);
490 a917d384 pbrook
        r->sector = lba * s->cluster_size;
491 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
492 2e5d83bb pbrook
        break;
493 2e5d83bb pbrook
    case 0x0a:
494 2e5d83bb pbrook
    case 0x2a:
495 2e5d83bb pbrook
        DPRINTF("Write (sector %d, count %d)\n", lba, len);
496 a917d384 pbrook
        r->sector = lba * s->cluster_size;
497 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
498 2e5d83bb pbrook
        is_write = 1;
499 2e5d83bb pbrook
        break;
500 7d8406be pbrook
    case 0x35:
501 e91c8a77 ths
        DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len);
502 7a6cba61 pbrook
        bdrv_flush(s->bdrv);
503 7d8406be pbrook
        break;
504 2e5d83bb pbrook
    case 0x43:
505 2e5d83bb pbrook
        {
506 7c22dd52 pbrook
            int start_track, format, msf, toclen;
507 2e5d83bb pbrook
508 2e5d83bb pbrook
            msf = buf[1] & 2;
509 2e5d83bb pbrook
            format = buf[2] & 0xf;
510 2e5d83bb pbrook
            start_track = buf[6];
511 2e5d83bb pbrook
            bdrv_get_geometry(s->bdrv, &nb_sectors);
512 2e5d83bb pbrook
            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
513 2e5d83bb pbrook
            switch(format) {
514 2e5d83bb pbrook
            case 0:
515 a917d384 pbrook
                toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
516 2e5d83bb pbrook
                break;
517 2e5d83bb pbrook
            case 1:
518 2e5d83bb pbrook
                /* multi session : only a single session defined */
519 7c22dd52 pbrook
                toclen = 12;
520 a917d384 pbrook
                memset(outbuf, 0, 12);
521 a917d384 pbrook
                outbuf[1] = 0x0a;
522 a917d384 pbrook
                outbuf[2] = 0x01;
523 a917d384 pbrook
                outbuf[3] = 0x01;
524 2e5d83bb pbrook
                break;
525 2e5d83bb pbrook
            case 2:
526 a917d384 pbrook
                toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
527 2e5d83bb pbrook
                break;
528 2e5d83bb pbrook
            default:
529 7c22dd52 pbrook
                goto error_cmd;
530 7c22dd52 pbrook
            }
531 7c22dd52 pbrook
            if (toclen > 0) {
532 7c22dd52 pbrook
                if (len > toclen)
533 7c22dd52 pbrook
                  len = toclen;
534 a917d384 pbrook
                r->buf_len = len;
535 7c22dd52 pbrook
                break;
536 2e5d83bb pbrook
            }
537 7c22dd52 pbrook
        error_cmd:
538 7c22dd52 pbrook
            DPRINTF("Read TOC error\n");
539 7c22dd52 pbrook
            goto fail;
540 2e5d83bb pbrook
        }
541 17acfe32 pbrook
    case 0x46:
542 17acfe32 pbrook
        DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
543 a917d384 pbrook
        memset(outbuf, 0, 8);
544 17acfe32 pbrook
        /* ??? This shoud probably return much more information.  For now
545 17acfe32 pbrook
           just return the basic header indicating the CD-ROM profile.  */
546 a917d384 pbrook
        outbuf[7] = 8; // CD-ROM
547 a917d384 pbrook
        r->buf_len = 8;
548 17acfe32 pbrook
        break;
549 2e5d83bb pbrook
    case 0x56:
550 2e5d83bb pbrook
        DPRINTF("Reserve(10)\n");
551 2e5d83bb pbrook
        if (buf[1] & 3)
552 2e5d83bb pbrook
            goto fail;
553 2e5d83bb pbrook
        break;
554 2e5d83bb pbrook
    case 0x57:
555 2e5d83bb pbrook
        DPRINTF("Release(10)\n");
556 2e5d83bb pbrook
        if (buf[1] & 3)
557 2e5d83bb pbrook
            goto fail;
558 2e5d83bb pbrook
        break;
559 2e5d83bb pbrook
    case 0xa0:
560 2e5d83bb pbrook
        DPRINTF("Report LUNs (len %d)\n", len);
561 2e5d83bb pbrook
        if (len < 16)
562 2e5d83bb pbrook
            goto fail;
563 a917d384 pbrook
        memset(outbuf, 0, 16);
564 a917d384 pbrook
        outbuf[3] = 8;
565 a917d384 pbrook
        r->buf_len = 16;
566 2e5d83bb pbrook
        break;
567 2e5d83bb pbrook
    default:
568 2e5d83bb pbrook
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
569 2e5d83bb pbrook
    fail:
570 a917d384 pbrook
        scsi_command_complete(r, SENSE_ILLEGAL_REQUEST);
571 2e5d83bb pbrook
        return 0;
572 2e5d83bb pbrook
    }
573 a917d384 pbrook
    if (r->sector_count == 0 && r->buf_len == 0) {
574 a917d384 pbrook
        scsi_command_complete(r, SENSE_NO_SENSE);
575 a917d384 pbrook
    }
576 a917d384 pbrook
    len = r->sector_count * 512 + r->buf_len;
577 a917d384 pbrook
    if (is_write) {
578 a917d384 pbrook
        return -len;
579 a917d384 pbrook
    } else {
580 a917d384 pbrook
        if (!r->sector_count)
581 a917d384 pbrook
            r->sector_count = -1;
582 a917d384 pbrook
        return len;
583 2e5d83bb pbrook
    }
584 2e5d83bb pbrook
}
585 2e5d83bb pbrook
586 8ccc2ace ths
static void scsi_destroy(SCSIDevice *d)
587 2e5d83bb pbrook
{
588 8ccc2ace ths
    qemu_free(d->state);
589 8ccc2ace ths
    qemu_free(d);
590 2e5d83bb pbrook
}
591 2e5d83bb pbrook
592 8ccc2ace ths
SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
593 8ccc2ace ths
                           scsi_completionfn completion, void *opaque)
594 2e5d83bb pbrook
{
595 8ccc2ace ths
    SCSIDevice *d;
596 8ccc2ace ths
    SCSIDeviceState *s;
597 2e5d83bb pbrook
598 8ccc2ace ths
    s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
599 2e5d83bb pbrook
    s->bdrv = bdrv;
600 a917d384 pbrook
    s->tcq = tcq;
601 2e5d83bb pbrook
    s->completion = completion;
602 2e5d83bb pbrook
    s->opaque = opaque;
603 2e5d83bb pbrook
    if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
604 7c22dd52 pbrook
        s->cluster_size = 4;
605 2e5d83bb pbrook
    } else {
606 7c22dd52 pbrook
        s->cluster_size = 1;
607 2e5d83bb pbrook
    }
608 2e5d83bb pbrook
609 8ccc2ace ths
    d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
610 8ccc2ace ths
    d->state = s;
611 8ccc2ace ths
    d->destroy = scsi_destroy;
612 8ccc2ace ths
    d->send_command = scsi_send_command;
613 8ccc2ace ths
    d->read_data = scsi_read_data;
614 8ccc2ace ths
    d->write_data = scsi_write_data;
615 8ccc2ace ths
    d->cancel_io = scsi_cancel_io;
616 8ccc2ace ths
    d->get_buf = scsi_get_buf;
617 2e5d83bb pbrook
618 8ccc2ace ths
    return d;
619 8ccc2ace ths
}