Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 7fc42b4b

History | View | Annotate | Download (16.9 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 2e5d83bb pbrook
#include "vl.h"
29 2e5d83bb pbrook
30 2e5d83bb pbrook
#define SENSE_NO_SENSE        0
31 1aacf348 pbrook
#define SENSE_NOT_READY       2
32 4d611c9a pbrook
#define SENSE_HARDWARE_ERROR  4
33 2e5d83bb pbrook
#define SENSE_ILLEGAL_REQUEST 5
34 2e5d83bb pbrook
35 a917d384 pbrook
#define SCSI_DMA_BUF_SIZE    65536
36 a917d384 pbrook
37 a917d384 pbrook
typedef struct SCSIRequest {
38 a917d384 pbrook
    SCSIDevice *dev;
39 2e5d83bb pbrook
    uint32_t tag;
40 2e5d83bb pbrook
    /* ??? We should probably keep track of whether the data trasfer is
41 2e5d83bb pbrook
       a read or a write.  Currently we rely on the host getting it right.  */
42 a917d384 pbrook
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
43 2e5d83bb pbrook
    int sector;
44 2e5d83bb pbrook
    int sector_count;
45 a917d384 pbrook
    /* The amounnt of data in the buffer.  */
46 2e5d83bb pbrook
    int buf_len;
47 a917d384 pbrook
    uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
48 4d611c9a pbrook
    BlockDriverAIOCB *aiocb;
49 a917d384 pbrook
    struct SCSIRequest *next;
50 a917d384 pbrook
} SCSIRequest;
51 a917d384 pbrook
52 a917d384 pbrook
struct SCSIDevice
53 a917d384 pbrook
{
54 a917d384 pbrook
    BlockDriverState *bdrv;
55 a917d384 pbrook
    SCSIRequest *requests;
56 a917d384 pbrook
    /* The qemu block layer uses a fixed 512 byte sector size.
57 a917d384 pbrook
       This is the number of 512 byte blocks in a single scsi sector.  */
58 a917d384 pbrook
    int cluster_size;
59 a917d384 pbrook
    int sense;
60 a917d384 pbrook
    int tcq;
61 4d611c9a pbrook
    /* Completion functions may be called from either scsi_{read,write}_data
62 4d611c9a pbrook
       or from the AIO completion routines.  */
63 2e5d83bb pbrook
    scsi_completionfn completion;
64 2e5d83bb pbrook
    void *opaque;
65 2e5d83bb pbrook
};
66 2e5d83bb pbrook
67 a917d384 pbrook
/* Global pool of SCSIRequest structures.  */
68 a917d384 pbrook
static SCSIRequest *free_requests = NULL;
69 a917d384 pbrook
70 a917d384 pbrook
static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
71 2e5d83bb pbrook
{
72 a917d384 pbrook
    SCSIRequest *r;
73 a917d384 pbrook
74 a917d384 pbrook
    if (free_requests) {
75 a917d384 pbrook
        r = free_requests;
76 a917d384 pbrook
        free_requests = r->next;
77 a917d384 pbrook
    } else {
78 a917d384 pbrook
        r = qemu_malloc(sizeof(SCSIRequest));
79 a917d384 pbrook
    }
80 a917d384 pbrook
    r->dev = s;
81 a917d384 pbrook
    r->tag = tag;
82 a917d384 pbrook
    r->sector_count = 0;
83 a917d384 pbrook
    r->buf_len = 0;
84 a917d384 pbrook
    r->aiocb = NULL;
85 a917d384 pbrook
86 a917d384 pbrook
    r->next = s->requests;
87 a917d384 pbrook
    s->requests = r;
88 a917d384 pbrook
    return r;
89 2e5d83bb pbrook
}
90 2e5d83bb pbrook
91 a917d384 pbrook
static void scsi_remove_request(SCSIRequest *r)
92 4d611c9a pbrook
{
93 a917d384 pbrook
    SCSIRequest *last;
94 a917d384 pbrook
    SCSIDevice *s = r->dev;
95 a917d384 pbrook
96 a917d384 pbrook
    if (s->requests == r) {
97 a917d384 pbrook
        s->requests = r->next;
98 a917d384 pbrook
    } else {
99 a917d384 pbrook
        last = s->requests;
100 a917d384 pbrook
        while (last && last->next != r)
101 a917d384 pbrook
            last = last->next;
102 a917d384 pbrook
        if (last) {
103 a917d384 pbrook
            last->next = r->next;
104 a917d384 pbrook
        } else {
105 a917d384 pbrook
            BADF("Orphaned request\n");
106 a917d384 pbrook
        }
107 a917d384 pbrook
    }
108 a917d384 pbrook
    r->next = free_requests;
109 a917d384 pbrook
    free_requests = r;
110 4d611c9a pbrook
}
111 4d611c9a pbrook
112 a917d384 pbrook
static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag)
113 4d611c9a pbrook
{
114 a917d384 pbrook
    SCSIRequest *r;
115 4d611c9a pbrook
116 a917d384 pbrook
    r = s->requests;
117 a917d384 pbrook
    while (r && r->tag != tag)
118 a917d384 pbrook
        r = r->next;
119 4d611c9a pbrook
120 a917d384 pbrook
    return r;
121 a917d384 pbrook
}
122 a917d384 pbrook
123 a917d384 pbrook
/* Helper function for command completion.  */
124 a917d384 pbrook
static void scsi_command_complete(SCSIRequest *r, int sense)
125 a917d384 pbrook
{
126 a917d384 pbrook
    SCSIDevice *s = r->dev;
127 a917d384 pbrook
    uint32_t tag;
128 a917d384 pbrook
    DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
129 a917d384 pbrook
    s->sense = sense;
130 a917d384 pbrook
    tag = r->tag;
131 a917d384 pbrook
    scsi_remove_request(r);
132 a917d384 pbrook
    s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
133 4d611c9a pbrook
}
134 4d611c9a pbrook
135 4d611c9a pbrook
/* Cancel a pending data transfer.  */
136 a917d384 pbrook
void scsi_cancel_io(SCSIDevice *s, uint32_t tag)
137 4d611c9a pbrook
{
138 a917d384 pbrook
    SCSIRequest *r;
139 a917d384 pbrook
    DPRINTF("Cancel tag=0x%x\n", tag);
140 a917d384 pbrook
    r = scsi_find_request(s, tag);
141 a917d384 pbrook
    if (r) {
142 a917d384 pbrook
        if (r->aiocb)
143 a917d384 pbrook
            bdrv_aio_cancel(r->aiocb);
144 a917d384 pbrook
        r->aiocb = NULL;
145 a917d384 pbrook
        scsi_remove_request(r);
146 a917d384 pbrook
    }
147 a917d384 pbrook
}
148 a917d384 pbrook
149 a917d384 pbrook
static void scsi_read_complete(void * opaque, int ret)
150 a917d384 pbrook
{
151 a917d384 pbrook
    SCSIRequest *r = (SCSIRequest *)opaque;
152 a917d384 pbrook
    SCSIDevice *s = r->dev;
153 a917d384 pbrook
154 a917d384 pbrook
    if (ret) {
155 a917d384 pbrook
        DPRINTF("IO error\n");
156 a917d384 pbrook
        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
157 4d611c9a pbrook
        return;
158 4d611c9a pbrook
    }
159 a917d384 pbrook
    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
160 a917d384 pbrook
161 a917d384 pbrook
    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
162 4d611c9a pbrook
}
163 4d611c9a pbrook
164 a917d384 pbrook
/* Read more data from scsi device into buffer.  */
165 a917d384 pbrook
void scsi_read_data(SCSIDevice *s, uint32_t tag)
166 2e5d83bb pbrook
{
167 a917d384 pbrook
    SCSIRequest *r;
168 2e5d83bb pbrook
    uint32_t n;
169 2e5d83bb pbrook
170 a917d384 pbrook
    r = scsi_find_request(s, tag);
171 a917d384 pbrook
    if (!r) {
172 a917d384 pbrook
        BADF("Bad read tag 0x%x\n", tag);
173 a917d384 pbrook
        /* ??? This is the wrong error.  */
174 a917d384 pbrook
        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
175 a917d384 pbrook
        return;
176 2e5d83bb pbrook
    }
177 a917d384 pbrook
    if (r->sector_count == (uint32_t)-1) {
178 a917d384 pbrook
        DPRINTF("Read buf_len=%d\n", r->buf_len);
179 a917d384 pbrook
        r->sector_count = 0;
180 a917d384 pbrook
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
181 a917d384 pbrook
        return;
182 2e5d83bb pbrook
    }
183 a917d384 pbrook
    DPRINTF("Read sector_count=%d\n", r->sector_count);
184 a917d384 pbrook
    if (r->sector_count == 0) {
185 a917d384 pbrook
        scsi_command_complete(r, SENSE_NO_SENSE);
186 a917d384 pbrook
        return;
187 2e5d83bb pbrook
    }
188 2e5d83bb pbrook
189 a917d384 pbrook
    n = r->sector_count;
190 a917d384 pbrook
    if (n > SCSI_DMA_BUF_SIZE / 512)
191 a917d384 pbrook
        n = SCSI_DMA_BUF_SIZE / 512;
192 a917d384 pbrook
193 a917d384 pbrook
    r->buf_len = n * 512;
194 a917d384 pbrook
    r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
195 a917d384 pbrook
                             scsi_read_complete, r);
