Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ bc927e48

History | View | Annotate | Download (73.9 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 87ecb68b pbrook
#include "qemu-common.h"
32 2f792016 Markus Armbruster
#include "qemu-error.h"
33 43b443b6 Gerd Hoffmann
#include "scsi.h"
34 0d65e1f8 Gerd Hoffmann
#include "scsi-defs.h"
35 666daa68 Markus Armbruster
#include "sysemu.h"
36 2446333c Blue Swirl
#include "blockdev.h"
37 9db1c0f7 Markus Armbruster
#include "hw/block-common.h"
38 5d0d2467 Paolo Bonzini
#include "dma.h"
39 22864256 blueswir1
40 336a6915 Paolo Bonzini
#ifdef __linux
41 336a6915 Paolo Bonzini
#include <scsi/sg.h>
42 336a6915 Paolo Bonzini
#endif
43 336a6915 Paolo Bonzini
44 f0f72ffe aurel32
#define SCSI_DMA_BUF_SIZE    131072
45 57575058 balrog
#define SCSI_MAX_INQUIRY_LEN 256
46 380feaff Paolo Bonzini
#define SCSI_MAX_MODE_LEN    256
47 a917d384 pbrook
48 d52affa7 Gerd Hoffmann
typedef struct SCSIDiskState SCSIDiskState;
49 d52affa7 Gerd Hoffmann
50 4c41d2ef Gerd Hoffmann
typedef struct SCSIDiskReq {
51 4c41d2ef Gerd Hoffmann
    SCSIRequest req;
52 a917d384 pbrook
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
53 e035b43d aliguori
    uint64_t sector;
54 e035b43d aliguori
    uint32_t sector_count;
55 7285477a Paolo Bonzini
    uint32_t buflen;
56 a0e66a69 Paolo Bonzini
    bool started;
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 bfe3d7ac Paolo Bonzini
#define SCSI_DISK_F_REMOVABLE   0
63 da8365db Paolo Bonzini
#define SCSI_DISK_F_DPOFUA      1
64 bfe3d7ac Paolo Bonzini
65 d52affa7 Gerd Hoffmann
struct SCSIDiskState
66 a917d384 pbrook
{
67 d52affa7 Gerd Hoffmann
    SCSIDevice qdev;
68 bfe3d7ac Paolo Bonzini
    uint32_t features;
69 8a9c16f6 Paolo Bonzini
    bool media_changed;
70 3c2f7c12 Paolo Bonzini
    bool media_event;
71 4480de19 Paolo Bonzini
    bool eject_request;
72 27395add Paolo Bonzini
    uint64_t wwn;
73 213189ab Markus Armbruster
    QEMUBH *bh;
74 383b4d9b Gerd Hoffmann
    char *version;
75 a0fef654 Markus Armbruster
    char *serial;
76 353815aa Dmitry Fleytman
    char *vendor;
77 353815aa Dmitry Fleytman
    char *product;
78 ece0d5e9 Markus Armbruster
    bool tray_open;
79 81b1008d Markus Armbruster
    bool tray_locked;
80 2e5d83bb pbrook
};
81 2e5d83bb pbrook
82 71544d30 Paolo Bonzini
static int scsi_handle_rw_error(SCSIDiskReq *r, int error);
83 5dba48a8 Kevin Wolf
84 ad2d30f7 Paolo Bonzini
static void scsi_free_request(SCSIRequest *req)
85 4d611c9a pbrook
{
86 ad2d30f7 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
87 ad2d30f7 Paolo Bonzini
88 7285477a Paolo Bonzini
    if (r->iov.iov_base) {
89 7285477a Paolo Bonzini
        qemu_vfree(r->iov.iov_base);
90 7285477a Paolo Bonzini
    }
91 4d611c9a pbrook
}
92 4d611c9a pbrook
93 b45ef674 Paolo Bonzini
/* Helper function for command completion with sense.  */
94 b45ef674 Paolo Bonzini
static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
95 ed3a34a3 Gerd Hoffmann
{
96 02fa69b6 Blue Swirl
    DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
97 02fa69b6 Blue Swirl
            r->req.tag, sense.key, sense.asc, sense.ascq);
98 b45ef674 Paolo Bonzini
    scsi_req_build_sense(&r->req, sense);
99 b45ef674 Paolo Bonzini
    scsi_req_complete(&r->req, CHECK_CONDITION);
100 4d611c9a pbrook
}
101 4d611c9a pbrook
102 4d611c9a pbrook
/* Cancel a pending data transfer.  */
103 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
104 4d611c9a pbrook
{
105 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
106 5c6c0e51 Hannes Reinecke
107 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
108 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
109 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
110 c7bae6a7 Paolo Bonzini
111 c7bae6a7 Paolo Bonzini
        /* This reference was left in by scsi_*_data.  We take ownership of
112 c7bae6a7 Paolo Bonzini
         * it the moment scsi_req_cancel is called, independent of whether
113 c7bae6a7 Paolo Bonzini
         * bdrv_aio_cancel completes the request or not.  */
114 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
115 a917d384 pbrook
    }
116 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
117 a917d384 pbrook
}
118 a917d384 pbrook
119 43b978b9 Paolo Bonzini
static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
120 103b40f5 Paolo Bonzini
{
121 7285477a Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
122 7285477a Paolo Bonzini
123 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
124 43b978b9 Paolo Bonzini
        r->buflen = size;
125 44740c38 Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
126 7285477a Paolo Bonzini
    }
127 7285477a Paolo Bonzini
    r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
128 103b40f5 Paolo Bonzini
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
129 103b40f5 Paolo Bonzini
    return r->qiov.size / 512;
130 103b40f5 Paolo Bonzini
}
131 103b40f5 Paolo Bonzini
132 43b978b9 Paolo Bonzini
static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
133 43b978b9 Paolo Bonzini
{
134 43b978b9 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
135 43b978b9 Paolo Bonzini
136 43b978b9 Paolo Bonzini
    qemu_put_be64s(f, &r->sector);
137 43b978b9 Paolo Bonzini
    qemu_put_be32s(f, &r->sector_count);
138 43b978b9 Paolo Bonzini
    qemu_put_be32s(f, &r->buflen);
139 18eef3bc Gerd Hoffmann
    if (r->buflen) {
140 18eef3bc Gerd Hoffmann
        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
141 18eef3bc Gerd Hoffmann
            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
142 18eef3bc Gerd Hoffmann
        } else if (!req->retry) {
143 18eef3bc Gerd Hoffmann
            uint32_t len = r->iov.iov_len;
144 18eef3bc Gerd Hoffmann
            qemu_put_be32s(f, &len);
145 18eef3bc Gerd Hoffmann
            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
146 18eef3bc Gerd Hoffmann
        }
147 43b978b9 Paolo Bonzini
    }
148 43b978b9 Paolo Bonzini
}
149 43b978b9 Paolo Bonzini
150 43b978b9 Paolo Bonzini
static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
151 43b978b9 Paolo Bonzini
{
152 43b978b9 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
153 43b978b9 Paolo Bonzini
154 43b978b9 Paolo Bonzini
    qemu_get_be64s(f, &r->sector);
155 43b978b9 Paolo Bonzini
    qemu_get_be32s(f, &r->sector_count);
156 43b978b9 Paolo Bonzini
    qemu_get_be32s(f, &r->buflen);
157 43b978b9 Paolo Bonzini
    if (r->buflen) {
158 43b978b9 Paolo Bonzini
        scsi_init_iovec(r, r->buflen);
159 43b978b9 Paolo Bonzini
        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
160 43b978b9 Paolo Bonzini
            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
161 18eef3bc Gerd Hoffmann
        } else if (!r->req.retry) {
162 18eef3bc Gerd Hoffmann
            uint32_t len;
163 18eef3bc Gerd Hoffmann
            qemu_get_be32s(f, &len);
164 18eef3bc Gerd Hoffmann
            r->iov.iov_len = len;
165 18eef3bc Gerd Hoffmann
            assert(r->iov.iov_len <= r->buflen);
166 18eef3bc Gerd Hoffmann
            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
167 43b978b9 Paolo Bonzini
        }
168 43b978b9 Paolo Bonzini
    }
169 43b978b9 Paolo Bonzini
170 43b978b9 Paolo Bonzini
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
171 43b978b9 Paolo Bonzini
}
172 43b978b9 Paolo Bonzini
173 c1b35247 Paolo Bonzini
static void scsi_aio_complete(void *opaque, int ret)
174 5d0d2467 Paolo Bonzini
{
175 5d0d2467 Paolo Bonzini
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
176 5d0d2467 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
177 5d0d2467 Paolo Bonzini
178 46e3f30e Paolo Bonzini
    assert(r->req.aiocb != NULL);
179 46e3f30e Paolo Bonzini
    r->req.aiocb = NULL;
180 5d0d2467 Paolo Bonzini
    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
181 5d0d2467 Paolo Bonzini
182 80624c93 Paolo Bonzini
    if (ret < 0) {
183 5d0d2467 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
184 5d0d2467 Paolo Bonzini
            goto done;
185 5d0d2467 Paolo Bonzini
        }
186 5d0d2467 Paolo Bonzini
    }
187 5d0d2467 Paolo Bonzini
188 5d0d2467 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
189 5d0d2467 Paolo Bonzini
190 5d0d2467 Paolo Bonzini
done:
191 b8aba8d7 Paolo Bonzini
    if (!r->req.io_canceled) {
192 b8aba8d7 Paolo Bonzini
        scsi_req_unref(&r->req);
193 b8aba8d7 Paolo Bonzini
    }
194 5d0d2467 Paolo Bonzini
}
195 5d0d2467 Paolo Bonzini
196 7e8c49c5 Paolo Bonzini
static bool scsi_is_cmd_fua(SCSICommand *cmd)
197 7e8c49c5 Paolo Bonzini
{
198 7e8c49c5 Paolo Bonzini
    switch (cmd->buf[0]) {
199 7e8c49c5 Paolo Bonzini
    case READ_10:
200 7e8c49c5 Paolo Bonzini
    case READ_12:
201 7e8c49c5 Paolo Bonzini
    case READ_16:
202 7e8c49c5 Paolo Bonzini
    case WRITE_10:
203 7e8c49c5 Paolo Bonzini
    case WRITE_12:
204 7e8c49c5 Paolo Bonzini
    case WRITE_16:
205 7e8c49c5 Paolo Bonzini
        return (cmd->buf[1] & 8) != 0;
206 7e8c49c5 Paolo Bonzini
207 7f64f8e2 Paolo Bonzini
    case VERIFY_10:
208 7f64f8e2 Paolo Bonzini
    case VERIFY_12:
209 7f64f8e2 Paolo Bonzini
    case VERIFY_16:
210 7e8c49c5 Paolo Bonzini
    case WRITE_VERIFY_10:
211 7e8c49c5 Paolo Bonzini
    case WRITE_VERIFY_12:
212 7e8c49c5 Paolo Bonzini
    case WRITE_VERIFY_16:
213 7e8c49c5 Paolo Bonzini
        return true;
214 7e8c49c5 Paolo Bonzini
215 7e8c49c5 Paolo Bonzini
    case READ_6:
216 7e8c49c5 Paolo Bonzini
    case WRITE_6:
217 7e8c49c5 Paolo Bonzini
    default:
218 7e8c49c5 Paolo Bonzini
        return false;
219 7e8c49c5 Paolo Bonzini
    }
220 7e8c49c5 Paolo Bonzini
}
221 7e8c49c5 Paolo Bonzini
222 7e8c49c5 Paolo Bonzini
static void scsi_write_do_fua(SCSIDiskReq *r)
223 7e8c49c5 Paolo Bonzini
{
224 7e8c49c5 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
225 7e8c49c5 Paolo Bonzini
226 7e8c49c5 Paolo Bonzini
    if (scsi_is_cmd_fua(&r->req.cmd)) {
227 7e8c49c5 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
228 c1b35247 Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
229 7e8c49c5 Paolo Bonzini
        return;
230 7e8c49c5 Paolo Bonzini
    }
231 7e8c49c5 Paolo Bonzini
232 7e8c49c5 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
233 7e8c49c5 Paolo Bonzini
    if (!r->req.io_canceled) {
234 7e8c49c5 Paolo Bonzini
        scsi_req_unref(&r->req);
235 7e8c49c5 Paolo Bonzini
    }
236 7e8c49c5 Paolo Bonzini
}
237 7e8c49c5 Paolo Bonzini
238 b77912a7 Paolo Bonzini
static void scsi_dma_complete(void *opaque, int ret)
239 a917d384 pbrook
{
240 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
241 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
242 a917d384 pbrook
243 46e3f30e Paolo Bonzini
    assert(r->req.aiocb != NULL);
244 46e3f30e Paolo Bonzini
    r->req.aiocb = NULL;
245 46e3f30e Paolo Bonzini
    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
246 a597e79c Christoph Hellwig
247 80624c93 Paolo Bonzini
    if (ret < 0) {
248 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
249 c7bae6a7 Paolo Bonzini
            goto done;
250 5dba48a8 Kevin Wolf
        }
251 4d611c9a pbrook
    }
252 5dba48a8 Kevin Wolf
253 b77912a7 Paolo Bonzini
    r->sector += r->sector_count;
254 b77912a7 Paolo Bonzini
    r->sector_count = 0;
255 7e8c49c5 Paolo Bonzini
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
256 7e8c49c5 Paolo Bonzini
        scsi_write_do_fua(r);
257 7e8c49c5 Paolo Bonzini
        return;
258 7e8c49c5 Paolo Bonzini
    } else {
259 7e8c49c5 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
260 7e8c49c5 Paolo Bonzini
    }
261 c7bae6a7 Paolo Bonzini
262 c7bae6a7 Paolo Bonzini
done:
263 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
264 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
265 c7bae6a7 Paolo Bonzini
    }
266 4d611c9a pbrook
}
267 4d611c9a pbrook
268 b77912a7 Paolo Bonzini
static void scsi_read_complete(void * opaque, int ret)
269 0a4ac106 Paolo Bonzini
{
270 0a4ac106 Paolo Bonzini
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
271 0a4ac106 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
272 b77912a7 Paolo Bonzini
    int n;
273 0a4ac106 Paolo Bonzini
274 46e3f30e Paolo Bonzini
    assert(r->req.aiocb != NULL);
275 46e3f30e Paolo Bonzini
    r->req.aiocb = NULL;
276 46e3f30e Paolo Bonzini
    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
277 0a4ac106 Paolo Bonzini
278 0a4ac106 Paolo Bonzini
    if (ret < 0) {
279 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
280 c7bae6a7 Paolo Bonzini
            goto done;
281 0a4ac106 Paolo Bonzini
        }
282 0a4ac106 Paolo Bonzini
    }
283 0a4ac106 Paolo Bonzini
284 b77912a7 Paolo Bonzini
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
285 b77912a7 Paolo Bonzini
286 b77912a7 Paolo Bonzini
    n = r->qiov.size / 512;
287 b77912a7 Paolo Bonzini
    r->sector += n;
288 b77912a7 Paolo Bonzini
    r->sector_count -= n;
289 b77912a7 Paolo Bonzini
    scsi_req_data(&r->req, r->qiov.size);
290 c7bae6a7 Paolo Bonzini
291 c7bae6a7 Paolo Bonzini
done:
292 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
293 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
294 c7bae6a7 Paolo Bonzini
    }
295 0a4ac106 Paolo Bonzini
}
296 5dba48a8 Kevin Wolf
297 ac668426 Paolo Bonzini
/* Actually issue a read to the block device.  */
298 ac668426 Paolo Bonzini
static void scsi_do_read(void *opaque, int ret)
299 ac668426 Paolo Bonzini
{
300 ac668426 Paolo Bonzini
    SCSIDiskReq *r = opaque;
301 ac668426 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
302 ac668426 Paolo Bonzini
    uint32_t n;
303 ac668426 Paolo Bonzini
304 ac668426 Paolo Bonzini
    if (r->req.aiocb != NULL) {
305 ac668426 Paolo Bonzini
        r->req.aiocb = NULL;
306 ac668426 Paolo Bonzini
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
307 ac668426 Paolo Bonzini
    }
308 ac668426 Paolo Bonzini
309 ac668426 Paolo Bonzini
    if (ret < 0) {
310 ac668426 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
311 ac668426 Paolo Bonzini
            goto done;
312 ac668426 Paolo Bonzini
        }
313 ac668426 Paolo Bonzini
    }
314 ac668426 Paolo Bonzini
315 31e8fd86 Paolo Bonzini
    if (r->req.io_canceled) {
316 31e8fd86 Paolo Bonzini
        return;
317 31e8fd86 Paolo Bonzini
    }
318 31e8fd86 Paolo Bonzini
319 31e8fd86 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
320 31e8fd86 Paolo Bonzini
    scsi_req_ref(&r->req);
321 31e8fd86 Paolo Bonzini
322 ac668426 Paolo Bonzini
    if (r->req.sg) {
323 ac668426 Paolo Bonzini
        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
324 ac668426 Paolo Bonzini
        r->req.resid -= r->req.sg->size;
325 ac668426 Paolo Bonzini
        r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
326 ac668426 Paolo Bonzini
                                     scsi_dma_complete, r);
327 ac668426 Paolo Bonzini
    } else {
328 ac668426 Paolo Bonzini
        n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
329 ac668426 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
330 ac668426 Paolo Bonzini
        r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
331 ac668426 Paolo Bonzini
                                      scsi_read_complete, r);
332 ac668426 Paolo Bonzini
    }
333 ac668426 Paolo Bonzini
334 ac668426 Paolo Bonzini
done:
335 ac668426 Paolo Bonzini
    if (!r->req.io_canceled) {
336 ac668426 Paolo Bonzini
        scsi_req_unref(&r->req);
337 ac668426 Paolo Bonzini
    }
338 ac668426 Paolo Bonzini
}
339 ac668426 Paolo Bonzini
340 5c6c0e51 Hannes Reinecke
/* Read more data from scsi device into buffer.  */
341 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
342 2e5d83bb pbrook
{
343 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
344 5dba48a8 Kevin Wolf
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
345 ac668426 Paolo Bonzini
    bool first;
346 2e5d83bb pbrook
347 a917d384 pbrook
    DPRINTF("Read sector_count=%d\n", r->sector_count);
348 a917d384 pbrook
    if (r->sector_count == 0) {
349 b45ef674 Paolo Bonzini
        /* This also clears the sense buffer for REQUEST SENSE.  */
350 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
351 a917d384 pbrook
        return;
352 2e5d83bb pbrook
    }
353 2e5d83bb pbrook
354 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
355 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
356 6fa2c95f Stefan Hajnoczi
357 c7bae6a7 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
358 c7bae6a7 Paolo Bonzini
    scsi_req_ref(&r->req);
359 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
360 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
361 efb9ee02 Hannes Reinecke
        scsi_read_complete(r, -EINVAL);
362 efb9ee02 Hannes Reinecke
        return;
363 efb9ee02 Hannes Reinecke
    }
364 efb9ee02 Hannes Reinecke
365 a1aff5bf Markus Armbruster
    if (s->tray_open) {
366 a1aff5bf Markus Armbruster
        scsi_read_complete(r, -ENOMEDIUM);
367 c7bae6a7 Paolo Bonzini
        return;
368 a1aff5bf Markus Armbruster
    }
369 c7bae6a7 Paolo Bonzini
370 ac668426 Paolo Bonzini
    first = !r->started;
371 a0e66a69 Paolo Bonzini
    r->started = true;
372 ac668426 Paolo Bonzini
    if (first && scsi_is_cmd_fua(&r->req.cmd)) {
373 ac668426 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
374 ac668426 Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_do_read, r);
375 5d0d2467 Paolo Bonzini
    } else {
376 ac668426 Paolo Bonzini
        scsi_do_read(r, 0);
377 5d0d2467 Paolo Bonzini
    }
378 2e5d83bb pbrook
}
379 2e5d83bb pbrook
380 c7bae6a7 Paolo Bonzini
/*
381 c7bae6a7 Paolo Bonzini
 * scsi_handle_rw_error has two return values.  0 means that the error
382 c7bae6a7 Paolo Bonzini
 * must be ignored, 1 means that the error has been processed and the
383 c7bae6a7 Paolo Bonzini
 * caller should not do anything else for this request.  Note that
384 c7bae6a7 Paolo Bonzini
 * scsi_handle_rw_error always manages its reference counts, independent
385 c7bae6a7 Paolo Bonzini
 * of the return value.
386 c7bae6a7 Paolo Bonzini
 */
