Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ 0fd76ff4

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