196 a917d384 pbrook
    if (r->aiocb == NULL)
197 a917d384 pbrook
        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
198 a917d384 pbrook
    r->sector += n;
199 a917d384 pbrook
    r->sector_count -= n;
200 2e5d83bb pbrook
}
201 2e5d83bb pbrook
202 4d611c9a pbrook
static void scsi_write_complete(void * opaque, int ret)
203 4d611c9a pbrook
{
204 a917d384 pbrook
    SCSIRequest *r = (SCSIRequest *)opaque;
205 a917d384 pbrook
    SCSIDevice *s = r->dev;
206 a917d384 pbrook
    uint32_t len;
207 4d611c9a pbrook
208 4d611c9a pbrook
    if (ret) {
209 4d611c9a pbrook
        fprintf(stderr, "scsi-disc: IO write error\n");
210 4d611c9a pbrook
        exit(1);
211 4d611c9a pbrook
    }
212 4d611c9a pbrook
213 a917d384 pbrook
    r->aiocb = NULL;
214 a917d384 pbrook
    if (r->sector_count == 0) {
215 a917d384 pbrook
        scsi_command_complete(r, SENSE_NO_SENSE);
216 a917d384 pbrook
    } else {
217 a917d384 pbrook
        len = r->sector_count * 512;
218 a917d384 pbrook
        if (len > SCSI_DMA_BUF_SIZE) {
219 a917d384 pbrook
            len = SCSI_DMA_BUF_SIZE;
220 a917d384 pbrook
        }
221 a917d384 pbrook
        r->buf_len = len;
222 a917d384 pbrook
        DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
223 a917d384 pbrook
        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
224 4d611c9a pbrook
    }
225 4d611c9a pbrook
}
226 4d611c9a pbrook
227 4d611c9a pbrook
/* Write data to a scsi device.  Returns nonzero on failure.
228 4d611c9a pbrook
   The transfer may complete asynchronously.  */