387 71544d30 Paolo Bonzini
static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
388 5dba48a8 Kevin Wolf
{
389 1ceee0d5 Paolo Bonzini
    bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
390 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
391 3e1caa5f Paolo Bonzini
    BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error);
392 ea8a5d7f aliguori
393 3e1caa5f Paolo Bonzini
    if (action == BDRV_ACTION_REPORT) {
394 efb9ee02 Hannes Reinecke
        switch (error) {
395 7e218df5 Paolo Bonzini
        case ENOMEDIUM:
396 7e218df5 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
397 7e218df5 Paolo Bonzini
            break;
398 efb9ee02 Hannes Reinecke
        case ENOMEM:
399 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
400 efb9ee02 Hannes Reinecke
            break;
401 efb9ee02 Hannes Reinecke
        case EINVAL:
402 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
403 efb9ee02 Hannes Reinecke
            break;
404 efb9ee02 Hannes Reinecke
        default:
405 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
406 efb9ee02 Hannes Reinecke
            break;
407 a1f0cce2 Hannes Reinecke
        }
408 ea8a5d7f aliguori
    }
409 3e1caa5f Paolo Bonzini
    bdrv_error_action(s->qdev.conf.bs, action, is_read, error);
410 3e1caa5f Paolo Bonzini
    if (action == BDRV_ACTION_STOP) {
411 3e1caa5f Paolo Bonzini
        scsi_req_retry(&r->req);
412 3e1caa5f Paolo Bonzini
    }
413 3e1caa5f Paolo Bonzini
    return action != BDRV_ACTION_IGNORE;
414 ea8a5d7f aliguori
}
415 ea8a5d7f aliguori
416 4d611c9a pbrook
static void scsi_write_complete(void * opaque, int ret)
417 4d611c9a pbrook
{
418 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
419 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
420 ea8a5d7f aliguori
    uint32_t n;
421 ea8a5d7f aliguori
422 8e321cc6 Paolo Bonzini
    if (r->req.aiocb != NULL) {
423 8e321cc6 Paolo Bonzini
        r->req.aiocb = NULL;
424 44740c38 Paolo Bonzini
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
425 8e321cc6 Paolo Bonzini
    }
426 a597e79c Christoph Hellwig
427 80624c93 Paolo Bonzini
    if (ret < 0) {
428 71544d30 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
429 c7bae6a7 Paolo Bonzini
            goto done;
430 5dba48a8 Kevin Wolf
        }
431 4d611c9a pbrook
    }
432 4d611c9a pbrook
433 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
434 ea8a5d7f aliguori
    r->sector += n;
435 ea8a5d7f aliguori
    r->sector_count -= n;
436 a917d384 pbrook
    if (r->sector_count == 0) {
437 7e8c49c5 Paolo Bonzini
        scsi_write_do_fua(r);
438 7e8c49c5 Paolo Bonzini
        return;
439 a917d384 pbrook
    } else {
440 43b978b9 Paolo Bonzini
        scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
441 79fb50bb Paolo Bonzini
        DPRINTF("Write complete tag=0x%x more=%zd\n", r->req.tag, r->qiov.size);
442 103b40f5 Paolo Bonzini
        scsi_req_data(&r->req, r->qiov.size);
443 4d611c9a pbrook
    }
444 c7bae6a7 Paolo Bonzini
445 c7bae6a7 Paolo Bonzini
done:
446 c7bae6a7 Paolo Bonzini
    if (!r->req.io_canceled) {
447 c7bae6a7 Paolo Bonzini
        scsi_req_unref(&r->req);
448 c7bae6a7 Paolo Bonzini
    }
449 4d611c9a pbrook
}
450 4d611c9a pbrook
451 42741212 Paolo Bonzini
static void scsi_write_data(SCSIRequest *req)
452 ea8a5d7f aliguori
{
453 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
454 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
455 ea8a5d7f aliguori
    uint32_t n;
456 ea8a5d7f aliguori
457 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
458 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
459 6fa2c95f Stefan Hajnoczi
460 c7bae6a7 Paolo Bonzini
    /* The request is used as the AIO opaque value, so add a ref.  */
461 c7bae6a7 Paolo Bonzini
    scsi_req_ref(&r->req);
462 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
463 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
464 efb9ee02 Hannes Reinecke
        scsi_write_complete(r, -EINVAL);
465 42741212 Paolo Bonzini
        return;
466 efb9ee02 Hannes Reinecke
    }
467 efb9ee02 Hannes Reinecke
468 5d0d2467 Paolo Bonzini
    if (!r->req.sg && !r->qiov.size) {
469 5d0d2467 Paolo Bonzini
        /* Called for the first time.  Ask the driver to send us more data.  */
470 a0e66a69 Paolo Bonzini
        r->started = true;
471 5d0d2467 Paolo Bonzini
        scsi_write_complete(r, 0);
472 5d0d2467 Paolo Bonzini
        return;
473 5d0d2467 Paolo Bonzini
    }
474 5d0d2467 Paolo Bonzini
    if (s->tray_open) {
475 5d0d2467 Paolo Bonzini
        scsi_write_complete(r, -ENOMEDIUM);
476 5d0d2467 Paolo Bonzini
        return;
477 5d0d2467 Paolo Bonzini
    }
478 5d0d2467 Paolo Bonzini
479 7f64f8e2 Paolo Bonzini
    if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 ||
480 7f64f8e2 Paolo Bonzini
        r->req.cmd.buf[0] == VERIFY_16) {
481 7f64f8e2 Paolo Bonzini
        if (r->req.sg) {
482 7f64f8e2 Paolo Bonzini
            scsi_dma_complete(r, 0);
483 7f64f8e2 Paolo Bonzini
        } else {
484 7f64f8e2 Paolo Bonzini
            scsi_write_complete(r, 0);
485 7f64f8e2 Paolo Bonzini
        }
486 7f64f8e2 Paolo Bonzini
        return;
487 7f64f8e2 Paolo Bonzini
    }
488 7f64f8e2 Paolo Bonzini
489 5d0d2467 Paolo Bonzini
    if (r->req.sg) {
490 5d0d2467 Paolo Bonzini
        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
491 5d0d2467 Paolo Bonzini
        r->req.resid -= r->req.sg->size;
492 5d0d2467 Paolo Bonzini
        r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
493 5d0d2467 Paolo Bonzini
                                      scsi_dma_complete, r);
494 5d0d2467 Paolo Bonzini
    } else {
495 5d0d2467 Paolo Bonzini
        n = r->qiov.size / 512;
496 44740c38 Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
497 44740c38 Paolo Bonzini
        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
498 103b40f5 Paolo Bonzini
                                       scsi_write_complete, r);
499 ea8a5d7f aliguori
    }
500 a917d384 pbrook
}
501 2e5d83bb pbrook
502 a917d384 pbrook
/* Return a pointer to the data buffer.  */
503 5c6c0e51 Hannes Reinecke
static uint8_t *scsi_get_buf(SCSIRequest *req)
504 a917d384 pbrook
{
505 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
506 2e5d83bb pbrook
507 3f4cb3d3 blueswir1
    return (uint8_t *)r->iov.iov_base;
508 2e5d83bb pbrook
}
509 2e5d83bb pbrook
510 0b06c059 Gerd Hoffmann
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
511 0b06c059 Gerd Hoffmann
{
512 383b4d9b Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
513 0b06c059 Gerd Hoffmann
    int buflen = 0;
514 82579390 Paolo Bonzini
    int start;
515 0b06c059 Gerd Hoffmann
516 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[1] & 0x1) {
517 0b06c059 Gerd Hoffmann
        /* Vital product data */
518 0b06c059 Gerd Hoffmann
        uint8_t page_code = req->cmd.buf[2];
519 0b06c059 Gerd Hoffmann
520 e39be482 Paolo Bonzini
        outbuf[buflen++] = s->qdev.type & 0x1f;
521 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = page_code ; // this page
522 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = 0x00;
523 82579390 Paolo Bonzini
        outbuf[buflen++] = 0x00;
524 82579390 Paolo Bonzini
        start = buflen;
525 0b06c059 Gerd Hoffmann
526 0b06c059 Gerd Hoffmann
        switch (page_code) {
527 0b06c059 Gerd Hoffmann
        case 0x00: /* Supported page codes, mandatory */
528 39d98982 Hannes Reinecke
        {
529 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Supported pages] "
530 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
531 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
532 f01b5931 Paolo Bonzini
            if (s->serial) {
533 3e1c0c9a Hannes Reinecke
                outbuf[buflen++] = 0x80; // unit serial number
534 f01b5931 Paolo Bonzini
            }
535 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x83; // device identification
536 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_DISK) {
537 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb0; // block limits
538 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb2; // thin provisioning
539 39d98982 Hannes Reinecke
            }
540 0b06c059 Gerd Hoffmann
            break;
541 39d98982 Hannes Reinecke
        }
542 0b06c059 Gerd Hoffmann
        case 0x80: /* Device serial number, optional */
543 0b06c059 Gerd Hoffmann
        {
544 3e1c0c9a Hannes Reinecke
            int l;
545 0b06c059 Gerd Hoffmann
546 3e1c0c9a Hannes Reinecke
            if (!s->serial) {
547 3e1c0c9a Hannes Reinecke
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
548 3e1c0c9a Hannes Reinecke
                return -1;
549 3e1c0c9a Hannes Reinecke
            }
550 3e1c0c9a Hannes Reinecke
551 3e1c0c9a Hannes Reinecke
            l = strlen(s->serial);
552 f01b5931 Paolo Bonzini
            if (l > 20) {
553 0b06c059 Gerd Hoffmann
                l = 20;
554 f01b5931 Paolo Bonzini
            }
555 0b06c059 Gerd Hoffmann
556 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Serial number] "
557 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
558 a0fef654 Markus Armbruster
            memcpy(outbuf+buflen, s->serial, l);
559 0b06c059 Gerd Hoffmann
            buflen += l;
560 0b06c059 Gerd Hoffmann
            break;
561 0b06c059 Gerd Hoffmann
        }
562 0b06c059 Gerd Hoffmann
563 0b06c059 Gerd Hoffmann
        case 0x83: /* Device identification page, mandatory */
564 0b06c059 Gerd Hoffmann
        {
565 fd930791 Paolo Bonzini
            const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
566 fd930791 Paolo Bonzini
            int max_len = s->serial ? 20 : 255 - 8;
567 fd930791 Paolo Bonzini
            int id_len = strlen(str);
568 0b06c059 Gerd Hoffmann
569 f01b5931 Paolo Bonzini
            if (id_len > max_len) {
570 0b06c059 Gerd Hoffmann
                id_len = max_len;
571 f01b5931 Paolo Bonzini
            }
572 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Device identification] "
573 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
574 0b06c059 Gerd Hoffmann
575 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x2; // ASCII
576 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // not officially assigned
577 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // reserved
578 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = id_len; // length of data following
579 fd930791 Paolo Bonzini
            memcpy(outbuf+buflen, str, id_len);
580 0b06c059 Gerd Hoffmann
            buflen += id_len;
581 27395add Paolo Bonzini
582 27395add Paolo Bonzini
            if (s->wwn) {
583 27395add Paolo Bonzini
                outbuf[buflen++] = 0x1; // Binary
584 27395add Paolo Bonzini
                outbuf[buflen++] = 0x3; // NAA
585 27395add Paolo Bonzini
                outbuf[buflen++] = 0;   // reserved
586 27395add Paolo Bonzini
                outbuf[buflen++] = 8;
587 27395add Paolo Bonzini
                stq_be_p(&outbuf[buflen], s->wwn);
588 27395add Paolo Bonzini
                buflen += 8;
589 27395add Paolo Bonzini
            }
590 0b06c059 Gerd Hoffmann
            break;
591 0b06c059 Gerd Hoffmann
        }
592 ea3bd56f Christoph Hellwig
        case 0xb0: /* block limits */
593 ee3659e3 Christoph Hellwig
        {
594 ea3bd56f Christoph Hellwig
            unsigned int unmap_sectors =
595 ea3bd56f Christoph Hellwig
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
596 8cfacf07 Christoph Hellwig
            unsigned int min_io_size =
597 8cfacf07 Christoph Hellwig
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
598 8cfacf07 Christoph Hellwig
            unsigned int opt_io_size =
599 8cfacf07 Christoph Hellwig
                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
600 ee3659e3 Christoph Hellwig
601 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_ROM) {
602 39d98982 Hannes Reinecke
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
603 39d98982 Hannes Reinecke
                        page_code);
604 39d98982 Hannes Reinecke
                return -1;
605 39d98982 Hannes Reinecke
            }
606 ee3659e3 Christoph Hellwig
            /* required VPD size with unmap support */
607 82579390 Paolo Bonzini
            buflen = 0x40;
608 ee3659e3 Christoph Hellwig
            memset(outbuf + 4, 0, buflen - 4);
609 ee3659e3 Christoph Hellwig
610 ee3659e3 Christoph Hellwig
            /* optimal transfer length granularity */
611 ee3659e3 Christoph Hellwig
            outbuf[6] = (min_io_size >> 8) & 0xff;
612 ee3659e3 Christoph Hellwig
            outbuf[7] = min_io_size & 0xff;
613 ee3659e3 Christoph Hellwig
614 ee3659e3 Christoph Hellwig
            /* optimal transfer length */
615 ee3659e3 Christoph Hellwig
            outbuf[12] = (opt_io_size >> 24) & 0xff;
616 ee3659e3 Christoph Hellwig
            outbuf[13] = (opt_io_size >> 16) & 0xff;
617 ee3659e3 Christoph Hellwig
            outbuf[14] = (opt_io_size >> 8) & 0xff;
618 ee3659e3 Christoph Hellwig
            outbuf[15] = opt_io_size & 0xff;
619 ea3bd56f Christoph Hellwig
620 ea3bd56f Christoph Hellwig
            /* optimal unmap granularity */
621 ea3bd56f Christoph Hellwig
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
622 ea3bd56f Christoph Hellwig
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
623 ea3bd56f Christoph Hellwig
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
624 ea3bd56f Christoph Hellwig
            outbuf[31] = unmap_sectors & 0xff;
625 ea3bd56f Christoph Hellwig
            break;
626 ea3bd56f Christoph Hellwig
        }
627 ea3bd56f Christoph Hellwig
        case 0xb2: /* thin provisioning */
628 ea3bd56f Christoph Hellwig
        {
629 82579390 Paolo Bonzini
            buflen = 8;
630 ea3bd56f Christoph Hellwig
            outbuf[4] = 0;
631 5222aaf2 Paolo Bonzini
            outbuf[5] = 0xe0; /* unmap & write_same 10/16 all supported */
632 f644a290 Ronnie Sahlberg
            outbuf[6] = s->qdev.conf.discard_granularity ? 2 : 1;
633 ea3bd56f Christoph Hellwig
            outbuf[7] = 0;
634 ee3659e3 Christoph Hellwig
            break;
635 ee3659e3 Christoph Hellwig
        }
636 0b06c059 Gerd Hoffmann
        default:
637 0b06c059 Gerd Hoffmann
            return -1;
638 0b06c059 Gerd Hoffmann
        }
639 0b06c059 Gerd Hoffmann
        /* done with EVPD */
640 82579390 Paolo Bonzini
        assert(buflen - start <= 255);
641 82579390 Paolo Bonzini
        outbuf[start - 1] = buflen - start;
642 0b06c059 Gerd Hoffmann
        return buflen;
643 0b06c059 Gerd Hoffmann
    }
644 0b06c059 Gerd Hoffmann
645 0b06c059 Gerd Hoffmann
    /* Standard INQUIRY data */
646 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[2] != 0) {
647 0b06c059 Gerd Hoffmann
        return -1;
648 0b06c059 Gerd Hoffmann
    }
649 0b06c059 Gerd Hoffmann
650 0b06c059 Gerd Hoffmann
    /* PAGE CODE == 0 */
651 0b06c059 Gerd Hoffmann
    buflen = req->cmd.xfer;
652 f01b5931 Paolo Bonzini
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
653 0b06c059 Gerd Hoffmann
        buflen = SCSI_MAX_INQUIRY_LEN;
654 f01b5931 Paolo Bonzini
    }
655 0b06c059 Gerd Hoffmann
    memset(outbuf, 0, buflen);
656 0b06c059 Gerd Hoffmann
657 f37bd73b Hannes Reinecke
    outbuf[0] = s->qdev.type & 0x1f;
658 bfe3d7ac Paolo Bonzini
    outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0;
659 353815aa Dmitry Fleytman
660 353815aa Dmitry Fleytman
    strpadcpy((char *) &outbuf[16], 16, s->product, ' ');
661 353815aa Dmitry Fleytman
    strpadcpy((char *) &outbuf[8], 8, s->vendor, ' ');
662 353815aa Dmitry Fleytman
663 314b1811 Gerd Hoffmann
    memset(&outbuf[32], 0, 4);
664 552fee93 Markus Armbruster
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
665 99aba0c4 Christoph Hellwig
    /*
666 99aba0c4 Christoph Hellwig
     * We claim conformance to SPC-3, which is required for guests
667 99aba0c4 Christoph Hellwig
     * to ask for modern features like READ CAPACITY(16) or the
668 99aba0c4 Christoph Hellwig
     * block characteristics VPD page by default.  Not all of SPC-3
669 99aba0c4 Christoph Hellwig
     * is actually implemented, but we're good enough.
670 99aba0c4 Christoph Hellwig
     */
671 ee3659e3 Christoph Hellwig
    outbuf[2] = 5;
672 1109c894 Ronnie Sahlberg
    outbuf[3] = 2 | 0x10; /* Format 2, HiSup */
673 ad3cea42 Artyom Tarasenko
674 ad3cea42 Artyom Tarasenko
    if (buflen > 36) {
675 ad3cea42 Artyom Tarasenko
        outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
676 ad3cea42 Artyom Tarasenko
    } else {
677 ad3cea42 Artyom Tarasenko
        /* If the allocation length of CDB is too small,
678 ad3cea42 Artyom Tarasenko
               the additional length is not adjusted */
679 ad3cea42 Artyom Tarasenko
        outbuf[4] = 36 - 5;
680 ad3cea42 Artyom Tarasenko
    }
681 ad3cea42 Artyom Tarasenko
682 0b06c059 Gerd Hoffmann
    /* Sync data transfer and TCQ.  */
683 afd4030c Paolo Bonzini
    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
684 0b06c059 Gerd Hoffmann
    return buflen;
685 0b06c059 Gerd Hoffmann
}
686 0b06c059 Gerd Hoffmann
687 430ee2f2 Paolo Bonzini
static inline bool media_is_dvd(SCSIDiskState *s)
688 430ee2f2 Paolo Bonzini
{
689 430ee2f2 Paolo Bonzini
    uint64_t nb_sectors;
690 430ee2f2 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
691 430ee2f2 Paolo Bonzini
        return false;
692 430ee2f2 Paolo Bonzini
    }
693 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
694 430ee2f2 Paolo Bonzini
        return false;
695 430ee2f2 Paolo Bonzini
    }
696 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
697 430ee2f2 Paolo Bonzini
    return nb_sectors > CD_MAX_SECTORS;
698 430ee2f2 Paolo Bonzini
}
699 430ee2f2 Paolo Bonzini
700 ceb792ef Paolo Bonzini
static inline bool media_is_cd(SCSIDiskState *s)
701 ceb792ef Paolo Bonzini
{
702 ceb792ef Paolo Bonzini
    uint64_t nb_sectors;
703 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
704 ceb792ef Paolo Bonzini
        return false;
705 ceb792ef Paolo Bonzini
    }
706 44740c38 Paolo Bonzini
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
707 ceb792ef Paolo Bonzini
        return false;
708 ceb792ef Paolo Bonzini
    }
709 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
710 ceb792ef Paolo Bonzini
    return nb_sectors <= CD_MAX_SECTORS;
711 ceb792ef Paolo Bonzini
}
712 ceb792ef Paolo Bonzini
713 1a4f0c3a Paolo Bonzini
static int scsi_read_disc_information(SCSIDiskState *s, SCSIDiskReq *r,
714 1a4f0c3a Paolo Bonzini
                                      uint8_t *outbuf)
