Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ fd930791

History | View | Annotate | Download (58 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 fd930791 Paolo Bonzini
            const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
475 fd930791 Paolo Bonzini
            int max_len = s->serial ? 20 : 255 - 8;
476 fd930791 Paolo Bonzini
            int id_len = strlen(str);
477 0b06c059 Gerd Hoffmann
478 f01b5931 Paolo Bonzini
            if (id_len > max_len) {
479 0b06c059 Gerd Hoffmann
                id_len = max_len;
480 f01b5931 Paolo Bonzini
            }
481 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Device identification] "
482 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
483 0b06c059 Gerd Hoffmann
484 39d98982 Hannes Reinecke
            outbuf[buflen++] = 4 + id_len;
485 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x2; // ASCII
486 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // not officially assigned
487 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // reserved
488 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = id_len; // length of data following
489 0b06c059 Gerd Hoffmann
490 fd930791 Paolo Bonzini
            memcpy(outbuf+buflen, str, id_len);
491 0b06c059 Gerd Hoffmann
            buflen += id_len;
492 0b06c059 Gerd Hoffmann
            break;
493 0b06c059 Gerd Hoffmann
        }
494 ea3bd56f Christoph Hellwig
        case 0xb0: /* block limits */
495 ee3659e3 Christoph Hellwig
        {
496 ea3bd56f Christoph Hellwig
            unsigned int unmap_sectors =
497 ea3bd56f Christoph Hellwig
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
498 8cfacf07 Christoph Hellwig
            unsigned int min_io_size =
499 8cfacf07 Christoph Hellwig
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
500 8cfacf07 Christoph Hellwig
            unsigned int opt_io_size =
501 8cfacf07 Christoph Hellwig
                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
502 ee3659e3 Christoph Hellwig
503 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_ROM) {
504 39d98982 Hannes Reinecke
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
505 39d98982 Hannes Reinecke
                        page_code);
506 39d98982 Hannes Reinecke
                return -1;
507 39d98982 Hannes Reinecke
            }
508 ee3659e3 Christoph Hellwig
            /* required VPD size with unmap support */
509 ee3659e3 Christoph Hellwig
            outbuf[3] = buflen = 0x3c;
510 ee3659e3 Christoph Hellwig
511 ee3659e3 Christoph Hellwig
            memset(outbuf + 4, 0, buflen - 4);
512 ee3659e3 Christoph Hellwig
513 ee3659e3 Christoph Hellwig
            /* optimal transfer length granularity */
514 ee3659e3 Christoph Hellwig
            outbuf[6] = (min_io_size >> 8) & 0xff;
515 ee3659e3 Christoph Hellwig
            outbuf[7] = min_io_size & 0xff;
516 ee3659e3 Christoph Hellwig
517 ee3659e3 Christoph Hellwig
            /* optimal transfer length */
518 ee3659e3 Christoph Hellwig
            outbuf[12] = (opt_io_size >> 24) & 0xff;
519 ee3659e3 Christoph Hellwig
            outbuf[13] = (opt_io_size >> 16) & 0xff;
520 ee3659e3 Christoph Hellwig
            outbuf[14] = (opt_io_size >> 8) & 0xff;
521 ee3659e3 Christoph Hellwig
            outbuf[15] = opt_io_size & 0xff;
522 ea3bd56f Christoph Hellwig
523 ea3bd56f Christoph Hellwig
            /* optimal unmap granularity */
524 ea3bd56f Christoph Hellwig
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
525 ea3bd56f Christoph Hellwig
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
526 ea3bd56f Christoph Hellwig
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
527 ea3bd56f Christoph Hellwig
            outbuf[31] = unmap_sectors & 0xff;
528 ea3bd56f Christoph Hellwig
            break;
529 ea3bd56f Christoph Hellwig
        }
530 ea3bd56f Christoph Hellwig
        case 0xb2: /* thin provisioning */
531 ea3bd56f Christoph Hellwig
        {
532 ea3bd56f Christoph Hellwig
            outbuf[3] = buflen = 8;
533 ea3bd56f Christoph Hellwig
            outbuf[4] = 0;
534 ea3bd56f Christoph Hellwig
            outbuf[5] = 0x40; /* write same with unmap supported */
535 ea3bd56f Christoph Hellwig
            outbuf[6] = 0;
536 ea3bd56f Christoph Hellwig
            outbuf[7] = 0;
537 ee3659e3 Christoph Hellwig
            break;
538 ee3659e3 Christoph Hellwig
        }
539 0b06c059 Gerd Hoffmann
        default:
540 0b06c059 Gerd Hoffmann
            BADF("Error: unsupported Inquiry (EVPD[%02X]) "
541 0b06c059 Gerd Hoffmann
                 "buffer size %zd\n", page_code, req->cmd.xfer);
542 0b06c059 Gerd Hoffmann
            return -1;
543 0b06c059 Gerd Hoffmann
        }
544 0b06c059 Gerd Hoffmann
        /* done with EVPD */
545 0b06c059 Gerd Hoffmann
        return buflen;
546 0b06c059 Gerd Hoffmann
    }
547 0b06c059 Gerd Hoffmann
548 0b06c059 Gerd Hoffmann
    /* Standard INQUIRY data */
549 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[2] != 0) {
550 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) page or code "
551 0b06c059 Gerd Hoffmann
             "is non-zero [%02X]\n", req->cmd.buf[2]);
552 0b06c059 Gerd Hoffmann
        return -1;
553 0b06c059 Gerd Hoffmann
    }
554 0b06c059 Gerd Hoffmann
555 0b06c059 Gerd Hoffmann
    /* PAGE CODE == 0 */
556 0b06c059 Gerd Hoffmann
    if (req->cmd.xfer < 5) {
557 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) buffer size %zd "
558 0b06c059 Gerd Hoffmann
             "is less than 5\n", req->cmd.xfer);
559 0b06c059 Gerd Hoffmann
        return -1;
560 0b06c059 Gerd Hoffmann
    }
561 0b06c059 Gerd Hoffmann
562 0b06c059 Gerd Hoffmann
    buflen = req->cmd.xfer;
563 f01b5931 Paolo Bonzini
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
564 0b06c059 Gerd Hoffmann
        buflen = SCSI_MAX_INQUIRY_LEN;
565 f01b5931 Paolo Bonzini
    }
566 0b06c059 Gerd Hoffmann
    memset(outbuf, 0, buflen);
567 0b06c059 Gerd Hoffmann
568 f37bd73b Hannes Reinecke
    outbuf[0] = s->qdev.type & 0x1f;
569 e39be482 Paolo Bonzini
    outbuf[1] = s->removable ? 0x80 : 0;
570 f37bd73b Hannes Reinecke
    if (s->qdev.type == TYPE_ROM) {
571 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
572 0b06c059 Gerd Hoffmann
    } else {
573 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
574 0b06c059 Gerd Hoffmann
    }
575 550fe6c6 Laszlo Ast
    memcpy(&outbuf[8], "QEMU    ", 8);
576 314b1811 Gerd Hoffmann
    memset(&outbuf[32], 0, 4);
577 552fee93 Markus Armbruster
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
578 99aba0c4 Christoph Hellwig
    /*
579 99aba0c4 Christoph Hellwig
     * We claim conformance to SPC-3, which is required for guests
580 99aba0c4 Christoph Hellwig
     * to ask for modern features like READ CAPACITY(16) or the
581 99aba0c4 Christoph Hellwig
     * block characteristics VPD page by default.  Not all of SPC-3
582 99aba0c4 Christoph Hellwig
     * is actually implemented, but we're good enough.
583 99aba0c4 Christoph Hellwig
     */
584 ee3659e3 Christoph Hellwig
    outbuf[2] = 5;
585 0b06c059 Gerd Hoffmann
    outbuf[3] = 2; /* Format 2 */
586 ad3cea42 Artyom Tarasenko
587 ad3cea42 Artyom Tarasenko
    if (buflen > 36) {
588 ad3cea42 Artyom Tarasenko
        outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
589 ad3cea42 Artyom Tarasenko
    } else {
590 ad3cea42 Artyom Tarasenko
        /* If the allocation length of CDB is too small,
591 ad3cea42 Artyom Tarasenko
               the additional length is not adjusted */
592 ad3cea42 Artyom Tarasenko
        outbuf[4] = 36 - 5;
593 ad3cea42 Artyom Tarasenko
    }
594 ad3cea42 Artyom Tarasenko
595 0b06c059 Gerd Hoffmann
    /* Sync data transfer and TCQ.  */
596 afd4030c Paolo Bonzini
    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
597 0b06c059 Gerd Hoffmann
    return buflen;
598 0b06c059 Gerd Hoffmann
}
599 0b06c059 Gerd Hoffmann
600 430ee2f2 Paolo Bonzini
static inline bool media_is_dvd(SCSIDiskState *s)
601 430ee2f2 Paolo Bonzini
{
602 430ee2f2 Paolo Bonzini
    uint64_t nb_sectors;
603 430ee2f2 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
604 430ee2f2 Paolo Bonzini
        return false;
605 430ee2f2 Paolo Bonzini
    }
606 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
607 430ee2f2 Paolo Bonzini
        return false;
608 430ee2f2 Paolo Bonzini
    }
609 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
610 430ee2f2 Paolo Bonzini
    return nb_sectors > CD_MAX_SECTORS;
611 430ee2f2 Paolo Bonzini
}
612 430ee2f2 Paolo Bonzini
613 ceb792ef Paolo Bonzini
static inline bool media_is_cd(SCSIDiskState *s)
614 ceb792ef Paolo Bonzini
{
615 ceb792ef Paolo Bonzini
    uint64_t nb_sectors;
616 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
617 ceb792ef Paolo Bonzini
        return false;
618 ceb792ef Paolo Bonzini
    }
619 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
620 ceb792ef Paolo Bonzini
        return false;
621 ceb792ef Paolo Bonzini
    }
622 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
623 ceb792ef Paolo Bonzini
    return nb_sectors <= CD_MAX_SECTORS;
624 ceb792ef Paolo Bonzini
}
625 ceb792ef Paolo Bonzini
626 b6c251ab Paolo Bonzini
static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
627 b6c251ab Paolo Bonzini
                                   uint8_t *outbuf)
628 b6c251ab Paolo Bonzini
{
629 ceb792ef Paolo Bonzini
    static const int rds_caps_size[5] = {
630 ceb792ef Paolo Bonzini
        [0] = 2048 + 4,
631 ceb792ef Paolo Bonzini
        [1] = 4 + 4,
632 ceb792ef Paolo Bonzini
        [3] = 188 + 4,
633 ceb792ef Paolo Bonzini
        [4] = 2048 + 4,
634 ceb792ef Paolo Bonzini
    };
635 ceb792ef Paolo Bonzini
636 ceb792ef Paolo Bonzini
    uint8_t media = r->req.cmd.buf[1];
637 ceb792ef Paolo Bonzini
    uint8_t layer = r->req.cmd.buf[6];
638 ceb792ef Paolo Bonzini
    uint8_t format = r->req.cmd.buf[7];
639 ceb792ef Paolo Bonzini
    int size = -1;
640 ceb792ef Paolo Bonzini
641 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
642 ceb792ef Paolo Bonzini
        return -1;
643 ceb792ef Paolo Bonzini
    }
