Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 6a90e308

History | View | Annotate | Download (32.7 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 43b443b6 Gerd Hoffmann
#include "scsi.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 c79662f7 Naphtali Sprei
            if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM ||
637 c79662f7 Naphtali Sprei
                bdrv_is_read_only(s->dinfo->bdrv)) {
638 a917d384 pbrook
                outbuf[2] = 0x80; /* Readonly.  */
639 17acfe32 pbrook
            }
640 17acfe32 pbrook
            p += 4;
641 6550f2e6 Artyom Tarasenko
            bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
642 6550f2e6 Artyom Tarasenko
            if ((~dbd) & nb_sectors) {
643 6550f2e6 Artyom Tarasenko
                nb_sectors /= s->cluster_size;
644 6550f2e6 Artyom Tarasenko
                nb_sectors--;
645 6550f2e6 Artyom Tarasenko
                if (nb_sectors > 0xffffff)
646 6550f2e6 Artyom Tarasenko
                    nb_sectors = 0xffffff;
647 6550f2e6 Artyom Tarasenko
                outbuf[3] = 8; /* Block descriptor length  */
648 6550f2e6 Artyom Tarasenko
                p[0] = 0; /* media density code */
649 6550f2e6 Artyom Tarasenko
                p[1] = (nb_sectors >> 16) & 0xff;
650 6550f2e6 Artyom Tarasenko
                p[2] = (nb_sectors >> 8) & 0xff;
651 6550f2e6 Artyom Tarasenko
                p[3] = nb_sectors & 0xff;
652 6550f2e6 Artyom Tarasenko
                p[4] = 0; /* reserved */
653 6550f2e6 Artyom Tarasenko
                p[5] = 0; /* bytes 5-7 are the sector size in bytes */
654 6550f2e6 Artyom Tarasenko
                p[6] = s->cluster_size * 2;
655 6550f2e6 Artyom Tarasenko
                p[7] = 0;
656 6550f2e6 Artyom Tarasenko
                p += 8;
657 6550f2e6 Artyom Tarasenko
            }