229 a917d384 pbrook
int scsi_write_data(SCSIDevice *s, uint32_t tag)
230 2e5d83bb pbrook
{
231 a917d384 pbrook
    SCSIRequest *r;
232 2e5d83bb pbrook
    uint32_t n;
233 2e5d83bb pbrook
234 a917d384 pbrook
    DPRINTF("Write data tag=0x%x\n", tag);
235 a917d384 pbrook
    r = scsi_find_request(s, tag);
236 a917d384 pbrook
    if (!r) {
237 a917d384 pbrook
        BADF("Bad write tag 0x%x\n", tag);
238 a917d384 pbrook
        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
239 2e5d83bb pbrook
        return 1;
240 2e5d83bb pbrook
    }
241 a917d384 pbrook
    if (r->aiocb)
242 a917d384 pbrook
        BADF("Data transfer already in progress\n");
243 a917d384 pbrook
    n = r->buf_len / 512;
244 a917d384 pbrook
    if (n) {
245 a917d384 pbrook
        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
246 a917d384 pbrook
                                  scsi_write_complete, r);
247 a917d384 pbrook
        if (r->aiocb == NULL)
248 a917d384 pbrook
            scsi_command_complete(r, SENSE_HARDWARE_ERROR);
249 a917d384 pbrook
        r->sector += n;
250 a917d384 pbrook
        r->sector_count -= n;
251 a917d384 pbrook
    } else {
252 a917d384 pbrook
        /* Invoke completion routine to fetch data from host.  */
253 a917d384 pbrook
        scsi_write_complete(r, 0);
254 2e5d83bb pbrook
    }