644 ceb792ef Paolo Bonzini
    if (media != 0) {
645 ceb792ef Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
646 ceb792ef Paolo Bonzini
        return -1;
647 ceb792ef Paolo Bonzini
    }
648 ceb792ef Paolo Bonzini
649 ceb792ef Paolo Bonzini
    if (format != 0xff) {
650 44740c38 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
651 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
652 ceb792ef Paolo Bonzini
            return -1;
653 ceb792ef Paolo Bonzini
        }
654 ceb792ef Paolo Bonzini
        if (media_is_cd(s)) {
655 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
656 ceb792ef Paolo Bonzini
            return -1;
657 ceb792ef Paolo Bonzini
        }
658 ceb792ef Paolo Bonzini
        if (format >= ARRAY_SIZE(rds_caps_size)) {
659 ceb792ef Paolo Bonzini
            return -1;
660 ceb792ef Paolo Bonzini
        }
661 ceb792ef Paolo Bonzini
        size = rds_caps_size[format];
662 ceb792ef Paolo Bonzini
        memset(outbuf, 0, size);
663 ceb792ef Paolo Bonzini
    }
664 ceb792ef Paolo Bonzini
665 ceb792ef Paolo Bonzini
    switch (format) {
666 ceb792ef Paolo Bonzini
    case 0x00: {
667 ceb792ef Paolo Bonzini
        /* Physical format information */
668 ceb792ef Paolo Bonzini
        uint64_t nb_sectors;
669 ceb792ef Paolo Bonzini
        if (layer != 0) {
670 ceb792ef Paolo Bonzini
            goto fail;
671 ceb792ef Paolo Bonzini
        }
672 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
673 ceb792ef Paolo Bonzini
674 ceb792ef Paolo Bonzini
        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
675 ceb792ef Paolo Bonzini
        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
676 ceb792ef Paolo Bonzini
        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
677 ceb792ef Paolo Bonzini
        outbuf[7] = 0;   /* default densities */
678 ceb792ef Paolo Bonzini
679 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
680 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
681 ceb792ef Paolo Bonzini
        break;
682 ceb792ef Paolo Bonzini
    }
683 ceb792ef Paolo Bonzini
684 ceb792ef Paolo Bonzini
    case 0x01: /* DVD copyright information, all zeros */
685 ceb792ef Paolo Bonzini
        break;
686 ceb792ef Paolo Bonzini
687 ceb792ef Paolo Bonzini
    case 0x03: /* BCA information - invalid field for no BCA info */
688 ceb792ef Paolo Bonzini
        return -1;
689 ceb792ef Paolo Bonzini
690 ceb792ef Paolo Bonzini
    case 0x04: /* DVD disc manufacturing information, all zeros */
691 ceb792ef Paolo Bonzini
        break;
692 ceb792ef Paolo Bonzini
693 ceb792ef Paolo Bonzini
    case 0xff: { /* List capabilities */
694 ceb792ef Paolo Bonzini
        int i;
695 ceb792ef Paolo Bonzini
        size = 4;
696 ceb792ef Paolo Bonzini
        for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
697 ceb792ef Paolo Bonzini
            if (!rds_caps_size[i]) {
698 ceb792ef Paolo Bonzini
                continue;
699 ceb792ef Paolo Bonzini
            }
700 ceb792ef Paolo Bonzini
            outbuf[size] = i;
701 ceb792ef Paolo Bonzini
            outbuf[size + 1] = 0x40; /* Not writable, readable */
702 ceb792ef Paolo Bonzini
            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
703 ceb792ef Paolo Bonzini
            size += 4;
704 ceb792ef Paolo Bonzini
        }
705 ceb792ef Paolo Bonzini
        break;
706 ceb792ef Paolo Bonzini
     }
707 ceb792ef Paolo Bonzini
708 ceb792ef Paolo Bonzini
    default:
709 ceb792ef Paolo Bonzini
        return -1;
710 ceb792ef Paolo Bonzini
    }
711 ceb792ef Paolo Bonzini
712 ceb792ef Paolo Bonzini
    /* Size of buffer, not including 2 byte size field */
713 ceb792ef Paolo Bonzini
    stw_be_p(outbuf, size - 2);
714 ceb792ef Paolo Bonzini
    return size;
715 ceb792ef Paolo Bonzini
716 ceb792ef Paolo Bonzini
fail:
717 b6c251ab Paolo Bonzini
    return -1;
718 b6c251ab Paolo Bonzini
}
719 b6c251ab Paolo Bonzini
720 3c2f7c12 Paolo Bonzini
static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
721 b6c251ab Paolo Bonzini
{
722 3c2f7c12 Paolo Bonzini
    uint8_t event_code, media_status;
723 3c2f7c12 Paolo Bonzini
724 3c2f7c12 Paolo Bonzini
    media_status = 0;
725 3c2f7c12 Paolo Bonzini
    if (s->tray_open) {
726 3c2f7c12 Paolo Bonzini
        media_status = MS_TRAY_OPEN;
727 44740c38 Paolo Bonzini
    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
728 3c2f7c12 Paolo Bonzini
        media_status = MS_MEDIA_PRESENT;
729 3c2f7c12 Paolo Bonzini
    }
730 3c2f7c12 Paolo Bonzini
731 3c2f7c12 Paolo Bonzini
    /* Event notification descriptor */
732 3c2f7c12 Paolo Bonzini
    event_code = MEC_NO_CHANGE;
733 4480de19 Paolo Bonzini
    if (media_status != MS_TRAY_OPEN) {
734 4480de19 Paolo Bonzini
        if (s->media_event) {
735 4480de19 Paolo Bonzini
            event_code = MEC_NEW_MEDIA;
736 4480de19 Paolo Bonzini
            s->media_event = false;
737 4480de19 Paolo Bonzini
        } else if (s->eject_request) {
738 4480de19 Paolo Bonzini
            event_code = MEC_EJECT_REQUESTED;
739 4480de19 Paolo Bonzini
            s->eject_request = false;
740 4480de19 Paolo Bonzini
        }
741 3c2f7c12 Paolo Bonzini
    }
742 3c2f7c12 Paolo Bonzini
743 3c2f7c12 Paolo Bonzini
    outbuf[0] = event_code;
744 3c2f7c12 Paolo Bonzini
    outbuf[1] = media_status;
745 3c2f7c12 Paolo Bonzini
746 3c2f7c12 Paolo Bonzini
    /* These fields are reserved, just clear them. */
747 3c2f7c12 Paolo Bonzini
    outbuf[2] = 0;
748 3c2f7c12 Paolo Bonzini
    outbuf[3] = 0;
749 3c2f7c12 Paolo Bonzini
    return 4;
750 3c2f7c12 Paolo Bonzini
}
751 3c2f7c12 Paolo Bonzini
752 3c2f7c12 Paolo Bonzini
static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
753 3c2f7c12 Paolo Bonzini
                                              uint8_t *outbuf)
754 3c2f7c12 Paolo Bonzini
{
755 3c2f7c12 Paolo Bonzini
    int size;
756 3c2f7c12 Paolo Bonzini
    uint8_t *buf = r->req.cmd.buf;
757 3c2f7c12 Paolo Bonzini
    uint8_t notification_class_request = buf[4];
758 3c2f7c12 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
759 3c2f7c12 Paolo Bonzini
        return -1;
760 3c2f7c12 Paolo Bonzini
    }
761 3c2f7c12 Paolo Bonzini
    if ((buf[1] & 1) == 0) {
762 3c2f7c12 Paolo Bonzini
        /* asynchronous */
763 3c2f7c12 Paolo Bonzini
        return -1;
764 3c2f7c12 Paolo Bonzini
    }
765 3c2f7c12 Paolo Bonzini
766 3c2f7c12 Paolo Bonzini
    size = 4;
767 3c2f7c12 Paolo Bonzini
    outbuf[0] = outbuf[1] = 0;
768 3c2f7c12 Paolo Bonzini
    outbuf[3] = 1 << GESN_MEDIA; /* supported events */
769 3c2f7c12 Paolo Bonzini
    if (notification_class_request & (1 << GESN_MEDIA)) {
770 3c2f7c12 Paolo Bonzini
        outbuf[2] = GESN_MEDIA;
771 3c2f7c12 Paolo Bonzini
        size += scsi_event_status_media(s, &outbuf[size]);
772 3c2f7c12 Paolo Bonzini
    } else {
773 3c2f7c12 Paolo Bonzini
        outbuf[2] = 0x80;
774 3c2f7c12 Paolo Bonzini
    }
775 3c2f7c12 Paolo Bonzini
    stw_be_p(outbuf, size - 4);
776 3c2f7c12 Paolo Bonzini
    return size;
777 b6c251ab Paolo Bonzini
}
778 b6c251ab Paolo Bonzini
779 430ee2f2 Paolo Bonzini
static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
780 b6c251ab Paolo Bonzini
{
781 430ee2f2 Paolo Bonzini
    int current;
782 430ee2f2 Paolo Bonzini
783 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
784 b6c251ab Paolo Bonzini
        return -1;
785 b6c251ab Paolo Bonzini
    }
786 430ee2f2 Paolo Bonzini
    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
787 430ee2f2 Paolo Bonzini
    memset(outbuf, 0, 40);
788 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
789 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[6], current);
790 430ee2f2 Paolo Bonzini
    /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
791 430ee2f2 Paolo Bonzini
    outbuf[10] = 0x03; /* persistent, current */
792 430ee2f2 Paolo Bonzini
    outbuf[11] = 8; /* two profiles */
793 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
794 430ee2f2 Paolo Bonzini
    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
795 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
796 430ee2f2 Paolo Bonzini
    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
797 430ee2f2 Paolo Bonzini
    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
798 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[20], 1);
799 430ee2f2 Paolo Bonzini
    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
800 430ee2f2 Paolo Bonzini
    outbuf[23] = 8;
801 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[24], 1); /* SCSI */
802 430ee2f2 Paolo Bonzini
    outbuf[28] = 1; /* DBE = 1, mandatory */
803 430ee2f2 Paolo Bonzini
    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
804 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[32], 3);
805 430ee2f2 Paolo Bonzini
    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
806 430ee2f2 Paolo Bonzini
    outbuf[35] = 4;
807 430ee2f2 Paolo Bonzini
    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
808 430ee2f2 Paolo Bonzini
    /* TODO: Random readable, CD read, DVD read, drive serial number,
809 430ee2f2 Paolo Bonzini
       power management */
810 430ee2f2 Paolo Bonzini
    return 40;
811 b6c251ab Paolo Bonzini
}
812 b6c251ab Paolo Bonzini
813 b6c251ab Paolo Bonzini
static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
814 b6c251ab Paolo Bonzini
{
815 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
816 b6c251ab Paolo Bonzini
        return -1;
817 b6c251ab Paolo Bonzini
    }
818 b6c251ab Paolo Bonzini
    memset(outbuf, 0, 8);
819 b6c251ab Paolo Bonzini
    outbuf[5] = 1; /* CD-ROM */