658 6550f2e6 Artyom Tarasenko
659 5e65a310 blueswir1
            if (page == 4) {
660 5e65a310 blueswir1
                int cylinders, heads, secs;
661 5e65a310 blueswir1
662 5e65a310 blueswir1
                /* Rigid disk device geometry page. */
663 5e65a310 blueswir1
                p[0] = 4;
664 5e65a310 blueswir1
                p[1] = 0x16;
665 5e65a310 blueswir1
                /* if a geometry hint is available, use it */
666 d52affa7 Gerd Hoffmann
                bdrv_get_geometry_hint(s->dinfo->bdrv, &cylinders, &heads, &secs);
667 5e65a310 blueswir1
                p[2] = (cylinders >> 16) & 0xff;
668 5e65a310 blueswir1
                p[3] = (cylinders >> 8) & 0xff;
669 5e65a310 blueswir1
                p[4] = cylinders & 0xff;
670 5e65a310 blueswir1
                p[5] = heads & 0xff;
671 5e65a310 blueswir1
                /* Write precomp start cylinder, disabled */
672 5e65a310 blueswir1
                p[6] = (cylinders >> 16) & 0xff;
673 5e65a310 blueswir1
                p[7] = (cylinders >> 8) & 0xff;
674 5e65a310 blueswir1
                p[8] = cylinders & 0xff;
675 5e65a310 blueswir1
                /* Reduced current start cylinder, disabled */
676 5e65a310 blueswir1
                p[9] = (cylinders >> 16) & 0xff;
677 5e65a310 blueswir1
                p[10] = (cylinders >> 8) & 0xff;
678 5e65a310 blueswir1
                p[11] = cylinders & 0xff;
679 5e65a310 blueswir1
                /* Device step rate [ns], 200ns */
680 5e65a310 blueswir1
                p[12] = 0;
681 5e65a310 blueswir1
                p[13] = 200;
682 5e65a310 blueswir1
                /* Landing zone cylinder */
683 5e65a310 blueswir1
                p[14] = 0xff;
684 5e65a310 blueswir1
                p[15] =  0xff;
685 5e65a310 blueswir1
                p[16] = 0xff;
686 5e65a310 blueswir1
                /* Medium rotation rate [rpm], 5400 rpm */
687 5e65a310 blueswir1
                p[20] = (5400 >> 8) & 0xff;
688 5e65a310 blueswir1
                p[21] = 5400 & 0xff;
689 5e65a310 blueswir1
                p += 0x16;
690 5e65a310 blueswir1
            } else if (page == 5) {
691 5e65a310 blueswir1
                int cylinders, heads, secs;
692 5e65a310 blueswir1
693 5e65a310 blueswir1
                /* Flexible disk device geometry page. */
694 5e65a310 blueswir1
                p[0] = 5;
695 5e65a310 blueswir1
                p[1] = 0x1e;
696 5e65a310 blueswir1
                /* Transfer rate [kbit/s], 5Mbit/s */
697 5e65a310 blueswir1
                p[2] = 5000 >> 8;
698 5e65a310 blueswir1
                p[3] = 5000 & 0xff;
699 5e65a310 blueswir1
                /* if a geometry hint is available, use it */
700 d52affa7 Gerd Hoffmann
                bdrv_get_geometry_hint(s->dinfo->bdrv, &cylinders, &heads, &secs);
701 5e65a310 blueswir1
                p[4] = heads & 0xff;
702 5e65a310 blueswir1
                p[5] = secs & 0xff;
703 5e65a310 blueswir1
                p[6] = s->cluster_size * 2;
704 5e65a310 blueswir1
                p[8] = (cylinders >> 8) & 0xff;
705 5e65a310 blueswir1
                p[9] = cylinders & 0xff;
706 5e65a310 blueswir1
                /* Write precomp start cylinder, disabled */
707 5e65a310 blueswir1
                p[10] = (cylinders >> 8) & 0xff;
708 5e65a310 blueswir1
                p[11] = cylinders & 0xff;
709 5e65a310 blueswir1
                /* Reduced current start cylinder, disabled */
710 5e65a310 blueswir1
                p[12] = (cylinders >> 8) & 0xff;
711 5e65a310 blueswir1
                p[13] = cylinders & 0xff;
712 5e65a310 blueswir1
                /* Device step rate [100us], 100us */
713 5e65a310 blueswir1
                p[14] = 0;
714 5e65a310 blueswir1
                p[15] = 1;
715 5e65a310 blueswir1
                /* Device step pulse width [us], 1us */
716 5e65a310 blueswir1
                p[16] = 1;
717 5e65a310 blueswir1
                /* Device head settle delay [100us], 100us */
718 5e65a310 blueswir1
                p[17] = 0;
719 5e65a310 blueswir1
                p[18] = 1;
720 5e65a310 blueswir1
                /* Motor on delay [0.1s], 0.1s */
721 5e65a310 blueswir1
                p[19] = 1;
722 5e65a310 blueswir1
                /* Motor off delay [0.1s], 0.1s */
723 5e65a310 blueswir1
                p[20] = 1;
724 5e65a310 blueswir1
                /* Medium rotation rate [rpm], 5400 rpm */
725 5e65a310 blueswir1
                p[28] = (5400 >> 8) & 0xff;
726 5e65a310 blueswir1
                p[29] = 5400 & 0xff;
727 5e65a310 blueswir1
                p += 0x1e;
728 5e65a310 blueswir1
            } else if ((page == 8 || page == 0x3f)) {
729 17acfe32 pbrook
                /* Caching page.  */
730 67cd24a8 ths
                memset(p,0,20);
731 17acfe32 pbrook
                p[0] = 8;
732 17acfe32 pbrook
                p[1] = 0x12;
733 e900a7b7 Christoph Hellwig
                if (bdrv_enable_write_cache(s->dinfo->bdrv)) {
734 e900a7b7 Christoph Hellwig
                     p[2] = 4; /* WCE */
735 e900a7b7 Christoph Hellwig
                }
736 67cd24a8 ths
                p += 20;
737 17acfe32 pbrook
            }
