Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ dc828ca1

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