Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ f3e3aa8c

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