738 17acfe32 pbrook
            if ((page == 0x3f || page == 0x2a)
739 d52affa7 Gerd Hoffmann
                    && (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM)) {
740 17acfe32 pbrook
                /* CD Capabilities and Mechanical Status page. */
741 17acfe32 pbrook
                p[0] = 0x2a;
742 17acfe32 pbrook
                p[1] = 0x14;
743 17acfe32 pbrook
                p[2] = 3; // CD-R & CD-RW read
744 17acfe32 pbrook
                p[3] = 0; // Writing not supported
745 17acfe32 pbrook
                p[4] = 0x7f; /* Audio, composite, digital out,
746 17acfe32 pbrook
                                         mode 2 form 1&2, multi session */
747 17acfe32 pbrook
                p[5] = 0xff; /* CD DA, DA accurate, RW supported,
748 17acfe32 pbrook
                                         RW corrected, C2 errors, ISRC,
749 17acfe32 pbrook
                                         UPC, Bar code */
750 d52affa7 Gerd Hoffmann
                p[6] = 0x2d | (bdrv_is_locked(s->dinfo->bdrv)? 2 : 0);
751 17acfe32 pbrook
                /* Locking supported, jumper present, eject, tray */
752 17acfe32 pbrook
                p[7] = 0; /* no volume & mute control, no
753 17acfe32 pbrook
                                      changer */
754 17acfe32 pbrook
                p[8] = (50 * 176) >> 8; // 50x read speed
755 17acfe32 pbrook
                p[9] = (50 * 176) & 0xff;
756 17acfe32 pbrook
                p[10] = 0 >> 8; // No volume
757 17acfe32 pbrook
                p[11] = 0 & 0xff;
758 17acfe32 pbrook
                p[12] = 2048 >> 8; // 2M buffer
759 17acfe32 pbrook
                p[13] = 2048 & 0xff;
760 17acfe32 pbrook
                p[14] = (16 * 176) >> 8; // 16x read speed current
761 17acfe32 pbrook
                p[15] = (16 * 176) & 0xff;
762 17acfe32 pbrook
                p[18] = (16 * 176) >> 8; // 16x write speed
763 17acfe32 pbrook
                p[19] = (16 * 176) & 0xff;
764 17acfe32 pbrook
                p[20] = (16 * 176) >> 8; // 16x write speed current
765 17acfe32 pbrook
                p[21] = (16 * 176) & 0xff;
766 67cd24a8 ths
                p += 22;
767 17acfe32 pbrook
            }
768 c87c0672 aliguori
            r->iov.iov_len = p - outbuf;
769 c87c0672 aliguori
            outbuf[0] = r->iov.iov_len - 4;
770 c87c0672 aliguori
            if (r->iov.iov_len > len)
771 c87c0672 aliguori
                r->iov.iov_len = len;
772 7d8406be pbrook
        }
773 17acfe32 pbrook
        break;
774 17acfe32 pbrook
    case 0x1b:
775 17acfe32 pbrook
        DPRINTF("Start Stop Unit\n");
776 d52affa7 Gerd Hoffmann
        if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM &&
777 b2056c16 blueswir1
            (buf[4] & 2))
778 b2056c16 blueswir1
            /* load/eject medium */
779 d52affa7 Gerd Hoffmann
            bdrv_eject(s->dinfo->bdrv, !(buf[4] & 1));
780 17acfe32 pbrook
        break;
781 17acfe32 pbrook
    case 0x1e:
782 17acfe32 pbrook
        DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
783 d52affa7 Gerd Hoffmann
        bdrv_set_locked(s->dinfo->bdrv, buf[4] & 1);
784 2e5d83bb pbrook
        break;
785 2e5d83bb pbrook
    case 0x25:
786 2e5d83bb pbrook
        DPRINTF("Read Capacity\n");
787 2e5d83bb pbrook
        /* The normal LEN field for this command is zero.  */
788 a917d384 pbrook
        memset(outbuf, 0, 8);
789 d52affa7 Gerd Hoffmann
        bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
790 c1c0438c aliguori
        nb_sectors /= s->cluster_size;
791 51c1ebb1 pbrook
        /* Returned value is the address of the last sector.  */
792 51c1ebb1 pbrook
        if (nb_sectors) {
793 51c1ebb1 pbrook
            nb_sectors--;
794 274fb0e1 aliguori
            /* Remember the new size for read/write sanity checking. */
795 274fb0e1 aliguori
            s->max_lba = nb_sectors;
796 e035b43d aliguori
            /* Clip to 2TB, instead of returning capacity modulo 2TB. */
797 e035b43d aliguori
            if (nb_sectors > UINT32_MAX)
798 e035b43d aliguori
                nb_sectors = UINT32_MAX;
799 a917d384 pbrook
            outbuf[0] = (nb_sectors >> 24) & 0xff;
800 a917d384 pbrook
            outbuf[1] = (nb_sectors >> 16) & 0xff;
801 a917d384 pbrook
            outbuf[2] = (nb_sectors >> 8) & 0xff;
802 a917d384 pbrook
            outbuf[3] = nb_sectors & 0xff;
803 a917d384 pbrook
            outbuf[4] = 0;
804 a917d384 pbrook
            outbuf[5] = 0;
805 a917d384 pbrook
            outbuf[6] = s->cluster_size * 2;
806 a917d384 pbrook
            outbuf[7] = 0;
807 c87c0672 aliguori
            r->iov.iov_len = 8;
808 51c1ebb1 pbrook
        } else {
809 58a2c436 blueswir1
        notready:
810 22864256 blueswir1
            scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
811 35f1df84 pbrook
            return 0;
812 51c1ebb1 pbrook
        }
