Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 03f48b07

History | View | Annotate | Download (57.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 ad3cea42 Artyom Tarasenko
 * Modifications:
9 ad3cea42 Artyom Tarasenko
 *  2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
10 ad3cea42 Artyom Tarasenko
 *                                 when the allocation length of CDB is smaller
11 ad3cea42 Artyom Tarasenko
 *                                 than 36.
12 ad3cea42 Artyom Tarasenko
 *  2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
13 ad3cea42 Artyom Tarasenko
 *                                 MODE SENSE response.
14 2e5d83bb pbrook
 *
15 8e31bf38 Matthew Fernandez
 * This code is licensed under the LGPL.
16 a917d384 pbrook
 *
17 a917d384 pbrook
 * Note that this file only handles the SCSI architecture model and device
18 1d4db89c balrog
 * commands.  Emulation of interface/link layer protocols is handled by
19 1d4db89c balrog
 * the host adapter emulator.
20 2e5d83bb pbrook
 */
21 2e5d83bb pbrook
22 2e5d83bb pbrook
//#define DEBUG_SCSI
23 2e5d83bb pbrook
24 2e5d83bb pbrook
#ifdef DEBUG_SCSI
25 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) \
26 001faf32 Blue Swirl
do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
27 2e5d83bb pbrook
#else
28 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do {} while(0)
29 2e5d83bb pbrook
#endif
30 2e5d83bb pbrook
31 001faf32 Blue Swirl
#define BADF(fmt, ...) \
32 001faf32 Blue Swirl
do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
33 2e5d83bb pbrook
34 87ecb68b pbrook
#include "qemu-common.h"
35 2f792016 Markus Armbruster
#include "qemu-error.h"
36 43b443b6 Gerd Hoffmann
#include "scsi.h"
37 0d65e1f8 Gerd Hoffmann
#include "scsi-defs.h"
38 666daa68 Markus Armbruster
#include "sysemu.h"
39 2446333c Blue Swirl
#include "blockdev.h"
40 d1a0739d Markus Armbruster
#include "block_int.h"
41 5d0d2467 Paolo Bonzini
#include "dma.h"
42 22864256 blueswir1
43 336a6915 Paolo Bonzini
#ifdef __linux
44 336a6915 Paolo Bonzini
#include <scsi/sg.h>
45 336a6915 Paolo Bonzini
#endif
46 336a6915 Paolo Bonzini
47 f0f72ffe aurel32
#define SCSI_DMA_BUF_SIZE    131072
48 57575058 balrog
#define SCSI_MAX_INQUIRY_LEN 256
49 a917d384 pbrook
50 d52affa7 Gerd Hoffmann
typedef struct SCSIDiskState SCSIDiskState;
51 d52affa7 Gerd Hoffmann
52 4c41d2ef Gerd Hoffmann
typedef struct SCSIDiskReq {
53 4c41d2ef Gerd Hoffmann
    SCSIRequest req;
54 a917d384 pbrook
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
55 e035b43d aliguori
    uint64_t sector;
56 e035b43d aliguori
    uint32_t sector_count;
57 7285477a Paolo Bonzini
    uint32_t buflen;
58 c87c0672 aliguori
    struct iovec iov;
59 c87c0672 aliguori
    QEMUIOVector qiov;
60 a597e79c Christoph Hellwig
    BlockAcctCookie acct;
61 4c41d2ef Gerd Hoffmann
} SCSIDiskReq;
62 a917d384 pbrook
63 d52affa7 Gerd Hoffmann
struct SCSIDiskState
64 a917d384 pbrook
{
65 d52affa7 Gerd Hoffmann
    SCSIDevice qdev;
66 419e691f Stefan Hajnoczi
    uint32_t removable;
67 8a9c16f6 Paolo Bonzini
    bool media_changed;
68 3c2f7c12 Paolo Bonzini
    bool media_event;
69 4480de19 Paolo Bonzini
    bool eject_request;
70 213189ab Markus Armbruster
    QEMUBH *bh;
71 383b4d9b Gerd Hoffmann
    char *version;
72 a0fef654 Markus Armbruster
    char *serial;
73 ece0d5e9 Markus Armbruster
    bool tray_open;
74 81b1008d Markus Armbruster
    bool tray_locked;
75 2e5d83bb pbrook
};
76 2e5d83bb pbrook
77 71544d30 Paolo Bonzini
static int scsi_handle_rw_error(SCSIDiskReq *r, int error);
78 5dba48a8 Kevin Wolf
79 ad2d30f7 Paolo Bonzini
static void scsi_free_request(SCSIRequest *req)
80 4d611c9a pbrook
{
81 ad2d30f7 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
82 ad2d30f7 Paolo Bonzini
83 7285477a Paolo Bonzini
    if (r->iov.iov_base) {
84 7285477a Paolo Bonzini
        qemu_vfree(r->iov.iov_base);
85 7285477a Paolo Bonzini
    }
86 4d611c9a pbrook
}
87 4d611c9a pbrook
88 b45ef674 Paolo Bonzini
/* Helper function for command completion with sense.  */
89 b45ef674 Paolo Bonzini
static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
90 ed3a34a3 Gerd Hoffmann
{
91 02fa69b6 Blue Swirl
    DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
92 02fa69b6 Blue Swirl
            r->req.tag, sense.key, sense.asc, sense.ascq);
93 b45ef674 Paolo Bonzini
    scsi_req_build_sense(&r->req, sense);
94 b45ef674 Paolo Bonzini
    scsi_req_complete(&r->req, CHECK_CONDITION);
95 4d611c9a pbrook
}
96 4d611c9a pbrook
97 4d611c9a pbrook
/* Cancel a pending data transfer.  */
98 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
99 4d611c9a pbrook
{
100 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
101 5c6c0e51 Hannes Reinecke
102 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
103 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
104 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
105 c7bae6a7 Paolo Bonzini
106 c7bae6a7 Paolo Bonzini
        /* This reference was left in by scsi_*_data.  We take ownership of
107 c7bae6a7 Paolo Bonzini
         * it the moment scsi_req_cancel is called, independent of whether
108 c7bae6a7 Paolo Bonzini
         * bdrv_aio_cancel completes the request or not.  */
109 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
110 a917d384 pbrook
    }
111 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
112 a917d384 pbrook
}
113 a917d384 pbrook
114 43b978b9 Paolo Bonzini
static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
115 103b40f5 Paolo Bonzini
{
116 7285477a Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
117 7285477a Paolo Bonzini
118 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
119 43b978b9 Paolo Bonzini
        r->buflen = size;
120 44740c38 Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
121 7285477a Paolo Bonzini
    }
122 7285477a Paolo Bonzini
    r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
123 103b40f5 Paolo Bonzini
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
124 103b40f5 Paolo Bonzini
    return r->qiov.size / 512;
125 103b40f5 Paolo Bonzini
}
126 103b40f5 Paolo Bonzini
127 43b978b9 Paolo Bonzini
static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
128 43b978b9 Paolo Bonzini
{
129 43b978b9 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
130 43b978b9 Paolo Bonzini
131 43b978b9 Paolo Bonzini
    qemu_put_be64s(f, &r->sector);
132 43b978b9 Paolo Bonzini
    qemu_put_be32s(f, &r->sector_count);
133 43b978b9 Paolo Bonzini
    qemu_put_be32s(f, &r->buflen);
134 43b978b9 Paolo Bonzini
    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
135 43b978b9 Paolo Bonzini
        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
136 43b978b9 Paolo Bonzini
    }
137 43b978b9 Paolo Bonzini
}
138 43b978b9 Paolo Bonzini
139 43b978b9 Paolo Bonzini
static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
140 43b978b9 Paolo Bonzini
{
141 43b978b9 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
142 43b978b9 Paolo Bonzini
143 43b978b9 Paolo Bonzini
    qemu_get_be64s(f, &r->sector);
144 43b978b9 Paolo Bonzini
    qemu_get_be32s(f, &r->sector_count);
145 43b978b9 Paolo Bonzini
    qemu_get_be32s(f, &r->buflen);
146 43b978b9 Paolo Bonzini
    if (r->buflen) {
147 43b978b9 Paolo Bonzini
        scsi_init_iovec(r, r->buflen);
148 43b978b9 Paolo Bonzini
        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
149 43b978b9 Paolo Bonzini
            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
150 43b978b9 Paolo Bonzini
        }
151 43b978b9 Paolo Bonzini
    }
152 43b978b9 Paolo Bonzini
153 43b978b9 Paolo Bonzini
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
154 43b978b9 Paolo Bonzini
}
155 43b978b9 Paolo Bonzini
156 5d0d2467 Paolo Bonzini
static void scsi_dma_complete(void *opaque, int ret)
157 5d0d2467 Paolo Bonzini
{
158 5d0d2467 Paolo Bonzini
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
159 5d0d2467 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
160 5d0d2467 Paolo Bonzini
161 5d0d2467 Paolo Bonzini
    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
162 5d0d2467 Paolo Bonzini
163 5d0d2467 Paolo Bonzini
    if (ret) {
164 5d0d2467 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
165 5d0d2467 Paolo Bonzini
            goto done;
166 5d0d2467 Paolo Bonzini
        }
167 5d0d2467 Paolo Bonzini
    }
168 5d0d2467 Paolo Bonzini
169 5d0d2467 Paolo Bonzini
    r->sector += r->sector_count;
170 5d0d2467 Paolo Bonzini
    r->sector_count = 0;
171 5d0d2467 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
172 5d0d2467 Paolo Bonzini
173 5d0d2467 Paolo Bonzini
done:
174 5d0d2467 Paolo Bonzini
    scsi_req_unref(&r->req);
175 5d0d2467 Paolo Bonzini
}
176 5d0d2467 Paolo Bonzini
177 a917d384 pbrook
static void scsi_read_complete(void * opaque, int ret)
178 a917d384 pbrook
{
179 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
180 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
181 5dba48a8 Kevin Wolf
    int n;
182 a917d384 pbrook
183 8e321cc6 Paolo Bonzini
    if (r->req.aiocb != NULL) {
184 8e321cc6 Paolo Bonzini
        r->req.aiocb = NULL;
185 44740c38 Paolo Bonzini
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
186 8e321cc6 Paolo Bonzini
    }
187 a597e79c Christoph Hellwig
188 a917d384 pbrook
    if (ret) {
189 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
190 c7bae6a7 Paolo Bonzini
            goto done;
191 5dba48a8 Kevin Wolf
        }
192 4d611c9a pbrook
    }
193 5dba48a8 Kevin Wolf
194 103b40f5 Paolo Bonzini
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
195 a917d384 pbrook
196 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
197 5dba48a8 Kevin Wolf
    r->sector += n;
198 5dba48a8 Kevin Wolf
    r->sector_count -= n;
199 103b40f5 Paolo Bonzini
    scsi_req_data(&r->req, r->qiov.size);
200 c7bae6a7 Paolo Bonzini
201 c7bae6a7 Paolo Bonzini
done:
202 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
203 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
204 c7bae6a7 Paolo Bonzini
    }
205 4d611c9a pbrook
}
206 4d611c9a pbrook
207 0a4ac106 Paolo Bonzini
static void scsi_flush_complete(void * opaque, int ret)
208 0a4ac106 Paolo Bonzini
{
209 0a4ac106 Paolo Bonzini
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
210 0a4ac106 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
211 0a4ac106 Paolo Bonzini
212 0a4ac106 Paolo Bonzini
    if (r->req.aiocb != NULL) {
213 0a4ac106 Paolo Bonzini
        r->req.aiocb = NULL;
214 44740c38 Paolo Bonzini
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
215 0a4ac106 Paolo Bonzini
    }
216 0a4ac106 Paolo Bonzini
217 0a4ac106 Paolo Bonzini
    if (ret < 0) {
218 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
219 c7bae6a7 Paolo Bonzini
            goto done;
220 0a4ac106 Paolo Bonzini
        }
221 0a4ac106 Paolo Bonzini
    }
222 0a4ac106 Paolo Bonzini
223 0a4ac106 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
224 c7bae6a7 Paolo Bonzini
225 c7bae6a7 Paolo Bonzini
done:
226 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
227 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
228 c7bae6a7 Paolo Bonzini
    }
229 0a4ac106 Paolo Bonzini
}
230 5dba48a8 Kevin Wolf
231 5c6c0e51 Hannes Reinecke
/* Read more data from scsi device into buffer.  */
232 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
233 2e5d83bb pbrook
{
234 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
235 5dba48a8 Kevin Wolf
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
236 2e5d83bb pbrook
    uint32_t n;
237 2e5d83bb pbrook
238 a917d384 pbrook
    if (r->sector_count == (uint32_t)-1) {
239 aa2b1e89 Bernhard Kohl
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
240 a917d384 pbrook
        r->sector_count = 0;
241 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, r->iov.iov_len);
242 a917d384 pbrook
        return;
243 2e5d83bb pbrook
    }
244 a917d384 pbrook
    DPRINTF("Read sector_count=%d\n", r->sector_count);
245 a917d384 pbrook
    if (r->sector_count == 0) {
246 b45ef674 Paolo Bonzini
        /* This also clears the sense buffer for REQUEST SENSE.  */
247 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
248 a917d384 pbrook
        return;
249 2e5d83bb pbrook
    }
250 2e5d83bb pbrook
251 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
252 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
253 6fa2c95f Stefan Hajnoczi
254 c7bae6a7 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
255 c7bae6a7 Paolo Bonzini
    scsi_req_ref(&r->req);
256 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
257 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
258 efb9ee02 Hannes Reinecke
        scsi_read_complete(r, -EINVAL);
259 efb9ee02 Hannes Reinecke
        return;
260 efb9ee02 Hannes Reinecke
    }
261 efb9ee02 Hannes Reinecke
262 a1aff5bf Markus Armbruster
    if (s->tray_open) {
263 a1aff5bf Markus Armbruster
        scsi_read_complete(r, -ENOMEDIUM);
264 c7bae6a7 Paolo Bonzini
        return;
265 a1aff5bf Markus Armbruster
    }
266 c7bae6a7 Paolo Bonzini
267 5d0d2467 Paolo Bonzini
    if (r->req.sg) {
268 5d0d2467 Paolo Bonzini
        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
269 5d0d2467 Paolo Bonzini
        r->req.resid -= r->req.sg->size;
270 5d0d2467 Paolo Bonzini
        r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
271 5d0d2467 Paolo Bonzini
                                     scsi_dma_complete, r);
272 5d0d2467 Paolo Bonzini
    } else {
273 43b978b9 Paolo Bonzini
        n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
274 5d0d2467 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
275 5d0d2467 Paolo Bonzini
        r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
276 5d0d2467 Paolo Bonzini
                                      scsi_read_complete, r);