255 2e5d83bb pbrook
256 a917d384 pbrook
    return 0;
257 a917d384 pbrook
}
258 2e5d83bb pbrook
259 a917d384 pbrook
/* Return a pointer to the data buffer.  */
260 a917d384 pbrook
uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag)
261 a917d384 pbrook
{
262 a917d384 pbrook
    SCSIRequest *r;
263 2e5d83bb pbrook
264 a917d384 pbrook
    r = scsi_find_request(s, tag);
265 a917d384 pbrook
    if (!r) {
266 a917d384 pbrook
        BADF("Bad buffer tag 0x%x\n", tag);
267 a917d384 pbrook
        return NULL;
268 4d611c9a pbrook
    }
269 a917d384 pbrook
    return r->dma_buf;
270 2e5d83bb pbrook
}
271 2e5d83bb pbrook
272 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
273 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
274 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
275 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
276 2e5d83bb pbrook
277 0fc5c15a pbrook
int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
278 2e5d83bb pbrook
{
279 2e5d83bb pbrook
    int64_t nb_sectors;
280 2e5d83bb pbrook
    uint32_t lba;
281 2e5d83bb pbrook
    uint32_t len;
282 2e5d83bb pbrook
    int cmdlen;
283 2e5d83bb pbrook
    int is_write;
284 a917d384 pbrook
    uint8_t command;
285 a917d384 pbrook
    uint8_t *outbuf;
286 a917d384 pbrook
    SCSIRequest *r;
287 a917d384 pbrook
288 a917d384 pbrook
    command = buf[0];
289 a917d384 pbrook
    r = scsi_find_request(s, tag);
290 a917d384 pbrook
    if (r) {
291 a917d384 pbrook
        BADF("Tag 0x%x already in use\n", tag);
292 a917d384 pbrook
        scsi_cancel_io(s, tag);
293 a917d384 pbrook
    }
294 a917d384 pbrook
    /* ??? Tags are not unique for different luns.  We only implement a
295 a917d384 pbrook
       single lun, so this should not matter.  */
296 a917d384 pbrook
    r = scsi_new_request(s, tag);
297 a917d384 pbrook
    outbuf = r->dma_buf;
298 2e5d83bb pbrook
    is_write = 0;
299 a917d384 pbrook
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
300 a917d384 pbrook
    switch (command >> 5) {
301 2e5d83bb pbrook
    case 0:
302 2e5d83bb pbrook
        lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
303 2e5d83bb pbrook
        len = buf[4];
304 2e5d83bb pbrook
        cmdlen = 6;
305 2e5d83bb pbrook
        break;
306 2e5d83bb pbrook
    case 1:
307 2e5d83bb pbrook
    case 2:
308 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
309 2e5d83bb pbrook
        len = buf[8] | (buf[7] << 8);
310 2e5d83bb pbrook
        cmdlen = 10;
311 2e5d83bb pbrook
        break;
312 2e5d83bb pbrook
    case 4:
313 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
314 2e5d83bb pbrook
        len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
315 2e5d83bb pbrook
        cmdlen = 16;
316 2e5d83bb pbrook
        break;
317 2e5d83bb pbrook
    case 5:
318 2e5d83bb pbrook
        lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
319 2e5d83bb pbrook
        len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
320 2e5d83bb pbrook
        cmdlen = 12;
321 2e5d83bb pbrook
        break;
322 2e5d83bb pbrook
    default:
323 a917d384 pbrook
        BADF("Unsupported command length, command %x\n", command);
324 2e5d83bb pbrook
        goto fail;
325 2e5d83bb pbrook
    }
326 2e5d83bb pbrook
#ifdef DEBUG_SCSI
327 2e5d83bb pbrook
    {
328 2e5d83bb pbrook
        int i;
329 2e5d83bb pbrook
        for (i = 1; i < cmdlen; i++) {
330 2e5d83bb pbrook
            printf(" 0x%02x", buf[i]);
331 2e5d83bb pbrook
        }
332 2e5d83bb pbrook
        printf("\n");
333 2e5d83bb pbrook
    }
334 2e5d83bb pbrook
#endif
335 0fc5c15a pbrook
    if (lun || buf[1] >> 5) {
336 2e5d83bb pbrook
        /* Only LUN 0 supported.  */
337 0fc5c15a pbrook
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
338 2e5d83bb pbrook
        goto fail;
339 2e5d83bb pbrook
    }
340 a917d384 pbrook
    switch (command) {
341 2e5d83bb pbrook
    case 0x0:
342 2e5d83bb pbrook
        DPRINTF("Test Unit Ready\n");
343 2e5d83bb pbrook
        break;
344 2e5d83bb pbrook
    case 0x03:
345 2e5d83bb pbrook
        DPRINTF("Request Sense (len %d)\n", len);
346 2e5d83bb pbrook
        if (len < 4)
347 2e5d83bb pbrook
            goto fail;
348 67cd24a8 ths
        memset(outbuf, 0, 4);
349 a917d384 pbrook
        outbuf[0] = 0xf0;
350 a917d384 pbrook
        outbuf[1] = 0;
351 a917d384 pbrook
        outbuf[2] = s->sense;
352 a917d384 pbrook
        r->buf_len = 4;
353 2e5d83bb pbrook
        break;
354 2e5d83bb pbrook
    case 0x12:
355 7d8406be pbrook
        DPRINTF("Inquiry (len %d)\n", len);
356 2e5d83bb pbrook
        if (len < 36) {
357 2e5d83bb pbrook
            BADF("Inquiry buffer too small (%d)\n", len);
358 2e5d83bb pbrook
        }
359 a917d384 pbrook
        memset(outbuf, 0, 36);
360 2e5d83bb pbrook
        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
361 a917d384 pbrook
            outbuf[0] = 5;
362 a917d384 pbrook
            outbuf[1] = 0x80;
363 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU CD-ROM    ", 16);
364 2e5d83bb pbrook
        } else {
365 a917d384 pbrook
            outbuf[0] = 0;
366 a917d384 pbrook
            memcpy(&outbuf[16], "QEMU HARDDISK  ", 16);
367 2e5d83bb pbrook
        }
368 a917d384 pbrook
        memcpy(&outbuf[8], "QEMU   ", 8);
369 a917d384 pbrook
        memcpy(&outbuf[32], QEMU_VERSION, 4);
370 17acfe32 pbrook
        /* Identify device as SCSI-3 rev 1.
371 17acfe32 pbrook
           Some later commands are also implemented. */
372 a917d384 pbrook
        outbuf[2] = 3;
373 a917d384 pbrook
        outbuf[3] = 2; /* Format 2 */
374 67cd24a8 ths
        outbuf[4] = 31;
375 a917d384 pbrook
        /* Sync data transfer and TCQ.  */
376 a917d384 pbrook
        outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
377 a917d384 pbrook
        r->buf_len = 36;
378 2e5d83bb pbrook
        break;
379 2e5d83bb pbrook
    case 0x16:
380 2e5d83bb pbrook
        DPRINTF("Reserve(6)\n");
381 2e5d83bb pbrook
        if (buf[1] & 1)
382 2e5d83bb pbrook
            goto fail;
383 2e5d83bb pbrook
        break;
384 2e5d83bb pbrook
    case 0x17:
385 2e5d83bb pbrook
        DPRINTF("Release(6)\n");
386 2e5d83bb pbrook
        if (buf[1] & 1)
387 2e5d83bb pbrook
            goto fail;
388 2e5d83bb pbrook
        break;
389 2e5d83bb pbrook
    case 0x1a:
390 7d8406be pbrook
    case 0x5a:
391 17acfe32 pbrook
        {
392 a917d384 pbrook
            uint8_t *p;
393 17acfe32 pbrook
            int page;
394 17acfe32 pbrook
395 17acfe32 pbrook
            page = buf[2] & 0x3f;
396 17acfe32 pbrook
            DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
397 a917d384 pbrook
            p = outbuf;
398 17acfe32 pbrook
            memset(p, 0, 4);
399 a917d384 pbrook
            outbuf[1] = 0; /* Default media type.  */
400 a917d384 pbrook
            outbuf[3] = 0; /* Block descriptor length.  */
401 17acfe32 pbrook
            if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
402 a917d384 pbrook
                outbuf[2] = 0x80; /* Readonly.  */
403 17acfe32 pbrook
            }
404 17acfe32 pbrook
            p += 4;
405 17acfe32 pbrook
            if ((page == 8 || page == 0x3f)) {
406 17acfe32 pbrook
                /* Caching page.  */
407 67cd24a8 ths
                memset(p,0,20);
408 17acfe32 pbrook
                p[0] = 8;
409 17acfe32 pbrook
                p[1] = 0x12;
410 17acfe32 pbrook
                p[2] = 4; /* WCE */
411 67cd24a8 ths
                p += 20;
412 17acfe32 pbrook
            }
413 17acfe32 pbrook
            if ((page == 0x3f || page == 0x2a)
414 17acfe32 pbrook
                    && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
415 17acfe32 pbrook
                /* CD Capabilities and Mechanical Status page. */
416 17acfe32 pbrook
                p[0] = 0x2a;
417 17acfe32 pbrook
                p[1] = 0x14;
418 17acfe32 pbrook
                p[2] = 3; // CD-R & CD-RW read
419 17acfe32 pbrook
                p[3] = 0; // Writing not supported
420 17acfe32 pbrook
                p[4] = 0x7f; /* Audio, composite, digital out,
421 17acfe32 pbrook
                                         mode 2 form 1&2, multi session */
422 17acfe32 pbrook
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
423 17acfe32 pbrook
                                         RW corrected, C2 errors, ISRC,
424 17acfe32 pbrook
                                         UPC, Bar code */
425 17acfe32 pbrook
                p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
426 17acfe32 pbrook
                /* Locking supported, jumper present, eject, tray */
427 17acfe32 pbrook
                p[7] = 0; /* no volume & mute control, no
428 17acfe32 pbrook
                                      changer */
429 17acfe32 pbrook
                p[8] = (50 * 176) >> 8; // 50x read speed
430 17acfe32 pbrook
                p[9] = (50 * 176) & 0xff;
431 17acfe32 pbrook
                p[10] = 0 >> 8; // No volume
432 17acfe32 pbrook
                p[11] = 0 & 0xff;
433 17acfe32 pbrook
                p[12] = 2048 >> 8; // 2M buffer
434 17acfe32 pbrook
                p[13] = 2048 & 0xff;
435 17acfe32 pbrook
                p[14] = (16 * 176) >> 8; // 16x read speed current
436 17acfe32 pbrook
                p[15] = (16 * 176) & 0xff;
437 17acfe32 pbrook
                p[18] = (16 * 176) >> 8; // 16x write speed
438 17acfe32 pbrook
                p[19] = (16 * 176) & 0xff;
439 17acfe32 pbrook
                p[20] = (16 * 176) >> 8; // 16x write speed current
440 17acfe32 pbrook
                p[21] = (16 * 176) & 0xff;
441 67cd24a8 ths
                p += 22;
442 17acfe32 pbrook
            }
443 a917d384 pbrook
            r->buf_len = p - outbuf;
444 a917d384 pbrook
            outbuf[0] = r->buf_len - 4;
445 a917d384 pbrook
            if (r->buf_len > len)
446 a917d384 pbrook
                r->buf_len = len;
447 7d8406be pbrook
        }