813 2e5d83bb pbrook
        break;
814 2e5d83bb pbrook
    case 0x08:
815 2e5d83bb pbrook
    case 0x28:
816 86106e59 aliguori
    case 0x88:
817 0bf9e31a Blue Swirl
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
818 274fb0e1 aliguori
        if (lba > s->max_lba)
819 274fb0e1 aliguori
            goto illegal_lba;
820 a917d384 pbrook
        r->sector = lba * s->cluster_size;
821 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
822 2e5d83bb pbrook
        break;
823 2e5d83bb pbrook
    case 0x0a:
824 2e5d83bb pbrook
    case 0x2a:
825 86106e59 aliguori
    case 0x8a:
826 0bf9e31a Blue Swirl
        DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
827 274fb0e1 aliguori
        if (lba > s->max_lba)
828 274fb0e1 aliguori
            goto illegal_lba;
829 a917d384 pbrook
        r->sector = lba * s->cluster_size;
830 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
831 2e5d83bb pbrook
        is_write = 1;
832 2e5d83bb pbrook
        break;
833 7d8406be pbrook
    case 0x35:
834 0bf9e31a Blue Swirl
        DPRINTF("Synchronise cache (sector %" PRId64 ", count %d)\n", lba, len);
835 d52affa7 Gerd Hoffmann
        bdrv_flush(s->dinfo->bdrv);
836 7d8406be pbrook
        break;
837 2e5d83bb pbrook
    case 0x43:
838 2e5d83bb pbrook
        {
839 7c22dd52 pbrook
            int start_track, format, msf, toclen;
840 2e5d83bb pbrook
841 2e5d83bb pbrook
            msf = buf[1] & 2;
842 2e5d83bb pbrook
            format = buf[2] & 0xf;
843 2e5d83bb pbrook
            start_track = buf[6];
844 d52affa7 Gerd Hoffmann
            bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
845 2e5d83bb pbrook
            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
846 ee16b24a blueswir1
            nb_sectors /= s->cluster_size;
847 2e5d83bb pbrook
            switch(format) {
848 2e5d83bb pbrook
            case 0:
849 a917d384 pbrook
                toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
850 2e5d83bb pbrook
                break;
851 2e5d83bb pbrook
            case 1:
852 2e5d83bb pbrook
                /* multi session : only a single session defined */
853 7c22dd52 pbrook
                toclen = 12;
854 a917d384 pbrook
                memset(outbuf, 0, 12);
855 a917d384 pbrook
                outbuf[1] = 0x0a;
856 a917d384 pbrook
                outbuf[2] = 0x01;
857 a917d384 pbrook
                outbuf[3] = 0x01;
858 2e5d83bb pbrook
                break;
859 2e5d83bb pbrook
            case 2:
860 a917d384 pbrook
                toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
861 2e5d83bb pbrook
                break;
862 2e5d83bb pbrook
            default:
863 7c22dd52 pbrook
                goto error_cmd;
864 7c22dd52 pbrook
            }
865 7c22dd52 pbrook
            if (toclen > 0) {
866 7c22dd52 pbrook
                if (len > toclen)
867 7c22dd52 pbrook
                  len = toclen;
868 c87c0672 aliguori
                r->iov.iov_len = len;
869 7c22dd52 pbrook
                break;
870 2e5d83bb pbrook
            }
871 7c22dd52 pbrook
        error_cmd:
872 7c22dd52 pbrook
            DPRINTF("Read TOC error\n");
873 7c22dd52 pbrook
            goto fail;
874 2e5d83bb pbrook
        }
875 17acfe32 pbrook
    case 0x46:
876 17acfe32 pbrook
        DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
877 a917d384 pbrook
        memset(outbuf, 0, 8);
878 1235fc06 ths
        /* ??? This should probably return much more information.  For now
879 17acfe32 pbrook
           just return the basic header indicating the CD-ROM profile.  */
880 a917d384 pbrook
        outbuf[7] = 8; // CD-ROM
881 c87c0672 aliguori
        r->iov.iov_len = 8;
882 17acfe32 pbrook
        break;
883 2e5d83bb pbrook
    case 0x56:
884 2e5d83bb pbrook
        DPRINTF("Reserve(10)\n");