277 5d0d2467 Paolo Bonzini
    }
278 2e5d83bb pbrook
}
279 2e5d83bb pbrook
280 c7bae6a7 Paolo Bonzini
/*
281 c7bae6a7 Paolo Bonzini
 * scsi_handle_rw_error has two return values.  0 means that the error
282 c7bae6a7 Paolo Bonzini
 * must be ignored, 1 means that the error has been processed and the
283 c7bae6a7 Paolo Bonzini
 * caller should not do anything else for this request.  Note that
284 c7bae6a7 Paolo Bonzini
 * scsi_handle_rw_error always manages its reference counts, independent
285 c7bae6a7 Paolo Bonzini
 * of the return value.
286 c7bae6a7 Paolo Bonzini
 */
287 71544d30 Paolo Bonzini
static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
288 5dba48a8 Kevin Wolf
{
289 71544d30 Paolo Bonzini
    int is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
290 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
291 44740c38 Paolo Bonzini
    BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
292 ea8a5d7f aliguori
293 380f640f Luiz Capitulino
    if (action == BLOCK_ERR_IGNORE) {
294 329c0a48 Luiz Capitulino
        bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read);
295 ea8a5d7f aliguori
        return 0;
296 380f640f Luiz Capitulino
    }
297 ea8a5d7f aliguori
298 ea8a5d7f aliguori
    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
299 ea8a5d7f aliguori
            || action == BLOCK_ERR_STOP_ANY) {
300 5dba48a8 Kevin Wolf
301 329c0a48 Luiz Capitulino
        bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
302 0461d5a6 Luiz Capitulino
        vm_stop(RUN_STATE_IO_ERROR);
303 44740c38 Paolo Bonzini
        bdrv_iostatus_set_err(s->qdev.conf.bs, error);
304 71544d30 Paolo Bonzini
        scsi_req_retry(&r->req);
305 ea8a5d7f aliguori
    } else {
306 efb9ee02 Hannes Reinecke
        switch (error) {
307 7e218df5 Paolo Bonzini
        case ENOMEDIUM:
308 7e218df5 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
309 7e218df5 Paolo Bonzini
            break;
310 efb9ee02 Hannes Reinecke
        case ENOMEM:
311 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
312 efb9ee02 Hannes Reinecke
            break;
313 efb9ee02 Hannes Reinecke
        case EINVAL:
314 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
315 efb9ee02 Hannes Reinecke
            break;
316 efb9ee02 Hannes Reinecke
        default:
317 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
318 efb9ee02 Hannes Reinecke
            break;
319 a1f0cce2 Hannes Reinecke
        }
320 329c0a48 Luiz Capitulino
        bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read);
321 ea8a5d7f aliguori
    }
322 ea8a5d7f aliguori
    return 1;
323 ea8a5d7f aliguori
}
324 ea8a5d7f aliguori
325 4d611c9a pbrook
static void scsi_write_complete(void * opaque, int ret)
326 4d611c9a pbrook
{
327 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
328 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
329 ea8a5d7f aliguori
    uint32_t n;
330 ea8a5d7f aliguori
331 8e321cc6 Paolo Bonzini
    if (r->req.aiocb != NULL) {
332 8e321cc6 Paolo Bonzini
        r->req.aiocb = NULL;
333 44740c38 Paolo Bonzini
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
334 8e321cc6 Paolo Bonzini
    }
335 a597e79c Christoph Hellwig
336 4d611c9a pbrook
    if (ret) {
337 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
338 c7bae6a7 Paolo Bonzini
            goto done;
339 5dba48a8 Kevin Wolf
        }
340 4d611c9a pbrook
    }
341 4d611c9a pbrook
342 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
343 ea8a5d7f aliguori
    r->sector += n;
344 ea8a5d7f aliguori
    r->sector_count -= n;
345 a917d384 pbrook
    if (r->sector_count == 0) {
346 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
347 a917d384 pbrook
    } else {
348 43b978b9 Paolo Bonzini
        scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
349 103b40f5 Paolo Bonzini
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
350 103b40f5 Paolo Bonzini
        scsi_req_data(&r->req, r->qiov.size);
351 4d611c9a pbrook
    }
352 c7bae6a7 Paolo Bonzini
353 c7bae6a7 Paolo Bonzini
done:
354 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
355 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
356 c7bae6a7 Paolo Bonzini
    }
357 4d611c9a pbrook
}
358 4d611c9a pbrook
359 42741212 Paolo Bonzini
static void scsi_write_data(SCSIRequest *req)
360 ea8a5d7f aliguori
{
361 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
362 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
363 ea8a5d7f aliguori
    uint32_t n;
364 ea8a5d7f aliguori
365 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
366 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
367 6fa2c95f Stefan Hajnoczi
368 c7bae6a7 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
369 c7bae6a7 Paolo Bonzini
    scsi_req_ref(&r->req);
370 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
371 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
372 efb9ee02 Hannes Reinecke
        scsi_write_complete(r, -EINVAL);
373 42741212 Paolo Bonzini
        return;
374 efb9ee02 Hannes Reinecke
    }
375 efb9ee02 Hannes Reinecke
376 5d0d2467 Paolo Bonzini
    if (!r->req.sg && !r->qiov.size) {
377 5d0d2467 Paolo Bonzini
        /* Called for the first time.  Ask the driver to send us more data.  */
378 5d0d2467 Paolo Bonzini
        scsi_write_complete(r, 0);
379 5d0d2467 Paolo Bonzini
        return;
380 5d0d2467 Paolo Bonzini
    }
381 5d0d2467 Paolo Bonzini
    if (s->tray_open) {
382 5d0d2467 Paolo Bonzini
        scsi_write_complete(r, -ENOMEDIUM);
383 5d0d2467 Paolo Bonzini
        return;
384 5d0d2467 Paolo Bonzini
    }
385 5d0d2467 Paolo Bonzini
386 5d0d2467 Paolo Bonzini
    if (r->req.sg) {
387 5d0d2467 Paolo Bonzini
        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
388 5d0d2467 Paolo Bonzini
        r->req.resid -= r->req.sg->size;
389 5d0d2467 Paolo Bonzini
        r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
390 5d0d2467 Paolo Bonzini
                                      scsi_dma_complete, r);
391 5d0d2467 Paolo Bonzini
    } else {
392 5d0d2467 Paolo Bonzini
        n = r->qiov.size / 512;
393 44740c38 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
394 44740c38 Paolo Bonzini
        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
395 103b40f5 Paolo Bonzini
                                       scsi_write_complete, r);
396 ea8a5d7f aliguori
    }
397 a917d384 pbrook
}
398 2e5d83bb pbrook
399 a917d384 pbrook
/* Return a pointer to the data buffer.  */
400 5c6c0e51 Hannes Reinecke
static uint8_t *scsi_get_buf(SCSIRequest *req)
401 a917d384 pbrook
{
402 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
403 2e5d83bb pbrook
404 3f4cb3d3 blueswir1
    return (uint8_t *)r->iov.iov_base;
405 2e5d83bb pbrook
}
406 2e5d83bb pbrook
407 0b06c059 Gerd Hoffmann
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
408 0b06c059 Gerd Hoffmann
{
409 383b4d9b Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
410 0b06c059 Gerd Hoffmann
    int buflen = 0;
411 0b06c059 Gerd Hoffmann
412 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[1] & 0x2) {
413 0b06c059 Gerd Hoffmann
        /* Command support data - optional, not implemented */
414 0b06c059 Gerd Hoffmann
        BADF("optional INQUIRY command support request not implemented\n");
415 0b06c059 Gerd Hoffmann
        return -1;
416 0b06c059 Gerd Hoffmann
    }
417 0b06c059 Gerd Hoffmann
418 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[1] & 0x1) {
419 0b06c059 Gerd Hoffmann
        /* Vital product data */
420 0b06c059 Gerd Hoffmann
        uint8_t page_code = req->cmd.buf[2];
421 0b06c059 Gerd Hoffmann
        if (req->cmd.xfer < 4) {
422 0b06c059 Gerd Hoffmann
            BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
423 0b06c059 Gerd Hoffmann
                 "less than 4\n", page_code, req->cmd.xfer);
424 0b06c059 Gerd Hoffmann
            return -1;
425 0b06c059 Gerd Hoffmann
        }
426 0b06c059 Gerd Hoffmann
427 e39be482 Paolo Bonzini
        outbuf[buflen++] = s->qdev.type & 0x1f;
428 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = page_code ; // this page
429 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = 0x00;
430 0b06c059 Gerd Hoffmann
431 0b06c059 Gerd Hoffmann
        switch (page_code) {
432 0b06c059 Gerd Hoffmann
        case 0x00: /* Supported page codes, mandatory */
433 39d98982 Hannes Reinecke
        {
434 39d98982 Hannes Reinecke
            int pages;
435 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Supported pages] "
436 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
437 39d98982 Hannes Reinecke
            pages = buflen++;
438 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
439 f01b5931 Paolo Bonzini
            if (s->serial) {
440 3e1c0c9a Hannes Reinecke
                outbuf[buflen++] = 0x80; // unit serial number
441 f01b5931 Paolo Bonzini
            }
442 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x83; // device identification
443 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_DISK) {
444 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb0; // block limits
445 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb2; // thin provisioning
446 39d98982 Hannes Reinecke
            }
447 39d98982 Hannes Reinecke
            outbuf[pages] = buflen - pages - 1; // number of pages
448 0b06c059 Gerd Hoffmann
            break;
449 39d98982 Hannes Reinecke
        }
450 0b06c059 Gerd Hoffmann
        case 0x80: /* Device serial number, optional */
451 0b06c059 Gerd Hoffmann
        {
452 3e1c0c9a Hannes Reinecke
            int l;
453 0b06c059 Gerd Hoffmann
454 3e1c0c9a Hannes Reinecke
            if (!s->serial) {
455 3e1c0c9a Hannes Reinecke
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
456 3e1c0c9a Hannes Reinecke
                return -1;
457 3e1c0c9a Hannes Reinecke
            }
458 3e1c0c9a Hannes Reinecke
459 3e1c0c9a Hannes Reinecke
            l = strlen(s->serial);
460 f01b5931 Paolo Bonzini
            if (l > 20) {
461 0b06c059 Gerd Hoffmann
                l = 20;
462 f01b5931 Paolo Bonzini
            }
463 0b06c059 Gerd Hoffmann
464 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Serial number] "
465 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
466 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = l;
467 a0fef654 Markus Armbruster
            memcpy(outbuf+buflen, s->serial, l);
468 0b06c059 Gerd Hoffmann
            buflen += l;
469 0b06c059 Gerd Hoffmann
            break;
470 0b06c059 Gerd Hoffmann
        }
471 0b06c059 Gerd Hoffmann
472 0b06c059 Gerd Hoffmann
        case 0x83: /* Device identification page, mandatory */
473 0b06c059 Gerd Hoffmann
        {
474 0b06c059 Gerd Hoffmann
            int max_len = 255 - 8;
475 44740c38 Paolo Bonzini
            int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
476 0b06c059 Gerd Hoffmann
477 f01b5931 Paolo Bonzini
            if (id_len > max_len) {
478 0b06c059 Gerd Hoffmann
                id_len = max_len;
479 f01b5931 Paolo Bonzini
            }
480 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Device identification] "
481 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
482 0b06c059 Gerd Hoffmann
483 39d98982 Hannes Reinecke
            outbuf[buflen++] = 4 + id_len;
484 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x2; // ASCII
485 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // not officially assigned
486 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // reserved
487 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = id_len; // length of data following
488 0b06c059 Gerd Hoffmann
489 44740c38 Paolo Bonzini
            memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
490 0b06c059 Gerd Hoffmann
            buflen += id_len;
491 0b06c059 Gerd Hoffmann
            break;
492 0b06c059 Gerd Hoffmann
        }
493 ea3bd56f Christoph Hellwig
        case 0xb0: /* block limits */
494 ee3659e3 Christoph Hellwig
        {
495 ea3bd56f Christoph Hellwig
            unsigned int unmap_sectors =
496 ea3bd56f Christoph Hellwig
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
497 8cfacf07 Christoph Hellwig
            unsigned int min_io_size =
498 8cfacf07 Christoph Hellwig
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
499 8cfacf07 Christoph Hellwig
            unsigned int opt_io_size =
500 8cfacf07 Christoph Hellwig
                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
501 ee3659e3 Christoph Hellwig
502 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_ROM) {
503 39d98982 Hannes Reinecke
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
504 39d98982 Hannes Reinecke
                        page_code);
505 39d98982 Hannes Reinecke
                return -1;
506 39d98982 Hannes Reinecke
            }
507 ee3659e3 Christoph Hellwig
            /* required VPD size with unmap support */
508 ee3659e3 Christoph Hellwig
            outbuf[3] = buflen = 0x3c;
509 ee3659e3 Christoph Hellwig
510 ee3659e3 Christoph Hellwig
            memset(outbuf + 4, 0, buflen - 4);
511 ee3659e3 Christoph Hellwig
512 ee3659e3 Christoph Hellwig
            /* optimal transfer length granularity */
513 ee3659e3 Christoph Hellwig
            outbuf[6] = (min_io_size >> 8) & 0xff;
514 ee3659e3 Christoph Hellwig
            outbuf[7] = min_io_size & 0xff;
515 ee3659e3 Christoph Hellwig
516 ee3659e3 Christoph Hellwig
            /* optimal transfer length */
517 ee3659e3 Christoph Hellwig
            outbuf[12] = (opt_io_size >> 24) & 0xff;
518 ee3659e3 Christoph Hellwig
            outbuf[13] = (opt_io_size >> 16) & 0xff;
519 ee3659e3 Christoph Hellwig
            outbuf[14] = (opt_io_size >> 8) & 0xff;
520 ee3659e3 Christoph Hellwig
            outbuf[15] = opt_io_size & 0xff;
521 ea3bd56f Christoph Hellwig
522 ea3bd56f Christoph Hellwig
            /* optimal unmap granularity */
523 ea3bd56f Christoph Hellwig
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
524 ea3bd56f Christoph Hellwig
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
525 ea3bd56f Christoph Hellwig
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
526 ea3bd56f Christoph Hellwig
            outbuf[31] = unmap_sectors & 0xff;
527 ea3bd56f Christoph Hellwig
            break;
528 ea3bd56f Christoph Hellwig
        }
529 ea3bd56f Christoph Hellwig
        case 0xb2: /* thin provisioning */