448 17acfe32 pbrook
        break;
449 17acfe32 pbrook
    case 0x1b:
450 17acfe32 pbrook
        DPRINTF("Start Stop Unit\n");
451 17acfe32 pbrook
        break;
452 17acfe32 pbrook
    case 0x1e:
453 17acfe32 pbrook
        DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
454 17acfe32 pbrook
        bdrv_set_locked(s->bdrv, buf[4] & 1);
455 2e5d83bb pbrook
        break;
456 2e5d83bb pbrook
    case 0x25:
457 2e5d83bb pbrook
        DPRINTF("Read Capacity\n");
458 2e5d83bb pbrook
        /* The normal LEN field for this command is zero.  */
459 a917d384 pbrook
        memset(outbuf, 0, 8);
460 2e5d83bb pbrook
        bdrv_get_geometry(s->bdrv, &nb_sectors);
461 51c1ebb1 pbrook
        /* Returned value is the address of the last sector.  */
462 51c1ebb1 pbrook
        if (nb_sectors) {
463 51c1ebb1 pbrook
            nb_sectors--;
464 a917d384 pbrook
            outbuf[0] = (nb_sectors >> 24) & 0xff;
465 a917d384 pbrook
            outbuf[1] = (nb_sectors >> 16) & 0xff;
466 a917d384 pbrook
            outbuf[2] = (nb_sectors >> 8) & 0xff;
467 a917d384 pbrook
            outbuf[3] = nb_sectors & 0xff;
468 a917d384 pbrook
            outbuf[4] = 0;
469 a917d384 pbrook
            outbuf[5] = 0;
470 a917d384 pbrook
            outbuf[6] = s->cluster_size * 2;
471 a917d384 pbrook
            outbuf[7] = 0;
472 a917d384 pbrook
            r->buf_len = 8;
473 51c1ebb1 pbrook
        } else {
474 a917d384 pbrook
            scsi_command_complete(r, SENSE_NOT_READY);
475 35f1df84 pbrook
            return 0;
476 51c1ebb1 pbrook
        }