715 1a4f0c3a Paolo Bonzini
{
716 1a4f0c3a Paolo Bonzini
    uint8_t type = r->req.cmd.buf[1] & 7;
717 1a4f0c3a Paolo Bonzini
718 1a4f0c3a Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
719 1a4f0c3a Paolo Bonzini
        return -1;
720 1a4f0c3a Paolo Bonzini
    }
721 1a4f0c3a Paolo Bonzini
722 1a4f0c3a Paolo Bonzini
    /* Types 1/2 are only defined for Blu-Ray.  */
723 1a4f0c3a Paolo Bonzini
    if (type != 0) {
724 1a4f0c3a Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
725 1a4f0c3a Paolo Bonzini
        return -1;
726 1a4f0c3a Paolo Bonzini
    }
727 1a4f0c3a Paolo Bonzini
728 1a4f0c3a Paolo Bonzini
    memset(outbuf, 0, 34);
729 1a4f0c3a Paolo Bonzini
    outbuf[1] = 32;
730 1a4f0c3a Paolo Bonzini
    outbuf[2] = 0xe; /* last session complete, disc finalized */
731 1a4f0c3a Paolo Bonzini
    outbuf[3] = 1;   /* first track on disc */
732 1a4f0c3a Paolo Bonzini
    outbuf[4] = 1;   /* # of sessions */
733 1a4f0c3a Paolo Bonzini
    outbuf[5] = 1;   /* first track of last session */
734 1a4f0c3a Paolo Bonzini
    outbuf[6] = 1;   /* last track of last session */
735 1a4f0c3a Paolo Bonzini
    outbuf[7] = 0x20; /* unrestricted use */
736 1a4f0c3a Paolo Bonzini
    outbuf[8] = 0x00; /* CD-ROM or DVD-ROM */
737 1a4f0c3a Paolo Bonzini
    /* 9-10-11: most significant byte corresponding bytes 4-5-6 */
738 1a4f0c3a Paolo Bonzini
    /* 12-23: not meaningful for CD-ROM or DVD-ROM */
739 1a4f0c3a Paolo Bonzini
    /* 24-31: disc bar code */
740 1a4f0c3a Paolo Bonzini
    /* 32: disc application code */
741 1a4f0c3a Paolo Bonzini
    /* 33: number of OPC tables */
742 1a4f0c3a Paolo Bonzini
743 1a4f0c3a Paolo Bonzini
    return 34;
744 1a4f0c3a Paolo Bonzini
}
745 1a4f0c3a Paolo Bonzini
746 b6c251ab Paolo Bonzini
static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
747 b6c251ab Paolo Bonzini
                                   uint8_t *outbuf)
748 b6c251ab Paolo Bonzini
{
749 ceb792ef Paolo Bonzini
    static const int rds_caps_size[5] = {
750 ceb792ef Paolo Bonzini
        [0] = 2048 + 4,
751 ceb792ef Paolo Bonzini
        [1] = 4 + 4,
752 ceb792ef Paolo Bonzini
        [3] = 188 + 4,
753 ceb792ef Paolo Bonzini
        [4] = 2048 + 4,
754 ceb792ef Paolo Bonzini
    };
755 ceb792ef Paolo Bonzini
756 ceb792ef Paolo Bonzini
    uint8_t media = r->req.cmd.buf[1];
757 ceb792ef Paolo Bonzini
    uint8_t layer = r->req.cmd.buf[6];
758 ceb792ef Paolo Bonzini
    uint8_t format = r->req.cmd.buf[7];
759 ceb792ef Paolo Bonzini
    int size = -1;
760 ceb792ef Paolo Bonzini
761 ceb792ef Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
762 ceb792ef Paolo Bonzini
        return -1;
763 ceb792ef Paolo Bonzini
    }
764 ceb792ef Paolo Bonzini
    if (media != 0) {
765 ceb792ef Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
766 ceb792ef Paolo Bonzini
        return -1;
767 ceb792ef Paolo Bonzini
    }
768 ceb792ef Paolo Bonzini
769 ceb792ef Paolo Bonzini
    if (format != 0xff) {
770 44740c38 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
771 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
772 ceb792ef Paolo Bonzini
            return -1;
773 ceb792ef Paolo Bonzini
        }
774 ceb792ef Paolo Bonzini
        if (media_is_cd(s)) {
775 ceb792ef Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
776 ceb792ef Paolo Bonzini
            return -1;
777 ceb792ef Paolo Bonzini
        }
778 ceb792ef Paolo Bonzini
        if (format >= ARRAY_SIZE(rds_caps_size)) {
779 ceb792ef Paolo Bonzini
            return -1;
780 ceb792ef Paolo Bonzini
        }
781 ceb792ef Paolo Bonzini
        size = rds_caps_size[format];
782 ceb792ef Paolo Bonzini
        memset(outbuf, 0, size);
783 ceb792ef Paolo Bonzini
    }
784 ceb792ef Paolo Bonzini
785 ceb792ef Paolo Bonzini
    switch (format) {
786 ceb792ef Paolo Bonzini
    case 0x00: {
787 ceb792ef Paolo Bonzini
        /* Physical format information */
788 ceb792ef Paolo Bonzini
        uint64_t nb_sectors;
789 ceb792ef Paolo Bonzini
        if (layer != 0) {
790 ceb792ef Paolo Bonzini
            goto fail;
791 ceb792ef Paolo Bonzini
        }
792 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
793 ceb792ef Paolo Bonzini
794 ceb792ef Paolo Bonzini
        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
795 ceb792ef Paolo Bonzini
        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
796 ceb792ef Paolo Bonzini
        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
797 ceb792ef Paolo Bonzini
        outbuf[7] = 0;   /* default densities */
798 ceb792ef Paolo Bonzini
799 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
800 ceb792ef Paolo Bonzini
        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
801 ceb792ef Paolo Bonzini
        break;
802 ceb792ef Paolo Bonzini
    }
803 ceb792ef Paolo Bonzini
804 ceb792ef Paolo Bonzini
    case 0x01: /* DVD copyright information, all zeros */
805 ceb792ef Paolo Bonzini
        break;
806 ceb792ef Paolo Bonzini
807 ceb792ef Paolo Bonzini
    case 0x03: /* BCA information - invalid field for no BCA info */
808 ceb792ef Paolo Bonzini
        return -1;
809 ceb792ef Paolo Bonzini
810 ceb792ef Paolo Bonzini
    case 0x04: /* DVD disc manufacturing information, all zeros */
811 ceb792ef Paolo Bonzini
        break;
812 ceb792ef Paolo Bonzini
813 ceb792ef Paolo Bonzini
    case 0xff: { /* List capabilities */
814 ceb792ef Paolo Bonzini
        int i;
815 ceb792ef Paolo Bonzini
        size = 4;
816 ceb792ef Paolo Bonzini
        for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
817 ceb792ef Paolo Bonzini
            if (!rds_caps_size[i]) {
818 ceb792ef Paolo Bonzini
                continue;
819 ceb792ef Paolo Bonzini
            }
820 ceb792ef Paolo Bonzini
            outbuf[size] = i;
821 ceb792ef Paolo Bonzini
            outbuf[size + 1] = 0x40; /* Not writable, readable */
822 ceb792ef Paolo Bonzini
            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
823 ceb792ef Paolo Bonzini
            size += 4;
824 ceb792ef Paolo Bonzini
        }
825 ceb792ef Paolo Bonzini
        break;
826 ceb792ef Paolo Bonzini
     }
827 ceb792ef Paolo Bonzini
828 ceb792ef Paolo Bonzini
    default:
829 ceb792ef Paolo Bonzini
        return -1;
830 ceb792ef Paolo Bonzini
    }
831 ceb792ef Paolo Bonzini
832 ceb792ef Paolo Bonzini
    /* Size of buffer, not including 2 byte size field */
833 ceb792ef Paolo Bonzini
    stw_be_p(outbuf, size - 2);
834 ceb792ef Paolo Bonzini
    return size;
835 ceb792ef Paolo Bonzini
836 ceb792ef Paolo Bonzini
fail:
837 b6c251ab Paolo Bonzini
    return -1;
838 b6c251ab Paolo Bonzini
}
839 b6c251ab Paolo Bonzini
840 3c2f7c12 Paolo Bonzini
static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
841 b6c251ab Paolo Bonzini
{
842 3c2f7c12 Paolo Bonzini
    uint8_t event_code, media_status;
843 3c2f7c12 Paolo Bonzini
844 3c2f7c12 Paolo Bonzini
    media_status = 0;
845 3c2f7c12 Paolo Bonzini
    if (s->tray_open) {
846 3c2f7c12 Paolo Bonzini
        media_status = MS_TRAY_OPEN;
847 44740c38 Paolo Bonzini
    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
848 3c2f7c12 Paolo Bonzini
        media_status = MS_MEDIA_PRESENT;
849 3c2f7c12 Paolo Bonzini
    }
850 3c2f7c12 Paolo Bonzini
851 3c2f7c12 Paolo Bonzini
    /* Event notification descriptor */
852 3c2f7c12 Paolo Bonzini
    event_code = MEC_NO_CHANGE;
853 4480de19 Paolo Bonzini
    if (media_status != MS_TRAY_OPEN) {
854 4480de19 Paolo Bonzini
        if (s->media_event) {
855 4480de19 Paolo Bonzini
            event_code = MEC_NEW_MEDIA;
856 4480de19 Paolo Bonzini
            s->media_event = false;
857 4480de19 Paolo Bonzini
        } else if (s->eject_request) {
858 4480de19 Paolo Bonzini
            event_code = MEC_EJECT_REQUESTED;
859 4480de19 Paolo Bonzini
            s->eject_request = false;
860 4480de19 Paolo Bonzini
        }
861 3c2f7c12 Paolo Bonzini
    }
862 3c2f7c12 Paolo Bonzini
863 3c2f7c12 Paolo Bonzini
    outbuf[0] = event_code;
864 3c2f7c12 Paolo Bonzini
    outbuf[1] = media_status;
865 3c2f7c12 Paolo Bonzini
866 3c2f7c12 Paolo Bonzini
    /* These fields are reserved, just clear them. */
867 3c2f7c12 Paolo Bonzini
    outbuf[2] = 0;
868 3c2f7c12 Paolo Bonzini
    outbuf[3] = 0;
869 3c2f7c12 Paolo Bonzini
    return 4;
870 3c2f7c12 Paolo Bonzini
}
871 3c2f7c12 Paolo Bonzini
872 3c2f7c12 Paolo Bonzini
static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
873 3c2f7c12 Paolo Bonzini
                                              uint8_t *outbuf)
874 3c2f7c12 Paolo Bonzini
{
875 3c2f7c12 Paolo Bonzini
    int size;
876 3c2f7c12 Paolo Bonzini
    uint8_t *buf = r->req.cmd.buf;
877 3c2f7c12 Paolo Bonzini
    uint8_t notification_class_request = buf[4];
878 3c2f7c12 Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
879 3c2f7c12 Paolo Bonzini
        return -1;
880 3c2f7c12 Paolo Bonzini
    }
881 3c2f7c12 Paolo Bonzini
    if ((buf[1] & 1) == 0) {
882 3c2f7c12 Paolo Bonzini
        /* asynchronous */
883 3c2f7c12 Paolo Bonzini
        return -1;
884 3c2f7c12 Paolo Bonzini
    }
885 3c2f7c12 Paolo Bonzini
886 3c2f7c12 Paolo Bonzini
    size = 4;
887 3c2f7c12 Paolo Bonzini
    outbuf[0] = outbuf[1] = 0;
888 3c2f7c12 Paolo Bonzini
    outbuf[3] = 1 << GESN_MEDIA; /* supported events */
889 3c2f7c12 Paolo Bonzini
    if (notification_class_request & (1 << GESN_MEDIA)) {
890 3c2f7c12 Paolo Bonzini
        outbuf[2] = GESN_MEDIA;
891 3c2f7c12 Paolo Bonzini
        size += scsi_event_status_media(s, &outbuf[size]);
892 3c2f7c12 Paolo Bonzini
    } else {
893 3c2f7c12 Paolo Bonzini
        outbuf[2] = 0x80;
894 3c2f7c12 Paolo Bonzini
    }
895 3c2f7c12 Paolo Bonzini
    stw_be_p(outbuf, size - 4);
896 3c2f7c12 Paolo Bonzini
    return size;
897 b6c251ab Paolo Bonzini
}
898 b6c251ab Paolo Bonzini
899 430ee2f2 Paolo Bonzini
static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
900 b6c251ab Paolo Bonzini
{
901 430ee2f2 Paolo Bonzini
    int current;
902 430ee2f2 Paolo Bonzini
903 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
904 b6c251ab Paolo Bonzini
        return -1;
905 b6c251ab Paolo Bonzini
    }
906 430ee2f2 Paolo Bonzini
    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
907 430ee2f2 Paolo Bonzini
    memset(outbuf, 0, 40);
908 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
909 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[6], current);
910 430ee2f2 Paolo Bonzini
    /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
911 430ee2f2 Paolo Bonzini
    outbuf[10] = 0x03; /* persistent, current */
912 430ee2f2 Paolo Bonzini
    outbuf[11] = 8; /* two profiles */
913 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
914 430ee2f2 Paolo Bonzini
    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
915 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
916 430ee2f2 Paolo Bonzini
    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
917 430ee2f2 Paolo Bonzini
    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
918 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[20], 1);
919 430ee2f2 Paolo Bonzini
    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
920 430ee2f2 Paolo Bonzini
    outbuf[23] = 8;
921 430ee2f2 Paolo Bonzini
    stl_be_p(&outbuf[24], 1); /* SCSI */
922 430ee2f2 Paolo Bonzini
    outbuf[28] = 1; /* DBE = 1, mandatory */
923 430ee2f2 Paolo Bonzini
    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
924 430ee2f2 Paolo Bonzini
    stw_be_p(&outbuf[32], 3);
925 430ee2f2 Paolo Bonzini
    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
926 430ee2f2 Paolo Bonzini
    outbuf[35] = 4;
927 430ee2f2 Paolo Bonzini
    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
928 430ee2f2 Paolo Bonzini
    /* TODO: Random readable, CD read, DVD read, drive serial number,
929 430ee2f2 Paolo Bonzini
       power management */
930 430ee2f2 Paolo Bonzini
    return 40;
931 b6c251ab Paolo Bonzini
}
932 b6c251ab Paolo Bonzini
933 b6c251ab Paolo Bonzini
static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
934 b6c251ab Paolo Bonzini
{
935 b6c251ab Paolo Bonzini
    if (s->qdev.type != TYPE_ROM) {
936 b6c251ab Paolo Bonzini
        return -1;
937 b6c251ab Paolo Bonzini
    }
938 b6c251ab Paolo Bonzini
    memset(outbuf, 0, 8);
939 b6c251ab Paolo Bonzini
    outbuf[5] = 1; /* CD-ROM */
940 b6c251ab Paolo Bonzini
    return 8;
941 b6c251ab Paolo Bonzini
}
942 b6c251ab Paolo Bonzini
943 cfc606da Paolo Bonzini
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
944 282ab04e Bernhard Kohl
                           int page_control)
945 ebddfcbe Gerd Hoffmann
{
946 a8f4bbe2 Paolo Bonzini
    static const int mode_sense_valid[0x3f] = {
947 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
948 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
949 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
950 a07c7dcd Paolo Bonzini
        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
951 a07c7dcd Paolo Bonzini
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
952 a8f4bbe2 Paolo Bonzini
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
953 a8f4bbe2 Paolo Bonzini
    };
954 ef405611 Paolo Bonzini
955 ef405611 Paolo Bonzini
    uint8_t *p = *p_outbuf + 2;
956 ef405611 Paolo Bonzini
    int length;
957 ebddfcbe Gerd Hoffmann
958 a8f4bbe2 Paolo Bonzini
    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
959 a8f4bbe2 Paolo Bonzini
        return -1;
960 a8f4bbe2 Paolo Bonzini
    }
961 a8f4bbe2 Paolo Bonzini
962 282ab04e Bernhard Kohl
    /*
963 282ab04e Bernhard Kohl
     * If Changeable Values are requested, a mask denoting those mode parameters
964 282ab04e Bernhard Kohl
     * that are changeable shall be returned. As we currently don't support
965 282ab04e Bernhard Kohl
     * parameter changes via MODE_SELECT all bits are returned set to zero.
966 282ab04e Bernhard Kohl
     * The buffer was already menset to zero by the caller of this function.
967 ef405611 Paolo Bonzini
     *
968 ef405611 Paolo Bonzini
     * The offsets here are off by two compared to the descriptions in the
969 ef405611 Paolo Bonzini
     * SCSI specs, because those include a 2-byte header.  This is unfortunate,
970 ef405611 Paolo Bonzini
     * but it is done so that offsets are consistent within our implementation
971 ef405611 Paolo Bonzini
     * of MODE SENSE and MODE SELECT.  MODE SELECT has to deal with both
972 ef405611 Paolo Bonzini
     * 2-byte and 4-byte headers.
973 282ab04e Bernhard Kohl
     */
974 ebddfcbe Gerd Hoffmann
    switch (page) {
975 67cc61e4 Paolo Bonzini
    case MODE_PAGE_HD_GEOMETRY:
976 ef405611 Paolo Bonzini
        length = 0x16;
977 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
978 cfc606da Paolo Bonzini
            break;
979 282ab04e Bernhard Kohl
        }
980 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
981 ef405611 Paolo Bonzini
        p[0] = (s->qdev.conf.cyls >> 16) & 0xff;
982 ef405611 Paolo Bonzini
        p[1] = (s->qdev.conf.cyls >> 8) & 0xff;
983 ef405611 Paolo Bonzini
        p[2] = s->qdev.conf.cyls & 0xff;
984 ef405611 Paolo Bonzini
        p[3] = s->qdev.conf.heads & 0xff;
985 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
986 ef405611 Paolo Bonzini
        p[4] = (s->qdev.conf.cyls >> 16) & 0xff;
987 ef405611 Paolo Bonzini
        p[5] = (s->qdev.conf.cyls >> 8) & 0xff;
988 ef405611 Paolo Bonzini
        p[6] = s->qdev.conf.cyls & 0xff;
989 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
990 ef405611 Paolo Bonzini
        p[7] = (s->qdev.conf.cyls >> 16) & 0xff;
991 ef405611 Paolo Bonzini
        p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
992 ef405611 Paolo Bonzini
        p[9] = s->qdev.conf.cyls & 0xff;
993 ebddfcbe Gerd Hoffmann
        /* Device step rate [ns], 200ns */
994 ef405611 Paolo Bonzini
        p[10] = 0;
995 ef405611 Paolo Bonzini
        p[11] = 200;
996 ebddfcbe Gerd Hoffmann
        /* Landing zone cylinder */
997 ef405611 Paolo Bonzini
        p[12] = 0xff;
998 ef405611 Paolo Bonzini
        p[13] =  0xff;
999 ebddfcbe Gerd Hoffmann
        p[14] = 0xff;
1000 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
1001 ef405611 Paolo Bonzini
        p[18] = (5400 >> 8) & 0xff;
1002 ef405611 Paolo Bonzini
        p[19] = 5400 & 0xff;
1003 cfc606da Paolo Bonzini
        break;
1004 ebddfcbe Gerd Hoffmann
1005 67cc61e4 Paolo Bonzini
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
1006 ef405611 Paolo Bonzini
        length = 0x1e;
1007 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
1008 cfc606da Paolo Bonzini
            break;
1009 282ab04e Bernhard Kohl
        }
1010 ebddfcbe Gerd Hoffmann
        /* Transfer rate [kbit/s], 5Mbit/s */
1011 ef405611 Paolo Bonzini
        p[0] = 5000 >> 8;
1012 ef405611 Paolo Bonzini
        p[1] = 5000 & 0xff;
1013 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
1014 ef405611 Paolo Bonzini
        p[2] = s->qdev.conf.heads & 0xff;
1015 ef405611 Paolo Bonzini
        p[3] = s->qdev.conf.secs & 0xff;
1016 ef405611 Paolo Bonzini
        p[4] = s->qdev.blocksize >> 8;
1017 ef405611 Paolo Bonzini
        p[6] = (s->qdev.conf.cyls >> 8) & 0xff;