530 ea3bd56f Christoph Hellwig
        {
531 ea3bd56f Christoph Hellwig
            outbuf[3] = buflen = 8;
532 ea3bd56f Christoph Hellwig
            outbuf[4] = 0;
533 ea3bd56f Christoph Hellwig
            outbuf[5] = 0x40; /* write same with unmap supported */
534 ea3bd56f Christoph Hellwig
            outbuf[6] = 0;
535 ea3bd56f Christoph Hellwig
            outbuf[7] = 0;
536 ee3659e3 Christoph Hellwig
            break;
537 ee3659e3 Christoph Hellwig
        }
538 0b06c059 Gerd Hoffmann
        default:
539 0b06c059 Gerd Hoffmann
            BADF("Error: unsupported Inquiry (EVPD[%02X]) "
540 0b06c059 Gerd Hoffmann
                 "buffer size %zd\n", page_code, req->cmd.xfer);
541 0b06c059 Gerd Hoffmann
            return -1;
542 0b06c059 Gerd Hoffmann
        }
543 0b06c059 Gerd Hoffmann
        /* done with EVPD */
544 0b06c059 Gerd Hoffmann
        return buflen;
545 0b06c059 Gerd Hoffmann
    }
546 0b06c059 Gerd Hoffmann
547 0b06c059 Gerd Hoffmann
    /* Standard INQUIRY data */
548 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[2] != 0) {
549 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) page or code "
550 0b06c059 Gerd Hoffmann
             "is non-zero [%02X]\n", req->cmd.buf[2]);
551 0b06c059 Gerd Hoffmann
        return -1;
552 0b06c059 Gerd Hoffmann
    }
553 0b06c059 Gerd Hoffmann
554 0b06c059 Gerd Hoffmann
    /* PAGE CODE == 0 */
555 0b06c059 Gerd Hoffmann
    if (req->cmd.xfer < 5) {
556 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) buffer size %zd "
557 0b06c059 Gerd Hoffmann
             "is less than 5\n", req->cmd.xfer);
558 0b06c059 Gerd Hoffmann
        return -1;
559 0b06c059 Gerd Hoffmann
    }
560 0b06c059 Gerd Hoffmann
561 0b06c059 Gerd Hoffmann
    buflen = req->cmd.xfer;
562 f01b5931 Paolo Bonzini
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
563 0b06c059 Gerd Hoffmann
        buflen = SCSI_MAX_INQUIRY_LEN;
564 f01b5931 Paolo Bonzini
    }
565 0b06c059 Gerd Hoffmann
    memset(outbuf, 0, buflen);
566 0b06c059 Gerd Hoffmann
567 f37bd73b Hannes Reinecke
    outbuf[0] = s->qdev.type & 0x1f;
568 e39be482 Paolo Bonzini
    outbuf[1] = s->removable ? 0x80 : 0;
569 f37bd73b Hannes Reinecke
    if (s->qdev.type == TYPE_ROM) {
570 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
571 0b06c059 Gerd Hoffmann
    } else {
572 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
573 0b06c059 Gerd Hoffmann
    }
574 550fe6c6 Laszlo Ast
    memcpy(&outbuf[8], "QEMU    ", 8);
575 314b1811 Gerd Hoffmann
    memset(&outbuf[32], 0, 4);
576 552fee93 Markus Armbruster
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
577 99aba0c4 Christoph Hellwig
    /*
578 99aba0c4 Christoph Hellwig
     * We claim conformance to SPC-3, which is required for guests
579 99aba0c4 Christoph Hellwig
     * to ask for modern features like READ CAPACITY(16) or the
580 99aba0c4 Christoph Hellwig
     * block characteristics VPD page by default.  Not all of SPC-3
581 99aba0c4 Christoph Hellwig
     * is actually implemented, but we're good enough.
582 99aba0c4 Christoph Hellwig
     */
583 ee3659e3 Christoph Hellwig
    outbuf[2] = 5;
584 0b06c059 Gerd Hoffmann
    outbuf[3] = 2; /* Format 2 */
585 ad3cea42 Artyom Tarasenko
586 ad3cea42 Artyom Tarasenko
    if (buflen > 36) {
587 ad3cea42 Artyom Tarasenko
        outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
588 ad3cea42 Artyom Tarasenko
    } else {
589 ad3cea42 Artyom Tarasenko
        /* If the allocation length of CDB is too small,
590 ad3cea42 Artyom Tarasenko
               the additional length is not adjusted */
591 ad3cea42 Artyom Tarasenko
        outbuf[4] = 36 - 5;
592 ad3cea42 Artyom Tarasenko
    }
593 ad3cea42 Artyom Tarasenko
594 0b06c059 Gerd Hoffmann
    /* Sync data transfer and TCQ.  */
595 afd4030c Paolo Bonzini
    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
596 0b06c059 Gerd Hoffmann
    return buflen;
597 0b06c059 Gerd Hoffmann
}
598 0b06c059 Gerd Hoffmann
599 430ee2f2 Paolo Bonzini
static inline bool media_is_dvd(SCSIDiskState *s)
600 430ee2f2 Paolo Bonzini
{
601 430ee2f2 Paolo Bonzini
    uint64_t nb_sectors;
602 430ee2f2 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
603 430ee2f2 Paolo Bonzini
        return false;
604 430ee2f2 Paolo Bonzini
    }
605 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
606 430ee2f2 Paolo Bonzini
        return false;
607 430ee2f2 Paolo Bonzini
    }
608 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
609 430ee2f2 Paolo Bonzini
    return nb_sectors > CD_MAX_SECTORS;
610 430ee2f2 Paolo Bonzini
}
611 430ee2f2 Paolo Bonzini
612 ceb792ef Paolo Bonzini
static inline bool media_is_cd(SCSIDiskState *s)
613 ceb792ef Paolo Bonzini
{
614 ceb792ef Paolo Bonzini
    uint64_t nb_sectors;
615 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
616 ceb792ef Paolo Bonzini
        return false;
617 ceb792ef Paolo Bonzini
    }
618 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
619 ceb792ef Paolo Bonzini
        return false;
620 ceb792ef Paolo Bonzini
    }
621 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
622 ceb792ef Paolo Bonzini
    return nb_sectors <= CD_MAX_SECTORS;
623 ceb792ef Paolo Bonzini
}
624 ceb792ef Paolo Bonzini
625 b6c251ab Paolo Bonzini
static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
626 b6c251ab Paolo Bonzini
                                   uint8_t *outbuf)
627 b6c251ab Paolo Bonzini
{
628 ceb792ef Paolo Bonzini
    static const int rds_caps_size[5] = {
629 ceb792ef Paolo Bonzini
        [0] = 2048 + 4,
630 ceb792ef Paolo Bonzini
        [1] = 4 + 4,
631 ceb792ef Paolo Bonzini
        [3] = 188 + 4,
632 ceb792ef Paolo Bonzini
        [4] = 2048 + 4,
633 ceb792ef Paolo Bonzini
    };
634 ceb792ef Paolo Bonzini
635 ceb792ef Paolo Bonzini
    uint8_t media = r->req.cmd.buf[1];
636 ceb792ef Paolo Bonzini
    uint8_t layer = r->req.cmd.buf[6];
637 ceb792ef Paolo Bonzini
    uint8_t format = r->req.cmd.buf[7];
638 ceb792ef Paolo Bonzini
    int size = -1;
639 ceb792ef Paolo Bonzini
640 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
641 ceb792ef Paolo Bonzini
        return -1;
642 ceb792ef Paolo Bonzini
    }
643 ceb792ef Paolo Bonzini
    if (media != 0) {
644 ceb792ef Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
645 ceb792ef Paolo Bonzini
        return -1;
646 ceb792ef Paolo Bonzini
    }
647 ceb792ef Paolo Bonzini
648 ceb792ef Paolo Bonzini
    if (format != 0xff) {
649 44740c38 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
650 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
651 ceb792ef Paolo Bonzini
            return -1;
652 ceb792ef Paolo Bonzini
        }
653 ceb792ef Paolo Bonzini
        if (media_is_cd(s)) {
654 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
655 ceb792ef Paolo Bonzini
            return -1;
656 ceb792ef Paolo Bonzini
        }
657 ceb792ef Paolo Bonzini
        if (format >= ARRAY_SIZE(rds_caps_size)) {
658 ceb792ef Paolo Bonzini
            return -1;
659 ceb792ef Paolo Bonzini
        }
660 ceb792ef Paolo Bonzini
        size = rds_caps_size[format];
661 ceb792ef Paolo Bonzini
        memset(outbuf, 0, size);
662 ceb792ef Paolo Bonzini
    }
663 ceb792ef Paolo Bonzini
664 ceb792ef Paolo Bonzini
    switch (format) {
665 ceb792ef Paolo Bonzini
    case 0x00: {
666 ceb792ef Paolo Bonzini
        /* Physical format information */
667 ceb792ef Paolo Bonzini
        uint64_t nb_sectors;
668 ceb792ef Paolo Bonzini
        if (layer != 0) {
669 ceb792ef Paolo Bonzini
            goto fail;
670 ceb792ef Paolo Bonzini
        }
671 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
672 ceb792ef Paolo Bonzini
673 ceb792ef Paolo Bonzini
        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
674 ceb792ef Paolo Bonzini
        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
675 ceb792ef Paolo Bonzini
        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
676 ceb792ef Paolo Bonzini
        outbuf[7] = 0;   /* default densities */
677 ceb792ef Paolo Bonzini
678 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
679 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
680 ceb792ef Paolo Bonzini
        break;
681 ceb792ef Paolo Bonzini
    }
682 ceb792ef Paolo Bonzini
683 ceb792ef Paolo Bonzini
    case 0x01: /* DVD copyright information, all zeros */
684 ceb792ef Paolo Bonzini
        break;
685 ceb792ef Paolo Bonzini
686 ceb792ef Paolo Bonzini
    case 0x03: /* BCA information - invalid field for no BCA info */
687 ceb792ef Paolo Bonzini
        return -1;
688 ceb792ef Paolo Bonzini
689 ceb792ef Paolo Bonzini
    case 0x04: /* DVD disc manufacturing information, all zeros */
690 ceb792ef Paolo Bonzini
        break;
691 ceb792ef Paolo Bonzini
692 ceb792ef Paolo Bonzini
    case 0xff: { /* List capabilities */
693 ceb792ef Paolo Bonzini
        int i;
694 ceb792ef Paolo Bonzini
        size = 4;
695 ceb792ef Paolo Bonzini
        for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
696 ceb792ef Paolo Bonzini
            if (!rds_caps_size[i]) {
697 ceb792ef Paolo Bonzini
                continue;
698 ceb792ef Paolo Bonzini
            }
699 ceb792ef Paolo Bonzini
            outbuf[size] = i;
700 ceb792ef Paolo Bonzini
            outbuf[size + 1] = 0x40; /* Not writable, readable */
701 ceb792ef Paolo Bonzini
            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
702 ceb792ef Paolo Bonzini
            size += 4;
703 ceb792ef Paolo Bonzini
        }
704 ceb792ef Paolo Bonzini
        break;
705 ceb792ef Paolo Bonzini
     }
706 ceb792ef Paolo Bonzini
707 ceb792ef Paolo Bonzini
    default:
708 ceb792ef Paolo Bonzini
        return -1;
709 ceb792ef Paolo Bonzini
    }
710 ceb792ef Paolo Bonzini
711 ceb792ef Paolo Bonzini
    /* Size of buffer, not including 2 byte size field */
712 ceb792ef Paolo Bonzini
    stw_be_p(outbuf, size - 2);
713 ceb792ef Paolo Bonzini
    return size;
714 ceb792ef Paolo Bonzini
715 ceb792ef Paolo Bonzini
fail:
716 b6c251ab Paolo Bonzini
    return -1;
717 b6c251ab Paolo Bonzini
}
718 b6c251ab Paolo Bonzini
719 3c2f7c12 Paolo Bonzini
static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
720 b6c251ab Paolo Bonzini
{
721 3c2f7c12 Paolo Bonzini
    uint8_t event_code, media_status;
722 3c2f7c12 Paolo Bonzini
723 3c2f7c12 Paolo Bonzini
    media_status = 0;
724 3c2f7c12 Paolo Bonzini
    if (s->tray_open) {
725 3c2f7c12 Paolo Bonzini
        media_status = MS_TRAY_OPEN;
726 44740c38 Paolo Bonzini
    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
727 3c2f7c12 Paolo Bonzini
        media_status = MS_MEDIA_PRESENT;
728 3c2f7c12 Paolo Bonzini
    }
729 3c2f7c12 Paolo Bonzini
730 3c2f7c12 Paolo Bonzini
    /* Event notification descriptor */
731 3c2f7c12 Paolo Bonzini
    event_code = MEC_NO_CHANGE;
732 4480de19 Paolo Bonzini
    if (media_status != MS_TRAY_OPEN) {
733 4480de19 Paolo Bonzini
        if (s->media_event) {
734 4480de19 Paolo Bonzini
            event_code = MEC_NEW_MEDIA;
735 4480de19 Paolo Bonzini
            s->media_event = false;
736 4480de19 Paolo Bonzini
        } else if (s->eject_request) {
737 4480de19 Paolo Bonzini
            event_code = MEC_EJECT_REQUESTED;
738 4480de19 Paolo Bonzini
            s->eject_request = false;
739 4480de19 Paolo Bonzini
        }
740 3c2f7c12 Paolo Bonzini
    }
741 3c2f7c12 Paolo Bonzini
742 3c2f7c12 Paolo Bonzini
    outbuf[0] = event_code;
743 3c2f7c12 Paolo Bonzini
    outbuf[1] = media_status;
744 3c2f7c12 Paolo Bonzini
745 3c2f7c12 Paolo Bonzini
    /* These fields are reserved, just clear them. */
746 3c2f7c12 Paolo Bonzini
    outbuf[2] = 0;
747 3c2f7c12 Paolo Bonzini
    outbuf[3] = 0;
748 3c2f7c12 Paolo Bonzini
    return 4;
749 3c2f7c12 Paolo Bonzini
}
750 3c2f7c12 Paolo Bonzini
751 3c2f7c12 Paolo Bonzini
static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
752 3c2f7c12 Paolo Bonzini
                                              uint8_t *outbuf)
753 3c2f7c12 Paolo Bonzini
{
754 3c2f7c12 Paolo Bonzini
    int size;
755 3c2f7c12 Paolo Bonzini
    uint8_t *buf = r->req.cmd.buf;
756 3c2f7c12 Paolo Bonzini
    uint8_t notification_class_request = buf[4];
757 3c2f7c12 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
758 3c2f7c12 Paolo Bonzini
        return -1;
759 3c2f7c12 Paolo Bonzini
    }
760 3c2f7c12 Paolo Bonzini
    if ((buf[1] & 1) == 0) {
761 3c2f7c12 Paolo Bonzini
        /* asynchronous */
762 3c2f7c12 Paolo Bonzini
        return -1;
763 3c2f7c12 Paolo Bonzini
    }