477 2e5d83bb pbrook
        break;
478 2e5d83bb pbrook
    case 0x08:
479 2e5d83bb pbrook
    case 0x28:
480 2e5d83bb pbrook
        DPRINTF("Read (sector %d, count %d)\n", lba, len);
481 a917d384 pbrook
        r->sector = lba * s->cluster_size;
482 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
483 2e5d83bb pbrook
        break;
484 2e5d83bb pbrook
    case 0x0a:
485 2e5d83bb pbrook
    case 0x2a:
486 2e5d83bb pbrook
        DPRINTF("Write (sector %d, count %d)\n", lba, len);
487 a917d384 pbrook
        r->sector = lba * s->cluster_size;
488 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
489 2e5d83bb pbrook
        is_write = 1;
490 2e5d83bb pbrook
        break;
491 7d8406be pbrook
    case 0x35:
492 e91c8a77 ths
        DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len);
493 7a6cba61 pbrook
        bdrv_flush(s->bdrv);
494 7d8406be pbrook
        break;
495 2e5d83bb pbrook
    case 0x43:
496 2e5d83bb pbrook
        {
497 7c22dd52 pbrook
            int start_track, format, msf, toclen;
498 2e5d83bb pbrook
499 2e5d83bb pbrook
            msf = buf[1] & 2;
500 2e5d83bb pbrook
            format = buf[2] & 0xf;
501 2e5d83bb pbrook
            start_track = buf[6];
502 2e5d83bb pbrook
            bdrv_get_geometry(s->bdrv, &nb_sectors);
503 2e5d83bb pbrook
            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
504 2e5d83bb pbrook
            switch(format) {
505 2e5d83bb pbrook
            case 0:
506 a917d384 pbrook
                toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
507 2e5d83bb pbrook
                break;
508 2e5d83bb pbrook
            case 1:
509 2e5d83bb pbrook
                /* multi session : only a single session defined */
510 7c22dd52 pbrook
                toclen = 12;
511 a917d384 pbrook
                memset(outbuf, 0, 12);
512 a917d384 pbrook
                outbuf[1] = 0x0a;
513 a917d384 pbrook
                outbuf[2] = 0x01;
514 a917d384 pbrook
                outbuf[3] = 0x01;
515 2e5d83bb pbrook
                break;
516 2e5d83bb pbrook
            case 2:
517 a917d384 pbrook
                toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
518 2e5d83bb pbrook
                break;
519 2e5d83bb pbrook
            default:
520 7c22dd52 pbrook
                goto error_cmd;
521 7c22dd52 pbrook
            }
522 7c22dd52 pbrook
            if (toclen > 0) {
523 7c22dd52 pbrook
                if (len > toclen)
524 7c22dd52 pbrook
                  len = toclen;
525 a917d384 pbrook
                r->buf_len = len;
526 7c22dd52 pbrook
                break;
527 2e5d83bb pbrook
            }
528 7c22dd52 pbrook
        error_cmd:
529 7c22dd52 pbrook
            DPRINTF("Read TOC error\n");
530 7c22dd52 pbrook
            goto fail;
531 2e5d83bb pbrook
        }