1018 ef405611 Paolo Bonzini
        p[7] = s->qdev.conf.cyls & 0xff;
1019 ef405611 Paolo Bonzini
        /* Write precomp start cylinder, disabled */
1020 d252df48 Markus Armbruster
        p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
1021 d252df48 Markus Armbruster
        p[9] = s->qdev.conf.cyls & 0xff;
1022 ef405611 Paolo Bonzini
        /* Reduced current start cylinder, disabled */
1023 d252df48 Markus Armbruster
        p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
1024 d252df48 Markus Armbruster
        p[11] = s->qdev.conf.cyls & 0xff;
1025 ebddfcbe Gerd Hoffmann
        /* Device step rate [100us], 100us */
1026 ef405611 Paolo Bonzini
        p[12] = 0;
1027 ef405611 Paolo Bonzini
        p[13] = 1;
1028 ebddfcbe Gerd Hoffmann
        /* Device step pulse width [us], 1us */
1029 ef405611 Paolo Bonzini
        p[14] = 1;
1030 ebddfcbe Gerd Hoffmann
        /* Device head settle delay [100us], 100us */
1031 ef405611 Paolo Bonzini
        p[15] = 0;
1032 ef405611 Paolo Bonzini
        p[16] = 1;
1033 ebddfcbe Gerd Hoffmann
        /* Motor on delay [0.1s], 0.1s */
1034 ef405611 Paolo Bonzini
        p[17] = 1;
1035 ebddfcbe Gerd Hoffmann
        /* Motor off delay [0.1s], 0.1s */
1036 ef405611 Paolo Bonzini
        p[18] = 1;
1037 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
1038 ef405611 Paolo Bonzini
        p[26] = (5400 >> 8) & 0xff;
1039 ef405611 Paolo Bonzini
        p[27] = 5400 & 0xff;
1040 cfc606da Paolo Bonzini
        break;
1041 ebddfcbe Gerd Hoffmann
1042 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CACHING:
1043 ef405611 Paolo Bonzini
        length = 0x12;
1044 96c91bbf Paolo Bonzini
        if (page_control == 1 || /* Changeable Values */
1045 96c91bbf Paolo Bonzini
            bdrv_enable_write_cache(s->qdev.conf.bs)) {
1046 ef405611 Paolo Bonzini
            p[0] = 4; /* WCE */
1047 ebddfcbe Gerd Hoffmann
        }
1048 cfc606da Paolo Bonzini
        break;
1049 ebddfcbe Gerd Hoffmann
1050 a07c7dcd Paolo Bonzini
    case MODE_PAGE_R_W_ERROR:
1051 ef405611 Paolo Bonzini
        length = 10;
1052 4f588b15 Paolo Bonzini
        if (page_control == 1) { /* Changeable Values */
1053 4f588b15 Paolo Bonzini
            break;
1054 4f588b15 Paolo Bonzini
        }
1055 ef405611 Paolo Bonzini
        p[0] = 0x80; /* Automatic Write Reallocation Enabled */
1056 a07c7dcd Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
1057 ef405611 Paolo Bonzini
            p[1] = 0x20; /* Read Retry Count */
1058 a07c7dcd Paolo Bonzini
        }
1059 a07c7dcd Paolo Bonzini
        break;
1060 a07c7dcd Paolo Bonzini
1061 a07c7dcd Paolo Bonzini
    case MODE_PAGE_AUDIO_CTL:
1062 ef405611 Paolo Bonzini
        length = 14;
1063 a07c7dcd Paolo Bonzini
        break;
1064 a07c7dcd Paolo Bonzini
1065 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CAPABILITIES:
1066 ef405611 Paolo Bonzini
        length = 0x14;
1067 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
1068 cfc606da Paolo Bonzini
            break;
1069 282ab04e Bernhard Kohl
        }
1070 a07c7dcd Paolo Bonzini
1071 ef405611 Paolo Bonzini
        p[0] = 0x3b; /* CD-R & CD-RW read */
1072 ef405611 Paolo Bonzini
        p[1] = 0; /* Writing not supported */
1073 ef405611 Paolo Bonzini
        p[2] = 0x7f; /* Audio, composite, digital out,
1074 ebddfcbe Gerd Hoffmann
                        mode 2 form 1&2, multi session */
1075 ef405611 Paolo Bonzini
        p[3] = 0xff; /* CD DA, DA accurate, RW supported,
1076 ebddfcbe Gerd Hoffmann
                        RW corrected, C2 errors, ISRC,
1077 ebddfcbe Gerd Hoffmann
                        UPC, Bar code */
1078 ef405611 Paolo Bonzini
        p[4] = 0x2d | (s->tray_locked ? 2 : 0);
1079 ebddfcbe Gerd Hoffmann
        /* Locking supported, jumper present, eject, tray */
1080 ef405611 Paolo Bonzini
        p[5] = 0; /* no volume & mute control, no
1081 ebddfcbe Gerd Hoffmann
                     changer */
1082 ef405611 Paolo Bonzini
        p[6] = (50 * 176) >> 8; /* 50x read speed */
1083 ef405611 Paolo Bonzini
        p[7] = (50 * 176) & 0xff;
1084 ef405611 Paolo Bonzini
        p[8] = 2 >> 8; /* Two volume levels */
1085 ef405611 Paolo Bonzini
        p[9] = 2 & 0xff;
1086 ef405611 Paolo Bonzini
        p[10] = 2048 >> 8; /* 2M buffer */
1087 ef405611 Paolo Bonzini
        p[11] = 2048 & 0xff;
1088 ef405611 Paolo Bonzini
        p[12] = (16 * 176) >> 8; /* 16x read speed current */
1089 ef405611 Paolo Bonzini
        p[13] = (16 * 176) & 0xff;
1090 ef405611 Paolo Bonzini
        p[16] = (16 * 176) >> 8; /* 16x write speed */
1091 ef405611 Paolo Bonzini
        p[17] = (16 * 176) & 0xff;
1092 ef405611 Paolo Bonzini
        p[18] = (16 * 176) >> 8; /* 16x write speed current */
1093 ebddfcbe Gerd Hoffmann
        p[19] = (16 * 176) & 0xff;
1094 cfc606da Paolo Bonzini
        break;
1095 ebddfcbe Gerd Hoffmann
1096 ebddfcbe Gerd Hoffmann
    default:
1097 cfc606da Paolo Bonzini
        return -1;
1098 ebddfcbe Gerd Hoffmann
    }
1099 cfc606da Paolo Bonzini
1100 ef405611 Paolo Bonzini
    assert(length < 256);
1101 ef405611 Paolo Bonzini
    (*p_outbuf)[0] = page;
1102 ef405611 Paolo Bonzini
    (*p_outbuf)[1] = length;
1103 ef405611 Paolo Bonzini
    *p_outbuf += length + 2;
1104 ef405611 Paolo Bonzini
    return length + 2;
1105 ebddfcbe Gerd Hoffmann
}
1106 ebddfcbe Gerd Hoffmann
1107 cfc606da Paolo Bonzini
static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
1108 ebddfcbe Gerd Hoffmann
{
1109 cfc606da Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
1110 ebddfcbe Gerd Hoffmann
    uint64_t nb_sectors;
1111 e590ecbe Paolo Bonzini
    bool dbd;
1112 e590ecbe Paolo Bonzini
    int page, buflen, ret, page_control;
1113 ebddfcbe Gerd Hoffmann
    uint8_t *p;
1114 ce512ee1 Bernhard Kohl
    uint8_t dev_specific_param;
1115 ebddfcbe Gerd Hoffmann
1116 e590ecbe Paolo Bonzini
    dbd = (r->req.cmd.buf[1] & 0x8) != 0;
1117 cfc606da Paolo Bonzini
    page = r->req.cmd.buf[2] & 0x3f;
1118 cfc606da Paolo Bonzini
    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
1119 aa2b1e89 Bernhard Kohl
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
1120 cfc606da Paolo Bonzini
        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
1121 cfc606da Paolo Bonzini
    memset(outbuf, 0, r->req.cmd.xfer);
1122 ebddfcbe Gerd Hoffmann
    p = outbuf;
1123 ebddfcbe Gerd Hoffmann
1124 e590ecbe Paolo Bonzini
    if (s->qdev.type == TYPE_DISK) {
1125 da8365db Paolo Bonzini
        dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;
1126 e590ecbe Paolo Bonzini
        if (bdrv_is_read_only(s->qdev.conf.bs)) {
1127 e590ecbe Paolo Bonzini
            dev_specific_param |= 0x80; /* Readonly.  */
1128 e590ecbe Paolo Bonzini
        }
1129 ce512ee1 Bernhard Kohl
    } else {
1130 e590ecbe Paolo Bonzini
        /* MMC prescribes that CD/DVD drives have no block descriptors,
1131 e590ecbe Paolo Bonzini
         * and defines no device-specific parameter.  */
1132 6a2de0f2 Paolo Bonzini
        dev_specific_param = 0x00;
1133 e590ecbe Paolo Bonzini
        dbd = true;
1134 ce512ee1 Bernhard Kohl
    }
1135 ce512ee1 Bernhard Kohl
1136 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1137 ce512ee1 Bernhard Kohl
        p[1] = 0; /* Default media type.  */
1138 ce512ee1 Bernhard Kohl
        p[2] = dev_specific_param;
1139 ce512ee1 Bernhard Kohl
        p[3] = 0; /* Block descriptor length.  */
1140 ce512ee1 Bernhard Kohl
        p += 4;
1141 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1142 ce512ee1 Bernhard Kohl
        p[2] = 0; /* Default media type.  */
1143 ce512ee1 Bernhard Kohl
        p[3] = dev_specific_param;
1144 ce512ee1 Bernhard Kohl
        p[6] = p[7] = 0; /* Block descriptor length.  */
1145 ce512ee1 Bernhard Kohl
        p += 8;
1146 ebddfcbe Gerd Hoffmann
    }
1147 ebddfcbe Gerd Hoffmann
1148 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1149 e590ecbe Paolo Bonzini
    if (!dbd && nb_sectors) {
1150 cfc606da Paolo Bonzini
        if (r->req.cmd.buf[0] == MODE_SENSE) {
1151 ce512ee1 Bernhard Kohl
            outbuf[3] = 8; /* Block descriptor length  */
1152 ce512ee1 Bernhard Kohl
        } else { /* MODE_SENSE_10 */
1153 ce512ee1 Bernhard Kohl
            outbuf[7] = 8; /* Block descriptor length  */
1154 ce512ee1 Bernhard Kohl
        }
1155 69377307 Paolo Bonzini
        nb_sectors /= (s->qdev.blocksize / 512);
1156 f01b5931 Paolo Bonzini
        if (nb_sectors > 0xffffff) {
1157 2488b740 Bernhard Kohl
            nb_sectors = 0;
1158 f01b5931 Paolo Bonzini
        }
1159 ebddfcbe Gerd Hoffmann
        p[0] = 0; /* media density code */
1160 ebddfcbe Gerd Hoffmann
        p[1] = (nb_sectors >> 16) & 0xff;
1161 ebddfcbe Gerd Hoffmann
        p[2] = (nb_sectors >> 8) & 0xff;
1162 ebddfcbe Gerd Hoffmann
        p[3] = nb_sectors & 0xff;
1163 ebddfcbe Gerd Hoffmann
        p[4] = 0; /* reserved */
1164 ebddfcbe Gerd Hoffmann
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
1165 69377307 Paolo Bonzini
        p[6] = s->qdev.blocksize >> 8;
1166 ebddfcbe Gerd Hoffmann
        p[7] = 0;
1167 ebddfcbe Gerd Hoffmann
        p += 8;
1168 ebddfcbe Gerd Hoffmann
    }
1169 ebddfcbe Gerd Hoffmann
1170 cfc606da Paolo Bonzini
    if (page_control == 3) {
1171 cfc606da Paolo Bonzini
        /* Saved Values */
1172 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
1173 cfc606da Paolo Bonzini
        return -1;
1174 282ab04e Bernhard Kohl
    }
1175 282ab04e Bernhard Kohl
1176 cfc606da Paolo Bonzini
    if (page == 0x3f) {
1177 cfc606da Paolo Bonzini
        for (page = 0; page <= 0x3e; page++) {
1178 cfc606da Paolo Bonzini
            mode_sense_page(s, page, &p, page_control);
1179 cfc606da Paolo Bonzini
        }
1180 cfc606da Paolo Bonzini
    } else {
1181 cfc606da Paolo Bonzini
        ret = mode_sense_page(s, page, &p, page_control);
1182 cfc606da Paolo Bonzini
        if (ret == -1) {
1183 cfc606da Paolo Bonzini
            return -1;
1184 cfc606da Paolo Bonzini
        }
1185 ebddfcbe Gerd Hoffmann
    }
1186 ebddfcbe Gerd Hoffmann
1187 ebddfcbe Gerd Hoffmann
    buflen = p - outbuf;
1188 ce512ee1 Bernhard Kohl
    /*
1189 ce512ee1 Bernhard Kohl
     * The mode data length field specifies the length in bytes of the
1190 ce512ee1 Bernhard Kohl
     * following data that is available to be transferred. The mode data
1191 ce512ee1 Bernhard Kohl
     * length does not include itself.
1192 ce512ee1 Bernhard Kohl
     */
1193 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1194 ce512ee1 Bernhard Kohl
        outbuf[0] = buflen - 1;
1195 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
1196 ce512ee1 Bernhard Kohl
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1197 ce512ee1 Bernhard Kohl
        outbuf[1] = (buflen - 2) & 0xff;
1198 ce512ee1 Bernhard Kohl
    }
1199 ebddfcbe Gerd Hoffmann
    return buflen;
1200 ebddfcbe Gerd Hoffmann
}
1201 ebddfcbe Gerd Hoffmann
1202 02880f43 Gerd Hoffmann
static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1203 02880f43 Gerd Hoffmann
{
1204 02880f43 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1205 02880f43 Gerd Hoffmann
    int start_track, format, msf, toclen;
1206 02880f43 Gerd Hoffmann
    uint64_t nb_sectors;
1207 02880f43 Gerd Hoffmann
1208 02880f43 Gerd Hoffmann
    msf = req->cmd.buf[1] & 2;
1209 02880f43 Gerd Hoffmann
    format = req->cmd.buf[2] & 0xf;
1210 02880f43 Gerd Hoffmann
    start_track = req->cmd.buf[6];
1211 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1212 02880f43 Gerd Hoffmann
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
1213 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1214 02880f43 Gerd Hoffmann
    switch (format) {
1215 02880f43 Gerd Hoffmann
    case 0:
1216 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1217 02880f43 Gerd Hoffmann
        break;
1218 02880f43 Gerd Hoffmann
    case 1:
1219 02880f43 Gerd Hoffmann
        /* multi session : only a single session defined */
1220 02880f43 Gerd Hoffmann
        toclen = 12;
1221 02880f43 Gerd Hoffmann
        memset(outbuf, 0, 12);
1222 02880f43 Gerd Hoffmann
        outbuf[1] = 0x0a;
1223 02880f43 Gerd Hoffmann
        outbuf[2] = 0x01;
1224 02880f43 Gerd Hoffmann
        outbuf[3] = 0x01;
1225 02880f43 Gerd Hoffmann
        break;
1226 02880f43 Gerd Hoffmann
    case 2:
1227 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1228 02880f43 Gerd Hoffmann
        break;
1229 02880f43 Gerd Hoffmann
    default:
1230 02880f43 Gerd Hoffmann
        return -1;
1231 02880f43 Gerd Hoffmann
    }
1232 02880f43 Gerd Hoffmann
    return toclen;
1233 02880f43 Gerd Hoffmann
}
1234 02880f43 Gerd Hoffmann
1235 68bb01f3 Markus Armbruster
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
1236 bfd52647 Markus Armbruster
{
1237 bfd52647 Markus Armbruster
    SCSIRequest *req = &r->req;
1238 bfd52647 Markus Armbruster
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1239 bfd52647 Markus Armbruster
    bool start = req->cmd.buf[4] & 1;
1240 bfd52647 Markus Armbruster
    bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
1241 ae5708b3 Ronnie Sahlberg
    int pwrcnd = req->cmd.buf[4] & 0xf0;
1242 ae5708b3 Ronnie Sahlberg
1243 ae5708b3 Ronnie Sahlberg
    if (pwrcnd) {
1244 ae5708b3 Ronnie Sahlberg
        /* eject/load only happens for power condition == 0 */
1245 ae5708b3 Ronnie Sahlberg
        return 0;
1246 ae5708b3 Ronnie Sahlberg
    }
1247 bfd52647 Markus Armbruster
1248 b456a71c Paolo Bonzini
    if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && loej) {
1249 68bb01f3 Markus Armbruster
        if (!start && !s->tray_open && s->tray_locked) {
1250 68bb01f3 Markus Armbruster
            scsi_check_condition(r,
1251 44740c38 Paolo Bonzini
                                 bdrv_is_inserted(s->qdev.conf.bs)
1252 68bb01f3 Markus Armbruster
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1253 68bb01f3 Markus Armbruster
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1254 68bb01f3 Markus Armbruster
            return -1;
1255 fdec4404 Markus Armbruster
        }
1256 d88b1819 Luiz Capitulino
1257 d88b1819 Luiz Capitulino
        if (s->tray_open != !start) {
1258 d88b1819 Luiz Capitulino
            bdrv_eject(s->qdev.conf.bs, !start);
1259 d88b1819 Luiz Capitulino
            s->tray_open = !start;
1260 d88b1819 Luiz Capitulino
        }
1261 bfd52647 Markus Armbruster
    }
1262 68bb01f3 Markus Armbruster
    return 0;
1263 bfd52647 Markus Armbruster
}
1264 bfd52647 Markus Armbruster
1265 314a3299 Paolo Bonzini
static void scsi_disk_emulate_read_data(SCSIRequest *req)
1266 314a3299 Paolo Bonzini
{
1267 314a3299 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1268 314a3299 Paolo Bonzini
    int buflen = r->iov.iov_len;
1269 314a3299 Paolo Bonzini
1270 314a3299 Paolo Bonzini
    if (buflen) {
1271 79fb50bb Paolo Bonzini
        DPRINTF("Read buf_len=%d\n", buflen);
1272 314a3299 Paolo Bonzini
        r->iov.iov_len = 0;
1273 314a3299 Paolo Bonzini
        r->started = true;
1274 314a3299 Paolo Bonzini
        scsi_req_data(&r->req, buflen);
1275 314a3299 Paolo Bonzini
        return;
1276 314a3299 Paolo Bonzini
    }
1277 314a3299 Paolo Bonzini
1278 314a3299 Paolo Bonzini
    /* This also clears the sense buffer for REQUEST SENSE.  */
1279 314a3299 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
1280 314a3299 Paolo Bonzini
}
1281 314a3299 Paolo Bonzini
1282 380feaff Paolo Bonzini
static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
1283 380feaff Paolo Bonzini
                                       uint8_t *inbuf, int inlen)