764 3c2f7c12 Paolo Bonzini
765 3c2f7c12 Paolo Bonzini
    size = 4;
766 3c2f7c12 Paolo Bonzini
    outbuf[0] = outbuf[1] = 0;
767 3c2f7c12 Paolo Bonzini
    outbuf[3] = 1 << GESN_MEDIA; /* supported events */
768 3c2f7c12 Paolo Bonzini
    if (notification_class_request & (1 << GESN_MEDIA)) {
769 3c2f7c12 Paolo Bonzini
        outbuf[2] = GESN_MEDIA;
770 3c2f7c12 Paolo Bonzini
        size += scsi_event_status_media(s, &outbuf[size]);
771 3c2f7c12 Paolo Bonzini
    } else {
772 3c2f7c12 Paolo Bonzini
        outbuf[2] = 0x80;
773 3c2f7c12 Paolo Bonzini
    }
774 3c2f7c12 Paolo Bonzini
    stw_be_p(outbuf, size - 4);
775 3c2f7c12 Paolo Bonzini
    return size;
776 b6c251ab Paolo Bonzini
}
777 b6c251ab Paolo Bonzini
778 430ee2f2 Paolo Bonzini
static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
779 b6c251ab Paolo Bonzini
{
780 430ee2f2 Paolo Bonzini
    int current;
781 430ee2f2 Paolo Bonzini
782 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
783 b6c251ab Paolo Bonzini
        return -1;
784 b6c251ab Paolo Bonzini
    }
785 430ee2f2 Paolo Bonzini
    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
786 430ee2f2 Paolo Bonzini
    memset(outbuf, 0, 40);
787 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
788 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[6], current);
789 430ee2f2 Paolo Bonzini
    /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
790 430ee2f2 Paolo Bonzini
    outbuf[10] = 0x03; /* persistent, current */
791 430ee2f2 Paolo Bonzini
    outbuf[11] = 8; /* two profiles */
792 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
793 430ee2f2 Paolo Bonzini
    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
794 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
795 430ee2f2 Paolo Bonzini
    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
796 430ee2f2 Paolo Bonzini
    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
797 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[20], 1);
798 430ee2f2 Paolo Bonzini
    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
799 430ee2f2 Paolo Bonzini
    outbuf[23] = 8;
800 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[24], 1); /* SCSI */
801 430ee2f2 Paolo Bonzini
    outbuf[28] = 1; /* DBE = 1, mandatory */
802 430ee2f2 Paolo Bonzini
    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
803 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[32], 3);
804 430ee2f2 Paolo Bonzini
    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
805 430ee2f2 Paolo Bonzini
    outbuf[35] = 4;
806 430ee2f2 Paolo Bonzini
    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
807 430ee2f2 Paolo Bonzini
    /* TODO: Random readable, CD read, DVD read, drive serial number,
808 430ee2f2 Paolo Bonzini
       power management */
809 430ee2f2 Paolo Bonzini
    return 40;
810 b6c251ab Paolo Bonzini
}
811 b6c251ab Paolo Bonzini
812 b6c251ab Paolo Bonzini
static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
813 b6c251ab Paolo Bonzini
{
814 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
815 b6c251ab Paolo Bonzini
        return -1;
816 b6c251ab Paolo Bonzini
    }
817 b6c251ab Paolo Bonzini
    memset(outbuf, 0, 8);
818 b6c251ab Paolo Bonzini
    outbuf[5] = 1; /* CD-ROM */
819 b6c251ab Paolo Bonzini
    return 8;
820 b6c251ab Paolo Bonzini
}
821 b6c251ab Paolo Bonzini
822 cfc606da Paolo Bonzini
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
823 282ab04e Bernhard Kohl
                           int page_control)
824 ebddfcbe Gerd Hoffmann
{
825 a8f4bbe2 Paolo Bonzini
    static const int mode_sense_valid[0x3f] = {
826 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
827 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
828 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
829 a07c7dcd Paolo Bonzini
        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
830 a07c7dcd Paolo Bonzini
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
831 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
832 a8f4bbe2 Paolo Bonzini
    };
833 a8f4bbe2 Paolo Bonzini
834 44740c38 Paolo Bonzini
    BlockDriverState *bdrv = s->qdev.conf.bs;
835 ebddfcbe Gerd Hoffmann
    int cylinders, heads, secs;
836 cfc606da Paolo Bonzini
    uint8_t *p = *p_outbuf;
837 ebddfcbe Gerd Hoffmann
838 a8f4bbe2 Paolo Bonzini
    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
839 a8f4bbe2 Paolo Bonzini
        return -1;
840 a8f4bbe2 Paolo Bonzini
    }
841 a8f4bbe2 Paolo Bonzini
842 a8f4bbe2 Paolo Bonzini
    p[0] = page;
843 a8f4bbe2 Paolo Bonzini
844 282ab04e Bernhard Kohl
    /*
845 282ab04e Bernhard Kohl
     * If Changeable Values are requested, a mask denoting those mode parameters
846 282ab04e Bernhard Kohl
     * that are changeable shall be returned. As we currently don't support
847 282ab04e Bernhard Kohl
     * parameter changes via MODE_SELECT all bits are returned set to zero.
848 282ab04e Bernhard Kohl
     * The buffer was already menset to zero by the caller of this function.
849 282ab04e Bernhard Kohl
     */
850 ebddfcbe Gerd Hoffmann
    switch (page) {
851 67cc61e4 Paolo Bonzini
    case MODE_PAGE_HD_GEOMETRY:
852 ebddfcbe Gerd Hoffmann
        p[1] = 0x16;
853 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
854 cfc606da Paolo Bonzini
            break;
855 282ab04e Bernhard Kohl
        }
856 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
857 245d0049 Paolo Bonzini
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
858 ebddfcbe Gerd Hoffmann
        p[2] = (cylinders >> 16) & 0xff;
859 ebddfcbe Gerd Hoffmann
        p[3] = (cylinders >> 8) & 0xff;
860 ebddfcbe Gerd Hoffmann
        p[4] = cylinders & 0xff;
861 ebddfcbe Gerd Hoffmann
        p[5] = heads & 0xff;
862 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
863 ebddfcbe Gerd Hoffmann
        p[6] = (cylinders >> 16) & 0xff;
864 ebddfcbe Gerd Hoffmann
        p[7] = (cylinders >> 8) & 0xff;
865 ebddfcbe Gerd Hoffmann
        p[8] = cylinders & 0xff;
866 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
867 ebddfcbe Gerd Hoffmann
        p[9] = (cylinders >> 16) & 0xff;
868 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
869 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
870 ebddfcbe Gerd Hoffmann
        /* Device step rate [ns], 200ns */
871 ebddfcbe Gerd Hoffmann
        p[12] = 0;
872 ebddfcbe Gerd Hoffmann
        p[13] = 200;
873 ebddfcbe Gerd Hoffmann
        /* Landing zone cylinder */
874 ebddfcbe Gerd Hoffmann
        p[14] = 0xff;
875 ebddfcbe Gerd Hoffmann
        p[15] =  0xff;
876 ebddfcbe Gerd Hoffmann
        p[16] = 0xff;
877 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
878 ebddfcbe Gerd Hoffmann
        p[20] = (5400 >> 8) & 0xff;
879 ebddfcbe Gerd Hoffmann
        p[21] = 5400 & 0xff;
880 cfc606da Paolo Bonzini
        break;
881 ebddfcbe Gerd Hoffmann
882 67cc61e4 Paolo Bonzini
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
883 ebddfcbe Gerd Hoffmann
        p[1] = 0x1e;
884 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
885 cfc606da Paolo Bonzini
            break;
886 282ab04e Bernhard Kohl
        }
887 ebddfcbe Gerd Hoffmann
        /* Transfer rate [kbit/s], 5Mbit/s */
888 ebddfcbe Gerd Hoffmann
        p[2] = 5000 >> 8;
889 ebddfcbe Gerd Hoffmann
        p[3] = 5000 & 0xff;
890 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
891 245d0049 Paolo Bonzini
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
892 ebddfcbe Gerd Hoffmann
        p[4] = heads & 0xff;
893 ebddfcbe Gerd Hoffmann
        p[5] = secs & 0xff;
894 69377307 Paolo Bonzini
        p[6] = s->qdev.blocksize >> 8;
895 ebddfcbe Gerd Hoffmann
        p[8] = (cylinders >> 8) & 0xff;
896 ebddfcbe Gerd Hoffmann
        p[9] = cylinders & 0xff;
897 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
898 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
899 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
900 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
901 ebddfcbe Gerd Hoffmann
        p[12] = (cylinders >> 8) & 0xff;
902 ebddfcbe Gerd Hoffmann
        p[13] = cylinders & 0xff;
903 ebddfcbe Gerd Hoffmann
        /* Device step rate [100us], 100us */
904 ebddfcbe Gerd Hoffmann
        p[14] = 0;
905 ebddfcbe Gerd Hoffmann
        p[15] = 1;
906 ebddfcbe Gerd Hoffmann
        /* Device step pulse width [us], 1us */
907 ebddfcbe Gerd Hoffmann
        p[16] = 1;
908 ebddfcbe Gerd Hoffmann
        /* Device head settle delay [100us], 100us */
909 ebddfcbe Gerd Hoffmann
        p[17] = 0;
910 ebddfcbe Gerd Hoffmann
        p[18] = 1;
911 ebddfcbe Gerd Hoffmann
        /* Motor on delay [0.1s], 0.1s */
912 ebddfcbe Gerd Hoffmann
        p[19] = 1;
913 ebddfcbe Gerd Hoffmann
        /* Motor off delay [0.1s], 0.1s */
914 ebddfcbe Gerd Hoffmann
        p[20] = 1;
915 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
916 ebddfcbe Gerd Hoffmann
        p[28] = (5400 >> 8) & 0xff;
917 ebddfcbe Gerd Hoffmann
        p[29] = 5400 & 0xff;
918 cfc606da Paolo Bonzini
        break;
919 ebddfcbe Gerd Hoffmann
920 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CACHING:
921 ebddfcbe Gerd Hoffmann
        p[0] = 8;
922 ebddfcbe Gerd Hoffmann
        p[1] = 0x12;
923 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
924 cfc606da Paolo Bonzini
            break;
925 282ab04e Bernhard Kohl
        }
926 44740c38 Paolo Bonzini
        if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
927 ebddfcbe Gerd Hoffmann
            p[2] = 4; /* WCE */
928 ebddfcbe Gerd Hoffmann
        }
929 cfc606da Paolo Bonzini
        break;
930 ebddfcbe Gerd Hoffmann
931 a07c7dcd Paolo Bonzini
    case MODE_PAGE_R_W_ERROR:
932 a07c7dcd Paolo Bonzini
        p[1] = 10;
933 a07c7dcd Paolo Bonzini
        p[2] = 0x80; /* Automatic Write Reallocation Enabled */
934 a07c7dcd Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
935 a07c7dcd Paolo Bonzini
            p[3] = 0x20; /* Read Retry Count */
936 a07c7dcd Paolo Bonzini
        }
937 a07c7dcd Paolo Bonzini
        break;
938 a07c7dcd Paolo Bonzini
939 a07c7dcd Paolo Bonzini
    case MODE_PAGE_AUDIO_CTL:
940 a07c7dcd Paolo Bonzini
        p[1] = 14;
941 a07c7dcd Paolo Bonzini
        break;
942 a07c7dcd Paolo Bonzini
943 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CAPABILITIES:
944 ebddfcbe Gerd Hoffmann
        p[1] = 0x14;
945 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
946 cfc606da Paolo Bonzini
            break;
947 282ab04e Bernhard Kohl
        }
948 a07c7dcd Paolo Bonzini
949 a07c7dcd Paolo Bonzini
        p[2] = 0x3b; /* CD-R & CD-RW read */
950 a07c7dcd Paolo Bonzini
        p[3] = 0; /* Writing not supported */
951 ebddfcbe Gerd Hoffmann
        p[4] = 0x7f; /* Audio, composite, digital out,
952 ebddfcbe Gerd Hoffmann
                        mode 2 form 1&2, multi session */
953 ebddfcbe Gerd Hoffmann
        p[5] = 0xff; /* CD DA, DA accurate, RW supported,
954 ebddfcbe Gerd Hoffmann
                        RW corrected, C2 errors, ISRC,
955 ebddfcbe Gerd Hoffmann
                        UPC, Bar code */
956 81b1008d Markus Armbruster
        p[6] = 0x2d | (s->tray_locked ? 2 : 0);
957 ebddfcbe Gerd Hoffmann
        /* Locking supported, jumper present, eject, tray */
958 ebddfcbe Gerd Hoffmann
        p[7] = 0; /* no volume & mute control, no
959 ebddfcbe Gerd Hoffmann
                     changer */
960 a07c7dcd Paolo Bonzini
        p[8] = (50 * 176) >> 8; /* 50x read speed */
961 ebddfcbe Gerd Hoffmann
        p[9] = (50 * 176) & 0xff;
962 a07c7dcd Paolo Bonzini
        p[10] = 2 >> 8; /* Two volume levels */
963 a07c7dcd Paolo Bonzini
        p[11] = 2 & 0xff;
964 a07c7dcd Paolo Bonzini
        p[12] = 2048 >> 8; /* 2M buffer */
965 ebddfcbe Gerd Hoffmann
        p[13] = 2048 & 0xff;
966 a07c7dcd Paolo Bonzini
        p[14] = (16 * 176) >> 8; /* 16x read speed current */
967 ebddfcbe Gerd Hoffmann
        p[15] = (16 * 176) & 0xff;
968 a07c7dcd Paolo Bonzini
        p[18] = (16 * 176) >> 8; /* 16x write speed */
969 ebddfcbe Gerd Hoffmann
        p[19] = (16 * 176) & 0xff;
970 a07c7dcd Paolo Bonzini
        p[20] = (16 * 176) >> 8; /* 16x write speed current */
971 ebddfcbe Gerd Hoffmann
        p[21] = (16 * 176) & 0xff;
972 cfc606da Paolo Bonzini
        break;
973 ebddfcbe Gerd Hoffmann
974 ebddfcbe Gerd Hoffmann
    default:
975 cfc606da Paolo Bonzini
        return -1;
976 ebddfcbe Gerd Hoffmann
    }
977 cfc606da Paolo Bonzini
978 cfc606da Paolo Bonzini
    *p_outbuf += p[1] + 2;
979 cfc606da Paolo Bonzini
    return p[1] + 2;