885 2e5d83bb pbrook
        if (buf[1] & 3)
886 2e5d83bb pbrook
            goto fail;
887 2e5d83bb pbrook
        break;
888 2e5d83bb pbrook
    case 0x57:
889 2e5d83bb pbrook
        DPRINTF("Release(10)\n");
890 2e5d83bb pbrook
        if (buf[1] & 3)
891 2e5d83bb pbrook
            goto fail;
892 2e5d83bb pbrook
        break;
893 86106e59 aliguori
    case 0x9e:
894 86106e59 aliguori
        /* Service Action In subcommands. */
895 86106e59 aliguori
        if ((buf[1] & 31) == 0x10) {
896 86106e59 aliguori
            DPRINTF("SAI READ CAPACITY(16)\n");
897 86106e59 aliguori
            memset(outbuf, 0, len);
898 d52affa7 Gerd Hoffmann
            bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
899 c1c0438c aliguori
            nb_sectors /= s->cluster_size;
900 86106e59 aliguori
            /* Returned value is the address of the last sector.  */
901 86106e59 aliguori
            if (nb_sectors) {
902 86106e59 aliguori
                nb_sectors--;
903 274fb0e1 aliguori
                /* Remember the new size for read/write sanity checking. */
904 274fb0e1 aliguori
                s->max_lba = nb_sectors;
905 86106e59 aliguori
                outbuf[0] = (nb_sectors >> 56) & 0xff;
906 86106e59 aliguori
                outbuf[1] = (nb_sectors >> 48) & 0xff;
907 86106e59 aliguori
                outbuf[2] = (nb_sectors >> 40) & 0xff;
908 86106e59 aliguori
                outbuf[3] = (nb_sectors >> 32) & 0xff;
909 86106e59 aliguori
                outbuf[4] = (nb_sectors >> 24) & 0xff;
910 86106e59 aliguori
                outbuf[5] = (nb_sectors >> 16) & 0xff;
911 86106e59 aliguori
                outbuf[6] = (nb_sectors >> 8) & 0xff;
912 86106e59 aliguori
                outbuf[7] = nb_sectors & 0xff;
913 86106e59 aliguori
                outbuf[8] = 0;
914 86106e59 aliguori
                outbuf[9] = 0;
915 86106e59 aliguori
                outbuf[10] = s->cluster_size * 2;
916 86106e59 aliguori
                outbuf[11] = 0;
917 86106e59 aliguori
                /* Protection, exponent and lowest lba field left blank. */
918 c87c0672 aliguori
                r->iov.iov_len = len;
919 86106e59 aliguori
            } else {
920 86106e59 aliguori
                scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
921 86106e59 aliguori
                return 0;
922 86106e59 aliguori
            }
923 86106e59 aliguori
            break;
924 86106e59 aliguori
        }
925 86106e59 aliguori
        DPRINTF("Unsupported Service Action In\n");
926 86106e59 aliguori
        goto fail;
927 2e5d83bb pbrook
    case 0xa0:
928 2e5d83bb pbrook
        DPRINTF("Report LUNs (len %d)\n", len);
929 2e5d83bb pbrook
        if (len < 16)
930 2e5d83bb pbrook
            goto fail;
931 a917d384 pbrook
        memset(outbuf, 0, 16);
932 a917d384 pbrook
        outbuf[3] = 8;
933 c87c0672 aliguori
        r->iov.iov_len = 16;
934 2e5d83bb pbrook
        break;
935 22864256 blueswir1
    case 0x2f:
936 0bf9e31a Blue Swirl
        DPRINTF("Verify (sector %" PRId64 ", count %d)\n", lba, len);
937 22864256 blueswir1
        break;
938 2e5d83bb pbrook
    default:
939 2e5d83bb pbrook
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
940 2e5d83bb pbrook
    fail:
941 22864256 blueswir1
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST);
942 2e5d83bb pbrook
        return 0;
943 274fb0e1 aliguori
    illegal_lba:
944 274fb0e1 aliguori
        scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
945 274fb0e1 aliguori
        return 0;
946 2e5d83bb pbrook
    }
947 c87c0672 aliguori
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
948 22864256 blueswir1
        scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
949 a917d384 pbrook
    }
950 c87c0672 aliguori
    len = r->sector_count * 512 + r->iov.iov_len;
951 a917d384 pbrook
    if (is_write) {
952 a917d384 pbrook
        return -len;
953 a917d384 pbrook
    } else {
954 a917d384 pbrook
        if (!r->sector_count)
955 a917d384 pbrook
            r->sector_count = -1;
956 a917d384 pbrook
        return len;
957 2e5d83bb pbrook
    }