820 b6c251ab Paolo Bonzini
    return 8;
821 b6c251ab Paolo Bonzini
}
822 b6c251ab Paolo Bonzini
823 cfc606da Paolo Bonzini
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
824 282ab04e Bernhard Kohl
                           int page_control)
825 ebddfcbe Gerd Hoffmann
{
826 a8f4bbe2 Paolo Bonzini
    static const int mode_sense_valid[0x3f] = {
827 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
828 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
829 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
830 a07c7dcd Paolo Bonzini
        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
831 a07c7dcd Paolo Bonzini
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
832 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
833 a8f4bbe2 Paolo Bonzini
    };
834 a8f4bbe2 Paolo Bonzini
835 44740c38 Paolo Bonzini
    BlockDriverState *bdrv = s->qdev.conf.bs;
836 ebddfcbe Gerd Hoffmann
    int cylinders, heads, secs;
837 cfc606da Paolo Bonzini
    uint8_t *p = *p_outbuf;
838 ebddfcbe Gerd Hoffmann
839 a8f4bbe2 Paolo Bonzini
    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
840 a8f4bbe2 Paolo Bonzini
        return -1;
841 a8f4bbe2 Paolo Bonzini
    }
842 a8f4bbe2 Paolo Bonzini
843 a8f4bbe2 Paolo Bonzini
    p[0] = page;
844 a8f4bbe2 Paolo Bonzini
845 282ab04e Bernhard Kohl
    /*
846 282ab04e Bernhard Kohl
     * If Changeable Values are requested, a mask denoting those mode parameters
847 282ab04e Bernhard Kohl
     * that are changeable shall be returned. As we currently don't support
848 282ab04e Bernhard Kohl
     * parameter changes via MODE_SELECT all bits are returned set to zero.
849 282ab04e Bernhard Kohl
     * The buffer was already menset to zero by the caller of this function.
850 282ab04e Bernhard Kohl
     */
851 ebddfcbe Gerd Hoffmann
    switch (page) {
852 67cc61e4 Paolo Bonzini
    case MODE_PAGE_HD_GEOMETRY:
853 ebddfcbe Gerd Hoffmann
        p[1] = 0x16;
854 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
855 cfc606da Paolo Bonzini
            break;
856 282ab04e Bernhard Kohl
        }
857 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
858 245d0049 Paolo Bonzini
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
859 ebddfcbe Gerd Hoffmann
        p[2] = (cylinders >> 16) & 0xff;
860 ebddfcbe Gerd Hoffmann
        p[3] = (cylinders >> 8) & 0xff;
861 ebddfcbe Gerd Hoffmann
        p[4] = cylinders & 0xff;
862 ebddfcbe Gerd Hoffmann
        p[5] = heads & 0xff;
863 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
864 ebddfcbe Gerd Hoffmann
        p[6] = (cylinders >> 16) & 0xff;
865 ebddfcbe Gerd Hoffmann
        p[7] = (cylinders >> 8) & 0xff;
866 ebddfcbe Gerd Hoffmann
        p[8] = cylinders & 0xff;
867 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
868 ebddfcbe Gerd Hoffmann
        p[9] = (cylinders >> 16) & 0xff;
869 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
870 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
871 ebddfcbe Gerd Hoffmann
        /* Device step rate [ns], 200ns */
872 ebddfcbe Gerd Hoffmann
        p[12] = 0;
873 ebddfcbe Gerd Hoffmann
        p[13] = 200;
874 ebddfcbe Gerd Hoffmann
        /* Landing zone cylinder */
875 ebddfcbe Gerd Hoffmann
        p[14] = 0xff;
876 ebddfcbe Gerd Hoffmann
        p[15] =  0xff;
877 ebddfcbe Gerd Hoffmann
        p[16] = 0xff;
878 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
879 ebddfcbe Gerd Hoffmann
        p[20] = (5400 >> 8) & 0xff;
880 ebddfcbe Gerd Hoffmann
        p[21] = 5400 & 0xff;
881 cfc606da Paolo Bonzini
        break;
882 ebddfcbe Gerd Hoffmann
883 67cc61e4 Paolo Bonzini
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
884 ebddfcbe Gerd Hoffmann
        p[1] = 0x1e;
885 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
886 cfc606da Paolo Bonzini
            break;
887 282ab04e Bernhard Kohl
        }
888 ebddfcbe Gerd Hoffmann
        /* Transfer rate [kbit/s], 5Mbit/s */
889 ebddfcbe Gerd Hoffmann
        p[2] = 5000 >> 8;
890 ebddfcbe Gerd Hoffmann
        p[3] = 5000 & 0xff;
891 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
892 245d0049 Paolo Bonzini
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
893 ebddfcbe Gerd Hoffmann
        p[4] = heads & 0xff;
894 ebddfcbe Gerd Hoffmann
        p[5] = secs & 0xff;
895 69377307 Paolo Bonzini
        p[6] = s->qdev.blocksize >> 8;
896 ebddfcbe Gerd Hoffmann
        p[8] = (cylinders >> 8) & 0xff;
897 ebddfcbe Gerd Hoffmann
        p[9] = cylinders & 0xff;
898 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
899 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
900 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
901 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
902 ebddfcbe Gerd Hoffmann
        p[12] = (cylinders >> 8) & 0xff;
903 ebddfcbe Gerd Hoffmann
        p[13] = cylinders & 0xff;
904 ebddfcbe Gerd Hoffmann
        /* Device step rate [100us], 100us */
905 ebddfcbe Gerd Hoffmann
        p[14] = 0;
906 ebddfcbe Gerd Hoffmann
        p[15] = 1;
907 ebddfcbe Gerd Hoffmann
        /* Device step pulse width [us], 1us */
908 ebddfcbe Gerd Hoffmann
        p[16] = 1;
909 ebddfcbe Gerd Hoffmann
        /* Device head settle delay [100us], 100us */
910 ebddfcbe Gerd Hoffmann
        p[17] = 0;
911 ebddfcbe Gerd Hoffmann
        p[18] = 1;
912 ebddfcbe Gerd Hoffmann
        /* Motor on delay [0.1s], 0.1s */
913 ebddfcbe Gerd Hoffmann
        p[19] = 1;
914 ebddfcbe Gerd Hoffmann
        /* Motor off delay [0.1s], 0.1s */
915 ebddfcbe Gerd Hoffmann
        p[20] = 1;
916 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
917 ebddfcbe Gerd Hoffmann
        p[28] = (5400 >> 8) & 0xff;
918 ebddfcbe Gerd Hoffmann
        p[29] = 5400 & 0xff;
919 cfc606da Paolo Bonzini
        break;
920 ebddfcbe Gerd Hoffmann
921 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CACHING:
922 ebddfcbe Gerd Hoffmann
        p[0] = 8;
923 ebddfcbe Gerd Hoffmann
        p[1] = 0x12;
924 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
925 cfc606da Paolo Bonzini
            break;
926 282ab04e Bernhard Kohl
        }
927 44740c38 Paolo Bonzini
        if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
928 ebddfcbe Gerd Hoffmann
            p[2] = 4; /* WCE */
929 ebddfcbe Gerd Hoffmann
        }
930 cfc606da Paolo Bonzini
        break;
931 ebddfcbe Gerd Hoffmann
932 a07c7dcd Paolo Bonzini
    case MODE_PAGE_R_W_ERROR:
933 a07c7dcd Paolo Bonzini
        p[1] = 10;
934 a07c7dcd Paolo Bonzini
        p[2] = 0x80; /* Automatic Write Reallocation Enabled */
935 a07c7dcd Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
936 a07c7dcd Paolo Bonzini
            p[3] = 0x20; /* Read Retry Count */
937 a07c7dcd Paolo Bonzini
        }
938 a07c7dcd Paolo Bonzini
        break;
939 a07c7dcd Paolo Bonzini
940 a07c7dcd Paolo Bonzini
    case MODE_PAGE_AUDIO_CTL:
941 a07c7dcd Paolo Bonzini
        p[1] = 14;
942 a07c7dcd Paolo Bonzini
        break;
943 a07c7dcd Paolo Bonzini
944 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CAPABILITIES:
945 ebddfcbe Gerd Hoffmann
        p[1] = 0x14;
946 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
947 cfc606da Paolo Bonzini
            break;
948 282ab04e Bernhard Kohl
        }
949 a07c7dcd Paolo Bonzini
950 a07c7dcd Paolo Bonzini
        p[2] = 0x3b; /* CD-R & CD-RW read */
951 a07c7dcd Paolo Bonzini
        p[3] = 0; /* Writing not supported */
952 ebddfcbe Gerd Hoffmann
        p[4] = 0x7f; /* Audio, composite, digital out,
953 ebddfcbe Gerd Hoffmann
                        mode 2 form 1&2, multi session */
954 ebddfcbe Gerd Hoffmann
        p[5] = 0xff; /* CD DA, DA accurate, RW supported,
955 ebddfcbe Gerd Hoffmann
                        RW corrected, C2 errors, ISRC,
956 ebddfcbe Gerd Hoffmann
                        UPC, Bar code */
957 81b1008d Markus Armbruster
        p[6] = 0x2d | (s->tray_locked ? 2 : 0);
958 ebddfcbe Gerd Hoffmann
        /* Locking supported, jumper present, eject, tray */
959 ebddfcbe Gerd Hoffmann
        p[7] = 0; /* no volume & mute control, no
960 ebddfcbe Gerd Hoffmann
                     changer */
961 a07c7dcd Paolo Bonzini
        p[8] = (50 * 176) >> 8; /* 50x read speed */
962 ebddfcbe Gerd Hoffmann
        p[9] = (50 * 176) & 0xff;
963 a07c7dcd Paolo Bonzini
        p[10] = 2 >> 8; /* Two volume levels */
964 a07c7dcd Paolo Bonzini
        p[11] = 2 & 0xff;
965 a07c7dcd Paolo Bonzini
        p[12] = 2048 >> 8; /* 2M buffer */
966 ebddfcbe Gerd Hoffmann
        p[13] = 2048 & 0xff;
967 a07c7dcd Paolo Bonzini
        p[14] = (16 * 176) >> 8; /* 16x read speed current */
968 ebddfcbe Gerd Hoffmann
        p[15] = (16 * 176) & 0xff;
969 a07c7dcd Paolo Bonzini
        p[18] = (16 * 176) >> 8; /* 16x write speed */
970 ebddfcbe Gerd Hoffmann
        p[19] = (16 * 176) & 0xff;
971 a07c7dcd Paolo Bonzini
        p[20] = (16 * 176) >> 8; /* 16x write speed current */
972 ebddfcbe Gerd Hoffmann
        p[21] = (16 * 176) & 0xff;
973 cfc606da Paolo Bonzini
        break;
974 ebddfcbe Gerd Hoffmann
975 ebddfcbe Gerd Hoffmann
    default:
976 cfc606da Paolo Bonzini
        return -1;
977 ebddfcbe Gerd Hoffmann
    }
978 cfc606da Paolo Bonzini
979 cfc606da Paolo Bonzini
    *p_outbuf += p[1] + 2;
980 cfc606da Paolo Bonzini
    return p[1] + 2;