1284 380feaff Paolo Bonzini
{
1285 380feaff Paolo Bonzini
    uint8_t mode_current[SCSI_MAX_MODE_LEN];
1286 380feaff Paolo Bonzini
    uint8_t mode_changeable[SCSI_MAX_MODE_LEN];
1287 380feaff Paolo Bonzini
    uint8_t *p;
1288 380feaff Paolo Bonzini
    int len, expected_len, changeable_len, i;
1289 380feaff Paolo Bonzini
1290 380feaff Paolo Bonzini
    /* The input buffer does not include the page header, so it is
1291 380feaff Paolo Bonzini
     * off by 2 bytes.
1292 380feaff Paolo Bonzini
     */
1293 380feaff Paolo Bonzini
    expected_len = inlen + 2;
1294 380feaff Paolo Bonzini
    if (expected_len > SCSI_MAX_MODE_LEN) {
1295 380feaff Paolo Bonzini
        return -1;
1296 380feaff Paolo Bonzini
    }
1297 380feaff Paolo Bonzini
1298 380feaff Paolo Bonzini
    p = mode_current;
1299 380feaff Paolo Bonzini
    memset(mode_current, 0, inlen + 2);
1300 380feaff Paolo Bonzini
    len = mode_sense_page(s, page, &p, 0);
1301 380feaff Paolo Bonzini
    if (len < 0 || len != expected_len) {
1302 380feaff Paolo Bonzini
        return -1;
1303 380feaff Paolo Bonzini
    }
1304 380feaff Paolo Bonzini
1305 380feaff Paolo Bonzini
    p = mode_changeable;
1306 380feaff Paolo Bonzini
    memset(mode_changeable, 0, inlen + 2);
1307 380feaff Paolo Bonzini
    changeable_len = mode_sense_page(s, page, &p, 1);
1308 380feaff Paolo Bonzini
    assert(changeable_len == len);
1309 380feaff Paolo Bonzini
1310 380feaff Paolo Bonzini
    /* Check that unchangeable bits are the same as what MODE SENSE
1311 380feaff Paolo Bonzini
     * would return.
1312 380feaff Paolo Bonzini
     */
1313 380feaff Paolo Bonzini
    for (i = 2; i < len; i++) {
1314 380feaff Paolo Bonzini
        if (((mode_current[i] ^ inbuf[i - 2]) & ~mode_changeable[i]) != 0) {
1315 380feaff Paolo Bonzini
            return -1;
1316 380feaff Paolo Bonzini
        }
1317 380feaff Paolo Bonzini
    }
1318 380feaff Paolo Bonzini
    return 0;
1319 380feaff Paolo Bonzini
}
1320 380feaff Paolo Bonzini
1321 380feaff Paolo Bonzini
static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page, uint8_t *p)
1322 380feaff Paolo Bonzini
{
1323 96c91bbf Paolo Bonzini
    switch (page) {
1324 96c91bbf Paolo Bonzini
    case MODE_PAGE_CACHING:
1325 96c91bbf Paolo Bonzini
        bdrv_set_enable_write_cache(s->qdev.conf.bs, (p[0] & 4) != 0);
1326 96c91bbf Paolo Bonzini
        break;
1327 96c91bbf Paolo Bonzini
1328 96c91bbf Paolo Bonzini
    default:
1329 96c91bbf Paolo Bonzini
        break;
1330 96c91bbf Paolo Bonzini
    }
1331 380feaff Paolo Bonzini
}
1332 380feaff Paolo Bonzini
1333 380feaff Paolo Bonzini
static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
1334 380feaff Paolo Bonzini
{
1335 380feaff Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
1336 380feaff Paolo Bonzini
1337 380feaff Paolo Bonzini
    while (len > 0) {
1338 380feaff Paolo Bonzini
        int page, subpage, page_len;
1339 380feaff Paolo Bonzini
1340 380feaff Paolo Bonzini
        /* Parse both possible formats for the mode page headers.  */
1341 380feaff Paolo Bonzini
        page = p[0] & 0x3f;
1342 380feaff Paolo Bonzini
        if (p[0] & 0x40) {
1343 380feaff Paolo Bonzini
            if (len < 4) {
1344 380feaff Paolo Bonzini
                goto invalid_param_len;
1345 380feaff Paolo Bonzini
            }
1346 380feaff Paolo Bonzini
            subpage = p[1];
1347 380feaff Paolo Bonzini
            page_len = lduw_be_p(&p[2]);
1348 380feaff Paolo Bonzini
            p += 4;
1349 380feaff Paolo Bonzini
            len -= 4;
1350 380feaff Paolo Bonzini
        } else {
1351 380feaff Paolo Bonzini
            if (len < 2) {
1352 380feaff Paolo Bonzini
                goto invalid_param_len;
1353 380feaff Paolo Bonzini
            }
1354 380feaff Paolo Bonzini
            subpage = 0;
1355 380feaff Paolo Bonzini
            page_len = p[1];
1356 380feaff Paolo Bonzini
            p += 2;
1357 380feaff Paolo Bonzini
            len -= 2;
1358 380feaff Paolo Bonzini
        }
1359 380feaff Paolo Bonzini
1360 380feaff Paolo Bonzini
        if (subpage) {
1361 380feaff Paolo Bonzini
            goto invalid_param;
1362 380feaff Paolo Bonzini
        }
1363 380feaff Paolo Bonzini
        if (page_len > len) {
1364 380feaff Paolo Bonzini
            goto invalid_param_len;
1365 380feaff Paolo Bonzini
        }
1366 380feaff Paolo Bonzini
1367 380feaff Paolo Bonzini
        if (!change) {
1368 380feaff Paolo Bonzini
            if (scsi_disk_check_mode_select(s, page, p, page_len) < 0) {
1369 380feaff Paolo Bonzini
                goto invalid_param;
1370 380feaff Paolo Bonzini
            }
1371 380feaff Paolo Bonzini
        } else {
1372 380feaff Paolo Bonzini
            scsi_disk_apply_mode_select(s, page, p);
1373 380feaff Paolo Bonzini
        }
1374 380feaff Paolo Bonzini
1375 380feaff Paolo Bonzini
        p += page_len;
1376 380feaff Paolo Bonzini
        len -= page_len;
1377 380feaff Paolo Bonzini
    }
1378 380feaff Paolo Bonzini
    return 0;
1379 380feaff Paolo Bonzini
1380 380feaff Paolo Bonzini
invalid_param:
1381 380feaff Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_PARAM));
1382 380feaff Paolo Bonzini
    return -1;
1383 380feaff Paolo Bonzini
1384 380feaff Paolo Bonzini
invalid_param_len:
1385 380feaff Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
1386 380feaff Paolo Bonzini
    return -1;
1387 380feaff Paolo Bonzini
}
1388 380feaff Paolo Bonzini
1389 380feaff Paolo Bonzini
static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
1390 380feaff Paolo Bonzini
{
1391 380feaff Paolo Bonzini
    uint8_t *p = inbuf;
1392 380feaff Paolo Bonzini
    int cmd = r->req.cmd.buf[0];
1393 380feaff Paolo Bonzini
    int len = r->req.cmd.xfer;
1394 380feaff Paolo Bonzini
    int hdr_len = (cmd == MODE_SELECT ? 4 : 8);
1395 380feaff Paolo Bonzini
    int bd_len;
1396 380feaff Paolo Bonzini
    int pass;
1397 380feaff Paolo Bonzini
1398 380feaff Paolo Bonzini
    /* We only support PF=1, SP=0.  */
1399 380feaff Paolo Bonzini
    if ((r->req.cmd.buf[1] & 0x11) != 0x10) {
1400 380feaff Paolo Bonzini
        goto invalid_field;
1401 380feaff Paolo Bonzini
    }
1402 380feaff Paolo Bonzini
1403 380feaff Paolo Bonzini
    if (len < hdr_len) {
1404 380feaff Paolo Bonzini
        goto invalid_param_len;
1405 380feaff Paolo Bonzini
    }
1406 380feaff Paolo Bonzini
1407 380feaff Paolo Bonzini
    bd_len = (cmd == MODE_SELECT ? p[3] : lduw_be_p(&p[6]));
1408 380feaff Paolo Bonzini
    len -= hdr_len;
1409 380feaff Paolo Bonzini
    p += hdr_len;
1410 380feaff Paolo Bonzini
    if (len < bd_len) {
1411 380feaff Paolo Bonzini
        goto invalid_param_len;
1412 380feaff Paolo Bonzini
    }
1413 380feaff Paolo Bonzini
    if (bd_len != 0 && bd_len != 8) {
1414 380feaff Paolo Bonzini
        goto invalid_param;
1415 380feaff Paolo Bonzini
    }
1416 380feaff Paolo Bonzini
1417 380feaff Paolo Bonzini
    len -= bd_len;
1418 380feaff Paolo Bonzini
    p += bd_len;
1419 380feaff Paolo Bonzini
1420 380feaff Paolo Bonzini
    /* Ensure no change is made if there is an error!  */
1421 380feaff Paolo Bonzini
    for (pass = 0; pass < 2; pass++) {
1422 380feaff Paolo Bonzini
        if (mode_select_pages(r, p, len, pass == 1) < 0) {
1423 380feaff Paolo Bonzini
            assert(pass == 0);
1424 380feaff Paolo Bonzini
            return;
1425 380feaff Paolo Bonzini
        }
1426 380feaff Paolo Bonzini
    }
1427 380feaff Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
1428 380feaff Paolo Bonzini
    return;
1429 380feaff Paolo Bonzini
1430 380feaff Paolo Bonzini
invalid_param:
1431 380feaff Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_PARAM));
1432 380feaff Paolo Bonzini
    return;
1433 380feaff Paolo Bonzini
1434 380feaff Paolo Bonzini
invalid_param_len:
1435 380feaff Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
1436 380feaff Paolo Bonzini
    return;
1437 380feaff Paolo Bonzini
1438 380feaff Paolo Bonzini
invalid_field:
1439 380feaff Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1440 380feaff Paolo Bonzini
}
1441 380feaff Paolo Bonzini
1442 444bc908 Paolo Bonzini
static inline bool check_lba_range(SCSIDiskState *s,
1443 444bc908 Paolo Bonzini
                                   uint64_t sector_num, uint32_t nb_sectors)
1444 444bc908 Paolo Bonzini
{
1445 444bc908 Paolo Bonzini
    /*
1446 444bc908 Paolo Bonzini
     * The first line tests that no overflow happens when computing the last
1447 444bc908 Paolo Bonzini
     * sector.  The second line tests that the last accessed sector is in
1448 444bc908 Paolo Bonzini
     * range.
1449 12ca76fc Paolo Bonzini
     *
1450 12ca76fc Paolo Bonzini
     * Careful, the computations should not underflow for nb_sectors == 0,
1451 12ca76fc Paolo Bonzini
     * and a 0-block read to the first LBA beyond the end of device is
1452 12ca76fc Paolo Bonzini
     * valid.
1453 444bc908 Paolo Bonzini
     */
1454 444bc908 Paolo Bonzini
    return (sector_num <= sector_num + nb_sectors &&
1455 12ca76fc Paolo Bonzini
            sector_num + nb_sectors <= s->qdev.max_lba + 1);
1456 444bc908 Paolo Bonzini
}
1457 444bc908 Paolo Bonzini
1458 5222aaf2 Paolo Bonzini
typedef struct UnmapCBData {
1459 5222aaf2 Paolo Bonzini
    SCSIDiskReq *r;
1460 5222aaf2 Paolo Bonzini
    uint8_t *inbuf;
1461 5222aaf2 Paolo Bonzini
    int count;
1462 5222aaf2 Paolo Bonzini
} UnmapCBData;
1463 5222aaf2 Paolo Bonzini
1464 5222aaf2 Paolo Bonzini
static void scsi_unmap_complete(void *opaque, int ret)
1465 5222aaf2 Paolo Bonzini
{
1466 5222aaf2 Paolo Bonzini
    UnmapCBData *data = opaque;
1467 5222aaf2 Paolo Bonzini
    SCSIDiskReq *r = data->r;
1468 5222aaf2 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
1469 5222aaf2 Paolo Bonzini
    uint64_t sector_num;
1470 5bb0b62e Stefan Weil
    uint32_t nb_sectors;
1471 5222aaf2 Paolo Bonzini
1472 5222aaf2 Paolo Bonzini
    r->req.aiocb = NULL;
1473 5222aaf2 Paolo Bonzini
    if (ret < 0) {
1474 5222aaf2 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret)) {
1475 5222aaf2 Paolo Bonzini
            goto done;
1476 5222aaf2 Paolo Bonzini
        }
1477 5222aaf2 Paolo Bonzini
    }
1478 5222aaf2 Paolo Bonzini
1479 5222aaf2 Paolo Bonzini
    if (data->count > 0 && !r->req.io_canceled) {
1480 5222aaf2 Paolo Bonzini
        sector_num = ldq_be_p(&data->inbuf[0]);
1481 5222aaf2 Paolo Bonzini
        nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
1482 444bc908 Paolo Bonzini
        if (!check_lba_range(s, sector_num, nb_sectors)) {
1483 5222aaf2 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1484 5222aaf2 Paolo Bonzini
            goto done;
1485 5222aaf2 Paolo Bonzini
        }
1486 5222aaf2 Paolo Bonzini
1487 5222aaf2 Paolo Bonzini
        r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
1488 5222aaf2 Paolo Bonzini
                                        sector_num * (s->qdev.blocksize / 512),
1489 5222aaf2 Paolo Bonzini
                                        nb_sectors * (s->qdev.blocksize / 512),
1490 5222aaf2 Paolo Bonzini
                                        scsi_unmap_complete, data);
1491 5222aaf2 Paolo Bonzini
        data->count--;
1492 5222aaf2 Paolo Bonzini
        data->inbuf += 16;
1493 5222aaf2 Paolo Bonzini
        return;
1494 5222aaf2 Paolo Bonzini
    }
1495 5222aaf2 Paolo Bonzini
1496 5222aaf2 Paolo Bonzini
done:
1497 5222aaf2 Paolo Bonzini
    if (data->count == 0) {
1498 5222aaf2 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1499 5222aaf2 Paolo Bonzini
    }
1500 5222aaf2 Paolo Bonzini
    if (!r->req.io_canceled) {
1501 5222aaf2 Paolo Bonzini
        scsi_req_unref(&r->req);
1502 5222aaf2 Paolo Bonzini
    }
1503 5222aaf2 Paolo Bonzini
    g_free(data);
1504 5222aaf2 Paolo Bonzini
}
1505 5222aaf2 Paolo Bonzini
1506 5222aaf2 Paolo Bonzini
static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
1507 5222aaf2 Paolo Bonzini
{
1508 5222aaf2 Paolo Bonzini
    uint8_t *p = inbuf;
1509 5222aaf2 Paolo Bonzini
    int len = r->req.cmd.xfer;
1510 5222aaf2 Paolo Bonzini
    UnmapCBData *data;
1511 5222aaf2 Paolo Bonzini
1512 5222aaf2 Paolo Bonzini
    if (len < 8) {
1513 5222aaf2 Paolo Bonzini
        goto invalid_param_len;
1514 5222aaf2 Paolo Bonzini
    }
1515 5222aaf2 Paolo Bonzini
    if (len < lduw_be_p(&p[0]) + 2) {
1516 5222aaf2 Paolo Bonzini
        goto invalid_param_len;
1517 5222aaf2 Paolo Bonzini
    }
1518 5222aaf2 Paolo Bonzini
    if (len < lduw_be_p(&p[2]) + 8) {
1519 5222aaf2 Paolo Bonzini
        goto invalid_param_len;
1520 5222aaf2 Paolo Bonzini
    }
1521 5222aaf2 Paolo Bonzini
    if (lduw_be_p(&p[2]) & 15) {
1522 5222aaf2 Paolo Bonzini
        goto invalid_param_len;
1523 5222aaf2 Paolo Bonzini
    }
1524 5222aaf2 Paolo Bonzini
1525 5222aaf2 Paolo Bonzini
    data = g_new0(UnmapCBData, 1);
1526 5222aaf2 Paolo Bonzini
    data->r = r;
1527 5222aaf2 Paolo Bonzini
    data->inbuf = &p[8];
1528 5222aaf2 Paolo Bonzini
    data->count = lduw_be_p(&p[2]) >> 4;
1529 5222aaf2 Paolo Bonzini
1530 5222aaf2 Paolo Bonzini
    /* The matching unref is in scsi_unmap_complete, before data is freed.  */
1531 5222aaf2 Paolo Bonzini
    scsi_req_ref(&r->req);
1532 5222aaf2 Paolo Bonzini
    scsi_unmap_complete(data, 0);
1533 5222aaf2 Paolo Bonzini
    return;
1534 5222aaf2 Paolo Bonzini
1535 5222aaf2 Paolo Bonzini
invalid_param_len:
1536 5222aaf2 Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
1537 5222aaf2 Paolo Bonzini
}
1538 5222aaf2 Paolo Bonzini
1539 314a3299 Paolo Bonzini
static void scsi_disk_emulate_write_data(SCSIRequest *req)
1540 314a3299 Paolo Bonzini
{
1541 af6d510d Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1542 af6d510d Paolo Bonzini
1543 af6d510d Paolo Bonzini
    if (r->iov.iov_len) {
1544 af6d510d Paolo Bonzini
        int buflen = r->iov.iov_len;
1545 79fb50bb Paolo Bonzini
        DPRINTF("Write buf_len=%d\n", buflen);
1546 af6d510d Paolo Bonzini
        r->iov.iov_len = 0;
1547 af6d510d Paolo Bonzini
        scsi_req_data(&r->req, buflen);
1548 af6d510d Paolo Bonzini
        return;
1549 af6d510d Paolo Bonzini
    }
1550 af6d510d Paolo Bonzini
1551 af6d510d Paolo Bonzini
    switch (req->cmd.buf[0]) {
1552 af6d510d Paolo Bonzini
    case MODE_SELECT:
1553 af6d510d Paolo Bonzini
    case MODE_SELECT_10:
1554 af6d510d Paolo Bonzini
        /* This also clears the sense buffer for REQUEST SENSE.  */
1555 380feaff Paolo Bonzini
        scsi_disk_emulate_mode_select(r, r->iov.iov_base);
1556 af6d510d Paolo Bonzini
        break;
1557 af6d510d Paolo Bonzini
1558 5222aaf2 Paolo Bonzini
    case UNMAP:
1559 5222aaf2 Paolo Bonzini
        scsi_disk_emulate_unmap(r, r->iov.iov_base);
1560 5222aaf2 Paolo Bonzini
        break;
1561 5222aaf2 Paolo Bonzini
1562 af6d510d Paolo Bonzini
    default:
1563 af6d510d Paolo Bonzini
        abort();
1564 af6d510d Paolo Bonzini
    }
1565 314a3299 Paolo Bonzini
}
1566 314a3299 Paolo Bonzini
1567 b08d0ea0 Paolo Bonzini
static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
1568 aa5dbdc1 Gerd Hoffmann
{
1569 b08d0ea0 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1570 e7e25e32 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1571 e7e25e32 Gerd Hoffmann
    uint64_t nb_sectors;
1572 7285477a Paolo Bonzini
    uint8_t *outbuf;
1573 af6d510d Paolo Bonzini
    int buflen;
1574 aa5dbdc1 Gerd Hoffmann
1575 b08d0ea0 Paolo Bonzini
    switch (req->cmd.buf[0]) {
1576 b08d0ea0 Paolo Bonzini
    case INQUIRY:
1577 b08d0ea0 Paolo Bonzini
    case MODE_SENSE:
1578 b08d0ea0 Paolo Bonzini
    case MODE_SENSE_10:
1579 b08d0ea0 Paolo Bonzini
    case RESERVE:
1580 b08d0ea0 Paolo Bonzini
    case RESERVE_10:
1581 b08d0ea0 Paolo Bonzini
    case RELEASE:
1582 b08d0ea0 Paolo Bonzini
    case RELEASE_10:
1583 b08d0ea0 Paolo Bonzini
    case START_STOP:
1584 b08d0ea0 Paolo Bonzini
    case ALLOW_MEDIUM_REMOVAL:
1585 b08d0ea0 Paolo Bonzini
    case GET_CONFIGURATION:
1586 b08d0ea0 Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1587 b08d0ea0 Paolo Bonzini
    case MECHANISM_STATUS:
1588 b08d0ea0 Paolo Bonzini
    case REQUEST_SENSE:
1589 b08d0ea0 Paolo Bonzini
        break;
1590 b08d0ea0 Paolo Bonzini
1591 b08d0ea0 Paolo Bonzini
    default:
1592 b08d0ea0 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1593 b08d0ea0 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1594 b08d0ea0 Paolo Bonzini
            return 0;
1595 b08d0ea0 Paolo Bonzini
        }
1596 b08d0ea0 Paolo Bonzini
        break;
1597 b08d0ea0 Paolo Bonzini
    }
1598 b08d0ea0 Paolo Bonzini
1599 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
1600 7285477a Paolo Bonzini
        /*
1601 7285477a Paolo Bonzini
         * FIXME: we shouldn't return anything bigger than 4k, but the code
1602 7285477a Paolo Bonzini
         * requires the buffer to be as big as req->cmd.xfer in several
1603 7285477a Paolo Bonzini
         * places.  So, do not allow CDBs with a very large ALLOCATION
1604 7285477a Paolo Bonzini
         * LENGTH.  The real fix would be to modify scsi_read_data and
1605 7285477a Paolo Bonzini
         * dma_buf_read, so that they return data beyond the buflen
1606 7285477a Paolo Bonzini
         * as all zeros.
1607 7285477a Paolo Bonzini
         */