958 2e5d83bb pbrook
}
959 2e5d83bb pbrook
960 56a14938 Gerd Hoffmann
static void scsi_destroy(SCSIDevice *dev)
961 56a14938 Gerd Hoffmann
{
962 56a14938 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
963 56a14938 Gerd Hoffmann
964 56a14938 Gerd Hoffmann
    drive_uninit(s->dinfo);
965 56a14938 Gerd Hoffmann
}
966 56a14938 Gerd Hoffmann
967 d52affa7 Gerd Hoffmann
static int scsi_disk_initfn(SCSIDevice *dev)
968 2e5d83bb pbrook
{
969 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
970 274fb0e1 aliguori
    uint64_t nb_sectors;
971 2e5d83bb pbrook
972 d52affa7 Gerd Hoffmann
    if (!s->dinfo || !s->dinfo->bdrv) {
973 d52affa7 Gerd Hoffmann
        qemu_error("scsi-disk: drive property not set\n");
974 d52affa7 Gerd Hoffmann
        return -1;
975 d52affa7 Gerd Hoffmann
    }
976 d52affa7 Gerd Hoffmann
977 d52affa7 Gerd Hoffmann
    if (bdrv_get_type_hint(s->dinfo->bdrv) == BDRV_TYPE_CDROM) {
978 7c22dd52 pbrook
        s->cluster_size = 4;
979 2e5d83bb pbrook
    } else {
980 7c22dd52 pbrook
        s->cluster_size = 1;
981 2e5d83bb pbrook
    }
982 d52affa7 Gerd Hoffmann
    bdrv_get_geometry(s->dinfo->bdrv, &nb_sectors);
983 274fb0e1 aliguori
    nb_sectors /= s->cluster_size;
984 274fb0e1 aliguori
    if (nb_sectors)
985 274fb0e1 aliguori
        nb_sectors--;
986 274fb0e1 aliguori
    s->max_lba = nb_sectors;
987 d52affa7 Gerd Hoffmann
    strncpy(s->drive_serial_str, drive_get_serial(s->dinfo->bdrv),
988 fa879c64 aliguori
            sizeof(s->drive_serial_str));
989 fa879c64 aliguori
    if (strlen(s->drive_serial_str) == 0)
990 00766a4e blueswir1
        pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
991 ea8a5d7f aliguori
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
992 d52affa7 Gerd Hoffmann
    return 0;
993 d52affa7 Gerd Hoffmann
}
994 d52affa7 Gerd Hoffmann
995 d52affa7 Gerd Hoffmann
static SCSIDeviceInfo scsi_disk_info = {
996 d52affa7 Gerd Hoffmann
    .qdev.name    = "scsi-disk",
997 d52affa7 Gerd Hoffmann
    .qdev.desc    = "virtual scsi disk or cdrom",
998 d52affa7 Gerd Hoffmann
    .qdev.size    = sizeof(SCSIDiskState),
999 d52affa7 Gerd Hoffmann
    .init         = scsi_disk_initfn,
1000 56a14938 Gerd Hoffmann
    .destroy      = scsi_destroy,
1001 d52affa7 Gerd Hoffmann
    .send_command = scsi_send_command,
1002 d52affa7 Gerd Hoffmann
    .read_data    = scsi_read_data,
1003 d52affa7 Gerd Hoffmann
    .write_data   = scsi_write_data,
1004 d52affa7 Gerd Hoffmann
    .cancel_io    = scsi_cancel_io,
1005 d52affa7 Gerd Hoffmann
    .get_buf      = scsi_get_buf,
1006 d52affa7 Gerd Hoffmann
    .qdev.props   = (Property[]) {
1007 d52affa7 Gerd Hoffmann
        DEFINE_PROP_DRIVE("drive", SCSIDiskState, dinfo),
1008 d52affa7 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
1009 d52affa7 Gerd Hoffmann
    },
1010 d52affa7 Gerd Hoffmann
};
1011 d52affa7 Gerd Hoffmann
1012 d52affa7 Gerd Hoffmann
static void scsi_disk_register_devices(void)
1013 d52affa7 Gerd Hoffmann
{
1014 d52affa7 Gerd Hoffmann
    scsi_qdev_register(&scsi_disk_info);
1015 8ccc2ace ths
}
1016 d52affa7 Gerd Hoffmann
device_init(scsi_disk_register_devices)