981 ebddfcbe Gerd Hoffmann
}
982 ebddfcbe Gerd Hoffmann
983 cfc606da Paolo Bonzini
static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
984 ebddfcbe Gerd Hoffmann
{
985 cfc606da Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
986 ebddfcbe Gerd Hoffmann
    uint64_t nb_sectors;
987 cfc606da Paolo Bonzini
    int page, dbd, buflen, ret, page_control;
988 ebddfcbe Gerd Hoffmann
    uint8_t *p;
989 ce512ee1 Bernhard Kohl
    uint8_t dev_specific_param;
990 ebddfcbe Gerd Hoffmann
991 cfc606da Paolo Bonzini
    dbd = r->req.cmd.buf[1]  & 0x8;
992 cfc606da Paolo Bonzini
    page = r->req.cmd.buf[2] & 0x3f;
993 cfc606da Paolo Bonzini
    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
994 aa2b1e89 Bernhard Kohl
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
995 cfc606da Paolo Bonzini
        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
996 cfc606da Paolo Bonzini
    memset(outbuf, 0, r->req.cmd.xfer);
997 ebddfcbe Gerd Hoffmann
    p = outbuf;
998 ebddfcbe Gerd Hoffmann
999 44740c38 Paolo Bonzini
    if (bdrv_is_read_only(s->qdev.conf.bs)) {
1000 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x80; /* Readonly.  */
1001 ce512ee1 Bernhard Kohl
    } else {
1002 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x00;
1003 ce512ee1 Bernhard Kohl
    }
1004 ce512ee1 Bernhard Kohl
1005 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1006 ce512ee1 Bernhard Kohl
        p[1] = 0; /* Default media type.  */
1007 ce512ee1 Bernhard Kohl
        p[2] = dev_specific_param;
1008 ce512ee1 Bernhard Kohl
        p[3] = 0; /* Block descriptor length.  */
1009 ce512ee1 Bernhard Kohl
        p += 4;
1010 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1011 ce512ee1 Bernhard Kohl
        p[2] = 0; /* Default media type.  */
1012 ce512ee1 Bernhard Kohl
        p[3] = dev_specific_param;
1013 ce512ee1 Bernhard Kohl
        p[6] = p[7] = 0; /* Block descriptor length.  */
1014 ce512ee1 Bernhard Kohl
        p += 8;
1015 ebddfcbe Gerd Hoffmann
    }
1016 ebddfcbe Gerd Hoffmann
1017 0fd76ff4 Paolo Bonzini
    /* MMC prescribes that CD/DVD drives have no block descriptors.  */
1018 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1019 0fd76ff4 Paolo Bonzini
    if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
1020 cfc606da Paolo Bonzini
        if (r->req.cmd.buf[0] == MODE_SENSE) {
1021 ce512ee1 Bernhard Kohl
            outbuf[3] = 8; /* Block descriptor length  */
1022 ce512ee1 Bernhard Kohl
        } else { /* MODE_SENSE_10 */
1023 ce512ee1 Bernhard Kohl
            outbuf[7] = 8; /* Block descriptor length  */
1024 ce512ee1 Bernhard Kohl
        }
1025 69377307 Paolo Bonzini
        nb_sectors /= (s->qdev.blocksize / 512);
1026 f01b5931 Paolo Bonzini
        if (nb_sectors > 0xffffff) {
1027 2488b740 Bernhard Kohl
            nb_sectors = 0;
1028 f01b5931 Paolo Bonzini
        }
1029 ebddfcbe Gerd Hoffmann
        p[0] = 0; /* media density code */
1030 ebddfcbe Gerd Hoffmann
        p[1] = (nb_sectors >> 16) & 0xff;
1031 ebddfcbe Gerd Hoffmann
        p[2] = (nb_sectors >> 8) & 0xff;
1032 ebddfcbe Gerd Hoffmann
        p[3] = nb_sectors & 0xff;
1033 ebddfcbe Gerd Hoffmann
        p[4] = 0; /* reserved */
1034 ebddfcbe Gerd Hoffmann
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
1035 69377307 Paolo Bonzini
        p[6] = s->qdev.blocksize >> 8;
1036 ebddfcbe Gerd Hoffmann
        p[7] = 0;
1037 ebddfcbe Gerd Hoffmann
        p += 8;
1038 ebddfcbe Gerd Hoffmann
    }
1039 ebddfcbe Gerd Hoffmann
1040 cfc606da Paolo Bonzini
    if (page_control == 3) {
1041 cfc606da Paolo Bonzini
        /* Saved Values */
1042 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
1043 cfc606da Paolo Bonzini
        return -1;
1044 282ab04e Bernhard Kohl
    }
1045 282ab04e Bernhard Kohl
1046 cfc606da Paolo Bonzini
    if (page == 0x3f) {
1047 cfc606da Paolo Bonzini
        for (page = 0; page <= 0x3e; page++) {
1048 cfc606da Paolo Bonzini
            mode_sense_page(s, page, &p, page_control);
1049 cfc606da Paolo Bonzini
        }
1050 cfc606da Paolo Bonzini
    } else {
1051 cfc606da Paolo Bonzini
        ret = mode_sense_page(s, page, &p, page_control);
1052 cfc606da Paolo Bonzini
        if (ret == -1) {
1053 cfc606da Paolo Bonzini
            return -1;
1054 cfc606da Paolo Bonzini
        }
1055 ebddfcbe Gerd Hoffmann
    }
1056 ebddfcbe Gerd Hoffmann
1057 ebddfcbe Gerd Hoffmann
    buflen = p - outbuf;
1058 ce512ee1 Bernhard Kohl
    /*
1059 ce512ee1 Bernhard Kohl
     * The mode data length field specifies the length in bytes of the
1060 ce512ee1 Bernhard Kohl
     * following data that is available to be transferred. The mode data
1061 ce512ee1 Bernhard Kohl
     * length does not include itself.
1062 ce512ee1 Bernhard Kohl
     */
1063 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1064 ce512ee1 Bernhard Kohl
        outbuf[0] = buflen - 1;
1065 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1066 ce512ee1 Bernhard Kohl
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1067 ce512ee1 Bernhard Kohl
        outbuf[1] = (buflen - 2) & 0xff;
1068 ce512ee1 Bernhard Kohl
    }
1069 ebddfcbe Gerd Hoffmann
    return buflen;
1070 ebddfcbe Gerd Hoffmann
}
1071 ebddfcbe Gerd Hoffmann
1072 02880f43 Gerd Hoffmann
static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1073 02880f43 Gerd Hoffmann
{
1074 02880f43 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1075 02880f43 Gerd Hoffmann
    int start_track, format, msf, toclen;
1076 02880f43 Gerd Hoffmann
    uint64_t nb_sectors;
1077 02880f43 Gerd Hoffmann
1078 02880f43 Gerd Hoffmann
    msf = req->cmd.buf[1] & 2;
1079 02880f43 Gerd Hoffmann
    format = req->cmd.buf[2] & 0xf;
1080 02880f43 Gerd Hoffmann
    start_track = req->cmd.buf[6];
1081 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1082 02880f43 Gerd Hoffmann
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
1083 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1084 02880f43 Gerd Hoffmann
    switch (format) {
1085 02880f43 Gerd Hoffmann
    case 0:
1086 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1087 02880f43 Gerd Hoffmann
        break;
1088 02880f43 Gerd Hoffmann
    case 1:
1089 02880f43 Gerd Hoffmann
        /* multi session : only a single session defined */
1090 02880f43 Gerd Hoffmann
        toclen = 12;
1091 02880f43 Gerd Hoffmann
        memset(outbuf, 0, 12);
1092 02880f43 Gerd Hoffmann
        outbuf[1] = 0x0a;
1093 02880f43 Gerd Hoffmann
        outbuf[2] = 0x01;
1094 02880f43 Gerd Hoffmann
        outbuf[3] = 0x01;
1095 02880f43 Gerd Hoffmann
        break;
1096 02880f43 Gerd Hoffmann
    case 2:
1097 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1098 02880f43 Gerd Hoffmann
        break;
1099 02880f43 Gerd Hoffmann
    default:
1100 02880f43 Gerd Hoffmann
        return -1;
1101 02880f43 Gerd Hoffmann
    }
1102 02880f43 Gerd Hoffmann
    return toclen;
1103 02880f43 Gerd Hoffmann
}
1104 02880f43 Gerd Hoffmann
1105 68bb01f3 Markus Armbruster
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
1106 bfd52647 Markus Armbruster
{
1107 bfd52647 Markus Armbruster
    SCSIRequest *req = &r->req;
1108 bfd52647 Markus Armbruster
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1109 bfd52647 Markus Armbruster
    bool start = req->cmd.buf[4] & 1;
1110 bfd52647 Markus Armbruster
    bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
1111 bfd52647 Markus Armbruster
1112 bfd52647 Markus Armbruster
    if (s->qdev.type == TYPE_ROM && loej) {
1113 68bb01f3 Markus Armbruster
        if (!start && !s->tray_open && s->tray_locked) {
1114 68bb01f3 Markus Armbruster
            scsi_check_condition(r,
1115 44740c38 Paolo Bonzini
                                 bdrv_is_inserted(s->qdev.conf.bs)
1116 68bb01f3 Markus Armbruster
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1117 68bb01f3 Markus Armbruster
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1118 68bb01f3 Markus Armbruster
            return -1;
1119 fdec4404 Markus Armbruster
        }
1120 d88b1819 Luiz Capitulino
1121 d88b1819 Luiz Capitulino
        if (s->tray_open != !start) {
1122 d88b1819 Luiz Capitulino
            bdrv_eject(s->qdev.conf.bs, !start);
1123 d88b1819 Luiz Capitulino
            s->tray_open = !start;
1124 d88b1819 Luiz Capitulino
        }
1125 bfd52647 Markus Armbruster
    }
1126 68bb01f3 Markus Armbruster
    return 0;
1127 bfd52647 Markus Armbruster
}
1128 bfd52647 Markus Armbruster
1129 7285477a Paolo Bonzini
static int scsi_disk_emulate_command(SCSIDiskReq *r)
1130 aa5dbdc1 Gerd Hoffmann
{
1131 8af7a3ab Kevin Wolf
    SCSIRequest *req = &r->req;
1132 e7e25e32 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1133 e7e25e32 Gerd Hoffmann
    uint64_t nb_sectors;
1134 7285477a Paolo Bonzini
    uint8_t *outbuf;
1135 aa5dbdc1 Gerd Hoffmann
    int buflen = 0;
1136 aa5dbdc1 Gerd Hoffmann
1137 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
1138 7285477a Paolo Bonzini
        /*
1139 7285477a Paolo Bonzini
         * FIXME: we shouldn't return anything bigger than 4k, but the code
1140 7285477a Paolo Bonzini
         * requires the buffer to be as big as req->cmd.xfer in several
1141 7285477a Paolo Bonzini
         * places.  So, do not allow CDBs with a very large ALLOCATION
1142 7285477a Paolo Bonzini
         * LENGTH.  The real fix would be to modify scsi_read_data and
1143 7285477a Paolo Bonzini
         * dma_buf_read, so that they return data beyond the buflen
1144 7285477a Paolo Bonzini
         * as all zeros.
1145 7285477a Paolo Bonzini
         */
1146 7285477a Paolo Bonzini
        if (req->cmd.xfer > 65536) {
1147 7285477a Paolo Bonzini
            goto illegal_request;
1148 7285477a Paolo Bonzini
        }
1149 7285477a Paolo Bonzini
        r->buflen = MAX(4096, req->cmd.xfer);
1150 44740c38 Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
1151 7285477a Paolo Bonzini
    }
1152 7285477a Paolo Bonzini
1153 7285477a Paolo Bonzini
    outbuf = r->iov.iov_base;
1154 aa5dbdc1 Gerd Hoffmann
    switch (req->cmd.buf[0]) {
1155 aa5dbdc1 Gerd Hoffmann
    case TEST_UNIT_READY:
1156 9bcaf4fe Paolo Bonzini
        assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
1157 5f71d32f Hannes Reinecke
        break;
1158 0b06c059 Gerd Hoffmann
    case INQUIRY:
1159 0b06c059 Gerd Hoffmann
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
1160 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1161 0b06c059 Gerd Hoffmann
            goto illegal_request;
1162 f01b5931 Paolo Bonzini
        }
1163 5f71d32f Hannes Reinecke
        break;
1164 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1165 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1166 cfc606da Paolo Bonzini
        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
1167 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1168 ebddfcbe Gerd Hoffmann
            goto illegal_request;
1169 f01b5931 Paolo Bonzini
        }