532 17acfe32 pbrook
    case 0x46:
533 17acfe32 pbrook
        DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
534 a917d384 pbrook
        memset(outbuf, 0, 8);
535 17acfe32 pbrook
        /* ??? This shoud probably return much more information.  For now
536 17acfe32 pbrook
           just return the basic header indicating the CD-ROM profile.  */
537 a917d384 pbrook
        outbuf[7] = 8; // CD-ROM
538 a917d384 pbrook
        r->buf_len = 8;
539 17acfe32 pbrook
        break;
540 2e5d83bb pbrook
    case 0x56:
541 2e5d83bb pbrook
        DPRINTF("Reserve(10)\n");
542 2e5d83bb pbrook
        if (buf[1] & 3)
543 2e5d83bb pbrook
            goto fail;
544 2e5d83bb pbrook
        break;
545 2e5d83bb pbrook
    case 0x57:
546 2e5d83bb pbrook
        DPRINTF("Release(10)\n");
547 2e5d83bb pbrook
        if (buf[1] & 3)
548 2e5d83bb pbrook
            goto fail;
549 2e5d83bb pbrook
        break;
550 2e5d83bb pbrook
    case 0xa0:
551 2e5d83bb pbrook
        DPRINTF("Report LUNs (len %d)\n", len);
552 2e5d83bb pbrook
        if (len < 16)