980 ebddfcbe Gerd Hoffmann
}
981 ebddfcbe Gerd Hoffmann
982 cfc606da Paolo Bonzini
static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
983 ebddfcbe Gerd Hoffmann
{
984 cfc606da Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
985 ebddfcbe Gerd Hoffmann
    uint64_t nb_sectors;
986 cfc606da Paolo Bonzini
    int page, dbd, buflen, ret, page_control;
987 ebddfcbe Gerd Hoffmann
    uint8_t *p;
988 ce512ee1 Bernhard Kohl
    uint8_t dev_specific_param;
989 ebddfcbe Gerd Hoffmann
990 cfc606da Paolo Bonzini
    dbd = r->req.cmd.buf[1]  & 0x8;
991 cfc606da Paolo Bonzini
    page = r->req.cmd.buf[2] & 0x3f;
992 cfc606da Paolo Bonzini
    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
993 aa2b1e89 Bernhard Kohl
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
994 cfc606da Paolo Bonzini
        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
995 cfc606da Paolo Bonzini
    memset(outbuf, 0, r->req.cmd.xfer);
996 ebddfcbe Gerd Hoffmann
    p = outbuf;
997 ebddfcbe Gerd Hoffmann
998 44740c38 Paolo Bonzini
    if (bdrv_is_read_only(s->qdev.conf.bs)) {
999 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x80; /* Readonly.  */
1000 ce512ee1 Bernhard Kohl
    } else {
1001 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x00;
1002 ce512ee1 Bernhard Kohl
    }
1003 ce512ee1 Bernhard Kohl
1004 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1005 ce512ee1 Bernhard Kohl
        p[1] = 0; /* Default media type.  */
1006 ce512ee1 Bernhard Kohl
        p[2] = dev_specific_param;
1007 ce512ee1 Bernhard Kohl
        p[3] = 0; /* Block descriptor length.  */
1008 ce512ee1 Bernhard Kohl
        p += 4;
1009 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1010 ce512ee1 Bernhard Kohl
        p[2] = 0; /* Default media type.  */
1011 ce512ee1 Bernhard Kohl
        p[3] = dev_specific_param;
1012 ce512ee1 Bernhard Kohl
        p[6] = p[7] = 0; /* Block descriptor length.  */
1013 ce512ee1 Bernhard Kohl
        p += 8;
1014 ebddfcbe Gerd Hoffmann
    }
1015 ebddfcbe Gerd Hoffmann
1016 0fd76ff4 Paolo Bonzini
    /* MMC prescribes that CD/DVD drives have no block descriptors.  */
1017 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1018 0fd76ff4 Paolo Bonzini
    if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
1019 cfc606da Paolo Bonzini
        if (r->req.cmd.buf[0] == MODE_SENSE) {
1020 ce512ee1 Bernhard Kohl
            outbuf[3] = 8; /* Block descriptor length  */
1021 ce512ee1 Bernhard Kohl
        } else { /* MODE_SENSE_10 */
1022 ce512ee1 Bernhard Kohl
            outbuf[7] = 8; /* Block descriptor length  */
1023 ce512ee1 Bernhard Kohl
        }
1024 69377307 Paolo Bonzini
        nb_sectors /= (s->qdev.blocksize / 512);
1025 f01b5931 Paolo Bonzini
        if (nb_sectors > 0xffffff) {
1026 2488b740 Bernhard Kohl
            nb_sectors = 0;
1027 f01b5931 Paolo Bonzini
        }
1028 ebddfcbe Gerd Hoffmann
        p[0] = 0; /* media density code */
1029 ebddfcbe Gerd Hoffmann
        p[1] = (nb_sectors >> 16) & 0xff;
1030 ebddfcbe Gerd Hoffmann
        p[2] = (nb_sectors >> 8) & 0xff;
1031 ebddfcbe Gerd Hoffmann
        p[3] = nb_sectors & 0xff;
1032 ebddfcbe Gerd Hoffmann
        p[4] = 0; /* reserved */
1033 ebddfcbe Gerd Hoffmann
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
1034 69377307 Paolo Bonzini
        p[6] = s->qdev.blocksize >> 8;
1035 ebddfcbe Gerd Hoffmann
        p[7] = 0;
1036 ebddfcbe Gerd Hoffmann
        p += 8;
1037 ebddfcbe Gerd Hoffmann
    }
1038 ebddfcbe Gerd Hoffmann
1039 cfc606da Paolo Bonzini
    if (page_control == 3) {
1040 cfc606da Paolo Bonzini
        /* Saved Values */
1041 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
1042 cfc606da Paolo Bonzini
        return -1;
1043 282ab04e Bernhard Kohl
    }
1044 282ab04e Bernhard Kohl
1045 cfc606da Paolo Bonzini
    if (page == 0x3f) {
1046 cfc606da Paolo Bonzini
        for (page = 0; page <= 0x3e; page++) {
1047 cfc606da Paolo Bonzini
            mode_sense_page(s, page, &p, page_control);
1048 cfc606da Paolo Bonzini
        }
1049 cfc606da Paolo Bonzini
    } else {
1050 cfc606da Paolo Bonzini
        ret = mode_sense_page(s, page, &p, page_control);
1051 cfc606da Paolo Bonzini
        if (ret == -1) {
1052 cfc606da Paolo Bonzini
            return -1;
1053 cfc606da Paolo Bonzini
        }
1054 ebddfcbe Gerd Hoffmann
    }
1055 ebddfcbe Gerd Hoffmann
1056 ebddfcbe Gerd Hoffmann
    buflen = p - outbuf;
1057 ce512ee1 Bernhard Kohl
    /*
1058 ce512ee1 Bernhard Kohl
     * The mode data length field specifies the length in bytes of the
1059 ce512ee1 Bernhard Kohl
     * following data that is available to be transferred. The mode data
1060 ce512ee1 Bernhard Kohl
     * length does not include itself.
1061 ce512ee1 Bernhard Kohl
     */
1062 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1063 ce512ee1 Bernhard Kohl
        outbuf[0] = buflen - 1;
1064 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1065 ce512ee1 Bernhard Kohl
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1066 ce512ee1 Bernhard Kohl
        outbuf[1] = (buflen - 2) & 0xff;
1067 ce512ee1 Bernhard Kohl
    }
1068 ebddfcbe Gerd Hoffmann
    return buflen;
1069 ebddfcbe Gerd Hoffmann
}
1070 ebddfcbe Gerd Hoffmann
1071 02880f43 Gerd Hoffmann
static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1072 02880f43 Gerd Hoffmann
{
1073 02880f43 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1074 02880f43 Gerd Hoffmann
    int start_track, format, msf, toclen;
1075 02880f43 Gerd Hoffmann
    uint64_t nb_sectors;
1076 02880f43 Gerd Hoffmann
1077 02880f43 Gerd Hoffmann
    msf = req->cmd.buf[1] & 2;
1078 02880f43 Gerd Hoffmann
    format = req->cmd.buf[2] & 0xf;
1079 02880f43 Gerd Hoffmann
    start_track = req->cmd.buf[6];
1080 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1081 02880f43 Gerd Hoffmann
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
1082 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1083 02880f43 Gerd Hoffmann
    switch (format) {
1084 02880f43 Gerd Hoffmann
    case 0:
1085 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1086 02880f43 Gerd Hoffmann
        break;
1087 02880f43 Gerd Hoffmann
    case 1:
1088 02880f43 Gerd Hoffmann
        /* multi session : only a single session defined */
1089 02880f43 Gerd Hoffmann
        toclen = 12;
1090 02880f43 Gerd Hoffmann
        memset(outbuf, 0, 12);
1091 02880f43 Gerd Hoffmann
        outbuf[1] = 0x0a;
1092 02880f43 Gerd Hoffmann
        outbuf[2] = 0x01;
1093 02880f43 Gerd Hoffmann
        outbuf[3] = 0x01;
1094 02880f43 Gerd Hoffmann
        break;
1095 02880f43 Gerd Hoffmann
    case 2:
1096 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1097 02880f43 Gerd Hoffmann
        break;
1098 02880f43 Gerd Hoffmann
    default:
1099 02880f43 Gerd Hoffmann
        return -1;
1100 02880f43 Gerd Hoffmann
    }
1101 02880f43 Gerd Hoffmann
    return toclen;
1102 02880f43 Gerd Hoffmann
}
1103 02880f43 Gerd Hoffmann
1104 68bb01f3 Markus Armbruster
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
1105 bfd52647 Markus Armbruster
{
1106 bfd52647 Markus Armbruster
    SCSIRequest *req = &r->req;
1107 bfd52647 Markus Armbruster
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1108 bfd52647 Markus Armbruster
    bool start = req->cmd.buf[4] & 1;
1109 bfd52647 Markus Armbruster
    bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
1110 bfd52647 Markus Armbruster
1111 bfd52647 Markus Armbruster
    if (s->qdev.type == TYPE_ROM && loej) {
1112 68bb01f3 Markus Armbruster
        if (!start && !s->tray_open && s->tray_locked) {
1113 68bb01f3 Markus Armbruster
            scsi_check_condition(r,
1114 44740c38 Paolo Bonzini
                                 bdrv_is_inserted(s->qdev.conf.bs)
1115 68bb01f3 Markus Armbruster
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1116 68bb01f3 Markus Armbruster
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1117 68bb01f3 Markus Armbruster
            return -1;
1118 fdec4404 Markus Armbruster
        }
1119 d88b1819 Luiz Capitulino
1120 d88b1819 Luiz Capitulino
        if (s->tray_open != !start) {
1121 d88b1819 Luiz Capitulino
            bdrv_eject(s->qdev.conf.bs, !start);
1122 d88b1819 Luiz Capitulino
            s->tray_open = !start;
1123 d88b1819 Luiz Capitulino
        }
1124 bfd52647 Markus Armbruster
    }
1125 68bb01f3 Markus Armbruster
    return 0;
1126 bfd52647 Markus Armbruster
}
1127 bfd52647 Markus Armbruster
1128 7285477a Paolo Bonzini
static int scsi_disk_emulate_command(SCSIDiskReq *r)
1129 aa5dbdc1 Gerd Hoffmann
{
1130 8af7a3ab Kevin Wolf
    SCSIRequest *req = &r->req;
1131 e7e25e32 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1132 e7e25e32 Gerd Hoffmann
    uint64_t nb_sectors;
1133 7285477a Paolo Bonzini
    uint8_t *outbuf;
1134 aa5dbdc1 Gerd Hoffmann
    int buflen = 0;
1135 aa5dbdc1 Gerd Hoffmann
1136 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
1137 7285477a Paolo Bonzini
        /*
1138 7285477a Paolo Bonzini
         * FIXME: we shouldn't return anything bigger than 4k, but the code
1139 7285477a Paolo Bonzini
         * requires the buffer to be as big as req->cmd.xfer in several
1140 7285477a Paolo Bonzini
         * places.  So, do not allow CDBs with a very large ALLOCATION
1141 7285477a Paolo Bonzini
         * LENGTH.  The real fix would be to modify scsi_read_data and
1142 7285477a Paolo Bonzini
         * dma_buf_read, so that they return data beyond the buflen
1143 7285477a Paolo Bonzini
         * as all zeros.
1144 7285477a Paolo Bonzini
         */
1145 7285477a Paolo Bonzini
        if (req->cmd.xfer > 65536) {
1146 7285477a Paolo Bonzini
            goto illegal_request;
1147 7285477a Paolo Bonzini
        }
1148 7285477a Paolo Bonzini
        r->buflen = MAX(4096, req->cmd.xfer);
1149 44740c38 Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
1150 7285477a Paolo Bonzini
    }
1151 7285477a Paolo Bonzini
1152 7285477a Paolo Bonzini
    outbuf = r->iov.iov_base;
1153 aa5dbdc1 Gerd Hoffmann
    switch (req->cmd.buf[0]) {
1154 aa5dbdc1 Gerd Hoffmann
    case TEST_UNIT_READY:
1155 44740c38 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1156 aa5dbdc1 Gerd Hoffmann
            goto not_ready;
1157 f01b5931 Paolo Bonzini
        }
1158 5f71d32f Hannes Reinecke
        break;
1159 0b06c059 Gerd Hoffmann
    case INQUIRY:
1160 0b06c059 Gerd Hoffmann
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
1161 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1162 0b06c059 Gerd Hoffmann
            goto illegal_request;
1163 f01b5931 Paolo Bonzini
        }
1164 5f71d32f Hannes Reinecke
        break;
1165 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1166 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1167 cfc606da Paolo Bonzini
        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
1168 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1169 ebddfcbe Gerd Hoffmann
            goto illegal_request;
1170 f01b5931 Paolo Bonzini
        }
1171 ebddfcbe Gerd Hoffmann
        break;
1172 02880f43 Gerd Hoffmann
    case READ_TOC:
1173 02880f43 Gerd Hoffmann
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
1174 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1175 02880f43 Gerd Hoffmann
            goto illegal_request;
1176 f01b5931 Paolo Bonzini
        }
1177 02880f43 Gerd Hoffmann
        break;
1178 3d53ba18 Gerd Hoffmann
    case RESERVE:
1179 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1180 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1181 f01b5931 Paolo Bonzini
        }
1182 3d53ba18 Gerd Hoffmann
        break;
1183 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1184 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1185 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1186 f01b5931 Paolo Bonzini
        }
1187 3d53ba18 Gerd Hoffmann
        break;
1188 3d53ba18 Gerd Hoffmann
    case RELEASE:
1189 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1190 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1191 f01b5931 Paolo Bonzini
        }
1192 3d53ba18 Gerd Hoffmann
        break;
1193 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1194 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1195 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1196 f01b5931 Paolo Bonzini
        }
1197 3d53ba18 Gerd Hoffmann
        break;
1198 8d3628ff Gerd Hoffmann
    case START_STOP:
1199 68bb01f3 Markus Armbruster
        if (scsi_disk_emulate_start_stop(r) < 0) {
1200 68bb01f3 Markus Armbruster
            return -1;
1201 68bb01f3 Markus Armbruster
        }
1202 5f71d32f Hannes Reinecke
        break;
1203 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1204 81b1008d Markus Armbruster
        s->tray_locked = req->cmd.buf[4] & 1;
1205 44740c38 Paolo Bonzini
        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
1206 5f71d32f Hannes Reinecke
        break;
1207 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1208 e7e25e32 Gerd Hoffmann
        /* The normal LEN field for this command is zero.  */
1209 5f71d32f Hannes Reinecke
        memset(outbuf, 0, 8);
1210 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1211 f01b5931 Paolo Bonzini
        if (!nb_sectors) {
1212 e7e25e32 Gerd Hoffmann
            goto not_ready;
1213 f01b5931 Paolo Bonzini
        }
1214 7cec78b6 Paolo Bonzini
        if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