1170 ebddfcbe Gerd Hoffmann
        break;
1171 02880f43 Gerd Hoffmann
    case READ_TOC:
1172 02880f43 Gerd Hoffmann
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
1173 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1174 02880f43 Gerd Hoffmann
            goto illegal_request;
1175 f01b5931 Paolo Bonzini
        }
1176 02880f43 Gerd Hoffmann
        break;
1177 3d53ba18 Gerd Hoffmann
    case RESERVE:
1178 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1179 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1180 f01b5931 Paolo Bonzini
        }
1181 3d53ba18 Gerd Hoffmann
        break;
1182 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1183 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1184 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1185 f01b5931 Paolo Bonzini
        }
1186 3d53ba18 Gerd Hoffmann
        break;
1187 3d53ba18 Gerd Hoffmann
    case RELEASE:
1188 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1189 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1190 f01b5931 Paolo Bonzini
        }
1191 3d53ba18 Gerd Hoffmann
        break;
1192 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1193 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1194 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1195 f01b5931 Paolo Bonzini
        }
1196 3d53ba18 Gerd Hoffmann
        break;
1197 8d3628ff Gerd Hoffmann
    case START_STOP:
1198 68bb01f3 Markus Armbruster
        if (scsi_disk_emulate_start_stop(r) < 0) {
1199 68bb01f3 Markus Armbruster
            return -1;
1200 68bb01f3 Markus Armbruster
        }
1201 5f71d32f Hannes Reinecke
        break;
1202 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1203 81b1008d Markus Armbruster
        s->tray_locked = req->cmd.buf[4] & 1;
1204 44740c38 Paolo Bonzini
        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
1205 5f71d32f Hannes Reinecke
        break;
1206 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1207 e7e25e32 Gerd Hoffmann
        /* The normal LEN field for this command is zero.  */
1208 5f71d32f Hannes Reinecke
        memset(outbuf, 0, 8);
1209 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1210 f01b5931 Paolo Bonzini
        if (!nb_sectors) {
1211 9bcaf4fe Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1212 9bcaf4fe Paolo Bonzini
            return -1;
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 9bcaf4fe Paolo Bonzini
                scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1273 9bcaf4fe Paolo Bonzini
                return -1;
1274 f01b5931 Paolo Bonzini
            }
1275 7cec78b6 Paolo Bonzini
            if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1276 7cec78b6 Paolo Bonzini
                goto illegal_request;
1277 7cec78b6 Paolo Bonzini
            }
1278 69377307 Paolo Bonzini
            nb_sectors /= s->qdev.blocksize / 512;
1279 5dd90e2a Gerd Hoffmann
            /* Returned value is the address of the last sector.  */
1280 5dd90e2a Gerd Hoffmann
            nb_sectors--;
1281 5dd90e2a Gerd Hoffmann
            /* Remember the new size for read/write sanity checking. */
1282 7877903a Paolo Bonzini
            s->qdev.max_lba = nb_sectors;
1283 5dd90e2a Gerd Hoffmann
            outbuf[0] = (nb_sectors >> 56) & 0xff;
1284 5dd90e2a Gerd Hoffmann
            outbuf[1] = (nb_sectors >> 48) & 0xff;
1285 5dd90e2a Gerd Hoffmann
            outbuf[2] = (nb_sectors >> 40) & 0xff;
1286 5dd90e2a Gerd Hoffmann
            outbuf[3] = (nb_sectors >> 32) & 0xff;
1287 5dd90e2a Gerd Hoffmann
            outbuf[4] = (nb_sectors >> 24) & 0xff;
1288 5dd90e2a Gerd Hoffmann
            outbuf[5] = (nb_sectors >> 16) & 0xff;
1289 5dd90e2a Gerd Hoffmann
            outbuf[6] = (nb_sectors >> 8) & 0xff;
1290 5dd90e2a Gerd Hoffmann
            outbuf[7] = nb_sectors & 0xff;
1291 5dd90e2a Gerd Hoffmann
            outbuf[8] = 0;
1292 5dd90e2a Gerd Hoffmann
            outbuf[9] = 0;
1293 69377307 Paolo Bonzini
            outbuf[10] = s->qdev.blocksize >> 8;
1294 5dd90e2a Gerd Hoffmann
            outbuf[11] = 0;
1295 ee3659e3 Christoph Hellwig
            outbuf[12] = 0;
1296 ee3659e3 Christoph Hellwig
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
1297 ea3bd56f Christoph Hellwig
1298 ea3bd56f Christoph Hellwig
            /* set TPE bit if the format supports discard */
1299 ea3bd56f Christoph Hellwig
            if (s->qdev.conf.discard_granularity) {
1300 ea3bd56f Christoph Hellwig
                outbuf[14] = 0x80;
1301 ea3bd56f Christoph Hellwig
            }
1302 ea3bd56f Christoph Hellwig
1303 5dd90e2a Gerd Hoffmann
            /* Protection, exponent and lowest lba field left blank. */
1304 5dd90e2a Gerd Hoffmann
            buflen = req->cmd.xfer;
1305 5dd90e2a Gerd Hoffmann
            break;
1306 5dd90e2a Gerd Hoffmann
        }
1307 5dd90e2a Gerd Hoffmann
        DPRINTF("Unsupported Service Action In\n");
1308 5dd90e2a Gerd Hoffmann
        goto illegal_request;
1309 5e30a07d Hannes Reinecke
    case VERIFY_10:
1310 88f8a5ed Gerd Hoffmann
        break;
1311 aa5dbdc1 Gerd Hoffmann
    default:
1312 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1313 a1f0cce2 Hannes Reinecke
        return -1;
1314 aa5dbdc1 Gerd Hoffmann
    }
1315 e2f0c49f Thomas Higdon
    buflen = MIN(buflen, req->cmd.xfer);
1316 aa5dbdc1 Gerd Hoffmann
    return buflen;
1317 aa5dbdc1 Gerd Hoffmann
1318 aa5dbdc1 Gerd Hoffmann
illegal_request:
1319 cfc606da Paolo Bonzini
    if (r->req.status == -1) {
1320 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1321 cfc606da Paolo Bonzini
    }
1322 8af7a3ab Kevin Wolf
    return -1;
1323 aa5dbdc1 Gerd Hoffmann
}
1324 aa5dbdc1 Gerd Hoffmann
1325 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
1326 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
1327 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
1328 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
1329 2e5d83bb pbrook
1330 5c6c0e51 Hannes Reinecke
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
1331 2e5d83bb pbrook
{
1332 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1333 5c6c0e51 Hannes Reinecke
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1334 ad2d30f7 Paolo Bonzini
    int32_t len;
1335 a917d384 pbrook
    uint8_t command;
1336 aa5dbdc1 Gerd Hoffmann
    int rc;
1337 a917d384 pbrook
1338 a917d384 pbrook
    command = buf[0];
1339 653c1c3f Hannes Reinecke
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
1340 2dd791b6 Hannes Reinecke
1341 2e5d83bb pbrook
#ifdef DEBUG_SCSI
1342 2e5d83bb pbrook
    {
1343 2e5d83bb pbrook
        int i;
1344 2dd791b6 Hannes Reinecke
        for (i = 1; i < r->req.cmd.len; i++) {
1345 2e5d83bb pbrook
            printf(" 0x%02x", buf[i]);
1346 2e5d83bb pbrook
        }
1347 2e5d83bb pbrook
        printf("\n");
1348 2e5d83bb pbrook
    }
1349 2e5d83bb pbrook
#endif
1350 aa5dbdc1 Gerd Hoffmann
1351 a917d384 pbrook
    switch (command) {
1352 9bcaf4fe Paolo Bonzini
    case INQUIRY:
1353 9bcaf4fe Paolo Bonzini
    case MODE_SENSE:
1354 9bcaf4fe Paolo Bonzini
    case MODE_SENSE_10:
1355 9bcaf4fe Paolo Bonzini
    case RESERVE:
1356 9bcaf4fe Paolo Bonzini
    case RESERVE_10:
1357 9bcaf4fe Paolo Bonzini
    case RELEASE:
1358 9bcaf4fe Paolo Bonzini
    case RELEASE_10:
1359 9bcaf4fe Paolo Bonzini
    case START_STOP:
1360 9bcaf4fe Paolo Bonzini
    case ALLOW_MEDIUM_REMOVAL:
1361 9bcaf4fe Paolo Bonzini
    case GET_CONFIGURATION:
1362 9bcaf4fe Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1363 9bcaf4fe Paolo Bonzini
    case MECHANISM_STATUS:
1364 9bcaf4fe Paolo Bonzini
    case REQUEST_SENSE:
1365 9bcaf4fe Paolo Bonzini
        break;
1366 9bcaf4fe Paolo Bonzini
1367 9bcaf4fe Paolo Bonzini
    default:
1368 9bcaf4fe Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1369 9bcaf4fe Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1370 9bcaf4fe Paolo Bonzini
            return 0;
1371 9bcaf4fe Paolo Bonzini
        }
1372 9bcaf4fe Paolo Bonzini
        break;
1373 9bcaf4fe Paolo Bonzini
    }