1608 7285477a Paolo Bonzini
        if (req->cmd.xfer > 65536) {
1609 7285477a Paolo Bonzini
            goto illegal_request;
1610 7285477a Paolo Bonzini
        }
1611 7285477a Paolo Bonzini
        r->buflen = MAX(4096, req->cmd.xfer);
1612 44740c38 Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
1613 7285477a Paolo Bonzini
    }
1614 7285477a Paolo Bonzini
1615 af6d510d Paolo Bonzini
    buflen = req->cmd.xfer;
1616 7285477a Paolo Bonzini
    outbuf = r->iov.iov_base;
1617 aa5dbdc1 Gerd Hoffmann
    switch (req->cmd.buf[0]) {
1618 aa5dbdc1 Gerd Hoffmann
    case TEST_UNIT_READY:
1619 9bcaf4fe Paolo Bonzini
        assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
1620 5f71d32f Hannes Reinecke
        break;
1621 0b06c059 Gerd Hoffmann
    case INQUIRY:
1622 0b06c059 Gerd Hoffmann
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
1623 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1624 0b06c059 Gerd Hoffmann
            goto illegal_request;
1625 f01b5931 Paolo Bonzini
        }
1626 5f71d32f Hannes Reinecke
        break;
1627 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1628 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1629 cfc606da Paolo Bonzini
        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
1630 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1631 ebddfcbe Gerd Hoffmann
            goto illegal_request;
1632 f01b5931 Paolo Bonzini
        }
1633 ebddfcbe Gerd Hoffmann
        break;
1634 02880f43 Gerd Hoffmann
    case READ_TOC:
1635 02880f43 Gerd Hoffmann
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
1636 f01b5931 Paolo Bonzini
        if (buflen < 0) {
1637 02880f43 Gerd Hoffmann
            goto illegal_request;
1638 f01b5931 Paolo Bonzini
        }
1639 02880f43 Gerd Hoffmann
        break;
1640 3d53ba18 Gerd Hoffmann
    case RESERVE:
1641 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1642 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1643 f01b5931 Paolo Bonzini
        }
1644 3d53ba18 Gerd Hoffmann
        break;
1645 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1646 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1647 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1648 f01b5931 Paolo Bonzini
        }
1649 3d53ba18 Gerd Hoffmann
        break;
1650 3d53ba18 Gerd Hoffmann
    case RELEASE:
1651 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
1652 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1653 f01b5931 Paolo Bonzini
        }
1654 3d53ba18 Gerd Hoffmann
        break;
1655 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1656 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
1657 3d53ba18 Gerd Hoffmann
            goto illegal_request;
1658 f01b5931 Paolo Bonzini
        }
1659 3d53ba18 Gerd Hoffmann
        break;
1660 8d3628ff Gerd Hoffmann
    case START_STOP:
1661 68bb01f3 Markus Armbruster
        if (scsi_disk_emulate_start_stop(r) < 0) {
1662 b08d0ea0 Paolo Bonzini
            return 0;
1663 68bb01f3 Markus Armbruster
        }
1664 5f71d32f Hannes Reinecke
        break;
1665 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1666 81b1008d Markus Armbruster
        s->tray_locked = req->cmd.buf[4] & 1;
1667 44740c38 Paolo Bonzini
        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
1668 5f71d32f Hannes Reinecke
        break;
1669 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1670 e7e25e32 Gerd Hoffmann
        /* The normal LEN field for this command is zero.  */
1671 5f71d32f Hannes Reinecke
        memset(outbuf, 0, 8);
1672 44740c38 Paolo Bonzini
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1673 f01b5931 Paolo Bonzini
        if (!nb_sectors) {
1674 9bcaf4fe Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1675 9bcaf4fe Paolo Bonzini
            return -1;
1676 f01b5931 Paolo Bonzini
        }
1677 7cec78b6 Paolo Bonzini
        if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
1678 7cec78b6 Paolo Bonzini
            goto illegal_request;
1679 7cec78b6 Paolo Bonzini
        }
1680 69377307 Paolo Bonzini
        nb_sectors /= s->qdev.blocksize / 512;
1681 e7e25e32 Gerd Hoffmann
        /* Returned value is the address of the last sector.  */
1682 e7e25e32 Gerd Hoffmann
        nb_sectors--;
1683 e7e25e32 Gerd Hoffmann
        /* Remember the new size for read/write sanity checking. */
1684 7877903a Paolo Bonzini
        s->qdev.max_lba = nb_sectors;
1685 e7e25e32 Gerd Hoffmann
        /* Clip to 2TB, instead of returning capacity modulo 2TB. */
1686 f01b5931 Paolo Bonzini
        if (nb_sectors > UINT32_MAX) {
1687 e7e25e32 Gerd Hoffmann
            nb_sectors = UINT32_MAX;
1688 f01b5931 Paolo Bonzini
        }
1689 e7e25e32 Gerd Hoffmann
        outbuf[0] = (nb_sectors >> 24) & 0xff;
1690 e7e25e32 Gerd Hoffmann
        outbuf[1] = (nb_sectors >> 16) & 0xff;
1691 e7e25e32 Gerd Hoffmann
        outbuf[2] = (nb_sectors >> 8) & 0xff;
1692 e7e25e32 Gerd Hoffmann
        outbuf[3] = nb_sectors & 0xff;
1693 e7e25e32 Gerd Hoffmann
        outbuf[4] = 0;
1694 e7e25e32 Gerd Hoffmann
        outbuf[5] = 0;
1695 69377307 Paolo Bonzini
        outbuf[6] = s->qdev.blocksize >> 8;
1696 e7e25e32 Gerd Hoffmann
        outbuf[7] = 0;
1697 e7e25e32 Gerd Hoffmann
        buflen = 8;
1698 5f71d32f Hannes Reinecke
        break;
1699 f3b338ef Paolo Bonzini
    case REQUEST_SENSE:
1700 f3b338ef Paolo Bonzini
        /* Just return "NO SENSE".  */
1701 f3b338ef Paolo Bonzini
        buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
1702 f3b338ef Paolo Bonzini
                                  (req->cmd.buf[1] & 1) == 0);
1703 f3b338ef Paolo Bonzini
        break;
1704 b6c251ab Paolo Bonzini
    case MECHANISM_STATUS:
1705 b6c251ab Paolo Bonzini
        buflen = scsi_emulate_mechanism_status(s, outbuf);
1706 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1707 b6c251ab Paolo Bonzini
            goto illegal_request;
1708 b6c251ab Paolo Bonzini
        }
1709 b6c251ab Paolo Bonzini
        break;
1710 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
1711 430ee2f2 Paolo Bonzini
        buflen = scsi_get_configuration(s, outbuf);
1712 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1713 b6c251ab Paolo Bonzini
            goto illegal_request;
1714 b6c251ab Paolo Bonzini
        }
1715 b6c251ab Paolo Bonzini
        break;
1716 b6c251ab Paolo Bonzini
    case GET_EVENT_STATUS_NOTIFICATION:
1717 b6c251ab Paolo Bonzini
        buflen = scsi_get_event_status_notification(s, r, outbuf);
1718 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1719 b6c251ab Paolo Bonzini
            goto illegal_request;
1720 b6c251ab Paolo Bonzini
        }
1721 b6c251ab Paolo Bonzini
        break;
1722 1a4f0c3a Paolo Bonzini
    case READ_DISC_INFORMATION:
1723 1a4f0c3a Paolo Bonzini
        buflen = scsi_read_disc_information(s, r, outbuf);
1724 1a4f0c3a Paolo Bonzini
        if (buflen < 0) {
1725 1a4f0c3a Paolo Bonzini
            goto illegal_request;
1726 1a4f0c3a Paolo Bonzini
        }
1727 1a4f0c3a Paolo Bonzini
        break;
1728 b6c251ab Paolo Bonzini
    case READ_DVD_STRUCTURE:
1729 b6c251ab Paolo Bonzini
        buflen = scsi_read_dvd_structure(s, r, outbuf);
1730 b6c251ab Paolo Bonzini
        if (buflen < 0) {
1731 b6c251ab Paolo Bonzini
            goto illegal_request;
1732 b6c251ab Paolo Bonzini
        }
1733 38215553 Gerd Hoffmann
        break;
1734 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
1735 5dd90e2a Gerd Hoffmann
        /* Service Action In subcommands. */
1736 f6515262 Paolo Bonzini
        if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
1737 5dd90e2a Gerd Hoffmann
            DPRINTF("SAI READ CAPACITY(16)\n");
1738 5dd90e2a Gerd Hoffmann
            memset(outbuf, 0, req->cmd.xfer);
1739 44740c38 Paolo Bonzini
            bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1740 f01b5931 Paolo Bonzini
            if (!nb_sectors) {
1741 9bcaf4fe Paolo Bonzini
                scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1742 9bcaf4fe Paolo Bonzini
                return -1;
1743 f01b5931 Paolo Bonzini
            }
1744 7cec78b6 Paolo Bonzini
            if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1745 7cec78b6 Paolo Bonzini
                goto illegal_request;
1746 7cec78b6 Paolo Bonzini
            }
1747 69377307 Paolo Bonzini
            nb_sectors /= s->qdev.blocksize / 512;
1748 5dd90e2a Gerd Hoffmann
            /* Returned value is the address of the last sector.  */
1749 5dd90e2a Gerd Hoffmann
            nb_sectors--;
1750 5dd90e2a Gerd Hoffmann
            /* Remember the new size for read/write sanity checking. */
1751 7877903a Paolo Bonzini
            s->qdev.max_lba = nb_sectors;
1752 5dd90e2a Gerd Hoffmann
            outbuf[0] = (nb_sectors >> 56) & 0xff;
1753 5dd90e2a Gerd Hoffmann
            outbuf[1] = (nb_sectors >> 48) & 0xff;
1754 5dd90e2a Gerd Hoffmann
            outbuf[2] = (nb_sectors >> 40) & 0xff;
1755 5dd90e2a Gerd Hoffmann
            outbuf[3] = (nb_sectors >> 32) & 0xff;
1756 5dd90e2a Gerd Hoffmann
            outbuf[4] = (nb_sectors >> 24) & 0xff;
1757 5dd90e2a Gerd Hoffmann
            outbuf[5] = (nb_sectors >> 16) & 0xff;
1758 5dd90e2a Gerd Hoffmann
            outbuf[6] = (nb_sectors >> 8) & 0xff;
1759 5dd90e2a Gerd Hoffmann
            outbuf[7] = nb_sectors & 0xff;
1760 5dd90e2a Gerd Hoffmann
            outbuf[8] = 0;
1761 5dd90e2a Gerd Hoffmann
            outbuf[9] = 0;
1762 69377307 Paolo Bonzini
            outbuf[10] = s->qdev.blocksize >> 8;
1763 5dd90e2a Gerd Hoffmann
            outbuf[11] = 0;
1764 ee3659e3 Christoph Hellwig
            outbuf[12] = 0;
1765 ee3659e3 Christoph Hellwig
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
1766 ea3bd56f Christoph Hellwig
1767 ea3bd56f Christoph Hellwig
            /* set TPE bit if the format supports discard */
1768 ea3bd56f Christoph Hellwig
            if (s->qdev.conf.discard_granularity) {
1769 ea3bd56f Christoph Hellwig
                outbuf[14] = 0x80;
1770 ea3bd56f Christoph Hellwig
            }
1771 ea3bd56f Christoph Hellwig
1772 5dd90e2a Gerd Hoffmann
            /* Protection, exponent and lowest lba field left blank. */
1773 5dd90e2a Gerd Hoffmann
            buflen = req->cmd.xfer;
1774 5dd90e2a Gerd Hoffmann
            break;
1775 5dd90e2a Gerd Hoffmann
        }
1776 5dd90e2a Gerd Hoffmann
        DPRINTF("Unsupported Service Action In\n");
1777 5dd90e2a Gerd Hoffmann
        goto illegal_request;
1778 101aa85f Paolo Bonzini
    case SYNCHRONIZE_CACHE:
1779 101aa85f Paolo Bonzini
        /* The request is used as the AIO opaque value, so add a ref.  */
1780 101aa85f Paolo Bonzini
        scsi_req_ref(&r->req);
1781 101aa85f Paolo Bonzini
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1782 101aa85f Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
1783 101aa85f Paolo Bonzini
        return 0;
1784 101aa85f Paolo Bonzini
    case SEEK_10:
1785 101aa85f Paolo Bonzini
        DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
1786 101aa85f Paolo Bonzini
        if (r->req.cmd.lba > s->qdev.max_lba) {
1787 101aa85f Paolo Bonzini
            goto illegal_lba;
1788 101aa85f Paolo Bonzini
        }
1789 101aa85f Paolo Bonzini
        break;
1790 101aa85f Paolo Bonzini
    case MODE_SELECT:
1791 101aa85f Paolo Bonzini
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1792 101aa85f Paolo Bonzini
        break;
1793 101aa85f Paolo Bonzini
    case MODE_SELECT_10:
1794 101aa85f Paolo Bonzini
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1795 101aa85f Paolo Bonzini
        break;
1796 5222aaf2 Paolo Bonzini
    case UNMAP:
1797 5222aaf2 Paolo Bonzini
        DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer);
1798 5222aaf2 Paolo Bonzini
        break;
1799 101aa85f Paolo Bonzini
    case WRITE_SAME_10:
1800 101aa85f Paolo Bonzini
    case WRITE_SAME_16:
1801 e93176d5 Paolo Bonzini
        nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
1802 6a8a685c Ronnie Sahlberg
        if (bdrv_is_read_only(s->qdev.conf.bs)) {
1803 6a8a685c Ronnie Sahlberg
            scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
1804 6a8a685c Ronnie Sahlberg
            return 0;
1805 6a8a685c Ronnie Sahlberg
        }
1806 444bc908 Paolo Bonzini
        if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) {
1807 101aa85f Paolo Bonzini
            goto illegal_lba;
1808 101aa85f Paolo Bonzini
        }
1809 101aa85f Paolo Bonzini
1810 101aa85f Paolo Bonzini
        /*
1811 101aa85f Paolo Bonzini
         * We only support WRITE SAME with the unmap bit set for now.
1812 101aa85f Paolo Bonzini
         */
1813 101aa85f Paolo Bonzini
        if (!(req->cmd.buf[1] & 0x8)) {
1814 101aa85f Paolo Bonzini
            goto illegal_request;
1815 101aa85f Paolo Bonzini
        }
1816 101aa85f Paolo Bonzini
1817 101aa85f Paolo Bonzini
        /* The request is used as the AIO opaque value, so add a ref.  */
1818 101aa85f Paolo Bonzini
        scsi_req_ref(&r->req);
1819 101aa85f Paolo Bonzini
        r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
1820 101aa85f Paolo Bonzini
                                        r->req.cmd.lba * (s->qdev.blocksize / 512),
1821 101aa85f Paolo Bonzini
                                        nb_sectors * (s->qdev.blocksize / 512),
1822 101aa85f Paolo Bonzini
                                        scsi_aio_complete, r);
1823 101aa85f Paolo Bonzini
        return 0;
1824 aa5dbdc1 Gerd Hoffmann
    default:
1825 b08d0ea0 Paolo Bonzini
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1826 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1827 b08d0ea0 Paolo Bonzini
        return 0;
1828 aa5dbdc1 Gerd Hoffmann
    }
1829 314a3299 Paolo Bonzini
    assert(!r->req.aiocb);
1830 b08d0ea0 Paolo Bonzini
    r->iov.iov_len = MIN(buflen, req->cmd.xfer);
1831 b08d0ea0 Paolo Bonzini
    if (r->iov.iov_len == 0) {
1832 b08d0ea0 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1833 b08d0ea0 Paolo Bonzini
    }
1834 af6d510d Paolo Bonzini
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1835 af6d510d Paolo Bonzini
        assert(r->iov.iov_len == req->cmd.xfer);
1836 af6d510d Paolo Bonzini
        return -r->iov.iov_len;
1837 af6d510d Paolo Bonzini
    } else {
1838 af6d510d Paolo Bonzini
        return r->iov.iov_len;
1839 af6d510d Paolo Bonzini
    }
1840 aa5dbdc1 Gerd Hoffmann
1841 aa5dbdc1 Gerd Hoffmann
illegal_request:
1842 cfc606da Paolo Bonzini
    if (r->req.status == -1) {
1843 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1844 cfc606da Paolo Bonzini
    }
1845 b08d0ea0 Paolo Bonzini
    return 0;
1846 101aa85f Paolo Bonzini
1847 101aa85f Paolo Bonzini
illegal_lba:
1848 101aa85f Paolo Bonzini
    scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1849 101aa85f Paolo Bonzini
    return 0;
1850 aa5dbdc1 Gerd Hoffmann
}
1851 aa5dbdc1 Gerd Hoffmann
1852 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
1853 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
1854 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
1855 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
1856 2e5d83bb pbrook
1857 b08d0ea0 Paolo Bonzini
static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
1858 2e5d83bb pbrook
{
1859 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1860 5c6c0e51 Hannes Reinecke
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1861 e93176d5 Paolo Bonzini
    uint32_t len;
1862 a917d384 pbrook
    uint8_t command;
1863 a917d384 pbrook
1864 a917d384 pbrook
    command = buf[0];
1865 aa5dbdc1 Gerd Hoffmann
1866 b08d0ea0 Paolo Bonzini
    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1867 b08d0ea0 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1868 b08d0ea0 Paolo Bonzini
        return 0;
1869 9bcaf4fe Paolo Bonzini
    }
1870 9bcaf4fe Paolo Bonzini
1871 e93176d5 Paolo Bonzini
    len = scsi_data_cdb_length(r->req.cmd.buf);
1872 9bcaf4fe Paolo Bonzini
    switch (command) {
1873 ebf46023 Gerd Hoffmann
    case READ_6:
1874 ebf46023 Gerd Hoffmann
    case READ_10:
1875 bd536cf3 Gerd Hoffmann
    case READ_12:
1876 bd536cf3 Gerd Hoffmann
    case READ_16:
1877 e93176d5 Paolo Bonzini
        DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len);
1878 96bdbbab Ronnie Sahlberg
        if (r->req.cmd.buf[1] & 0xe0) {
1879 96bdbbab Ronnie Sahlberg
            goto illegal_request;
1880 96bdbbab Ronnie Sahlberg
        }
1881 444bc908 Paolo Bonzini
        if (!check_lba_range(s, r->req.cmd.lba, len)) {
1882 274fb0e1 aliguori
            goto illegal_lba;
1883 f01b5931 Paolo Bonzini
        }
1884 69377307 Paolo Bonzini
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1885 69377307 Paolo Bonzini
        r->sector_count = len * (s->qdev.blocksize / 512);
1886 2e5d83bb pbrook
        break;
1887 ebf46023 Gerd Hoffmann
    case WRITE_6:
1888 ebf46023 Gerd Hoffmann
    case WRITE_10:
1889 bd536cf3 Gerd Hoffmann
    case WRITE_12:
1890 bd536cf3 Gerd Hoffmann
    case WRITE_16:
1891 5e30a07d Hannes Reinecke
    case WRITE_VERIFY_10:
1892 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_12:
1893 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_16:
1894 6a8a685c Ronnie Sahlberg
        if (bdrv_is_read_only(s->qdev.conf.bs)) {
1895 6a8a685c Ronnie Sahlberg
            scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
1896 6a8a685c Ronnie Sahlberg
            return 0;
1897 6a8a685c Ronnie Sahlberg
        }
1898 6a8a685c Ronnie Sahlberg
        /* fallthrough */
1899 6a8a685c Ronnie Sahlberg
    case VERIFY_10:
1900 6a8a685c Ronnie Sahlberg
    case VERIFY_12:
1901 6a8a685c Ronnie Sahlberg
    case VERIFY_16:
1902 e93176d5 Paolo Bonzini
        DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
1903 2dd791b6 Hannes Reinecke
                (command & 0xe) == 0xe ? "And Verify " : "",
1904 2dd791b6 Hannes Reinecke
                r->req.cmd.lba, len);
1905 96bdbbab Ronnie Sahlberg
        if (r->req.cmd.buf[1] & 0xe0) {
1906 96bdbbab Ronnie Sahlberg
            goto illegal_request;
1907 96bdbbab Ronnie Sahlberg
        }