1215 7cec78b6 Paolo Bonzini
            goto illegal_request;
1216 7cec78b6 Paolo Bonzini
        }
1217 69377307 Paolo Bonzini
        nb_sectors /= s->qdev.blocksize / 512;
1218 e7e25e32 Gerd Hoffmann
        /* Returned value is the address of the last sector.  */
1219 e7e25e32 Gerd Hoffmann
        nb_sectors--;
1220 e7e25e32 Gerd Hoffmann
        /* Remember the new size for read/write sanity checking. */
1221 7877903a Paolo Bonzini
        s->qdev.max_lba = nb_sectors;
1222 e7e25e32 Gerd Hoffmann
        /* Clip to 2TB, instead of returning capacity modulo 2TB. */
1223 f01b5931 Paolo Bonzini
        if (nb_sectors > UINT32_MAX) {
1224 e7e25e32 Gerd Hoffmann
            nb_sectors = UINT32_MAX;
1225 f01b5931 Paolo Bonzini
        }
1226 e7e25e32 Gerd Hoffmann
        outbuf[0] = (nb_sectors >> 24) & 0xff;
1227 e7e25e32 Gerd Hoffmann
        outbuf[1] = (nb_sectors >> 16) & 0xff;
1228 e7e25e32 Gerd Hoffmann
        outbuf[2] = (nb_sectors >> 8) & 0xff;
1229 e7e25e32 Gerd Hoffmann
        outbuf[3] = nb_sectors & 0xff;
1230 e7e25e32 Gerd Hoffmann
        outbuf[4] = 0;
1231 e7e25e32 Gerd Hoffmann
        outbuf[5] = 0;
1232 69377307 Paolo Bonzini
        outbuf[6] = s->qdev.blocksize >> 8;
1233 e7e25e32 Gerd Hoffmann
        outbuf[7] = 0;
1234 e7e25e32 Gerd Hoffmann
        buflen = 8;
1235 5f71d32f Hannes Reinecke
        break;
1236 f3b338ef Paolo Bonzini
    case REQUEST_SENSE:
1237 f3b338ef Paolo Bonzini
        /* Just return "NO SENSE".  */
1238 f3b338ef Paolo Bonzini
        buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
1239 f3b338ef Paolo Bonzini
                                  (req->cmd.buf[1] & 1) == 0);
1240 f3b338ef Paolo Bonzini
        break;
1241 b6c251ab Paolo Bonzini
    case MECHANISM_STATUS:
1242 b6c251ab Paolo Bonzini
        buflen = scsi_emulate_mechanism_status(s, outbuf);
1243 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1244 b6c251ab Paolo Bonzini
            goto illegal_request;
1245 b6c251ab Paolo Bonzini
        }
1246 b6c251ab Paolo Bonzini
        break;
1247 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
1248 430ee2f2 Paolo Bonzini
        buflen = scsi_get_configuration(s, outbuf);
1249 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1250 b6c251ab Paolo Bonzini
            goto illegal_request;
1251 b6c251ab Paolo Bonzini
        }
1252 b6c251ab Paolo Bonzini
        break;
1253 b6c251ab Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1254 b6c251ab Paolo Bonzini
        buflen = scsi_get_event_status_notification(s, r, outbuf);
1255 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1256 b6c251ab Paolo Bonzini
            goto illegal_request;
1257 b6c251ab Paolo Bonzini
        }
1258 b6c251ab Paolo Bonzini
        break;
1259 b6c251ab Paolo Bonzini
    case READ_DVD_STRUCTURE:
1260 b6c251ab Paolo Bonzini
        buflen = scsi_read_dvd_structure(s, r, outbuf);
1261 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1262 b6c251ab Paolo Bonzini
            goto illegal_request;
1263 b6c251ab Paolo Bonzini
        }
1264 38215553 Gerd Hoffmann
        break;
1265 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
1266 5dd90e2a Gerd Hoffmann
        /* Service Action In subcommands. */
1267 f6515262 Paolo Bonzini
        if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
1268 5dd90e2a Gerd Hoffmann
            DPRINTF("SAI READ CAPACITY(16)\n");
1269 5dd90e2a Gerd Hoffmann
            memset(outbuf, 0, req->cmd.xfer);
1270 44740c38 Paolo Bonzini
            bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1271 f01b5931 Paolo Bonzini
            if (!nb_sectors) {
1272 5dd90e2a Gerd Hoffmann
                goto not_ready;
1273 f01b5931 Paolo Bonzini
            }
1274 7cec78b6 Paolo Bonzini
            if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1275 7cec78b6 Paolo Bonzini
                goto illegal_request;
1276 7cec78b6 Paolo Bonzini
            }
1277 69377307 Paolo Bonzini
            nb_sectors /= s->qdev.blocksize / 512;
1278 5dd90e2a Gerd Hoffmann
            /* Returned value is the address of the last sector.  */
1279 5dd90e2a Gerd Hoffmann
            nb_sectors--;
1280 5dd90e2a Gerd Hoffmann
            /* Remember the new size for read/write sanity checking. */
1281 7877903a Paolo Bonzini
            s->qdev.max_lba = nb_sectors;
1282 5dd90e2a Gerd Hoffmann
            outbuf[0] = (nb_sectors >> 56) & 0xff;
1283 5dd90e2a Gerd Hoffmann
            outbuf[1] = (nb_sectors >> 48) & 0xff;
1284 5dd90e2a Gerd Hoffmann
            outbuf[2] = (nb_sectors >> 40) & 0xff;
1285 5dd90e2a Gerd Hoffmann
            outbuf[3] = (nb_sectors >> 32) & 0xff;
1286 5dd90e2a Gerd Hoffmann
            outbuf[4] = (nb_sectors >> 24) & 0xff;
1287 5dd90e2a Gerd Hoffmann
            outbuf[5] = (nb_sectors >> 16) & 0xff;
1288 5dd90e2a Gerd Hoffmann
            outbuf[6] = (nb_sectors >> 8) & 0xff;
1289 5dd90e2a Gerd Hoffmann
            outbuf[7] = nb_sectors & 0xff;
1290 5dd90e2a Gerd Hoffmann
            outbuf[8] = 0;
1291 5dd90e2a Gerd Hoffmann
            outbuf[9] = 0;
1292 69377307 Paolo Bonzini
            outbuf[10] = s->qdev.blocksize >> 8;
1293 5dd90e2a Gerd Hoffmann
            outbuf[11] = 0;
1294 ee3659e3 Christoph Hellwig
            outbuf[12] = 0;
1295 ee3659e3 Christoph Hellwig
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
1296 ea3bd56f Christoph Hellwig
1297 ea3bd56f Christoph Hellwig
            /* set TPE bit if the format supports discard */
1298 ea3bd56f Christoph Hellwig
            if (s->qdev.conf.discard_granularity) {
1299 ea3bd56f Christoph Hellwig
                outbuf[14] = 0x80;
1300 ea3bd56f Christoph Hellwig
            }
1301 ea3bd56f Christoph Hellwig
1302 5dd90e2a Gerd Hoffmann
            /* Protection, exponent and lowest lba field left blank. */
1303 5dd90e2a Gerd Hoffmann
            buflen = req->cmd.xfer;
1304 5dd90e2a Gerd Hoffmann
            break;
1305 5dd90e2a Gerd Hoffmann
        }
1306 5dd90e2a Gerd Hoffmann
        DPRINTF("Unsupported Service Action In\n");
1307 5dd90e2a Gerd Hoffmann
        goto illegal_request;
1308 5e30a07d Hannes Reinecke
    case VERIFY_10:
1309 88f8a5ed Gerd Hoffmann
        break;
1310 aa5dbdc1 Gerd Hoffmann
    default:
1311 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1312 a1f0cce2 Hannes Reinecke
        return -1;
1313 aa5dbdc1 Gerd Hoffmann
    }
1314 e2f0c49f Thomas Higdon
    buflen = MIN(buflen, req->cmd.xfer);
1315 aa5dbdc1 Gerd Hoffmann
    return buflen;
1316 aa5dbdc1 Gerd Hoffmann
1317 aa5dbdc1 Gerd Hoffmann
not_ready:
1318 44740c38 Paolo Bonzini
    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1319 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1320 a1f0cce2 Hannes Reinecke
    } else {
1321 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1322 a1f0cce2 Hannes Reinecke
    }
1323 8af7a3ab Kevin Wolf
    return -1;
1324 aa5dbdc1 Gerd Hoffmann
1325 aa5dbdc1 Gerd Hoffmann
illegal_request:
1326 cfc606da Paolo Bonzini
    if (r->req.status == -1) {
1327 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1328 cfc606da Paolo Bonzini
    }
1329 8af7a3ab Kevin Wolf
    return -1;
1330 aa5dbdc1 Gerd Hoffmann
}
1331 aa5dbdc1 Gerd Hoffmann
1332 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
1333 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
1334 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
1335 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
1336 2e5d83bb pbrook
1337 5c6c0e51 Hannes Reinecke
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
1338 2e5d83bb pbrook
{
1339 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1340 5c6c0e51 Hannes Reinecke
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1341 ad2d30f7 Paolo Bonzini
    int32_t len;
1342 a917d384 pbrook
    uint8_t command;
1343 aa5dbdc1 Gerd Hoffmann
    int rc;
1344 a917d384 pbrook
1345 a917d384 pbrook
    command = buf[0];
1346 653c1c3f Hannes Reinecke
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
1347 2dd791b6 Hannes Reinecke
1348 2e5d83bb pbrook
#ifdef DEBUG_SCSI
1349 2e5d83bb pbrook
    {
1350 2e5d83bb pbrook
        int i;
1351 2dd791b6 Hannes Reinecke
        for (i = 1; i < r->req.cmd.len; i++) {
1352 2e5d83bb pbrook
            printf(" 0x%02x", buf[i]);
1353 2e5d83bb pbrook
        }
1354 2e5d83bb pbrook
        printf("\n");
1355 2e5d83bb pbrook
    }
1356 2e5d83bb pbrook
#endif
1357 aa5dbdc1 Gerd Hoffmann
1358 a917d384 pbrook
    switch (command) {
1359 ebf46023 Gerd Hoffmann
    case TEST_UNIT_READY:
1360 0b06c059 Gerd Hoffmann
    case INQUIRY:
1361 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1362 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1363 3d53ba18 Gerd Hoffmann
    case RESERVE:
1364 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1365 3d53ba18 Gerd Hoffmann
    case RELEASE:
1366 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1367 8d3628ff Gerd Hoffmann
    case START_STOP:
1368 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1369 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1370 02880f43 Gerd Hoffmann
    case READ_TOC:
1371 b6c251ab Paolo Bonzini
    case READ_DVD_STRUCTURE:
1372 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
1373 b6c251ab Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1374 b6c251ab Paolo Bonzini
    case MECHANISM_STATUS:
1375 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
1376 f3b338ef Paolo Bonzini
    case REQUEST_SENSE:
1377 5e30a07d Hannes Reinecke
    case VERIFY_10:
1378 7285477a Paolo Bonzini
        rc = scsi_disk_emulate_command(r);
1379 8af7a3ab Kevin Wolf
        if (rc < 0) {
1380 0b06c059 Gerd Hoffmann
            return 0;
1381 aa5dbdc1 Gerd Hoffmann
        }
1382 8af7a3ab Kevin Wolf
1383 8af7a3ab Kevin Wolf
        r->iov.iov_len = rc;
1384 0b06c059 Gerd Hoffmann
        break;
1385 0a4ac106 Paolo Bonzini
    case SYNCHRONIZE_CACHE:
1386 c7bae6a7 Paolo Bonzini
        /* The request is used as the AIO opaque value, so add a ref.  */
1387 c7bae6a7 Paolo Bonzini
        scsi_req_ref(&r->req);
1388 44740c38 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1389 44740c38 Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
1390 0a4ac106 Paolo Bonzini
        return 0;
1391 ebf46023 Gerd Hoffmann
    case READ_6:
1392 ebf46023 Gerd Hoffmann
    case READ_10:
1393 bd536cf3 Gerd Hoffmann
    case READ_12:
1394 bd536cf3 Gerd Hoffmann
    case READ_16:
1395 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1396 2dd791b6 Hannes Reinecke
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
1397 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1398 274fb0e1 aliguori
            goto illegal_lba;
1399 f01b5931 Paolo Bonzini
        }
1400 69377307 Paolo Bonzini
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1401 69377307 Paolo Bonzini
        r->sector_count = len * (s->qdev.blocksize / 512);
1402 2e5d83bb pbrook
        break;
1403 ebf46023 Gerd Hoffmann
    case WRITE_6:
1404 ebf46023 Gerd Hoffmann
    case WRITE_10:
1405 bd536cf3 Gerd Hoffmann
    case WRITE_12:
1406 bd536cf3 Gerd Hoffmann
    case WRITE_16:
1407 5e30a07d Hannes Reinecke
    case WRITE_VERIFY_10:
1408 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_12:
1409 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_16:
1410 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1411 ebef0bbb Bernhard Kohl
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1412 2dd791b6 Hannes Reinecke
                (command & 0xe) == 0xe ? "And Verify " : "",
1413 2dd791b6 Hannes Reinecke
                r->req.cmd.lba, len);
1414 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1415 274fb0e1 aliguori
            goto illegal_lba;
1416 f01b5931 Paolo Bonzini
        }
1417 69377307 Paolo Bonzini
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1418 69377307 Paolo Bonzini
        r->sector_count = len * (s->qdev.blocksize / 512);
1419 2e5d83bb pbrook
        break;
1420 ebef0bbb Bernhard Kohl
    case MODE_SELECT:
1421 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1422 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1423 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1424 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 12) {
1425 ebef0bbb Bernhard Kohl
            goto fail;
1426 ebef0bbb Bernhard Kohl
        }
1427 ebef0bbb Bernhard Kohl
        break;
1428 ebef0bbb Bernhard Kohl
    case MODE_SELECT_10:
1429 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1430 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1431 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1432 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 16) {
1433 ebef0bbb Bernhard Kohl
            goto fail;
1434 ebef0bbb Bernhard Kohl
        }
1435 ebef0bbb Bernhard Kohl
        break;
1436 ebef0bbb Bernhard Kohl
    case SEEK_10:
1437 00a01ad4 Paolo Bonzini
        DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
1438 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1439 ebef0bbb Bernhard Kohl
            goto illegal_lba;
1440 ebef0bbb Bernhard Kohl
        }
1441 ebef0bbb Bernhard Kohl
        break;
1442 ea3bd56f Christoph Hellwig
    case WRITE_SAME_16:
1443 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1444 ea3bd56f Christoph Hellwig
1445 ea3bd56f Christoph Hellwig
        DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