1374 9bcaf4fe Paolo Bonzini
1375 9bcaf4fe Paolo Bonzini
    switch (command) {
1376 ebf46023 Gerd Hoffmann
    case TEST_UNIT_READY:
1377 0b06c059 Gerd Hoffmann
    case INQUIRY:
1378 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1379 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1380 3d53ba18 Gerd Hoffmann
    case RESERVE:
1381 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1382 3d53ba18 Gerd Hoffmann
    case RELEASE:
1383 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1384 8d3628ff Gerd Hoffmann
    case START_STOP:
1385 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1386 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1387 02880f43 Gerd Hoffmann
    case READ_TOC:
1388 b6c251ab Paolo Bonzini
    case READ_DVD_STRUCTURE:
1389 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
1390 b6c251ab Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1391 b6c251ab Paolo Bonzini
    case MECHANISM_STATUS:
1392 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
1393 f3b338ef Paolo Bonzini
    case REQUEST_SENSE:
1394 5e30a07d Hannes Reinecke
    case VERIFY_10:
1395 7285477a Paolo Bonzini
        rc = scsi_disk_emulate_command(r);
1396 8af7a3ab Kevin Wolf
        if (rc < 0) {
1397 0b06c059 Gerd Hoffmann
            return 0;
1398 aa5dbdc1 Gerd Hoffmann
        }
1399 8af7a3ab Kevin Wolf
1400 8af7a3ab Kevin Wolf
        r->iov.iov_len = rc;
1401 0b06c059 Gerd Hoffmann
        break;
1402 0a4ac106 Paolo Bonzini
    case SYNCHRONIZE_CACHE:
1403 c7bae6a7 Paolo Bonzini
        /* The request is used as the AIO opaque value, so add a ref.  */
1404 c7bae6a7 Paolo Bonzini
        scsi_req_ref(&r->req);
1405 44740c38 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1406 44740c38 Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
1407 0a4ac106 Paolo Bonzini
        return 0;
1408 ebf46023 Gerd Hoffmann
    case READ_6:
1409 ebf46023 Gerd Hoffmann
    case READ_10:
1410 bd536cf3 Gerd Hoffmann
    case READ_12:
1411 bd536cf3 Gerd Hoffmann
    case READ_16:
1412 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1413 2dd791b6 Hannes Reinecke
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", 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 ebf46023 Gerd Hoffmann
    case WRITE_6:
1421 ebf46023 Gerd Hoffmann
    case WRITE_10:
1422 bd536cf3 Gerd Hoffmann
    case WRITE_12:
1423 bd536cf3 Gerd Hoffmann
    case WRITE_16:
1424 5e30a07d Hannes Reinecke
    case WRITE_VERIFY_10:
1425 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_12:
1426 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_16:
1427 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1428 ebef0bbb Bernhard Kohl
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1429 2dd791b6 Hannes Reinecke
                (command & 0xe) == 0xe ? "And Verify " : "",
1430 2dd791b6 Hannes Reinecke
                r->req.cmd.lba, len);
1431 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1432 274fb0e1 aliguori
            goto illegal_lba;
1433 f01b5931 Paolo Bonzini
        }
1434 69377307 Paolo Bonzini
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1435 69377307 Paolo Bonzini
        r->sector_count = len * (s->qdev.blocksize / 512);
1436 2e5d83bb pbrook
        break;
1437 ebef0bbb Bernhard Kohl
    case MODE_SELECT:
1438 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1439 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1440 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1441 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 12) {
1442 ebef0bbb Bernhard Kohl
            goto fail;
1443 ebef0bbb Bernhard Kohl
        }
1444 ebef0bbb Bernhard Kohl
        break;
1445 ebef0bbb Bernhard Kohl
    case MODE_SELECT_10:
1446 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1447 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1448 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1449 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 16) {
1450 ebef0bbb Bernhard Kohl
            goto fail;
1451 ebef0bbb Bernhard Kohl
        }
1452 ebef0bbb Bernhard Kohl
        break;
1453 ebef0bbb Bernhard Kohl
    case SEEK_10:
1454 00a01ad4 Paolo Bonzini
        DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
1455 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1456 ebef0bbb Bernhard Kohl
            goto illegal_lba;
1457 ebef0bbb Bernhard Kohl
        }
1458 ebef0bbb Bernhard Kohl
        break;
1459 ea3bd56f Christoph Hellwig
    case WRITE_SAME_16:
1460 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1461 ea3bd56f Christoph Hellwig
1462 ea3bd56f Christoph Hellwig
        DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
1463 ea3bd56f Christoph Hellwig
                r->req.cmd.lba, len);
1464 ea3bd56f Christoph Hellwig
1465 7877903a Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1466 ea3bd56f Christoph Hellwig
            goto illegal_lba;
1467 ea3bd56f Christoph Hellwig
        }
1468 ea3bd56f Christoph Hellwig
1469 ea3bd56f Christoph Hellwig
        /*
1470 ea3bd56f Christoph Hellwig
         * We only support WRITE SAME with the unmap bit set for now.
1471 ea3bd56f Christoph Hellwig
         */
1472 ea3bd56f Christoph Hellwig
        if (!(buf[1] & 0x8)) {
1473 ea3bd56f Christoph Hellwig
            goto fail;
1474 ea3bd56f Christoph Hellwig
        }
1475 ea3bd56f Christoph Hellwig
1476 69377307 Paolo Bonzini
        rc = bdrv_discard(s->qdev.conf.bs,
1477 69377307 Paolo Bonzini
                          r->req.cmd.lba * (s->qdev.blocksize / 512),
1478 69377307 Paolo Bonzini
                          len * (s->qdev.blocksize / 512));
1479 ea3bd56f Christoph Hellwig
        if (rc < 0) {
1480 ea3bd56f Christoph Hellwig
            /* XXX: better error code ?*/
1481 ea3bd56f Christoph Hellwig
            goto fail;
1482 ea3bd56f Christoph Hellwig
        }
1483 ea3bd56f Christoph Hellwig
1484 ea3bd56f Christoph Hellwig
        break;
1485 2e5d83bb pbrook
    default:
1486 2dd791b6 Hannes Reinecke
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1487 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1488 a1f0cce2 Hannes Reinecke
        return 0;
1489 2e5d83bb pbrook
    fail:
1490 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1491 2dd791b6 Hannes Reinecke
        return 0;
1492 274fb0e1 aliguori
    illegal_lba:
1493 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1494 274fb0e1 aliguori
        return 0;
1495 2e5d83bb pbrook
    }
1496 c87c0672 aliguori
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1497 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1498 a917d384 pbrook
    }
1499 c87c0672 aliguori
    len = r->sector_count * 512 + r->iov.iov_len;
1500 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1501 efb9ee02 Hannes Reinecke
        return -len;
1502 a917d384 pbrook
    } else {
1503 f01b5931 Paolo Bonzini
        if (!r->sector_count) {
1504 a917d384 pbrook
            r->sector_count = -1;
1505 f01b5931 Paolo Bonzini
        }
1506 efb9ee02 Hannes Reinecke
        return len;
1507 2e5d83bb pbrook
    }
1508 2e5d83bb pbrook
}
1509 2e5d83bb pbrook
1510 e9447f35 Jan Kiszka
static void scsi_disk_reset(DeviceState *dev)
1511 e9447f35 Jan Kiszka
{
1512 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1513 e9447f35 Jan Kiszka
    uint64_t nb_sectors;
1514 e9447f35 Jan Kiszka
1515 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
1516 e9447f35 Jan Kiszka
1517 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1518 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1519 e9447f35 Jan Kiszka
    if (nb_sectors) {
1520 e9447f35 Jan Kiszka
        nb_sectors--;
1521 e9447f35 Jan Kiszka
    }
1522 7877903a Paolo Bonzini
    s->qdev.max_lba = nb_sectors;
1523 e9447f35 Jan Kiszka
}
1524 e9447f35 Jan Kiszka
1525 e9447f35 Jan Kiszka
static void scsi_destroy(SCSIDevice *dev)
1526 e9447f35 Jan Kiszka
{
1527 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1528 e9447f35 Jan Kiszka
1529 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1530 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
1531 56a14938 Gerd Hoffmann
}
1532 56a14938 Gerd Hoffmann
1533 7d4b4ba5 Markus Armbruster
static void scsi_cd_change_media_cb(void *opaque, bool load)
1534 2c6942fa Markus Armbruster
{
1535 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = opaque;
1536 8a9c16f6 Paolo Bonzini
1537 8a9c16f6 Paolo Bonzini
    /*
1538 8a9c16f6 Paolo Bonzini
     * When a CD gets changed, we have to report an ejected state and
1539 8a9c16f6 Paolo Bonzini
     * then a loaded state to guests so that they detect tray
1540 8a9c16f6 Paolo Bonzini
     * open/close and media change events.  Guests that do not use
1541 8a9c16f6 Paolo Bonzini
     * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1542 8a9c16f6 Paolo Bonzini
     * states rely on this behavior.
1543 8a9c16f6 Paolo Bonzini
     *
1544 8a9c16f6 Paolo Bonzini
     * media_changed governs the state machine used for unit attention
1545 8a9c16f6 Paolo Bonzini
     * report.  media_event is used by GET EVENT STATUS NOTIFICATION.
1546 8a9c16f6 Paolo Bonzini
     */
1547 8a9c16f6 Paolo Bonzini
    s->media_changed = load;
1548 8a9c16f6 Paolo Bonzini
    s->tray_open = !load;
1549 8a9c16f6 Paolo Bonzini
    s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
1550 3c2f7c12 Paolo Bonzini
    s->media_event = true;
1551 4480de19 Paolo Bonzini
    s->eject_request = false;
1552 4480de19 Paolo Bonzini
}
1553 4480de19 Paolo Bonzini
1554 4480de19 Paolo Bonzini
static void scsi_cd_eject_request_cb(void *opaque, bool force)
1555 4480de19 Paolo Bonzini
{
1556 4480de19 Paolo Bonzini
    SCSIDiskState *s = opaque;
1557 4480de19 Paolo Bonzini
1558 4480de19 Paolo Bonzini
    s->eject_request = true;
1559 4480de19 Paolo Bonzini
    if (force) {
1560 4480de19 Paolo Bonzini
        s->tray_locked = false;
1561 4480de19 Paolo Bonzini
    }
1562 2c6942fa Markus Armbruster
}
1563 2c6942fa Markus Armbruster
1564 e4def80b Markus Armbruster
static bool scsi_cd_is_tray_open(void *opaque)
1565 e4def80b Markus Armbruster
{
1566 e4def80b Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_open;
1567 e4def80b Markus Armbruster
}
1568 e4def80b Markus Armbruster
1569 f107639a Markus Armbruster
static bool scsi_cd_is_medium_locked(void *opaque)
1570 f107639a Markus Armbruster
{
1571 f107639a Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_locked;
1572 f107639a Markus Armbruster
}
1573 f107639a Markus Armbruster
1574 f107639a Markus Armbruster
static const BlockDevOps scsi_cd_block_ops = {
1575 2c6942fa Markus Armbruster
    .change_media_cb = scsi_cd_change_media_cb,
1576 4480de19 Paolo Bonzini
    .eject_request_cb = scsi_cd_eject_request_cb,
1577 e4def80b Markus Armbruster
    .is_tray_open = scsi_cd_is_tray_open,
1578 f107639a Markus Armbruster
    .is_medium_locked = scsi_cd_is_medium_locked,
1579 f107639a Markus Armbruster
};
1580 f107639a Markus Armbruster
1581 8a9c16f6 Paolo Bonzini
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
1582 8a9c16f6 Paolo Bonzini
{
1583 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1584 8a9c16f6 Paolo Bonzini
    if (s->media_changed) {
1585 8a9c16f6 Paolo Bonzini
        s->media_changed = false;
1586 8a9c16f6 Paolo Bonzini
        s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
1587 8a9c16f6 Paolo Bonzini
    }
1588 8a9c16f6 Paolo Bonzini
}
1589 8a9c16f6 Paolo Bonzini
1590 e39be482 Paolo Bonzini
static int scsi_initfn(SCSIDevice *dev)
1591 2e5d83bb pbrook
{
1592 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1593 f8b6cc00 Markus Armbruster
    DriveInfo *dinfo;
1594 2e5d83bb pbrook
1595 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
1596 6a84cb1f Markus Armbruster
        error_report("drive property not set");
1597 d52affa7 Gerd Hoffmann
        return -1;
1598 d52affa7 Gerd Hoffmann
    }