553 2e5d83bb pbrook
            goto fail;
554 a917d384 pbrook
        memset(outbuf, 0, 16);
555 a917d384 pbrook
        outbuf[3] = 8;
556 a917d384 pbrook
        r->buf_len = 16;
557 2e5d83bb pbrook
        break;
558 2e5d83bb pbrook
    default:
559 2e5d83bb pbrook
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
560 2e5d83bb pbrook
    fail:
561 a917d384 pbrook
        scsi_command_complete(r, SENSE_ILLEGAL_REQUEST);
562 2e5d83bb pbrook
        return 0;
563 2e5d83bb pbrook
    }
564 a917d384 pbrook
    if (r->sector_count == 0 && r->buf_len == 0) {
565 a917d384 pbrook
        scsi_command_complete(r, SENSE_NO_SENSE);
566 a917d384 pbrook
    }
567 a917d384 pbrook
    len = r->sector_count * 512 + r->buf_len;
568 a917d384 pbrook
    if (is_write) {
569 a917d384 pbrook
        return -len;
570 a917d384 pbrook
    } else {
571 a917d384 pbrook
        if (!r->sector_count)
572 a917d384 pbrook
            r->sector_count = -1;
573 a917d384 pbrook
        return len;
574 2e5d83bb pbrook
    }
575 2e5d83bb pbrook
}
576 2e5d83bb pbrook
577 2e5d83bb pbrook
void scsi_disk_destroy(SCSIDevice *s)
578 2e5d83bb pbrook
{
579 2e5d83bb pbrook
    qemu_free(s);
580 2e5d83bb pbrook
}
581 2e5d83bb pbrook
582 2e5d83bb pbrook
SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
583 a917d384 pbrook
                           int tcq,
584 2e5d83bb pbrook
                           scsi_completionfn completion,
585 2e5d83bb pbrook
                           void *opaque)
586 2e5d83bb pbrook
{
587 2e5d83bb pbrook
    SCSIDevice *s;
588 2e5d83bb pbrook
589 2e5d83bb pbrook
    s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
590 2e5d83bb pbrook
    s->bdrv = bdrv;
591 a917d384 pbrook
    s->tcq = tcq;
592 2e5d83bb pbrook
    s->completion = completion;
593 2e5d83bb pbrook
    s->opaque = opaque;
594 2e5d83bb pbrook
    if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
595 7c22dd52 pbrook
        s->cluster_size = 4;
596 2e5d83bb pbrook
    } else {
597 7c22dd52 pbrook
        s->cluster_size = 1;
598 2e5d83bb pbrook
    }
599 2e5d83bb pbrook
600 2e5d83bb pbrook
    return s;
601 2e5d83bb pbrook
}