Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ ef845c3b

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