1599 d52affa7 Gerd Hoffmann
1600 e39be482 Paolo Bonzini
    if (!s->removable && !bdrv_is_inserted(s->qdev.conf.bs)) {
1601 98f28ad7 Markus Armbruster
        error_report("Device needs media, but drive is empty");
1602 98f28ad7 Markus Armbruster
        return -1;
1603 98f28ad7 Markus Armbruster
    }
1604 98f28ad7 Markus Armbruster
1605 a0fef654 Markus Armbruster
    if (!s->serial) {
1606 f8b6cc00 Markus Armbruster
        /* try to fall back to value set with legacy -drive serial=... */
1607 44740c38 Paolo Bonzini
        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
1608 3e1c0c9a Hannes Reinecke
        if (*dinfo->serial) {
1609 7267c094 Anthony Liguori
            s->serial = g_strdup(dinfo->serial);
1610 3e1c0c9a Hannes Reinecke
        }
1611 a0fef654 Markus Armbruster
    }
1612 a0fef654 Markus Armbruster
1613 552fee93 Markus Armbruster
    if (!s->version) {
1614 7267c094 Anthony Liguori
        s->version = g_strdup(QEMU_VERSION);
1615 552fee93 Markus Armbruster
    }
1616 552fee93 Markus Armbruster
1617 44740c38 Paolo Bonzini
    if (bdrv_is_sg(s->qdev.conf.bs)) {
1618 6a84cb1f Markus Armbruster
        error_report("unwanted /dev/sg*");
1619 32bb404a Markus Armbruster
        return -1;
1620 32bb404a Markus Armbruster
    }
1621 32bb404a Markus Armbruster
1622 e39be482 Paolo Bonzini
    if (s->removable) {
1623 44740c38 Paolo Bonzini
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
1624 2e5d83bb pbrook
    }
1625 44740c38 Paolo Bonzini
    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
1626 8cfacf07 Christoph Hellwig
1627 44740c38 Paolo Bonzini
    bdrv_iostatus_enable(s->qdev.conf.bs);
1628 7082826e Paolo Bonzini
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
1629 d52affa7 Gerd Hoffmann
    return 0;
1630 d52affa7 Gerd Hoffmann
}
1631 d52affa7 Gerd Hoffmann
1632 b443ae67 Markus Armbruster
static int scsi_hd_initfn(SCSIDevice *dev)
1633 b443ae67 Markus Armbruster
{
1634 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1635 e39be482 Paolo Bonzini
    s->qdev.blocksize = s->qdev.conf.logical_block_size;
1636 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_DISK;
1637 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1638 b443ae67 Markus Armbruster
}
1639 b443ae67 Markus Armbruster
1640 b443ae67 Markus Armbruster
static int scsi_cd_initfn(SCSIDevice *dev)
1641 b443ae67 Markus Armbruster
{
1642 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1643 e39be482 Paolo Bonzini
    s->qdev.blocksize = 2048;
1644 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_ROM;
1645 e39be482 Paolo Bonzini
    s->removable = true;
1646 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1647 b443ae67 Markus Armbruster
}
1648 b443ae67 Markus Armbruster
1649 b443ae67 Markus Armbruster
static int scsi_disk_initfn(SCSIDevice *dev)
1650 b443ae67 Markus Armbruster
{
1651 95b5edcd Markus Armbruster
    DriveInfo *dinfo;
1652 b443ae67 Markus Armbruster
1653 b443ae67 Markus Armbruster
    if (!dev->conf.bs) {
1654 e39be482 Paolo Bonzini
        return scsi_initfn(dev);  /* ... and die there */
1655 b443ae67 Markus Armbruster
    }
1656 b443ae67 Markus Armbruster
1657 e39be482 Paolo Bonzini
    dinfo = drive_get_by_blockdev(dev->conf.bs);
1658 e39be482 Paolo Bonzini
    if (dinfo->media_cd) {
1659 e39be482 Paolo Bonzini
        return scsi_cd_initfn(dev);
1660 e39be482 Paolo Bonzini
    } else {
1661 e39be482 Paolo Bonzini
        return scsi_hd_initfn(dev);
1662 e39be482 Paolo Bonzini
    }
1663 b443ae67 Markus Armbruster
}
1664 b443ae67 Markus Armbruster
1665 adcf2754 Paolo Bonzini
static const SCSIReqOps scsi_disk_reqops = {
1666 8dbd4574 Paolo Bonzini
    .size         = sizeof(SCSIDiskReq),
1667 12010e7b Paolo Bonzini
    .free_req     = scsi_free_request,
1668 12010e7b Paolo Bonzini
    .send_command = scsi_send_command,
1669 12010e7b Paolo Bonzini
    .read_data    = scsi_read_data,
1670 12010e7b Paolo Bonzini
    .write_data   = scsi_write_data,
1671 12010e7b Paolo Bonzini
    .cancel_io    = scsi_cancel_io,
1672 12010e7b Paolo Bonzini
    .get_buf      = scsi_get_buf,
1673 43b978b9 Paolo Bonzini
    .load_request = scsi_disk_load_request,
1674 43b978b9 Paolo Bonzini
    .save_request = scsi_disk_save_request,
1675 8dbd4574 Paolo Bonzini
};
1676 8dbd4574 Paolo Bonzini
1677 63db0f0e Paolo Bonzini
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
1678 63db0f0e Paolo Bonzini
                                     uint8_t *buf, void *hba_private)
1679 8dbd4574 Paolo Bonzini
{
1680 8dbd4574 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1681 8dbd4574 Paolo Bonzini
    SCSIRequest *req;
1682 8dbd4574 Paolo Bonzini
1683 8dbd4574 Paolo Bonzini
    req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
1684 8dbd4574 Paolo Bonzini
    return req;
1685 8dbd4574 Paolo Bonzini
}
1686 8dbd4574 Paolo Bonzini
1687 336a6915 Paolo Bonzini
#ifdef __linux__
1688 336a6915 Paolo Bonzini
static int get_device_type(SCSIDiskState *s)
1689 336a6915 Paolo Bonzini
{
1690 336a6915 Paolo Bonzini
    BlockDriverState *bdrv = s->qdev.conf.bs;
1691 336a6915 Paolo Bonzini
    uint8_t cmd[16];
1692 336a6915 Paolo Bonzini
    uint8_t buf[36];
1693 336a6915 Paolo Bonzini
    uint8_t sensebuf[8];
1694 336a6915 Paolo Bonzini
    sg_io_hdr_t io_header;
1695 336a6915 Paolo Bonzini
    int ret;
1696 336a6915 Paolo Bonzini
1697 336a6915 Paolo Bonzini
    memset(cmd, 0, sizeof(cmd));
1698 336a6915 Paolo Bonzini
    memset(buf, 0, sizeof(buf));
1699 336a6915 Paolo Bonzini
    cmd[0] = INQUIRY;
1700 336a6915 Paolo Bonzini
    cmd[4] = sizeof(buf);
1701 336a6915 Paolo Bonzini
1702 336a6915 Paolo Bonzini
    memset(&io_header, 0, sizeof(io_header));
1703 336a6915 Paolo Bonzini
    io_header.interface_id = 'S';
1704 336a6915 Paolo Bonzini
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
1705 336a6915 Paolo Bonzini
    io_header.dxfer_len = sizeof(buf);
1706 336a6915 Paolo Bonzini
    io_header.dxferp = buf;
1707 336a6915 Paolo Bonzini
    io_header.cmdp = cmd;
1708 336a6915 Paolo Bonzini
    io_header.cmd_len = sizeof(cmd);
1709 336a6915 Paolo Bonzini
    io_header.mx_sb_len = sizeof(sensebuf);
1710 336a6915 Paolo Bonzini
    io_header.sbp = sensebuf;
1711 336a6915 Paolo Bonzini
    io_header.timeout = 6000; /* XXX */
1712 336a6915 Paolo Bonzini
1713 336a6915 Paolo Bonzini
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
1714 336a6915 Paolo Bonzini
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
1715 336a6915 Paolo Bonzini
        return -1;
1716 336a6915 Paolo Bonzini
    }
1717 336a6915 Paolo Bonzini
    s->qdev.type = buf[0];
1718 336a6915 Paolo Bonzini
    s->removable = (buf[1] & 0x80) != 0;
1719 336a6915 Paolo Bonzini
    return 0;
1720 336a6915 Paolo Bonzini
}
1721 336a6915 Paolo Bonzini
1722 336a6915 Paolo Bonzini
static int scsi_block_initfn(SCSIDevice *dev)
1723 336a6915 Paolo Bonzini
{
1724 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1725 336a6915 Paolo Bonzini
    int sg_version;
1726 336a6915 Paolo Bonzini
    int rc;
1727 336a6915 Paolo Bonzini
1728 336a6915 Paolo Bonzini
    if (!s->qdev.conf.bs) {
1729 336a6915 Paolo Bonzini
        error_report("scsi-block: drive property not set");
1730 336a6915 Paolo Bonzini
        return -1;
1731 336a6915 Paolo Bonzini
    }
1732 336a6915 Paolo Bonzini
1733 336a6915 Paolo Bonzini
    /* check we are using a driver managing SG_IO (version 3 and after) */
1734 336a6915 Paolo Bonzini
    if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
1735 336a6915 Paolo Bonzini
        sg_version < 30000) {
1736 336a6915 Paolo Bonzini
        error_report("scsi-block: scsi generic interface too old");
1737 336a6915 Paolo Bonzini
        return -1;
1738 336a6915 Paolo Bonzini
    }
1739 336a6915 Paolo Bonzini
1740 336a6915 Paolo Bonzini
    /* get device type from INQUIRY data */
1741 336a6915 Paolo Bonzini
    rc = get_device_type(s);
1742 336a6915 Paolo Bonzini
    if (rc < 0) {
1743 336a6915 Paolo Bonzini
        error_report("scsi-block: INQUIRY failed");
1744 336a6915 Paolo Bonzini
        return -1;
1745 336a6915 Paolo Bonzini
    }
1746 336a6915 Paolo Bonzini
1747 336a6915 Paolo Bonzini
    /* Make a guess for the block size, we'll fix it when the guest sends.
1748 336a6915 Paolo Bonzini
     * READ CAPACITY.  If they don't, they likely would assume these sizes
1749 336a6915 Paolo Bonzini
     * anyway. (TODO: check in /sys).
1750 336a6915 Paolo Bonzini
     */