1446 ea3bd56f Christoph Hellwig
                r->req.cmd.lba, len);
1447 ea3bd56f Christoph Hellwig
1448 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1449 ea3bd56f Christoph Hellwig
            goto illegal_lba;
1450 ea3bd56f Christoph Hellwig
        }
1451 ea3bd56f Christoph Hellwig
1452 ea3bd56f Christoph Hellwig
        /*
1453 ea3bd56f Christoph Hellwig
         * We only support WRITE SAME with the unmap bit set for now.
1454 ea3bd56f Christoph Hellwig
         */
1455 ea3bd56f Christoph Hellwig
        if (!(buf[1] & 0x8)) {
1456 ea3bd56f Christoph Hellwig
            goto fail;
1457 ea3bd56f Christoph Hellwig
        }
1458 ea3bd56f Christoph Hellwig
1459 69377307 Paolo Bonzini
        rc = bdrv_discard(s->qdev.conf.bs,
1460 69377307 Paolo Bonzini
                          r->req.cmd.lba * (s->qdev.blocksize / 512),
1461 69377307 Paolo Bonzini
                          len * (s->qdev.blocksize / 512));
1462 ea3bd56f Christoph Hellwig
        if (rc < 0) {
1463 ea3bd56f Christoph Hellwig
            /* XXX: better error code ?*/
1464 ea3bd56f Christoph Hellwig
            goto fail;
1465 ea3bd56f Christoph Hellwig
        }
1466 ea3bd56f Christoph Hellwig
1467 ea3bd56f Christoph Hellwig
        break;
1468 2e5d83bb pbrook
    default:
1469 2dd791b6 Hannes Reinecke
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1470 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1471 a1f0cce2 Hannes Reinecke
        return 0;
1472 2e5d83bb pbrook
    fail:
1473 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1474 2dd791b6 Hannes Reinecke
        return 0;
1475 274fb0e1 aliguori
    illegal_lba:
1476 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1477 274fb0e1 aliguori
        return 0;
1478 2e5d83bb pbrook
    }
1479 c87c0672 aliguori
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1480 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1481 a917d384 pbrook
    }
1482 c87c0672 aliguori
    len = r->sector_count * 512 + r->iov.iov_len;
1483 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1484 efb9ee02 Hannes Reinecke
        return -len;
1485 a917d384 pbrook
    } else {
1486 f01b5931 Paolo Bonzini
        if (!r->sector_count) {
1487 a917d384 pbrook
            r->sector_count = -1;
1488 f01b5931 Paolo Bonzini
        }
1489 efb9ee02 Hannes Reinecke
        return len;
1490 2e5d83bb pbrook
    }
1491 2e5d83bb pbrook
}
1492 2e5d83bb pbrook
1493 e9447f35 Jan Kiszka
static void scsi_disk_reset(DeviceState *dev)
1494 e9447f35 Jan Kiszka
{
1495 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1496 e9447f35 Jan Kiszka
    uint64_t nb_sectors;
1497 e9447f35 Jan Kiszka
1498 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
1499 e9447f35 Jan Kiszka
1500 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1501 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1502 e9447f35 Jan Kiszka
    if (nb_sectors) {
1503 e9447f35 Jan Kiszka
        nb_sectors--;
1504 e9447f35 Jan Kiszka
    }
1505 7877903a Paolo Bonzini
    s->qdev.max_lba = nb_sectors;
1506 e9447f35 Jan Kiszka
}
1507 e9447f35 Jan Kiszka
1508 e9447f35 Jan Kiszka
static void scsi_destroy(SCSIDevice *dev)
1509 e9447f35 Jan Kiszka
{
1510 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1511 e9447f35 Jan Kiszka
1512 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1513 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
1514 56a14938 Gerd Hoffmann
}
1515 56a14938 Gerd Hoffmann
1516 7d4b4ba5 Markus Armbruster
static void scsi_cd_change_media_cb(void *opaque, bool load)
1517 2c6942fa Markus Armbruster
{
1518 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = opaque;
1519 8a9c16f6 Paolo Bonzini
1520 8a9c16f6 Paolo Bonzini
    /*
1521 8a9c16f6 Paolo Bonzini
     * When a CD gets changed, we have to report an ejected state and
1522 8a9c16f6 Paolo Bonzini
     * then a loaded state to guests so that they detect tray
1523 8a9c16f6 Paolo Bonzini
     * open/close and media change events.  Guests that do not use
1524 8a9c16f6 Paolo Bonzini
     * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1525 8a9c16f6 Paolo Bonzini
     * states rely on this behavior.
1526 8a9c16f6 Paolo Bonzini
     *
1527 8a9c16f6 Paolo Bonzini
     * media_changed governs the state machine used for unit attention
1528 8a9c16f6 Paolo Bonzini
     * report.  media_event is used by GET EVENT STATUS NOTIFICATION.
1529 8a9c16f6 Paolo Bonzini
     */
1530 8a9c16f6 Paolo Bonzini
    s->media_changed = load;
1531 8a9c16f6 Paolo Bonzini
    s->tray_open = !load;
1532 8a9c16f6 Paolo Bonzini
    s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
1533 3c2f7c12 Paolo Bonzini
    s->media_event = true;
1534 4480de19 Paolo Bonzini
    s->eject_request = false;
1535 4480de19 Paolo Bonzini
}
1536 4480de19 Paolo Bonzini
1537 4480de19 Paolo Bonzini
static void scsi_cd_eject_request_cb(void *opaque, bool force)
1538 4480de19 Paolo Bonzini
{
1539 4480de19 Paolo Bonzini
    SCSIDiskState *s = opaque;
1540 4480de19 Paolo Bonzini
1541 4480de19 Paolo Bonzini
    s->eject_request = true;
1542 4480de19 Paolo Bonzini
    if (force) {
1543 4480de19 Paolo Bonzini
        s->tray_locked = false;
1544 4480de19 Paolo Bonzini
    }
1545 2c6942fa Markus Armbruster
}
1546 2c6942fa Markus Armbruster
1547 e4def80b Markus Armbruster
static bool scsi_cd_is_tray_open(void *opaque)
1548 e4def80b Markus Armbruster
{
1549 e4def80b Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_open;
1550 e4def80b Markus Armbruster
}
1551 e4def80b Markus Armbruster
1552 f107639a Markus Armbruster
static bool scsi_cd_is_medium_locked(void *opaque)
1553 f107639a Markus Armbruster
{
1554 f107639a Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_locked;
1555 f107639a Markus Armbruster
}
1556 f107639a Markus Armbruster
1557 f107639a Markus Armbruster
static const BlockDevOps scsi_cd_block_ops = {
1558 2c6942fa Markus Armbruster
    .change_media_cb = scsi_cd_change_media_cb,
1559 4480de19 Paolo Bonzini
    .eject_request_cb = scsi_cd_eject_request_cb,
1560 e4def80b Markus Armbruster
    .is_tray_open = scsi_cd_is_tray_open,
1561 f107639a Markus Armbruster
    .is_medium_locked = scsi_cd_is_medium_locked,
1562 f107639a Markus Armbruster
};
1563 f107639a Markus Armbruster
1564 8a9c16f6 Paolo Bonzini
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
1565 8a9c16f6 Paolo Bonzini
{
1566 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1567 8a9c16f6 Paolo Bonzini
    if (s->media_changed) {
1568 8a9c16f6 Paolo Bonzini
        s->media_changed = false;
1569 8a9c16f6 Paolo Bonzini
        s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
1570 8a9c16f6 Paolo Bonzini
    }
1571 8a9c16f6 Paolo Bonzini
}
1572 8a9c16f6 Paolo Bonzini
1573 e39be482 Paolo Bonzini
static int scsi_initfn(SCSIDevice *dev)
1574 2e5d83bb pbrook
{
1575 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1576 f8b6cc00 Markus Armbruster
    DriveInfo *dinfo;
1577 2e5d83bb pbrook
1578 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
1579 6a84cb1f Markus Armbruster
        error_report("drive property not set");
1580 d52affa7 Gerd Hoffmann
        return -1;
1581 d52affa7 Gerd Hoffmann
    }
1582 d52affa7 Gerd Hoffmann
1583 e39be482 Paolo Bonzini
    if (!s->removable && !bdrv_is_inserted(s->qdev.conf.bs)) {
1584 98f28ad7 Markus Armbruster
        error_report("Device needs media, but drive is empty");
1585 98f28ad7 Markus Armbruster
        return -1;
1586 98f28ad7 Markus Armbruster
    }
1587 98f28ad7 Markus Armbruster
1588 a0fef654 Markus Armbruster
    if (!s->serial) {
1589 f8b6cc00 Markus Armbruster
        /* try to fall back to value set with legacy -drive serial=... */
1590 44740c38 Paolo Bonzini
        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
1591 3e1c0c9a Hannes Reinecke
        if (*dinfo->serial) {
1592 7267c094 Anthony Liguori
            s->serial = g_strdup(dinfo->serial);
1593 3e1c0c9a Hannes Reinecke
        }
1594 a0fef654 Markus Armbruster
    }
1595 a0fef654 Markus Armbruster
1596 552fee93 Markus Armbruster
    if (!s->version) {
1597 7267c094 Anthony Liguori
        s->version = g_strdup(QEMU_VERSION);
1598 552fee93 Markus Armbruster
    }
1599 552fee93 Markus Armbruster
1600 44740c38 Paolo Bonzini
    if (bdrv_is_sg(s->qdev.conf.bs)) {
1601 6a84cb1f Markus Armbruster
        error_report("unwanted /dev/sg*");
1602 32bb404a Markus Armbruster
        return -1;
1603 32bb404a Markus Armbruster
    }
1604 32bb404a Markus Armbruster
1605 e39be482 Paolo Bonzini
    if (s->removable) {
1606 44740c38 Paolo Bonzini
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
1607 2e5d83bb pbrook
    }
1608 44740c38 Paolo Bonzini
    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
1609 8cfacf07 Christoph Hellwig
1610 44740c38 Paolo Bonzini
    bdrv_iostatus_enable(s->qdev.conf.bs);
1611 7082826e Paolo Bonzini
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
1612 d52affa7 Gerd Hoffmann
    return 0;
1613 d52affa7 Gerd Hoffmann
}
1614 d52affa7 Gerd Hoffmann
1615 b443ae67 Markus Armbruster
static int scsi_hd_initfn(SCSIDevice *dev)
1616 b443ae67 Markus Armbruster
{
1617 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1618 e39be482 Paolo Bonzini
    s->qdev.blocksize = s->qdev.conf.logical_block_size;
1619 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_DISK;
1620 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1621 b443ae67 Markus Armbruster
}
1622 b443ae67 Markus Armbruster
1623 b443ae67 Markus Armbruster
static int scsi_cd_initfn(SCSIDevice *dev)
1624 b443ae67 Markus Armbruster
{
1625 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1626 e39be482 Paolo Bonzini
    s->qdev.blocksize = 2048;
1627 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_ROM;
1628 e39be482 Paolo Bonzini
    s->removable = true;
1629 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1630 b443ae67 Markus Armbruster
}
1631 b443ae67 Markus Armbruster
1632 b443ae67 Markus Armbruster
static int scsi_disk_initfn(SCSIDevice *dev)
1633 b443ae67 Markus Armbruster
{
1634 95b5edcd Markus Armbruster
    DriveInfo *dinfo;
1635 b443ae67 Markus Armbruster
1636 b443ae67 Markus Armbruster
    if (!dev->conf.bs) {
1637 e39be482 Paolo Bonzini
        return scsi_initfn(dev);  /* ... and die there */
1638 b443ae67 Markus Armbruster
    }
1639 b443ae67 Markus Armbruster
1640 e39be482 Paolo Bonzini
    dinfo = drive_get_by_blockdev(dev->conf.bs);
1641 e39be482 Paolo Bonzini
    if (dinfo->media_cd) {
1642 e39be482 Paolo Bonzini
        return scsi_cd_initfn(dev);
1643 e39be482 Paolo Bonzini
    } else {
1644 e39be482 Paolo Bonzini
        return scsi_hd_initfn(dev);
1645 e39be482 Paolo Bonzini
    }
1646 b443ae67 Markus Armbruster
}
1647 b443ae67 Markus Armbruster
1648 adcf2754 Paolo Bonzini
static const SCSIReqOps scsi_disk_reqops = {
1649 8dbd4574 Paolo Bonzini
    .size         = sizeof(SCSIDiskReq),
1650 12010e7b Paolo Bonzini
    .free_req     = scsi_free_request,
1651 12010e7b Paolo Bonzini
    .send_command = scsi_send_command,
1652 12010e7b Paolo Bonzini
    .read_data    = scsi_read_data,
1653 12010e7b Paolo Bonzini
    .write_data   = scsi_write_data,
1654 12010e7b Paolo Bonzini
    .cancel_io    = scsi_cancel_io,
1655 12010e7b Paolo Bonzini
    .get_buf      = scsi_get_buf,
1656 43b978b9 Paolo Bonzini
    .load_request = scsi_disk_load_request,
1657 43b978b9 Paolo Bonzini
    .save_request = scsi_disk_save_request,
1658 8dbd4574 Paolo Bonzini
};
1659 8dbd4574 Paolo Bonzini
1660 63db0f0e Paolo Bonzini
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
1661 63db0f0e Paolo Bonzini
                                     uint8_t *buf, void *hba_private)