1908 444bc908 Paolo Bonzini
        if (!check_lba_range(s, r->req.cmd.lba, len)) {
1909 274fb0e1 aliguori
            goto illegal_lba;
1910 f01b5931 Paolo Bonzini
        }
1911 69377307 Paolo Bonzini
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1912 69377307 Paolo Bonzini
        r->sector_count = len * (s->qdev.blocksize / 512);
1913 2e5d83bb pbrook
        break;
1914 101aa85f Paolo Bonzini
    default:
1915 b08d0ea0 Paolo Bonzini
        abort();
1916 96bdbbab Ronnie Sahlberg
    illegal_request:
1917 96bdbbab Ronnie Sahlberg
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1918 96bdbbab Ronnie Sahlberg
        return 0;
1919 274fb0e1 aliguori
    illegal_lba:
1920 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1921 274fb0e1 aliguori
        return 0;
1922 2e5d83bb pbrook
    }
1923 b08d0ea0 Paolo Bonzini
    if (r->sector_count == 0) {
1924 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1925 a917d384 pbrook
    }
1926 b08d0ea0 Paolo Bonzini
    assert(r->iov.iov_len == 0);
1927 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1928 b08d0ea0 Paolo Bonzini
        return -r->sector_count * 512;
1929 a917d384 pbrook
    } else {
1930 b08d0ea0 Paolo Bonzini
        return r->sector_count * 512;
1931 2e5d83bb pbrook
    }
1932 2e5d83bb pbrook
}
1933 2e5d83bb pbrook
1934 e9447f35 Jan Kiszka
static void scsi_disk_reset(DeviceState *dev)
1935 e9447f35 Jan Kiszka
{
1936 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1937 e9447f35 Jan Kiszka
    uint64_t nb_sectors;
1938 e9447f35 Jan Kiszka
1939 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
1940 e9447f35 Jan Kiszka
1941 44740c38 Paolo Bonzini
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1942 69377307 Paolo Bonzini
    nb_sectors /= s->qdev.blocksize / 512;
1943 e9447f35 Jan Kiszka
    if (nb_sectors) {
1944 e9447f35 Jan Kiszka
        nb_sectors--;
1945 e9447f35 Jan Kiszka
    }
1946 7877903a Paolo Bonzini
    s->qdev.max_lba = nb_sectors;
1947 e9447f35 Jan Kiszka
}
1948 e9447f35 Jan Kiszka
1949 e9447f35 Jan Kiszka
static void scsi_destroy(SCSIDevice *dev)
1950 e9447f35 Jan Kiszka
{
1951 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1952 e9447f35 Jan Kiszka
1953 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1954 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
1955 56a14938 Gerd Hoffmann
}
1956 56a14938 Gerd Hoffmann
1957 aaebacef Paolo Bonzini
static void scsi_disk_resize_cb(void *opaque)
1958 aaebacef Paolo Bonzini
{
1959 aaebacef Paolo Bonzini
    SCSIDiskState *s = opaque;
1960 aaebacef Paolo Bonzini
1961 aaebacef Paolo Bonzini
    /* SPC lists this sense code as available only for
1962 aaebacef Paolo Bonzini
     * direct-access devices.
1963 aaebacef Paolo Bonzini
     */
1964 aaebacef Paolo Bonzini
    if (s->qdev.type == TYPE_DISK) {
1965 aaebacef Paolo Bonzini
        scsi_device_set_ua(&s->qdev, SENSE_CODE(CAPACITY_CHANGED));
1966 53200fad Paolo Bonzini
        scsi_device_report_change(&s->qdev, SENSE_CODE(CAPACITY_CHANGED));
1967 aaebacef Paolo Bonzini
    }
1968 aaebacef Paolo Bonzini
}
1969 aaebacef Paolo Bonzini
1970 7d4b4ba5 Markus Armbruster
static void scsi_cd_change_media_cb(void *opaque, bool load)
1971 2c6942fa Markus Armbruster
{
1972 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = opaque;
1973 8a9c16f6 Paolo Bonzini
1974 8a9c16f6 Paolo Bonzini
    /*
1975 8a9c16f6 Paolo Bonzini
     * When a CD gets changed, we have to report an ejected state and
1976 8a9c16f6 Paolo Bonzini
     * then a loaded state to guests so that they detect tray
1977 8a9c16f6 Paolo Bonzini
     * open/close and media change events.  Guests that do not use
1978 8a9c16f6 Paolo Bonzini
     * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1979 8a9c16f6 Paolo Bonzini
     * states rely on this behavior.
1980 8a9c16f6 Paolo Bonzini
     *
1981 8a9c16f6 Paolo Bonzini
     * media_changed governs the state machine used for unit attention
1982 8a9c16f6 Paolo Bonzini
     * report.  media_event is used by GET EVENT STATUS NOTIFICATION.
1983 8a9c16f6 Paolo Bonzini
     */
1984 8a9c16f6 Paolo Bonzini
    s->media_changed = load;
1985 8a9c16f6 Paolo Bonzini
    s->tray_open = !load;
1986 e48e84ea Paolo Bonzini
    scsi_device_set_ua(&s->qdev, SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM));
1987 3c2f7c12 Paolo Bonzini
    s->media_event = true;
1988 4480de19 Paolo Bonzini
    s->eject_request = false;
1989 4480de19 Paolo Bonzini
}
1990 4480de19 Paolo Bonzini
1991 4480de19 Paolo Bonzini
static void scsi_cd_eject_request_cb(void *opaque, bool force)
1992 4480de19 Paolo Bonzini
{
1993 4480de19 Paolo Bonzini
    SCSIDiskState *s = opaque;
1994 4480de19 Paolo Bonzini
1995 4480de19 Paolo Bonzini
    s->eject_request = true;
1996 4480de19 Paolo Bonzini
    if (force) {
1997 4480de19 Paolo Bonzini
        s->tray_locked = false;
1998 4480de19 Paolo Bonzini
    }
1999 2c6942fa Markus Armbruster
}
2000 2c6942fa Markus Armbruster
2001 e4def80b Markus Armbruster
static bool scsi_cd_is_tray_open(void *opaque)
2002 e4def80b Markus Armbruster
{
2003 e4def80b Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_open;
2004 e4def80b Markus Armbruster
}
2005 e4def80b Markus Armbruster
2006 f107639a Markus Armbruster
static bool scsi_cd_is_medium_locked(void *opaque)
2007 f107639a Markus Armbruster
{
2008 f107639a Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_locked;
2009 f107639a Markus Armbruster
}
2010 f107639a Markus Armbruster
2011 aaebacef Paolo Bonzini
static const BlockDevOps scsi_disk_removable_block_ops = {
2012 2c6942fa Markus Armbruster
    .change_media_cb = scsi_cd_change_media_cb,
2013 4480de19 Paolo Bonzini
    .eject_request_cb = scsi_cd_eject_request_cb,
2014 e4def80b Markus Armbruster
    .is_tray_open = scsi_cd_is_tray_open,
2015 f107639a Markus Armbruster
    .is_medium_locked = scsi_cd_is_medium_locked,
2016 aaebacef Paolo Bonzini
2017 aaebacef Paolo Bonzini
    .resize_cb = scsi_disk_resize_cb,
2018 aaebacef Paolo Bonzini
};
2019 aaebacef Paolo Bonzini
2020 aaebacef Paolo Bonzini
static const BlockDevOps scsi_disk_block_ops = {
2021 aaebacef Paolo Bonzini
    .resize_cb = scsi_disk_resize_cb,
2022 f107639a Markus Armbruster
};
2023 f107639a Markus Armbruster
2024 8a9c16f6 Paolo Bonzini
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
2025 8a9c16f6 Paolo Bonzini
{
2026 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2027 8a9c16f6 Paolo Bonzini
    if (s->media_changed) {
2028 8a9c16f6 Paolo Bonzini
        s->media_changed = false;
2029 e48e84ea Paolo Bonzini
        scsi_device_set_ua(&s->qdev, SENSE_CODE(MEDIUM_CHANGED));
2030 8a9c16f6 Paolo Bonzini
    }
2031 8a9c16f6 Paolo Bonzini
}
2032 8a9c16f6 Paolo Bonzini
2033 e39be482 Paolo Bonzini
static int scsi_initfn(SCSIDevice *dev)
2034 2e5d83bb pbrook
{
2035 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2036 2e5d83bb pbrook
2037 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
2038 6a84cb1f Markus Armbruster
        error_report("drive property not set");
2039 d52affa7 Gerd Hoffmann
        return -1;
2040 d52affa7 Gerd Hoffmann
    }
2041 d52affa7 Gerd Hoffmann
2042 bfe3d7ac Paolo Bonzini
    if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
2043 bfe3d7ac Paolo Bonzini
        !bdrv_is_inserted(s->qdev.conf.bs)) {
2044 98f28ad7 Markus Armbruster
        error_report("Device needs media, but drive is empty");
2045 98f28ad7 Markus Armbruster
        return -1;
2046 98f28ad7 Markus Armbruster
    }
2047 98f28ad7 Markus Armbruster
2048 911525db Markus Armbruster
    blkconf_serial(&s->qdev.conf, &s->serial);
2049 b2df4314 Markus Armbruster
    if (dev->type == TYPE_DISK
2050 b2df4314 Markus Armbruster
        && blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) {
2051 b7eb0c9f Markus Armbruster
        return -1;
2052 b7eb0c9f Markus Armbruster
    }
2053 a0fef654 Markus Armbruster
2054 552fee93 Markus Armbruster
    if (!s->version) {
2055 93bfef4c Crístian Viana
        s->version = g_strdup(qemu_get_version());
2056 552fee93 Markus Armbruster
    }
2057 353815aa Dmitry Fleytman
    if (!s->vendor) {
2058 353815aa Dmitry Fleytman
        s->vendor = g_strdup("QEMU");
2059 353815aa Dmitry Fleytman
    }
2060 552fee93 Markus Armbruster
2061 44740c38 Paolo Bonzini
    if (bdrv_is_sg(s->qdev.conf.bs)) {
2062 6a84cb1f Markus Armbruster
        error_report("unwanted /dev/sg*");
2063 32bb404a Markus Armbruster
        return -1;
2064 32bb404a Markus Armbruster
    }
2065 32bb404a Markus Armbruster
2066 bfe3d7ac Paolo Bonzini
    if (s->features & (1 << SCSI_DISK_F_REMOVABLE)) {
2067 aaebacef Paolo Bonzini
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_removable_block_ops, s);
2068 aaebacef Paolo Bonzini
    } else {
2069 aaebacef Paolo Bonzini
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_block_ops, s);
2070 2e5d83bb pbrook
    }
2071 44740c38 Paolo Bonzini
    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
2072 8cfacf07 Christoph Hellwig
2073 44740c38 Paolo Bonzini
    bdrv_iostatus_enable(s->qdev.conf.bs);
2074 7082826e Paolo Bonzini
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
2075 d52affa7 Gerd Hoffmann
    return 0;
2076 d52affa7 Gerd Hoffmann
}
2077 d52affa7 Gerd Hoffmann
2078 b443ae67 Markus Armbruster
static int scsi_hd_initfn(SCSIDevice *dev)
2079 b443ae67 Markus Armbruster
{
2080 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2081 e39be482 Paolo Bonzini
    s->qdev.blocksize = s->qdev.conf.logical_block_size;
2082 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_DISK;
2083 353815aa Dmitry Fleytman
    if (!s->product) {
2084 353815aa Dmitry Fleytman
        s->product = g_strdup("QEMU HARDDISK");
2085 353815aa Dmitry Fleytman
    }
2086 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
2087 b443ae67 Markus Armbruster
}
2088 b443ae67 Markus Armbruster
2089 b443ae67 Markus Armbruster
static int scsi_cd_initfn(SCSIDevice *dev)
2090 b443ae67 Markus Armbruster
{
2091 e39be482 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2092 e39be482 Paolo Bonzini
    s->qdev.blocksize = 2048;
2093 e39be482 Paolo Bonzini
    s->qdev.type = TYPE_ROM;
2094 bfe3d7ac Paolo Bonzini
    s->features |= 1 << SCSI_DISK_F_REMOVABLE;
2095 353815aa Dmitry Fleytman
    if (!s->product) {
2096 353815aa Dmitry Fleytman
        s->product = g_strdup("QEMU CD-ROM");
2097 353815aa Dmitry Fleytman
    }
2098 e39be482 Paolo Bonzini
    return scsi_initfn(&s->qdev);
2099 b443ae67 Markus Armbruster
}
2100 b443ae67 Markus Armbruster
2101 b443ae67 Markus Armbruster
static int scsi_disk_initfn(SCSIDevice *dev)
2102 b443ae67 Markus Armbruster
{
2103 95b5edcd Markus Armbruster
    DriveInfo *dinfo;
2104 b443ae67 Markus Armbruster
2105 b443ae67 Markus Armbruster
    if (!dev->conf.bs) {
2106 e39be482 Paolo Bonzini
        return scsi_initfn(dev);  /* ... and die there */
2107 b443ae67 Markus Armbruster
    }
2108 b443ae67 Markus Armbruster
2109 e39be482 Paolo Bonzini
    dinfo = drive_get_by_blockdev(dev->conf.bs);
2110 e39be482 Paolo Bonzini
    if (dinfo->media_cd) {
2111 e39be482 Paolo Bonzini
        return scsi_cd_initfn(dev);
2112 e39be482 Paolo Bonzini
    } else {
2113 e39be482 Paolo Bonzini
        return scsi_hd_initfn(dev);
2114 e39be482 Paolo Bonzini
    }
2115 b443ae67 Markus Armbruster
}
2116 b443ae67 Markus Armbruster
2117 b08d0ea0 Paolo Bonzini
static const SCSIReqOps scsi_disk_emulate_reqops = {
2118 8dbd4574 Paolo Bonzini
    .size         = sizeof(SCSIDiskReq),
2119 12010e7b Paolo Bonzini
    .free_req     = scsi_free_request,
2120 b08d0ea0 Paolo Bonzini
    .send_command = scsi_disk_emulate_command,
2121 314a3299 Paolo Bonzini
    .read_data    = scsi_disk_emulate_read_data,
2122 314a3299 Paolo Bonzini
    .write_data   = scsi_disk_emulate_write_data,
2123 b08d0ea0 Paolo Bonzini
    .get_buf      = scsi_get_buf,
2124 b08d0ea0 Paolo Bonzini
};
2125 b08d0ea0 Paolo Bonzini
2126 b08d0ea0 Paolo Bonzini
static const SCSIReqOps scsi_disk_dma_reqops = {
2127 b08d0ea0 Paolo Bonzini
    .size         = sizeof(SCSIDiskReq),
2128 b08d0ea0 Paolo Bonzini
    .free_req     = scsi_free_request,
2129 b08d0ea0 Paolo Bonzini
    .send_command = scsi_disk_dma_command,
2130 12010e7b Paolo Bonzini
    .read_data    = scsi_read_data,
2131 12010e7b Paolo Bonzini
    .write_data   = scsi_write_data,
2132 12010e7b Paolo Bonzini
    .cancel_io    = scsi_cancel_io,
2133 12010e7b Paolo Bonzini
    .get_buf      = scsi_get_buf,
2134 43b978b9 Paolo Bonzini
    .load_request = scsi_disk_load_request,
2135 43b978b9 Paolo Bonzini
    .save_request = scsi_disk_save_request,
2136 8dbd4574 Paolo Bonzini
};
2137 8dbd4574 Paolo Bonzini
2138 b08d0ea0 Paolo Bonzini
static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
2139 b08d0ea0 Paolo Bonzini
    [TEST_UNIT_READY]                 = &scsi_disk_emulate_reqops,
2140 b08d0ea0 Paolo Bonzini
    [INQUIRY]                         = &scsi_disk_emulate_reqops,
2141 b08d0ea0 Paolo Bonzini
    [MODE_SENSE]                      = &scsi_disk_emulate_reqops,
2142 b08d0ea0 Paolo Bonzini
    [MODE_SENSE_10]                   = &scsi_disk_emulate_reqops,
2143 b08d0ea0 Paolo Bonzini
    [START_STOP]                      = &scsi_disk_emulate_reqops,
2144 b08d0ea0 Paolo Bonzini
    [ALLOW_MEDIUM_REMOVAL]            = &scsi_disk_emulate_reqops,
2145 b08d0ea0 Paolo Bonzini
    [READ_CAPACITY_10]                = &scsi_disk_emulate_reqops,
2146 b08d0ea0 Paolo Bonzini
    [READ_TOC]                        = &scsi_disk_emulate_reqops,
2147 b08d0ea0 Paolo Bonzini
    [READ_DVD_STRUCTURE]              = &scsi_disk_emulate_reqops,
2148 b08d0ea0 Paolo Bonzini
    [READ_DISC_INFORMATION]           = &scsi_disk_emulate_reqops,
2149 b08d0ea0 Paolo Bonzini
    [GET_CONFIGURATION]               = &scsi_disk_emulate_reqops,
2150 b08d0ea0 Paolo Bonzini
    [GET_EVENT_STATUS_NOTIFICATION]   = &scsi_disk_emulate_reqops,
2151 b08d0ea0 Paolo Bonzini
    [MECHANISM_STATUS]                = &scsi_disk_emulate_reqops,
2152 b08d0ea0 Paolo Bonzini
    [SERVICE_ACTION_IN_16]            = &scsi_disk_emulate_reqops,
2153 b08d0ea0 Paolo Bonzini
    [REQUEST_SENSE]                   = &scsi_disk_emulate_reqops,
2154 b08d0ea0 Paolo Bonzini
    [SYNCHRONIZE_CACHE]               = &scsi_disk_emulate_reqops,
2155 b08d0ea0 Paolo Bonzini
    [SEEK_10]                         = &scsi_disk_emulate_reqops,
2156 b08d0ea0 Paolo Bonzini
    [MODE_SELECT]                     = &scsi_disk_emulate_reqops,
2157 b08d0ea0 Paolo Bonzini
    [MODE_SELECT_10]                  = &scsi_disk_emulate_reqops,
2158 5222aaf2 Paolo Bonzini
    [UNMAP]                           = &scsi_disk_emulate_reqops,
2159 b08d0ea0 Paolo Bonzini
    [WRITE_SAME_10]                   = &scsi_disk_emulate_reqops,
2160 b08d0ea0 Paolo Bonzini
    [WRITE_SAME_16]                   = &scsi_disk_emulate_reqops,
2161 b08d0ea0 Paolo Bonzini
2162 b08d0ea0 Paolo Bonzini
    [READ_6]                          = &scsi_disk_dma_reqops,
2163 b08d0ea0 Paolo Bonzini
    [READ_10]                         = &scsi_disk_dma_reqops,
2164 b08d0ea0 Paolo Bonzini
    [READ_12]                         = &scsi_disk_dma_reqops,
2165 b08d0ea0 Paolo Bonzini
    [READ_16]                         = &scsi_disk_dma_reqops,
2166 b08d0ea0 Paolo Bonzini
    [VERIFY_10]                       = &scsi_disk_dma_reqops,
2167 b08d0ea0 Paolo Bonzini
    [VERIFY_12]                       = &scsi_disk_dma_reqops,
2168 b08d0ea0 Paolo Bonzini
    [VERIFY_16]                       = &scsi_disk_dma_reqops,
2169 b08d0ea0 Paolo Bonzini
    [WRITE_6]                         = &scsi_disk_dma_reqops,
2170 b08d0ea0 Paolo Bonzini
    [WRITE_10]                        = &scsi_disk_dma_reqops,
2171 b08d0ea0 Paolo Bonzini
    [WRITE_12]                        = &scsi_disk_dma_reqops,
2172 b08d0ea0 Paolo Bonzini
    [WRITE_16]                        = &scsi_disk_dma_reqops,
2173 b08d0ea0 Paolo Bonzini
    [WRITE_VERIFY_10]                 = &scsi_disk_dma_reqops,
2174 b08d0ea0 Paolo Bonzini
    [WRITE_VERIFY_12]                 = &scsi_disk_dma_reqops,
2175 b08d0ea0 Paolo Bonzini
    [WRITE_VERIFY_16]                 = &scsi_disk_dma_reqops,
2176 b08d0ea0 Paolo Bonzini
};
2177 b08d0ea0 Paolo Bonzini
2178 63db0f0e Paolo Bonzini
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
2179 63db0f0e Paolo Bonzini
                                     uint8_t *buf, void *hba_private)
