Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 2558e0a6

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