1662 8dbd4574 Paolo Bonzini
{
1663 8dbd4574 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1664 8dbd4574 Paolo Bonzini
    SCSIRequest *req;
1665 8dbd4574 Paolo Bonzini
1666 8dbd4574 Paolo Bonzini
    req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
1667 8dbd4574 Paolo Bonzini
    return req;
1668 8dbd4574 Paolo Bonzini
}
1669 8dbd4574 Paolo Bonzini
1670 336a6915 Paolo Bonzini
#ifdef __linux__
1671 336a6915 Paolo Bonzini
static int get_device_type(SCSIDiskState *s)
1672 336a6915 Paolo Bonzini
{
1673 336a6915 Paolo Bonzini
    BlockDriverState *bdrv = s->qdev.conf.bs;
1674 336a6915 Paolo Bonzini
    uint8_t cmd[16];
1675 336a6915 Paolo Bonzini
    uint8_t buf[36];
1676 336a6915 Paolo Bonzini
    uint8_t sensebuf[8];
1677 336a6915 Paolo Bonzini
    sg_io_hdr_t io_header;
1678 336a6915 Paolo Bonzini
    int ret;
1679 336a6915 Paolo Bonzini
1680 336a6915 Paolo Bonzini
    memset(cmd, 0, sizeof(cmd));
1681 336a6915 Paolo Bonzini
    memset(buf, 0, sizeof(buf));
1682 336a6915 Paolo Bonzini
    cmd[0] = INQUIRY;
1683 336a6915 Paolo Bonzini
    cmd[4] = sizeof(buf);
1684 336a6915 Paolo Bonzini
1685 336a6915 Paolo Bonzini
    memset(&io_header, 0, sizeof(io_header));
1686 336a6915 Paolo Bonzini
    io_header.interface_id = 'S';
1687 336a6915 Paolo Bonzini
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
1688 336a6915 Paolo Bonzini
    io_header.dxfer_len = sizeof(buf);
1689 336a6915 Paolo Bonzini
    io_header.dxferp = buf;
1690 336a6915 Paolo Bonzini
    io_header.cmdp = cmd;
1691 336a6915 Paolo Bonzini
    io_header.cmd_len = sizeof(cmd);
1692 336a6915 Paolo Bonzini
    io_header.mx_sb_len = sizeof(sensebuf);
1693 336a6915 Paolo Bonzini
    io_header.sbp = sensebuf;
1694 336a6915 Paolo Bonzini
    io_header.timeout = 6000; /* XXX */
1695 336a6915 Paolo Bonzini
1696 336a6915 Paolo Bonzini
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
1697 336a6915 Paolo Bonzini
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
1698 336a6915 Paolo Bonzini
        return -1;
1699 336a6915 Paolo Bonzini
    }
1700 336a6915 Paolo Bonzini
    s->qdev.type = buf[0];
1701 336a6915 Paolo Bonzini
    s->removable = (buf[1] & 0x80) != 0;
1702 336a6915 Paolo Bonzini
    return 0;
1703 336a6915 Paolo Bonzini
}
1704 336a6915 Paolo Bonzini
1705 336a6915 Paolo Bonzini
static int scsi_block_initfn(SCSIDevice *dev)
1706 336a6915 Paolo Bonzini
{
1707 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1708 336a6915 Paolo Bonzini
    int sg_version;
1709 336a6915 Paolo Bonzini
    int rc;
1710 336a6915 Paolo Bonzini
1711 336a6915 Paolo Bonzini
    if (!s->qdev.conf.bs) {
1712 336a6915 Paolo Bonzini
        error_report("scsi-block: drive property not set");
1713 336a6915 Paolo Bonzini
        return -1;
1714 336a6915 Paolo Bonzini
    }
1715 336a6915 Paolo Bonzini
1716 336a6915 Paolo Bonzini
    /* check we are using a driver managing SG_IO (version 3 and after) */
1717 336a6915 Paolo Bonzini
    if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
1718 336a6915 Paolo Bonzini
        sg_version < 30000) {
1719 336a6915 Paolo Bonzini
        error_report("scsi-block: scsi generic interface too old");
1720 336a6915 Paolo Bonzini
        return -1;
1721 336a6915 Paolo Bonzini
    }
1722 336a6915 Paolo Bonzini
1723 336a6915 Paolo Bonzini
    /* get device type from INQUIRY data */
1724 336a6915 Paolo Bonzini
    rc = get_device_type(s);
1725 336a6915 Paolo Bonzini
    if (rc < 0) {
1726 336a6915 Paolo Bonzini
        error_report("scsi-block: INQUIRY failed");
1727 336a6915 Paolo Bonzini
        return -1;
1728 336a6915 Paolo Bonzini
    }
1729 336a6915 Paolo Bonzini
1730 336a6915 Paolo Bonzini
    /* Make a guess for the block size, we'll fix it when the guest sends.
1731 336a6915 Paolo Bonzini
     * READ CAPACITY.  If they don't, they likely would assume these sizes
1732 336a6915 Paolo Bonzini
     * anyway. (TODO: check in /sys).
1733 336a6915 Paolo Bonzini
     */
1734 336a6915 Paolo Bonzini
    if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
1735 336a6915 Paolo Bonzini
        s->qdev.blocksize = 2048;
1736 336a6915 Paolo Bonzini
    } else {
1737 336a6915 Paolo Bonzini
        s->qdev.blocksize = 512;
1738 336a6915 Paolo Bonzini
    }
1739 336a6915 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1740 336a6915 Paolo Bonzini
}
1741 336a6915 Paolo Bonzini
1742 336a6915 Paolo Bonzini
static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
1743 336a6915 Paolo Bonzini
                                           uint32_t lun, uint8_t *buf,
1744 336a6915 Paolo Bonzini
                                           void *hba_private)
1745 336a6915 Paolo Bonzini
{
1746 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1747 336a6915 Paolo Bonzini
1748 336a6915 Paolo Bonzini
    switch (buf[0]) {
1749 336a6915 Paolo Bonzini
    case READ_6:
1750 336a6915 Paolo Bonzini
    case READ_10:
1751 336a6915 Paolo Bonzini
    case READ_12:
1752 336a6915 Paolo Bonzini
    case READ_16:
1753 336a6915 Paolo Bonzini
    case WRITE_6:
1754 336a6915 Paolo Bonzini
    case WRITE_10:
1755 336a6915 Paolo Bonzini
    case WRITE_12:
1756 336a6915 Paolo Bonzini
    case WRITE_16:
1757 336a6915 Paolo Bonzini
    case WRITE_VERIFY_10:
1758 336a6915 Paolo Bonzini
    case WRITE_VERIFY_12:
1759 336a6915 Paolo Bonzini
    case WRITE_VERIFY_16:
1760 eaccf49e Paolo Bonzini
        /* If we are not using O_DIRECT, we might read stale data from the
1761 eaccf49e Paolo Bonzini
         * host cache if writes were made using other commands than these
1762 eaccf49e Paolo Bonzini
         * ones (such as WRITE SAME or EXTENDED COPY, etc.).  So, without
1763 eaccf49e Paolo Bonzini
         * O_DIRECT everything must go through SG_IO.
1764 eaccf49e Paolo Bonzini
         */
1765 eaccf49e Paolo Bonzini
        if (!(s->qdev.conf.bs->open_flags & BDRV_O_NOCACHE)) {
1766 eaccf49e Paolo Bonzini
            break;
1767 eaccf49e Paolo Bonzini
        }
1768 eaccf49e Paolo Bonzini
1769 33ebad12 Paolo Bonzini
        /* MMC writing cannot be done via pread/pwrite, because it sometimes
1770 33ebad12 Paolo Bonzini
         * involves writing beyond the maximum LBA or to negative LBA (lead-in).
1771 33ebad12 Paolo Bonzini
         * And once you do these writes, reading from the block device is
1772 33ebad12 Paolo Bonzini
         * unreliable, too.  It is even possible that reads deliver random data
1773 33ebad12 Paolo Bonzini
         * from the host page cache (this is probably a Linux bug).
1774 33ebad12 Paolo Bonzini
         *
1775 33ebad12 Paolo Bonzini
         * We might use scsi_disk_reqops as long as no writing commands are
1776 33ebad12 Paolo Bonzini
         * seen, but performance usually isn't paramount on optical media.  So,
1777 33ebad12 Paolo Bonzini
         * just make scsi-block operate the same as scsi-generic for them.
1778 33ebad12 Paolo Bonzini
         */
1779 eaccf49e Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
1780 eaccf49e Paolo Bonzini
            break;
1781 eaccf49e Paolo Bonzini
        }
1782 eaccf49e Paolo Bonzini
        return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
1783 eaccf49e Paolo Bonzini
                              hba_private);
1784 336a6915 Paolo Bonzini
    }
1785 336a6915 Paolo Bonzini
1786 336a6915 Paolo Bonzini
    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
1787 336a6915 Paolo Bonzini
                          hba_private);
1788 336a6915 Paolo Bonzini
}
1789 336a6915 Paolo Bonzini
#endif
1790 336a6915 Paolo Bonzini
1791 b443ae67 Markus Armbruster
#define DEFINE_SCSI_DISK_PROPERTIES()                           \
1792 b443ae67 Markus Armbruster
    DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),          \
1793 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
1794 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("serial",  SCSIDiskState, serial)
1795 b443ae67 Markus Armbruster
1796 39bffca2 Anthony Liguori
static Property scsi_hd_properties[] = {
1797 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1798 39bffca2 Anthony Liguori
    DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1799 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1800 39bffca2 Anthony Liguori
};
1801 39bffca2 Anthony Liguori
1802 43b978b9 Paolo Bonzini
static const VMStateDescription vmstate_scsi_disk_state = {
1803 43b978b9 Paolo Bonzini
    .name = "scsi-disk",
1804 43b978b9 Paolo Bonzini
    .version_id = 1,
1805 43b978b9 Paolo Bonzini
    .minimum_version_id = 1,
1806 43b978b9 Paolo Bonzini
    .minimum_version_id_old = 1,
1807 43b978b9 Paolo Bonzini
    .fields = (VMStateField[]) {
1808 43b978b9 Paolo Bonzini
        VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
1809 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_changed, SCSIDiskState),
1810 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_event, SCSIDiskState),
1811 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(eject_request, SCSIDiskState),
1812 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_open, SCSIDiskState),
1813 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_locked, SCSIDiskState),
1814 43b978b9 Paolo Bonzini
        VMSTATE_END_OF_LIST()
1815 43b978b9 Paolo Bonzini
    }
1816 43b978b9 Paolo Bonzini
};
1817 43b978b9 Paolo Bonzini
1818 b9eea3e6 Anthony Liguori
static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
1819 b9eea3e6 Anthony Liguori
{
1820 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1821 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1822 b9eea3e6 Anthony Liguori
1823 b9eea3e6 Anthony Liguori
    sc->init         = scsi_hd_initfn;
1824 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1825 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1826 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1827 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1828 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk";
1829 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1830 39bffca2 Anthony Liguori
    dc->props = scsi_hd_properties;
1831 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1832 b9eea3e6 Anthony Liguori
}
1833 b9eea3e6 Anthony Liguori
1834 39bffca2 Anthony Liguori
static TypeInfo scsi_hd_info = {
1835 39bffca2 Anthony Liguori
    .name          = "scsi-hd",
1836 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1837 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1838 39bffca2 Anthony Liguori
    .class_init    = scsi_hd_class_initfn,
1839 39bffca2 Anthony Liguori
};
1840 39bffca2 Anthony Liguori
1841 39bffca2 Anthony Liguori
static Property scsi_cd_properties[] = {
1842 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1843 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1844 b9eea3e6 Anthony Liguori
};
1845 b9eea3e6 Anthony Liguori
1846 b9eea3e6 Anthony Liguori
static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
1847 b9eea3e6 Anthony Liguori
{
1848 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1849 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1850 b9eea3e6 Anthony Liguori
1851 b9eea3e6 Anthony Liguori
    sc->init         = scsi_cd_initfn;
1852 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1853 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1854 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1855 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1856 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI CD-ROM";
1857 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1858 39bffca2 Anthony Liguori
    dc->props = scsi_cd_properties;
1859 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1860 b9eea3e6 Anthony Liguori
}
1861 b9eea3e6 Anthony Liguori
1862 39bffca2 Anthony Liguori
static TypeInfo scsi_cd_info = {
1863 39bffca2 Anthony Liguori
    .name          = "scsi-cd",
1864 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1865 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1866 39bffca2 Anthony Liguori
    .class_init    = scsi_cd_class_initfn,
1867 b9eea3e6 Anthony Liguori
};
1868 b9eea3e6 Anthony Liguori
1869 336a6915 Paolo Bonzini
#ifdef __linux__
1870 39bffca2 Anthony Liguori
static Property scsi_block_properties[] = {
1871 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1872 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1873 39bffca2 Anthony Liguori
};
1874 39bffca2 Anthony Liguori
1875 b9eea3e6 Anthony Liguori
static void scsi_block_class_initfn(ObjectClass *klass, void *data)
1876 b9eea3e6 Anthony Liguori
{
1877 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1878 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1879 b9eea3e6 Anthony Liguori
1880 b9eea3e6 Anthony Liguori
    sc->init         = scsi_block_initfn;
1881 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1882 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_block_new_request;
1883 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1884 39bffca2 Anthony Liguori
    dc->desc = "SCSI block device passthrough";
1885 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1886 39bffca2 Anthony Liguori
    dc->props = scsi_block_properties;
1887 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1888 b9eea3e6 Anthony Liguori
}
1889 b9eea3e6 Anthony Liguori
1890 39bffca2 Anthony Liguori
static TypeInfo scsi_block_info = {
1891 39bffca2 Anthony Liguori
    .name          = "scsi-block",
1892 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1893 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1894 39bffca2 Anthony Liguori
    .class_init    = scsi_block_class_initfn,
1895 b9eea3e6 Anthony Liguori
};
1896 336a6915 Paolo Bonzini
#endif
1897 b9eea3e6 Anthony Liguori
1898 39bffca2 Anthony Liguori
static Property scsi_disk_properties[] = {
1899 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1900 39bffca2 Anthony Liguori
    DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1901 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1902 39bffca2 Anthony Liguori
};
1903 39bffca2 Anthony Liguori
1904 b9eea3e6 Anthony Liguori
static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
1905 b9eea3e6 Anthony Liguori
{
1906 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1907 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1908 b9eea3e6 Anthony Liguori
1909 b9eea3e6 Anthony Liguori
    sc->init         = scsi_disk_initfn;
1910 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1911 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1912 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1913 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1914 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
1915 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1916 39bffca2 Anthony Liguori
    dc->props = scsi_disk_properties;
1917 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1918 b9eea3e6 Anthony Liguori
}
1919 b9eea3e6 Anthony Liguori
1920 39bffca2 Anthony Liguori
static TypeInfo scsi_disk_info = {
1921 39bffca2 Anthony Liguori
    .name          = "scsi-disk",
1922 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1923 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1924 39bffca2 Anthony Liguori
    .class_init    = scsi_disk_class_initfn,
1925 d52affa7 Gerd Hoffmann
};
1926 d52affa7 Gerd Hoffmann
1927 83f7d43a Andreas Färber
static void scsi_disk_register_types(void)
1928 d52affa7 Gerd Hoffmann
{
1929 39bffca2 Anthony Liguori
    type_register_static(&scsi_hd_info);
1930 39bffca2 Anthony Liguori
    type_register_static(&scsi_cd_info);
1931 b9eea3e6 Anthony Liguori
#ifdef __linux__
1932 39bffca2 Anthony Liguori
    type_register_static(&scsi_block_info);
1933 b9eea3e6 Anthony Liguori
#endif
1934 39bffca2 Anthony Liguori
    type_register_static(&scsi_disk_info);
1935 8ccc2ace ths
}
1936 83f7d43a Andreas Färber
1937 83f7d43a Andreas Färber
type_init(scsi_disk_register_types)