2180 8dbd4574 Paolo Bonzini
{
2181 8dbd4574 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
2182 8dbd4574 Paolo Bonzini
    SCSIRequest *req;
2183 b08d0ea0 Paolo Bonzini
    const SCSIReqOps *ops;
2184 b08d0ea0 Paolo Bonzini
    uint8_t command;
2185 8dbd4574 Paolo Bonzini
2186 79fb50bb Paolo Bonzini
    command = buf[0];
2187 79fb50bb Paolo Bonzini
    ops = scsi_disk_reqops_dispatch[command];
2188 79fb50bb Paolo Bonzini
    if (!ops) {
2189 79fb50bb Paolo Bonzini
        ops = &scsi_disk_emulate_reqops;
2190 79fb50bb Paolo Bonzini
    }
2191 79fb50bb Paolo Bonzini
    req = scsi_req_alloc(ops, &s->qdev, tag, lun, hba_private);
2192 79fb50bb Paolo Bonzini
2193 b08d0ea0 Paolo Bonzini
#ifdef DEBUG_SCSI
2194 79fb50bb Paolo Bonzini
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
2195 b08d0ea0 Paolo Bonzini
    {
2196 b08d0ea0 Paolo Bonzini
        int i;
2197 79fb50bb Paolo Bonzini
        for (i = 1; i < req->cmd.len; i++) {
2198 b08d0ea0 Paolo Bonzini
            printf(" 0x%02x", buf[i]);
2199 b08d0ea0 Paolo Bonzini
        }
2200 b08d0ea0 Paolo Bonzini
        printf("\n");
2201 b08d0ea0 Paolo Bonzini
    }
2202 b08d0ea0 Paolo Bonzini
#endif
2203 b08d0ea0 Paolo Bonzini
2204 8dbd4574 Paolo Bonzini
    return req;
2205 8dbd4574 Paolo Bonzini
}
2206 8dbd4574 Paolo Bonzini
2207 336a6915 Paolo Bonzini
#ifdef __linux__
2208 336a6915 Paolo Bonzini
static int get_device_type(SCSIDiskState *s)
2209 336a6915 Paolo Bonzini
{
2210 336a6915 Paolo Bonzini
    BlockDriverState *bdrv = s->qdev.conf.bs;
2211 336a6915 Paolo Bonzini
    uint8_t cmd[16];
2212 336a6915 Paolo Bonzini
    uint8_t buf[36];
2213 336a6915 Paolo Bonzini
    uint8_t sensebuf[8];
2214 336a6915 Paolo Bonzini
    sg_io_hdr_t io_header;
2215 336a6915 Paolo Bonzini
    int ret;
2216 336a6915 Paolo Bonzini
2217 336a6915 Paolo Bonzini
    memset(cmd, 0, sizeof(cmd));
2218 336a6915 Paolo Bonzini
    memset(buf, 0, sizeof(buf));
2219 336a6915 Paolo Bonzini
    cmd[0] = INQUIRY;
2220 336a6915 Paolo Bonzini
    cmd[4] = sizeof(buf);
2221 336a6915 Paolo Bonzini
2222 336a6915 Paolo Bonzini
    memset(&io_header, 0, sizeof(io_header));
2223 336a6915 Paolo Bonzini
    io_header.interface_id = 'S';
2224 336a6915 Paolo Bonzini
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
2225 336a6915 Paolo Bonzini
    io_header.dxfer_len = sizeof(buf);
2226 336a6915 Paolo Bonzini
    io_header.dxferp = buf;
2227 336a6915 Paolo Bonzini
    io_header.cmdp = cmd;
2228 336a6915 Paolo Bonzini
    io_header.cmd_len = sizeof(cmd);
2229 336a6915 Paolo Bonzini
    io_header.mx_sb_len = sizeof(sensebuf);
2230 336a6915 Paolo Bonzini
    io_header.sbp = sensebuf;
2231 336a6915 Paolo Bonzini
    io_header.timeout = 6000; /* XXX */
2232 336a6915 Paolo Bonzini
2233 336a6915 Paolo Bonzini
    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
2234 336a6915 Paolo Bonzini
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
2235 336a6915 Paolo Bonzini
        return -1;
2236 336a6915 Paolo Bonzini
    }
2237 336a6915 Paolo Bonzini
    s->qdev.type = buf[0];
2238 bfe3d7ac Paolo Bonzini
    if (buf[1] & 0x80) {
2239 bfe3d7ac Paolo Bonzini
        s->features |= 1 << SCSI_DISK_F_REMOVABLE;
2240 bfe3d7ac Paolo Bonzini
    }
2241 336a6915 Paolo Bonzini
    return 0;
2242 336a6915 Paolo Bonzini
}
2243 336a6915 Paolo Bonzini
2244 336a6915 Paolo Bonzini
static int scsi_block_initfn(SCSIDevice *dev)
2245 336a6915 Paolo Bonzini
{
2246 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2247 336a6915 Paolo Bonzini
    int sg_version;
2248 336a6915 Paolo Bonzini
    int rc;
2249 336a6915 Paolo Bonzini
2250 336a6915 Paolo Bonzini
    if (!s->qdev.conf.bs) {
2251 336a6915 Paolo Bonzini
        error_report("scsi-block: drive property not set");
2252 336a6915 Paolo Bonzini
        return -1;
2253 336a6915 Paolo Bonzini
    }
2254 336a6915 Paolo Bonzini
2255 336a6915 Paolo Bonzini
    /* check we are using a driver managing SG_IO (version 3 and after) */
2256 336a6915 Paolo Bonzini
    if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
2257 336a6915 Paolo Bonzini
        sg_version < 30000) {
2258 336a6915 Paolo Bonzini
        error_report("scsi-block: scsi generic interface too old");
2259 336a6915 Paolo Bonzini
        return -1;
2260 336a6915 Paolo Bonzini
    }
2261 336a6915 Paolo Bonzini
2262 336a6915 Paolo Bonzini
    /* get device type from INQUIRY data */
2263 336a6915 Paolo Bonzini
    rc = get_device_type(s);
2264 336a6915 Paolo Bonzini
    if (rc < 0) {
2265 336a6915 Paolo Bonzini
        error_report("scsi-block: INQUIRY failed");
2266 336a6915 Paolo Bonzini
        return -1;
2267 336a6915 Paolo Bonzini
    }
2268 336a6915 Paolo Bonzini
2269 336a6915 Paolo Bonzini
    /* Make a guess for the block size, we'll fix it when the guest sends.
2270 336a6915 Paolo Bonzini
     * READ CAPACITY.  If they don't, they likely would assume these sizes
2271 336a6915 Paolo Bonzini
     * anyway. (TODO: check in /sys).
2272 336a6915 Paolo Bonzini
     */
2273 336a6915 Paolo Bonzini
    if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
2274 336a6915 Paolo Bonzini
        s->qdev.blocksize = 2048;
2275 336a6915 Paolo Bonzini
    } else {
2276 336a6915 Paolo Bonzini
        s->qdev.blocksize = 512;
2277 336a6915 Paolo Bonzini
    }
2278 336a6915 Paolo Bonzini
    return scsi_initfn(&s->qdev);
2279 336a6915 Paolo Bonzini
}
2280 336a6915 Paolo Bonzini
2281 336a6915 Paolo Bonzini
static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
2282 336a6915 Paolo Bonzini
                                           uint32_t lun, uint8_t *buf,
2283 336a6915 Paolo Bonzini
                                           void *hba_private)
2284 336a6915 Paolo Bonzini
{
2285 336a6915 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
2286 336a6915 Paolo Bonzini
2287 336a6915 Paolo Bonzini
    switch (buf[0]) {
2288 336a6915 Paolo Bonzini
    case READ_6:
2289 336a6915 Paolo Bonzini
    case READ_10:
2290 336a6915 Paolo Bonzini
    case READ_12:
2291 336a6915 Paolo Bonzini
    case READ_16:
2292 7f64f8e2 Paolo Bonzini
    case VERIFY_10:
2293 7f64f8e2 Paolo Bonzini
    case VERIFY_12:
2294 7f64f8e2 Paolo Bonzini
    case VERIFY_16:
2295 336a6915 Paolo Bonzini
    case WRITE_6:
2296 336a6915 Paolo Bonzini
    case WRITE_10:
2297 336a6915 Paolo Bonzini
    case WRITE_12:
2298 336a6915 Paolo Bonzini
    case WRITE_16:
2299 336a6915 Paolo Bonzini
    case WRITE_VERIFY_10:
2300 336a6915 Paolo Bonzini
    case WRITE_VERIFY_12:
2301 336a6915 Paolo Bonzini
    case WRITE_VERIFY_16:
2302 eaccf49e Paolo Bonzini
        /* If we are not using O_DIRECT, we might read stale data from the
2303 eaccf49e Paolo Bonzini
         * host cache if writes were made using other commands than these
2304 eaccf49e Paolo Bonzini
         * ones (such as WRITE SAME or EXTENDED COPY, etc.).  So, without
2305 eaccf49e Paolo Bonzini
         * O_DIRECT everything must go through SG_IO.
2306 eaccf49e Paolo Bonzini
         */
2307 137745c5 Markus Armbruster
        if (bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE) {
2308 eaccf49e Paolo Bonzini
            break;
2309 eaccf49e Paolo Bonzini
        }
2310 eaccf49e Paolo Bonzini
2311 33ebad12 Paolo Bonzini
        /* MMC writing cannot be done via pread/pwrite, because it sometimes
2312 33ebad12 Paolo Bonzini
         * involves writing beyond the maximum LBA or to negative LBA (lead-in).
2313 33ebad12 Paolo Bonzini
         * And once you do these writes, reading from the block device is
2314 33ebad12 Paolo Bonzini
         * unreliable, too.  It is even possible that reads deliver random data
2315 33ebad12 Paolo Bonzini
         * from the host page cache (this is probably a Linux bug).
2316 33ebad12 Paolo Bonzini
         *
2317 b08d0ea0 Paolo Bonzini
         * We might use scsi_disk_dma_reqops as long as no writing commands are
2318 33ebad12 Paolo Bonzini
         * seen, but performance usually isn't paramount on optical media.  So,
2319 33ebad12 Paolo Bonzini
         * just make scsi-block operate the same as scsi-generic for them.
2320 33ebad12 Paolo Bonzini
         */
2321 b08d0ea0 Paolo Bonzini
        if (s->qdev.type != TYPE_ROM) {
2322 b08d0ea0 Paolo Bonzini
            return scsi_req_alloc(&scsi_disk_dma_reqops, &s->qdev, tag, lun,
2323 b08d0ea0 Paolo Bonzini
                                  hba_private);
2324 b08d0ea0 Paolo Bonzini
        }
2325 336a6915 Paolo Bonzini
    }
2326 336a6915 Paolo Bonzini
2327 336a6915 Paolo Bonzini
    return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
2328 336a6915 Paolo Bonzini
                          hba_private);
2329 336a6915 Paolo Bonzini
}
2330 336a6915 Paolo Bonzini
#endif
2331 336a6915 Paolo Bonzini
2332 353815aa Dmitry Fleytman
#define DEFINE_SCSI_DISK_PROPERTIES()                                \
2333 353815aa Dmitry Fleytman
    DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),               \
2334 353815aa Dmitry Fleytman
    DEFINE_PROP_STRING("ver", SCSIDiskState, version),               \
2335 353815aa Dmitry Fleytman
    DEFINE_PROP_STRING("serial", SCSIDiskState, serial),             \
2336 353815aa Dmitry Fleytman
    DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor),             \
2337 353815aa Dmitry Fleytman
    DEFINE_PROP_STRING("product", SCSIDiskState, product)
2338 b443ae67 Markus Armbruster
2339 39bffca2 Anthony Liguori
static Property scsi_hd_properties[] = {
2340 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
2341 bfe3d7ac Paolo Bonzini
    DEFINE_PROP_BIT("removable", SCSIDiskState, features,
2342 bfe3d7ac Paolo Bonzini
                    SCSI_DISK_F_REMOVABLE, false),
2343 da8365db Paolo Bonzini
    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
2344 da8365db Paolo Bonzini
                    SCSI_DISK_F_DPOFUA, false),
2345 27395add Paolo Bonzini
    DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
2346 d252df48 Markus Armbruster
    DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
2347 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
2348 39bffca2 Anthony Liguori
};
2349 39bffca2 Anthony Liguori
2350 43b978b9 Paolo Bonzini
static const VMStateDescription vmstate_scsi_disk_state = {
2351 43b978b9 Paolo Bonzini
    .name = "scsi-disk",
2352 43b978b9 Paolo Bonzini
    .version_id = 1,
2353 43b978b9 Paolo Bonzini
    .minimum_version_id = 1,
2354 43b978b9 Paolo Bonzini
    .minimum_version_id_old = 1,
2355 43b978b9 Paolo Bonzini
    .fields = (VMStateField[]) {
2356 43b978b9 Paolo Bonzini
        VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
2357 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_changed, SCSIDiskState),
2358 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(media_event, SCSIDiskState),
2359 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(eject_request, SCSIDiskState),
2360 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_open, SCSIDiskState),
2361 43b978b9 Paolo Bonzini
        VMSTATE_BOOL(tray_locked, SCSIDiskState),
2362 43b978b9 Paolo Bonzini
        VMSTATE_END_OF_LIST()
2363 43b978b9 Paolo Bonzini
    }
2364 43b978b9 Paolo Bonzini
};
2365 43b978b9 Paolo Bonzini
2366 b9eea3e6 Anthony Liguori
static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
2367 b9eea3e6 Anthony Liguori
{
2368 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
2369 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2370 b9eea3e6 Anthony Liguori
2371 b9eea3e6 Anthony Liguori
    sc->init         = scsi_hd_initfn;
2372 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
2373 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
2374 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
2375 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
2376 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk";
2377 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
2378 39bffca2 Anthony Liguori
    dc->props = scsi_hd_properties;
2379 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
2380 b9eea3e6 Anthony Liguori
}
2381 b9eea3e6 Anthony Liguori
2382 39bffca2 Anthony Liguori
static TypeInfo scsi_hd_info = {
2383 39bffca2 Anthony Liguori
    .name          = "scsi-hd",
2384 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
2385 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
2386 39bffca2 Anthony Liguori
    .class_init    = scsi_hd_class_initfn,
2387 39bffca2 Anthony Liguori
};
2388 39bffca2 Anthony Liguori
2389 39bffca2 Anthony Liguori
static Property scsi_cd_properties[] = {
2390 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
2391 27395add Paolo Bonzini
    DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
2392 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
2393 b9eea3e6 Anthony Liguori
};
2394 b9eea3e6 Anthony Liguori
2395 b9eea3e6 Anthony Liguori
static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
2396 b9eea3e6 Anthony Liguori
{
2397 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
2398 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2399 b9eea3e6 Anthony Liguori
2400 b9eea3e6 Anthony Liguori
    sc->init         = scsi_cd_initfn;
2401 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
2402 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
2403 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
2404 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
2405 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI CD-ROM";
2406 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
2407 39bffca2 Anthony Liguori
    dc->props = scsi_cd_properties;
2408 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
2409 b9eea3e6 Anthony Liguori
}
2410 b9eea3e6 Anthony Liguori
2411 39bffca2 Anthony Liguori
static TypeInfo scsi_cd_info = {
2412 39bffca2 Anthony Liguori
    .name          = "scsi-cd",
2413 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
2414 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
2415 39bffca2 Anthony Liguori
    .class_init    = scsi_cd_class_initfn,
2416 b9eea3e6 Anthony Liguori
};
2417 b9eea3e6 Anthony Liguori
2418 336a6915 Paolo Bonzini
#ifdef __linux__
2419 39bffca2 Anthony Liguori
static Property scsi_block_properties[] = {
2420 03847837 Paolo Bonzini
    DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
2421 0f1da449 Paolo Bonzini
    DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
2422 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
2423 39bffca2 Anthony Liguori
};
2424 39bffca2 Anthony Liguori
2425 b9eea3e6 Anthony Liguori
static void scsi_block_class_initfn(ObjectClass *klass, void *data)
2426 b9eea3e6 Anthony Liguori
{
2427 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
2428 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2429 b9eea3e6 Anthony Liguori
2430 b9eea3e6 Anthony Liguori
    sc->init         = scsi_block_initfn;
2431 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
2432 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_block_new_request;
2433 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
2434 39bffca2 Anthony Liguori
    dc->desc = "SCSI block device passthrough";
2435 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
2436 39bffca2 Anthony Liguori
    dc->props = scsi_block_properties;
2437 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
2438 b9eea3e6 Anthony Liguori
}
2439 b9eea3e6 Anthony Liguori
2440 39bffca2 Anthony Liguori
static TypeInfo scsi_block_info = {
2441 39bffca2 Anthony Liguori
    .name          = "scsi-block",
2442 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
2443 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
2444 39bffca2 Anthony Liguori
    .class_init    = scsi_block_class_initfn,
2445 b9eea3e6 Anthony Liguori
};
2446 336a6915 Paolo Bonzini
#endif
2447 b9eea3e6 Anthony Liguori
2448 39bffca2 Anthony Liguori
static Property scsi_disk_properties[] = {
2449 39bffca2 Anthony Liguori
    DEFINE_SCSI_DISK_PROPERTIES(),
2450 bfe3d7ac Paolo Bonzini
    DEFINE_PROP_BIT("removable", SCSIDiskState, features,
2451 bfe3d7ac Paolo Bonzini
                    SCSI_DISK_F_REMOVABLE, false),
2452 da8365db Paolo Bonzini
    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
2453 da8365db Paolo Bonzini
                    SCSI_DISK_F_DPOFUA, false),
2454 27395add Paolo Bonzini
    DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
2455 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
2456 39bffca2 Anthony Liguori
};
2457 39bffca2 Anthony Liguori
2458 b9eea3e6 Anthony Liguori
static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
2459 b9eea3e6 Anthony Liguori
{
2460 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
2461 b9eea3e6 Anthony Liguori
    SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2462 b9eea3e6 Anthony Liguori
2463 b9eea3e6 Anthony Liguori
    sc->init         = scsi_disk_initfn;
2464 b9eea3e6 Anthony Liguori
    sc->destroy      = scsi_destroy;
2465 b9eea3e6 Anthony Liguori
    sc->alloc_req    = scsi_new_request;
2466 b9eea3e6 Anthony Liguori
    sc->unit_attention_reported = scsi_disk_unit_attention_reported;
2467 39bffca2 Anthony Liguori
    dc->fw_name = "disk";
2468 39bffca2 Anthony Liguori
    dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
2469 39bffca2 Anthony Liguori
    dc->reset = scsi_disk_reset;
2470 39bffca2 Anthony Liguori
    dc->props = scsi_disk_properties;
2471 43b978b9 Paolo Bonzini
    dc->vmsd  = &vmstate_scsi_disk_state;
2472 b9eea3e6 Anthony Liguori
}
2473 b9eea3e6 Anthony Liguori
2474 39bffca2 Anthony Liguori
static TypeInfo scsi_disk_info = {
2475 39bffca2 Anthony Liguori
    .name          = "scsi-disk",
2476 39bffca2 Anthony Liguori
    .parent        = TYPE_SCSI_DEVICE,
2477 39bffca2 Anthony Liguori
    .instance_size = sizeof(SCSIDiskState),
2478 39bffca2 Anthony Liguori
    .class_init    = scsi_disk_class_initfn,
2479 d52affa7 Gerd Hoffmann
};
2480 d52affa7 Gerd Hoffmann
2481 83f7d43a Andreas Färber
static void scsi_disk_register_types(void)
2482 d52affa7 Gerd Hoffmann
{
2483 39bffca2 Anthony Liguori
    type_register_static(&scsi_hd_info);
2484 39bffca2 Anthony Liguori
    type_register_static(&scsi_cd_info);
2485 b9eea3e6 Anthony Liguori
#ifdef __linux__
2486 39bffca2 Anthony Liguori
    type_register_static(&scsi_block_info);
2487 b9eea3e6 Anthony Liguori
#endif
2488 39bffca2 Anthony Liguori
    type_register_static(&scsi_disk_info);
2489 8ccc2ace ths
}
2490 83f7d43a Andreas Färber
2491 83f7d43a Andreas Färber
type_init(scsi_disk_register_types)