Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ e57ec016

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