1751 336a6915 Paolo Bonzini
    if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
1752 336a6915 Paolo Bonzini
        s->qdev.blocksize = 2048;
1753 336a6915 Paolo Bonzini
    } else {
1754 336a6915 Paolo Bonzini
        s->qdev.blocksize = 512;
1755 336a6915 Paolo Bonzini
    }
1756 336a6915 Paolo Bonzini
    return scsi_initfn(&s->qdev);
1757 336a6915 Paolo Bonzini
}
1758 336a6915 Paolo Bonzini
1759 336a6915 Paolo Bonzini
static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
1760 336a6915 Paolo Bonzini
                                           uint32_t lun, uint8_t *buf,
1761 336a6915 Paolo Bonzini
                                           void *hba_private)
1762 336a6915 Paolo Bonzini
{
1763 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1764 336a6915 Paolo Bonzini
1765 336a6915 Paolo Bonzini
    switch (buf[0]) {
1766 336a6915 Paolo Bonzini
    case READ_6:
1767 336a6915 Paolo Bonzini
    case READ_10:
1768 336a6915 Paolo Bonzini
    case READ_12:
1769 336a6915 Paolo Bonzini
    case READ_16:
1770 336a6915 Paolo Bonzini
    case WRITE_6:
1771 336a6915 Paolo Bonzini
    case WRITE_10:
1772 336a6915 Paolo Bonzini
    case WRITE_12:
1773 336a6915 Paolo Bonzini
    case WRITE_16:
1774 336a6915 Paolo Bonzini
    case WRITE_VERIFY_10:
1775 336a6915 Paolo Bonzini
    case WRITE_VERIFY_12:
1776 336a6915 Paolo Bonzini
    case WRITE_VERIFY_16:
1777 eaccf49e Paolo Bonzini
        /* If we are not using O_DIRECT, we might read stale data from the
1778 eaccf49e Paolo Bonzini
         * host cache if writes were made using other commands than these
1779 eaccf49e Paolo Bonzini
         * ones (such as WRITE SAME or EXTENDED COPY, etc.).  So, without
1780 eaccf49e Paolo Bonzini
         * O_DIRECT everything must go through SG_IO.
1781 eaccf49e Paolo Bonzini
         */
1782 eaccf49e Paolo Bonzini
        if (!(s->qdev.conf.bs->open_flags & BDRV_O_NOCACHE)) {
1783 eaccf49e Paolo Bonzini
            break;
1784 eaccf49e Paolo Bonzini
        }
1785 eaccf49e Paolo Bonzini
1786 33ebad12 Paolo Bonzini
        /* MMC writing cannot be done via pread/pwrite, because it sometimes
1787 33ebad12 Paolo Bonzini
         * involves writing beyond the maximum LBA or to negative LBA (lead-in).
1788 33ebad12 Paolo Bonzini
         * And once you do these writes, reading from the block device is
1789 33ebad12 Paolo Bonzini
         * unreliable, too.  It is even possible that reads deliver random data
1790 33ebad12 Paolo Bonzini
         * from the host page cache (this is probably a Linux bug).
1791 33ebad12 Paolo Bonzini
         *
1792 33ebad12 Paolo Bonzini
         * We might use scsi_disk_reqops as long as no writing commands are
1793 33ebad12 Paolo Bonzini
         * seen, but performance usually isn't paramount on optical media.  So,
1794 33ebad12 Paolo Bonzini
         * just make scsi-block operate the same as scsi-generic for them.
1795 33ebad12 Paolo Bonzini
         */
1796 eaccf49e Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
1797 eaccf49e Paolo Bonzini
            break;
1798 eaccf49e Paolo Bonzini
        }
1799 eaccf49e Paolo Bonzini
        return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
1800 eaccf49e Paolo Bonzini
                              hba_private);
1801 336a6915 Paolo Bonzini
    }
1802 336a6915 Paolo Bonzini
1803 336a6915 Paolo Bonzini
    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
1804 336a6915 Paolo Bonzini
                          hba_private);
1805 336a6915 Paolo Bonzini
}
1806 336a6915 Paolo Bonzini
#endif
1807 336a6915 Paolo Bonzini
1808 b443ae67 Markus Armbruster
#define DEFINE_SCSI_DISK_PROPERTIES()                           \
1809 b443ae67 Markus Armbruster
    DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),          \
1810 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
1811 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("serial",  SCSIDiskState, serial)
1812 b443ae67 Markus Armbruster
1813 39bffca2 Anthony Liguori
static Property scsi_hd_properties[] = {
1814 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1815 39bffca2 Anthony Liguori
    DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1816 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1817 39bffca2 Anthony Liguori
};
1818 39bffca2 Anthony Liguori
1819 43b978b9 Paolo Bonzini
static const VMStateDescription vmstate_scsi_disk_state = {
1820 43b978b9 Paolo Bonzini
    .name = "scsi-disk",
1821 43b978b9 Paolo Bonzini
    .version_id = 1,
1822 43b978b9 Paolo Bonzini
    .minimum_version_id = 1,
1823 43b978b9 Paolo Bonzini
    .minimum_version_id_old = 1,
1824 43b978b9 Paolo Bonzini
    .fields = (VMStateField[]) {
1825 43b978b9 Paolo Bonzini
        VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
1826 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_changed, SCSIDiskState),
1827 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_event, SCSIDiskState),
1828 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(eject_request, SCSIDiskState),
1829 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_open, SCSIDiskState),
1830 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_locked, SCSIDiskState),
1831 43b978b9 Paolo Bonzini
        VMSTATE_END_OF_LIST()
1832 43b978b9 Paolo Bonzini
    }
1833 43b978b9 Paolo Bonzini
};
1834 43b978b9 Paolo Bonzini
1835 b9eea3e6 Anthony Liguori
static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
1836 b9eea3e6 Anthony Liguori
{
1837 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1838 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1839 b9eea3e6 Anthony Liguori
1840 b9eea3e6 Anthony Liguori
    sc->init         = scsi_hd_initfn;
1841 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1842 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1843 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1844 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1845 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk";
1846 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1847 39bffca2 Anthony Liguori
    dc->props = scsi_hd_properties;
1848 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1849 b9eea3e6 Anthony Liguori
}
1850 b9eea3e6 Anthony Liguori
1851 39bffca2 Anthony Liguori
static TypeInfo scsi_hd_info = {
1852 39bffca2 Anthony Liguori
    .name          = "scsi-hd",
1853 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1854 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1855 39bffca2 Anthony Liguori
    .class_init    = scsi_hd_class_initfn,
1856 39bffca2 Anthony Liguori
};
1857 39bffca2 Anthony Liguori
1858 39bffca2 Anthony Liguori
static Property scsi_cd_properties[] = {
1859 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1860 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1861 b9eea3e6 Anthony Liguori
};
1862 b9eea3e6 Anthony Liguori
1863 b9eea3e6 Anthony Liguori
static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
1864 b9eea3e6 Anthony Liguori
{
1865 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1866 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1867 b9eea3e6 Anthony Liguori
1868 b9eea3e6 Anthony Liguori
    sc->init         = scsi_cd_initfn;
1869 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1870 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1871 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1872 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1873 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI CD-ROM";
1874 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1875 39bffca2 Anthony Liguori
    dc->props = scsi_cd_properties;
1876 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1877 b9eea3e6 Anthony Liguori
}
1878 b9eea3e6 Anthony Liguori
1879 39bffca2 Anthony Liguori
static TypeInfo scsi_cd_info = {
1880 39bffca2 Anthony Liguori
    .name          = "scsi-cd",
1881 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1882 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1883 39bffca2 Anthony Liguori
    .class_init    = scsi_cd_class_initfn,
1884 b9eea3e6 Anthony Liguori
};
1885 b9eea3e6 Anthony Liguori
1886 336a6915 Paolo Bonzini
#ifdef __linux__
1887 39bffca2 Anthony Liguori
static Property scsi_block_properties[] = {
1888 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1889 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1890 39bffca2 Anthony Liguori
};
1891 39bffca2 Anthony Liguori
1892 b9eea3e6 Anthony Liguori
static void scsi_block_class_initfn(ObjectClass *klass, void *data)
1893 b9eea3e6 Anthony Liguori
{
1894 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1895 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1896 b9eea3e6 Anthony Liguori
1897 b9eea3e6 Anthony Liguori
    sc->init         = scsi_block_initfn;
1898 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1899 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_block_new_request;
1900 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1901 39bffca2 Anthony Liguori
    dc->desc = "SCSI block device passthrough";
1902 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1903 39bffca2 Anthony Liguori
    dc->props = scsi_block_properties;
1904 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1905 b9eea3e6 Anthony Liguori
}
1906 b9eea3e6 Anthony Liguori
1907 39bffca2 Anthony Liguori
static TypeInfo scsi_block_info = {
1908 39bffca2 Anthony Liguori
    .name          = "scsi-block",
1909 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1910 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1911 39bffca2 Anthony Liguori
    .class_init    = scsi_block_class_initfn,
1912 b9eea3e6 Anthony Liguori
};
1913 336a6915 Paolo Bonzini
#endif
1914 b9eea3e6 Anthony Liguori
1915 39bffca2 Anthony Liguori
static Property scsi_disk_properties[] = {
1916 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
1917 39bffca2 Anthony Liguori
    DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1918 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1919 39bffca2 Anthony Liguori
};
1920 39bffca2 Anthony Liguori
1921 b9eea3e6 Anthony Liguori
static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
1922 b9eea3e6 Anthony Liguori
{
1923 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1924 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1925 b9eea3e6 Anthony Liguori
1926 b9eea3e6 Anthony Liguori
    sc->init         = scsi_disk_initfn;
1927 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
1928 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
1929 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
1930 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
1931 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
1932 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
1933 39bffca2 Anthony Liguori
    dc->props = scsi_disk_properties;
1934 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
1935 b9eea3e6 Anthony Liguori
}
1936 b9eea3e6 Anthony Liguori
1937 39bffca2 Anthony Liguori
static TypeInfo scsi_disk_info = {
1938 39bffca2 Anthony Liguori
    .name          = "scsi-disk",
1939 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
1940 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
1941 39bffca2 Anthony Liguori
    .class_init    = scsi_disk_class_initfn,
1942 d52affa7 Gerd Hoffmann
};
1943 d52affa7 Gerd Hoffmann
1944 83f7d43a Andreas Färber
static void scsi_disk_register_types(void)
1945 d52affa7 Gerd Hoffmann
{
1946 39bffca2 Anthony Liguori
    type_register_static(&scsi_hd_info);
1947 39bffca2 Anthony Liguori
    type_register_static(&scsi_cd_info);
1948 b9eea3e6 Anthony Liguori
#ifdef __linux__
1949 39bffca2 Anthony Liguori
    type_register_static(&scsi_block_info);
1950 b9eea3e6 Anthony Liguori
#endif
1951 39bffca2 Anthony Liguori
    type_register_static(&scsi_disk_info);
1952 8ccc2ace ths
}
1953 83f7d43a Andreas Färber
1954 83f7d43a Andreas Färber
type_init(scsi_disk_register_types)