Statistics
| Branch: | Revision:

root / hw / scsi-disk.c @ f01b5931

History | View | Annotate | Download (42.5 kB)

1 2e5d83bb pbrook
/*
2 2e5d83bb pbrook
 * SCSI Device emulation
3 2e5d83bb pbrook
 *
4 2e5d83bb pbrook
 * Copyright (c) 2006 CodeSourcery.
5 2e5d83bb pbrook
 * Based on code by Fabrice Bellard
6 2e5d83bb pbrook
 *
7 2e5d83bb pbrook
 * Written by Paul Brook
8 ad3cea42 Artyom Tarasenko
 * Modifications:
9 ad3cea42 Artyom Tarasenko
 *  2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
10 ad3cea42 Artyom Tarasenko
 *                                 when the allocation length of CDB is smaller
11 ad3cea42 Artyom Tarasenko
 *                                 than 36.
12 ad3cea42 Artyom Tarasenko
 *  2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
13 ad3cea42 Artyom Tarasenko
 *                                 MODE SENSE response.
14 2e5d83bb pbrook
 *
15 8e31bf38 Matthew Fernandez
 * This code is licensed under the LGPL.
16 a917d384 pbrook
 *
17 a917d384 pbrook
 * Note that this file only handles the SCSI architecture model and device
18 1d4db89c balrog
 * commands.  Emulation of interface/link layer protocols is handled by
19 1d4db89c balrog
 * the host adapter emulator.
20 2e5d83bb pbrook
 */
21 2e5d83bb pbrook
22 2e5d83bb pbrook
//#define DEBUG_SCSI
23 2e5d83bb pbrook
24 2e5d83bb pbrook
#ifdef DEBUG_SCSI
25 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) \
26 001faf32 Blue Swirl
do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
27 2e5d83bb pbrook
#else
28 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do {} while(0)
29 2e5d83bb pbrook
#endif
30 2e5d83bb pbrook
31 001faf32 Blue Swirl
#define BADF(fmt, ...) \
32 001faf32 Blue Swirl
do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
33 2e5d83bb pbrook
34 87ecb68b pbrook
#include "qemu-common.h"
35 2f792016 Markus Armbruster
#include "qemu-error.h"
36 43b443b6 Gerd Hoffmann
#include "scsi.h"
37 0d65e1f8 Gerd Hoffmann
#include "scsi-defs.h"
38 666daa68 Markus Armbruster
#include "sysemu.h"
39 2446333c Blue Swirl
#include "blockdev.h"
40 d1a0739d Markus Armbruster
#include "block_int.h"
41 22864256 blueswir1
42 f0f72ffe aurel32
#define SCSI_DMA_BUF_SIZE    131072
43 57575058 balrog
#define SCSI_MAX_INQUIRY_LEN 256
44 a917d384 pbrook
45 5dba48a8 Kevin Wolf
#define SCSI_REQ_STATUS_RETRY           0x01
46 5dba48a8 Kevin Wolf
#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
47 5dba48a8 Kevin Wolf
#define SCSI_REQ_STATUS_RETRY_READ      0x00
48 5dba48a8 Kevin Wolf
#define SCSI_REQ_STATUS_RETRY_WRITE     0x02
49 78ced65e Kevin Wolf
#define SCSI_REQ_STATUS_RETRY_FLUSH     0x04
50 ea8a5d7f aliguori
51 d52affa7 Gerd Hoffmann
typedef struct SCSIDiskState SCSIDiskState;
52 d52affa7 Gerd Hoffmann
53 4c41d2ef Gerd Hoffmann
typedef struct SCSIDiskReq {
54 4c41d2ef Gerd Hoffmann
    SCSIRequest req;
55 a917d384 pbrook
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
56 e035b43d aliguori
    uint64_t sector;
57 e035b43d aliguori
    uint32_t sector_count;
58 7285477a Paolo Bonzini
    uint32_t buflen;
59 c87c0672 aliguori
    struct iovec iov;
60 c87c0672 aliguori
    QEMUIOVector qiov;
61 ea8a5d7f aliguori
    uint32_t status;
62 a597e79c Christoph Hellwig
    BlockAcctCookie acct;
63 4c41d2ef Gerd Hoffmann
} SCSIDiskReq;
64 a917d384 pbrook
65 d52affa7 Gerd Hoffmann
struct SCSIDiskState
66 a917d384 pbrook
{
67 d52affa7 Gerd Hoffmann
    SCSIDevice qdev;
68 428c149b Christoph Hellwig
    BlockDriverState *bs;
69 a917d384 pbrook
    /* The qemu block layer uses a fixed 512 byte sector size.
70 a917d384 pbrook
       This is the number of 512 byte blocks in a single scsi sector.  */
71 a917d384 pbrook
    int cluster_size;
72 419e691f Stefan Hajnoczi
    uint32_t removable;
73 274fb0e1 aliguori
    uint64_t max_lba;
74 8a9c16f6 Paolo Bonzini
    bool media_changed;
75 213189ab Markus Armbruster
    QEMUBH *bh;
76 383b4d9b Gerd Hoffmann
    char *version;
77 a0fef654 Markus Armbruster
    char *serial;
78 ece0d5e9 Markus Armbruster
    bool tray_open;
79 81b1008d Markus Armbruster
    bool tray_locked;
80 2e5d83bb pbrook
};
81 2e5d83bb pbrook
82 5dba48a8 Kevin Wolf
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
83 7285477a Paolo Bonzini
static int scsi_disk_emulate_command(SCSIDiskReq *r);
84 5dba48a8 Kevin Wolf
85 ad2d30f7 Paolo Bonzini
static void scsi_free_request(SCSIRequest *req)
86 4d611c9a pbrook
{
87 ad2d30f7 Paolo Bonzini
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
88 ad2d30f7 Paolo Bonzini
89 7285477a Paolo Bonzini
    if (r->iov.iov_base) {
90 7285477a Paolo Bonzini
        qemu_vfree(r->iov.iov_base);
91 7285477a Paolo Bonzini
    }
92 4d611c9a pbrook
}
93 4d611c9a pbrook
94 b45ef674 Paolo Bonzini
/* Helper function for command completion with sense.  */
95 b45ef674 Paolo Bonzini
static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
96 ed3a34a3 Gerd Hoffmann
{
97 02fa69b6 Blue Swirl
    DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
98 02fa69b6 Blue Swirl
            r->req.tag, sense.key, sense.asc, sense.ascq);
99 b45ef674 Paolo Bonzini
    scsi_req_build_sense(&r->req, sense);
100 b45ef674 Paolo Bonzini
    scsi_req_complete(&r->req, CHECK_CONDITION);
101 4d611c9a pbrook
}
102 4d611c9a pbrook
103 4d611c9a pbrook
/* Cancel a pending data transfer.  */
104 5c6c0e51 Hannes Reinecke
static void scsi_cancel_io(SCSIRequest *req)
105 4d611c9a pbrook
{
106 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
107 5c6c0e51 Hannes Reinecke
108 5c6c0e51 Hannes Reinecke
    DPRINTF("Cancel tag=0x%x\n", req->tag);
109 5c6c0e51 Hannes Reinecke
    if (r->req.aiocb) {
110 5c6c0e51 Hannes Reinecke
        bdrv_aio_cancel(r->req.aiocb);
111 a917d384 pbrook
    }
112 5c6c0e51 Hannes Reinecke
    r->req.aiocb = NULL;
113 a917d384 pbrook
}
114 a917d384 pbrook
115 103b40f5 Paolo Bonzini
static uint32_t scsi_init_iovec(SCSIDiskReq *r)
116 103b40f5 Paolo Bonzini
{
117 7285477a Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
118 7285477a Paolo Bonzini
119 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
120 7285477a Paolo Bonzini
        r->buflen = SCSI_DMA_BUF_SIZE;
121 7285477a Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
122 7285477a Paolo Bonzini
    }
123 7285477a Paolo Bonzini
    r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
124 103b40f5 Paolo Bonzini
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
125 103b40f5 Paolo Bonzini
    return r->qiov.size / 512;
126 103b40f5 Paolo Bonzini
}
127 103b40f5 Paolo Bonzini
128 a917d384 pbrook
static void scsi_read_complete(void * opaque, int ret)
129 a917d384 pbrook
{
130 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
131 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
132 5dba48a8 Kevin Wolf
    int n;
133 a917d384 pbrook
134 8e321cc6 Paolo Bonzini
    if (r->req.aiocb != NULL) {
135 8e321cc6 Paolo Bonzini
        r->req.aiocb = NULL;
136 8e321cc6 Paolo Bonzini
        bdrv_acct_done(s->bs, &r->acct);
137 8e321cc6 Paolo Bonzini
    }
138 a597e79c Christoph Hellwig
139 a917d384 pbrook
    if (ret) {
140 5dba48a8 Kevin Wolf
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
141 5dba48a8 Kevin Wolf
            return;
142 5dba48a8 Kevin Wolf
        }
143 4d611c9a pbrook
    }
144 5dba48a8 Kevin Wolf
145 103b40f5 Paolo Bonzini
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
146 a917d384 pbrook
147 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
148 5dba48a8 Kevin Wolf
    r->sector += n;
149 5dba48a8 Kevin Wolf
    r->sector_count -= n;
150 103b40f5 Paolo Bonzini
    scsi_req_data(&r->req, r->qiov.size);
151 4d611c9a pbrook
}
152 4d611c9a pbrook
153 0a4ac106 Paolo Bonzini
static void scsi_flush_complete(void * opaque, int ret)
154 0a4ac106 Paolo Bonzini
{
155 0a4ac106 Paolo Bonzini
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
156 0a4ac106 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
157 0a4ac106 Paolo Bonzini
158 0a4ac106 Paolo Bonzini
    if (r->req.aiocb != NULL) {
159 0a4ac106 Paolo Bonzini
        r->req.aiocb = NULL;
160 0a4ac106 Paolo Bonzini
        bdrv_acct_done(s->bs, &r->acct);
161 0a4ac106 Paolo Bonzini
    }
162 0a4ac106 Paolo Bonzini
163 0a4ac106 Paolo Bonzini
    if (ret < 0) {
164 0a4ac106 Paolo Bonzini
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
165 0a4ac106 Paolo Bonzini
            return;
166 0a4ac106 Paolo Bonzini
        }
167 0a4ac106 Paolo Bonzini
    }
168 0a4ac106 Paolo Bonzini
169 0a4ac106 Paolo Bonzini
    scsi_req_complete(&r->req, GOOD);
170 0a4ac106 Paolo Bonzini
}
171 5dba48a8 Kevin Wolf
172 5c6c0e51 Hannes Reinecke
/* Read more data from scsi device into buffer.  */
173 5c6c0e51 Hannes Reinecke
static void scsi_read_data(SCSIRequest *req)
174 2e5d83bb pbrook
{
175 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
176 5dba48a8 Kevin Wolf
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
177 2e5d83bb pbrook
    uint32_t n;
178 2e5d83bb pbrook
179 a917d384 pbrook
    if (r->sector_count == (uint32_t)-1) {
180 aa2b1e89 Bernhard Kohl
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
181 a917d384 pbrook
        r->sector_count = 0;
182 ab9adc88 Paolo Bonzini
        scsi_req_data(&r->req, r->iov.iov_len);
183 a917d384 pbrook
        return;
184 2e5d83bb pbrook
    }
185 a917d384 pbrook
    DPRINTF("Read sector_count=%d\n", r->sector_count);
186 a917d384 pbrook
    if (r->sector_count == 0) {
187 b45ef674 Paolo Bonzini
        /* This also clears the sense buffer for REQUEST SENSE.  */
188 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
189 a917d384 pbrook
        return;
190 2e5d83bb pbrook
    }
191 2e5d83bb pbrook
192 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
193 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
194 6fa2c95f Stefan Hajnoczi
195 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
196 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
197 efb9ee02 Hannes Reinecke
        scsi_read_complete(r, -EINVAL);
198 efb9ee02 Hannes Reinecke
        return;
199 efb9ee02 Hannes Reinecke
    }
200 efb9ee02 Hannes Reinecke
201 a1aff5bf Markus Armbruster
    if (s->tray_open) {
202 a1aff5bf Markus Armbruster
        scsi_read_complete(r, -ENOMEDIUM);
203 a1aff5bf Markus Armbruster
    }
204 103b40f5 Paolo Bonzini
    n = scsi_init_iovec(r);
205 a597e79c Christoph Hellwig
    bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
206 428c149b Christoph Hellwig
    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
207 c87c0672 aliguori
                              scsi_read_complete, r);
208 d33ea50a Kevin Wolf
    if (r->req.aiocb == NULL) {
209 d33ea50a Kevin Wolf
        scsi_read_complete(r, -EIO);
210 d33ea50a Kevin Wolf
    }
211 2e5d83bb pbrook
}
212 2e5d83bb pbrook
213 5dba48a8 Kevin Wolf
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
214 5dba48a8 Kevin Wolf
{
215 5dba48a8 Kevin Wolf
    int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
216 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
217 5dba48a8 Kevin Wolf
    BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
218 ea8a5d7f aliguori
219 380f640f Luiz Capitulino
    if (action == BLOCK_ERR_IGNORE) {
220 5dba48a8 Kevin Wolf
        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
221 ea8a5d7f aliguori
        return 0;
222 380f640f Luiz Capitulino
    }
223 ea8a5d7f aliguori
224 ea8a5d7f aliguori
    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
225 ea8a5d7f aliguori
            || action == BLOCK_ERR_STOP_ANY) {
226 5dba48a8 Kevin Wolf
227 5dba48a8 Kevin Wolf
        type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
228 5dba48a8 Kevin Wolf
        r->status |= SCSI_REQ_STATUS_RETRY | type;
229 5dba48a8 Kevin Wolf
230 5dba48a8 Kevin Wolf
        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
231 0461d5a6 Luiz Capitulino
        vm_stop(RUN_STATE_IO_ERROR);
232 9fb118e6 Luiz Capitulino
        bdrv_iostatus_set_err(s->bs, error);
233 ea8a5d7f aliguori
    } else {
234 efb9ee02 Hannes Reinecke
        switch (error) {
235 7e218df5 Paolo Bonzini
        case ENOMEDIUM:
236 7e218df5 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
237 7e218df5 Paolo Bonzini
            break;
238 efb9ee02 Hannes Reinecke
        case ENOMEM:
239 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
240 efb9ee02 Hannes Reinecke
            break;
241 efb9ee02 Hannes Reinecke
        case EINVAL:
242 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
243 efb9ee02 Hannes Reinecke
            break;
244 efb9ee02 Hannes Reinecke
        default:
245 b45ef674 Paolo Bonzini
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
246 efb9ee02 Hannes Reinecke
            break;
247 a1f0cce2 Hannes Reinecke
        }
248 5dba48a8 Kevin Wolf
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
249 ea8a5d7f aliguori
    }
250 ea8a5d7f aliguori
    return 1;
251 ea8a5d7f aliguori
}
252 ea8a5d7f aliguori
253 4d611c9a pbrook
static void scsi_write_complete(void * opaque, int ret)
254 4d611c9a pbrook
{
255 4c41d2ef Gerd Hoffmann
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
256 a597e79c Christoph Hellwig
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
257 ea8a5d7f aliguori
    uint32_t n;
258 ea8a5d7f aliguori
259 8e321cc6 Paolo Bonzini
    if (r->req.aiocb != NULL) {
260 8e321cc6 Paolo Bonzini
        r->req.aiocb = NULL;
261 8e321cc6 Paolo Bonzini
        bdrv_acct_done(s->bs, &r->acct);
262 8e321cc6 Paolo Bonzini
    }
263 a597e79c Christoph Hellwig
264 4d611c9a pbrook
    if (ret) {
265 5dba48a8 Kevin Wolf
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
266 ea8a5d7f aliguori
            return;
267 5dba48a8 Kevin Wolf
        }
268 4d611c9a pbrook
    }
269 4d611c9a pbrook
270 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
271 ea8a5d7f aliguori
    r->sector += n;
272 ea8a5d7f aliguori
    r->sector_count -= n;
273 a917d384 pbrook
    if (r->sector_count == 0) {
274 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
275 a917d384 pbrook
    } else {
276 103b40f5 Paolo Bonzini
        scsi_init_iovec(r);
277 103b40f5 Paolo Bonzini
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
278 103b40f5 Paolo Bonzini
        scsi_req_data(&r->req, r->qiov.size);
279 4d611c9a pbrook
    }
280 4d611c9a pbrook
}
281 4d611c9a pbrook
282 42741212 Paolo Bonzini
static void scsi_write_data(SCSIRequest *req)
283 ea8a5d7f aliguori
{
284 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
285 4c41d2ef Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
286 ea8a5d7f aliguori
    uint32_t n;
287 ea8a5d7f aliguori
288 6fa2c95f Stefan Hajnoczi
    /* No data transfer may already be in progress */
289 6fa2c95f Stefan Hajnoczi
    assert(r->req.aiocb == NULL);
290 6fa2c95f Stefan Hajnoczi
291 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
292 efb9ee02 Hannes Reinecke
        DPRINTF("Data transfer direction invalid\n");
293 efb9ee02 Hannes Reinecke
        scsi_write_complete(r, -EINVAL);
294 42741212 Paolo Bonzini
        return;
295 efb9ee02 Hannes Reinecke
    }
296 efb9ee02 Hannes Reinecke
297 103b40f5 Paolo Bonzini
    n = r->qiov.size / 512;
298 ea8a5d7f aliguori
    if (n) {
299 a1aff5bf Markus Armbruster
        if (s->tray_open) {
300 a1aff5bf Markus Armbruster
            scsi_write_complete(r, -ENOMEDIUM);
301 a1aff5bf Markus Armbruster
        }
302 a597e79c Christoph Hellwig
        bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
303 428c149b Christoph Hellwig
        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
304 103b40f5 Paolo Bonzini
                                       scsi_write_complete, r);
305 d33ea50a Kevin Wolf
        if (r->req.aiocb == NULL) {
306 a1f0cce2 Hannes Reinecke
            scsi_write_complete(r, -ENOMEM);
307 d33ea50a Kevin Wolf
        }
308 ea8a5d7f aliguori
    } else {
309 103b40f5 Paolo Bonzini
        /* Called for the first time.  Ask the driver to send us more data.  */
310 ea8a5d7f aliguori
        scsi_write_complete(r, 0);
311 ea8a5d7f aliguori
    }
312 a917d384 pbrook
}
313 2e5d83bb pbrook
314 213189ab Markus Armbruster
static void scsi_dma_restart_bh(void *opaque)
315 ea8a5d7f aliguori
{
316 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = opaque;
317 9af99d98 Gerd Hoffmann
    SCSIRequest *req;
318 9af99d98 Gerd Hoffmann
    SCSIDiskReq *r;
319 213189ab Markus Armbruster
320 213189ab Markus Armbruster
    qemu_bh_delete(s->bh);
321 213189ab Markus Armbruster
    s->bh = NULL;
322 ea8a5d7f aliguori
323 9af99d98 Gerd Hoffmann
    QTAILQ_FOREACH(req, &s->qdev.requests, next) {
324 9af99d98 Gerd Hoffmann
        r = DO_UPCAST(SCSIDiskReq, req, req);
325 ea8a5d7f aliguori
        if (r->status & SCSI_REQ_STATUS_RETRY) {
326 5dba48a8 Kevin Wolf
            int status = r->status;
327 78ced65e Kevin Wolf
            int ret;
328 78ced65e Kevin Wolf
329 5dba48a8 Kevin Wolf
            r->status &=
330 5dba48a8 Kevin Wolf
                ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
331 5dba48a8 Kevin Wolf
332 5dba48a8 Kevin Wolf
            switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
333 5dba48a8 Kevin Wolf
            case SCSI_REQ_STATUS_RETRY_READ:
334 5c6c0e51 Hannes Reinecke
                scsi_read_data(&r->req);
335 5dba48a8 Kevin Wolf
                break;
336 5dba48a8 Kevin Wolf
            case SCSI_REQ_STATUS_RETRY_WRITE:
337 5c6c0e51 Hannes Reinecke
                scsi_write_data(&r->req);
338 5dba48a8 Kevin Wolf
                break;
339 78ced65e Kevin Wolf
            case SCSI_REQ_STATUS_RETRY_FLUSH:
340 7285477a Paolo Bonzini
                ret = scsi_disk_emulate_command(r);
341 78ced65e Kevin Wolf
                if (ret == 0) {
342 b45ef674 Paolo Bonzini
                    scsi_req_complete(&r->req, GOOD);
343 78ced65e Kevin Wolf
                }
344 5dba48a8 Kevin Wolf
            }
345 ea8a5d7f aliguori
        }
346 ea8a5d7f aliguori
    }
347 ea8a5d7f aliguori
}
348 ea8a5d7f aliguori
349 1dfb4dd9 Luiz Capitulino
static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
350 213189ab Markus Armbruster
{
351 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = opaque;
352 213189ab Markus Armbruster
353 f01b5931 Paolo Bonzini
    if (!running) {
354 213189ab Markus Armbruster
        return;
355 f01b5931 Paolo Bonzini
    }
356 213189ab Markus Armbruster
    if (!s->bh) {
357 213189ab Markus Armbruster
        s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
358 213189ab Markus Armbruster
        qemu_bh_schedule(s->bh);
359 213189ab Markus Armbruster
    }
360 213189ab Markus Armbruster
}
361 213189ab Markus Armbruster
362 a917d384 pbrook
/* Return a pointer to the data buffer.  */
363 5c6c0e51 Hannes Reinecke
static uint8_t *scsi_get_buf(SCSIRequest *req)
364 a917d384 pbrook
{
365 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
366 2e5d83bb pbrook
367 3f4cb3d3 blueswir1
    return (uint8_t *)r->iov.iov_base;
368 2e5d83bb pbrook
}
369 2e5d83bb pbrook
370 0b06c059 Gerd Hoffmann
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
371 0b06c059 Gerd Hoffmann
{
372 383b4d9b Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
373 0b06c059 Gerd Hoffmann
    int buflen = 0;
374 0b06c059 Gerd Hoffmann
375 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[1] & 0x2) {
376 0b06c059 Gerd Hoffmann
        /* Command support data - optional, not implemented */
377 0b06c059 Gerd Hoffmann
        BADF("optional INQUIRY command support request not implemented\n");
378 0b06c059 Gerd Hoffmann
        return -1;
379 0b06c059 Gerd Hoffmann
    }
380 0b06c059 Gerd Hoffmann
381 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[1] & 0x1) {
382 0b06c059 Gerd Hoffmann
        /* Vital product data */
383 0b06c059 Gerd Hoffmann
        uint8_t page_code = req->cmd.buf[2];
384 0b06c059 Gerd Hoffmann
        if (req->cmd.xfer < 4) {
385 0b06c059 Gerd Hoffmann
            BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
386 0b06c059 Gerd Hoffmann
                 "less than 4\n", page_code, req->cmd.xfer);
387 0b06c059 Gerd Hoffmann
            return -1;
388 0b06c059 Gerd Hoffmann
        }
389 0b06c059 Gerd Hoffmann
390 f37bd73b Hannes Reinecke
        if (s->qdev.type == TYPE_ROM) {
391 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 5;
392 0b06c059 Gerd Hoffmann
        } else {
393 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;
394 0b06c059 Gerd Hoffmann
        }
395 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = page_code ; // this page
396 0b06c059 Gerd Hoffmann
        outbuf[buflen++] = 0x00;
397 0b06c059 Gerd Hoffmann
398 0b06c059 Gerd Hoffmann
        switch (page_code) {
399 0b06c059 Gerd Hoffmann
        case 0x00: /* Supported page codes, mandatory */
400 39d98982 Hannes Reinecke
        {
401 39d98982 Hannes Reinecke
            int pages;
402 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Supported pages] "
403 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
404 39d98982 Hannes Reinecke
            pages = buflen++;
405 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
406 f01b5931 Paolo Bonzini
            if (s->serial) {
407 3e1c0c9a Hannes Reinecke
                outbuf[buflen++] = 0x80; // unit serial number
408 f01b5931 Paolo Bonzini
            }
409 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x83; // device identification
410 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_DISK) {
411 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb0; // block limits
412 ea3bd56f Christoph Hellwig
                outbuf[buflen++] = 0xb2; // thin provisioning
413 39d98982 Hannes Reinecke
            }
414 39d98982 Hannes Reinecke
            outbuf[pages] = buflen - pages - 1; // number of pages
415 0b06c059 Gerd Hoffmann
            break;
416 39d98982 Hannes Reinecke
        }
417 0b06c059 Gerd Hoffmann
        case 0x80: /* Device serial number, optional */
418 0b06c059 Gerd Hoffmann
        {
419 3e1c0c9a Hannes Reinecke
            int l;
420 0b06c059 Gerd Hoffmann
421 3e1c0c9a Hannes Reinecke
            if (!s->serial) {
422 3e1c0c9a Hannes Reinecke
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
423 3e1c0c9a Hannes Reinecke
                return -1;
424 3e1c0c9a Hannes Reinecke
            }
425 3e1c0c9a Hannes Reinecke
426 3e1c0c9a Hannes Reinecke
            l = strlen(s->serial);
427 f01b5931 Paolo Bonzini
            if (l > req->cmd.xfer) {
428 0b06c059 Gerd Hoffmann
                l = req->cmd.xfer;
429 f01b5931 Paolo Bonzini
            }
430 f01b5931 Paolo Bonzini
            if (l > 20) {
431 0b06c059 Gerd Hoffmann
                l = 20;
432 f01b5931 Paolo Bonzini
            }
433 0b06c059 Gerd Hoffmann
434 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Serial number] "
435 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
436 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = l;
437 a0fef654 Markus Armbruster
            memcpy(outbuf+buflen, s->serial, l);
438 0b06c059 Gerd Hoffmann
            buflen += l;
439 0b06c059 Gerd Hoffmann
            break;
440 0b06c059 Gerd Hoffmann
        }
441 0b06c059 Gerd Hoffmann
442 0b06c059 Gerd Hoffmann
        case 0x83: /* Device identification page, mandatory */
443 0b06c059 Gerd Hoffmann
        {
444 0b06c059 Gerd Hoffmann
            int max_len = 255 - 8;
445 428c149b Christoph Hellwig
            int id_len = strlen(bdrv_get_device_name(s->bs));
446 0b06c059 Gerd Hoffmann
447 f01b5931 Paolo Bonzini
            if (id_len > max_len) {
448 0b06c059 Gerd Hoffmann
                id_len = max_len;
449 f01b5931 Paolo Bonzini
            }
450 0b06c059 Gerd Hoffmann
            DPRINTF("Inquiry EVPD[Device identification] "
451 0b06c059 Gerd Hoffmann
                    "buffer size %zd\n", req->cmd.xfer);
452 0b06c059 Gerd Hoffmann
453 39d98982 Hannes Reinecke
            outbuf[buflen++] = 4 + id_len;
454 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0x2; // ASCII
455 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // not officially assigned
456 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = 0;   // reserved
457 0b06c059 Gerd Hoffmann
            outbuf[buflen++] = id_len; // length of data following
458 0b06c059 Gerd Hoffmann
459 428c149b Christoph Hellwig
            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
460 0b06c059 Gerd Hoffmann
            buflen += id_len;
461 0b06c059 Gerd Hoffmann
            break;
462 0b06c059 Gerd Hoffmann
        }
463 ea3bd56f Christoph Hellwig
        case 0xb0: /* block limits */
464 ee3659e3 Christoph Hellwig
        {
465 ea3bd56f Christoph Hellwig
            unsigned int unmap_sectors =
466 ea3bd56f Christoph Hellwig
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
467 8cfacf07 Christoph Hellwig
            unsigned int min_io_size =
468 8cfacf07 Christoph Hellwig
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
469 8cfacf07 Christoph Hellwig
            unsigned int opt_io_size =
470 8cfacf07 Christoph Hellwig
                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
471 ee3659e3 Christoph Hellwig
472 f37bd73b Hannes Reinecke
            if (s->qdev.type == TYPE_ROM) {
473 39d98982 Hannes Reinecke
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
474 39d98982 Hannes Reinecke
                        page_code);
475 39d98982 Hannes Reinecke
                return -1;
476 39d98982 Hannes Reinecke
            }
477 ee3659e3 Christoph Hellwig
            /* required VPD size with unmap support */
478 ee3659e3 Christoph Hellwig
            outbuf[3] = buflen = 0x3c;
479 ee3659e3 Christoph Hellwig
480 ee3659e3 Christoph Hellwig
            memset(outbuf + 4, 0, buflen - 4);
481 ee3659e3 Christoph Hellwig
482 ee3659e3 Christoph Hellwig
            /* optimal transfer length granularity */
483 ee3659e3 Christoph Hellwig
            outbuf[6] = (min_io_size >> 8) & 0xff;
484 ee3659e3 Christoph Hellwig
            outbuf[7] = min_io_size & 0xff;
485 ee3659e3 Christoph Hellwig
486 ee3659e3 Christoph Hellwig
            /* optimal transfer length */
487 ee3659e3 Christoph Hellwig
            outbuf[12] = (opt_io_size >> 24) & 0xff;
488 ee3659e3 Christoph Hellwig
            outbuf[13] = (opt_io_size >> 16) & 0xff;
489 ee3659e3 Christoph Hellwig
            outbuf[14] = (opt_io_size >> 8) & 0xff;
490 ee3659e3 Christoph Hellwig
            outbuf[15] = opt_io_size & 0xff;
491 ea3bd56f Christoph Hellwig
492 ea3bd56f Christoph Hellwig
            /* optimal unmap granularity */
493 ea3bd56f Christoph Hellwig
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
494 ea3bd56f Christoph Hellwig
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
495 ea3bd56f Christoph Hellwig
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
496 ea3bd56f Christoph Hellwig
            outbuf[31] = unmap_sectors & 0xff;
497 ea3bd56f Christoph Hellwig
            break;
498 ea3bd56f Christoph Hellwig
        }
499 ea3bd56f Christoph Hellwig
        case 0xb2: /* thin provisioning */
500 ea3bd56f Christoph Hellwig
        {
501 ea3bd56f Christoph Hellwig
            outbuf[3] = buflen = 8;
502 ea3bd56f Christoph Hellwig
            outbuf[4] = 0;
503 ea3bd56f Christoph Hellwig
            outbuf[5] = 0x40; /* write same with unmap supported */
504 ea3bd56f Christoph Hellwig
            outbuf[6] = 0;
505 ea3bd56f Christoph Hellwig
            outbuf[7] = 0;
506 ee3659e3 Christoph Hellwig
            break;
507 ee3659e3 Christoph Hellwig
        }
508 0b06c059 Gerd Hoffmann
        default:
509 0b06c059 Gerd Hoffmann
            BADF("Error: unsupported Inquiry (EVPD[%02X]) "
510 0b06c059 Gerd Hoffmann
                 "buffer size %zd\n", page_code, req->cmd.xfer);
511 0b06c059 Gerd Hoffmann
            return -1;
512 0b06c059 Gerd Hoffmann
        }
513 0b06c059 Gerd Hoffmann
        /* done with EVPD */
514 0b06c059 Gerd Hoffmann
        return buflen;
515 0b06c059 Gerd Hoffmann
    }
516 0b06c059 Gerd Hoffmann
517 0b06c059 Gerd Hoffmann
    /* Standard INQUIRY data */
518 0b06c059 Gerd Hoffmann
    if (req->cmd.buf[2] != 0) {
519 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) page or code "
520 0b06c059 Gerd Hoffmann
             "is non-zero [%02X]\n", req->cmd.buf[2]);
521 0b06c059 Gerd Hoffmann
        return -1;
522 0b06c059 Gerd Hoffmann
    }
523 0b06c059 Gerd Hoffmann
524 0b06c059 Gerd Hoffmann
    /* PAGE CODE == 0 */
525 0b06c059 Gerd Hoffmann
    if (req->cmd.xfer < 5) {
526 0b06c059 Gerd Hoffmann
        BADF("Error: Inquiry (STANDARD) buffer size %zd "
527 0b06c059 Gerd Hoffmann
             "is less than 5\n", req->cmd.xfer);
528 0b06c059 Gerd Hoffmann
        return -1;
529 0b06c059 Gerd Hoffmann
    }
530 0b06c059 Gerd Hoffmann
531 0b06c059 Gerd Hoffmann
    buflen = req->cmd.xfer;
532 f01b5931 Paolo Bonzini
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
533 0b06c059 Gerd Hoffmann
        buflen = SCSI_MAX_INQUIRY_LEN;
534 f01b5931 Paolo Bonzini
    }
535 0b06c059 Gerd Hoffmann
    memset(outbuf, 0, buflen);
536 0b06c059 Gerd Hoffmann
537 f37bd73b Hannes Reinecke
    outbuf[0] = s->qdev.type & 0x1f;
538 f37bd73b Hannes Reinecke
    if (s->qdev.type == TYPE_ROM) {
539 0b06c059 Gerd Hoffmann
        outbuf[1] = 0x80;
540 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
541 0b06c059 Gerd Hoffmann
    } else {
542 419e691f Stefan Hajnoczi
        outbuf[1] = s->removable ? 0x80 : 0;
543 550fe6c6 Laszlo Ast
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
544 0b06c059 Gerd Hoffmann
    }
545 550fe6c6 Laszlo Ast
    memcpy(&outbuf[8], "QEMU    ", 8);
546 314b1811 Gerd Hoffmann
    memset(&outbuf[32], 0, 4);
547 552fee93 Markus Armbruster
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
548 99aba0c4 Christoph Hellwig
    /*
549 99aba0c4 Christoph Hellwig
     * We claim conformance to SPC-3, which is required for guests
550 99aba0c4 Christoph Hellwig
     * to ask for modern features like READ CAPACITY(16) or the
551 99aba0c4 Christoph Hellwig
     * block characteristics VPD page by default.  Not all of SPC-3
552 99aba0c4 Christoph Hellwig
     * is actually implemented, but we're good enough.
553 99aba0c4 Christoph Hellwig
     */
554 ee3659e3 Christoph Hellwig
    outbuf[2] = 5;
555 0b06c059 Gerd Hoffmann
    outbuf[3] = 2; /* Format 2 */
556 ad3cea42 Artyom Tarasenko
557 ad3cea42 Artyom Tarasenko
    if (buflen > 36) {
558 ad3cea42 Artyom Tarasenko
        outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
559 ad3cea42 Artyom Tarasenko
    } else {
560 ad3cea42 Artyom Tarasenko
        /* If the allocation length of CDB is too small,
561 ad3cea42 Artyom Tarasenko
               the additional length is not adjusted */
562 ad3cea42 Artyom Tarasenko
        outbuf[4] = 36 - 5;
563 ad3cea42 Artyom Tarasenko
    }
564 ad3cea42 Artyom Tarasenko
565 0b06c059 Gerd Hoffmann
    /* Sync data transfer and TCQ.  */
566 0b06c059 Gerd Hoffmann
    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
567 0b06c059 Gerd Hoffmann
    return buflen;
568 0b06c059 Gerd Hoffmann
}
569 0b06c059 Gerd Hoffmann
570 cfc606da Paolo Bonzini
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
571 282ab04e Bernhard Kohl
                           int page_control)
572 ebddfcbe Gerd Hoffmann
{
573 428c149b Christoph Hellwig
    BlockDriverState *bdrv = s->bs;
574 ebddfcbe Gerd Hoffmann
    int cylinders, heads, secs;
575 cfc606da Paolo Bonzini
    uint8_t *p = *p_outbuf;
576 ebddfcbe Gerd Hoffmann
577 282ab04e Bernhard Kohl
    /*
578 282ab04e Bernhard Kohl
     * If Changeable Values are requested, a mask denoting those mode parameters
579 282ab04e Bernhard Kohl
     * that are changeable shall be returned. As we currently don't support
580 282ab04e Bernhard Kohl
     * parameter changes via MODE_SELECT all bits are returned set to zero.
581 282ab04e Bernhard Kohl
     * The buffer was already menset to zero by the caller of this function.
582 282ab04e Bernhard Kohl
     */
583 ebddfcbe Gerd Hoffmann
    switch (page) {
584 67cc61e4 Paolo Bonzini
    case MODE_PAGE_HD_GEOMETRY:
585 cfc606da Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
586 cfc606da Paolo Bonzini
            return -1;
587 cfc606da Paolo Bonzini
        }
588 ebddfcbe Gerd Hoffmann
        p[0] = 4;
589 ebddfcbe Gerd Hoffmann
        p[1] = 0x16;
590 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
591 cfc606da Paolo Bonzini
            break;
592 282ab04e Bernhard Kohl
        }
593 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
594 ebddfcbe Gerd Hoffmann
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
595 ebddfcbe Gerd Hoffmann
        p[2] = (cylinders >> 16) & 0xff;
596 ebddfcbe Gerd Hoffmann
        p[3] = (cylinders >> 8) & 0xff;
597 ebddfcbe Gerd Hoffmann
        p[4] = cylinders & 0xff;
598 ebddfcbe Gerd Hoffmann
        p[5] = heads & 0xff;
599 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
600 ebddfcbe Gerd Hoffmann
        p[6] = (cylinders >> 16) & 0xff;
601 ebddfcbe Gerd Hoffmann
        p[7] = (cylinders >> 8) & 0xff;
602 ebddfcbe Gerd Hoffmann
        p[8] = cylinders & 0xff;
603 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
604 ebddfcbe Gerd Hoffmann
        p[9] = (cylinders >> 16) & 0xff;
605 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
606 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
607 ebddfcbe Gerd Hoffmann
        /* Device step rate [ns], 200ns */
608 ebddfcbe Gerd Hoffmann
        p[12] = 0;
609 ebddfcbe Gerd Hoffmann
        p[13] = 200;
610 ebddfcbe Gerd Hoffmann
        /* Landing zone cylinder */
611 ebddfcbe Gerd Hoffmann
        p[14] = 0xff;
612 ebddfcbe Gerd Hoffmann
        p[15] =  0xff;
613 ebddfcbe Gerd Hoffmann
        p[16] = 0xff;
614 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
615 ebddfcbe Gerd Hoffmann
        p[20] = (5400 >> 8) & 0xff;
616 ebddfcbe Gerd Hoffmann
        p[21] = 5400 & 0xff;
617 cfc606da Paolo Bonzini
        break;
618 ebddfcbe Gerd Hoffmann
619 67cc61e4 Paolo Bonzini
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
620 cfc606da Paolo Bonzini
        if (s->qdev.type == TYPE_ROM) {
621 cfc606da Paolo Bonzini
            return -1;
622 cfc606da Paolo Bonzini
        }
623 ebddfcbe Gerd Hoffmann
        p[0] = 5;
624 ebddfcbe Gerd Hoffmann
        p[1] = 0x1e;
625 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
626 cfc606da Paolo Bonzini
            break;
627 282ab04e Bernhard Kohl
        }
628 ebddfcbe Gerd Hoffmann
        /* Transfer rate [kbit/s], 5Mbit/s */
629 ebddfcbe Gerd Hoffmann
        p[2] = 5000 >> 8;
630 ebddfcbe Gerd Hoffmann
        p[3] = 5000 & 0xff;
631 ebddfcbe Gerd Hoffmann
        /* if a geometry hint is available, use it */
632 ebddfcbe Gerd Hoffmann
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
633 ebddfcbe Gerd Hoffmann
        p[4] = heads & 0xff;
634 ebddfcbe Gerd Hoffmann
        p[5] = secs & 0xff;
635 ebddfcbe Gerd Hoffmann
        p[6] = s->cluster_size * 2;
636 ebddfcbe Gerd Hoffmann
        p[8] = (cylinders >> 8) & 0xff;
637 ebddfcbe Gerd Hoffmann
        p[9] = cylinders & 0xff;
638 ebddfcbe Gerd Hoffmann
        /* Write precomp start cylinder, disabled */
639 ebddfcbe Gerd Hoffmann
        p[10] = (cylinders >> 8) & 0xff;
640 ebddfcbe Gerd Hoffmann
        p[11] = cylinders & 0xff;
641 ebddfcbe Gerd Hoffmann
        /* Reduced current start cylinder, disabled */
642 ebddfcbe Gerd Hoffmann
        p[12] = (cylinders >> 8) & 0xff;
643 ebddfcbe Gerd Hoffmann
        p[13] = cylinders & 0xff;
644 ebddfcbe Gerd Hoffmann
        /* Device step rate [100us], 100us */
645 ebddfcbe Gerd Hoffmann
        p[14] = 0;
646 ebddfcbe Gerd Hoffmann
        p[15] = 1;
647 ebddfcbe Gerd Hoffmann
        /* Device step pulse width [us], 1us */
648 ebddfcbe Gerd Hoffmann
        p[16] = 1;
649 ebddfcbe Gerd Hoffmann
        /* Device head settle delay [100us], 100us */
650 ebddfcbe Gerd Hoffmann
        p[17] = 0;
651 ebddfcbe Gerd Hoffmann
        p[18] = 1;
652 ebddfcbe Gerd Hoffmann
        /* Motor on delay [0.1s], 0.1s */
653 ebddfcbe Gerd Hoffmann
        p[19] = 1;
654 ebddfcbe Gerd Hoffmann
        /* Motor off delay [0.1s], 0.1s */
655 ebddfcbe Gerd Hoffmann
        p[20] = 1;
656 ebddfcbe Gerd Hoffmann
        /* Medium rotation rate [rpm], 5400 rpm */
657 ebddfcbe Gerd Hoffmann
        p[28] = (5400 >> 8) & 0xff;
658 ebddfcbe Gerd Hoffmann
        p[29] = 5400 & 0xff;
659 cfc606da Paolo Bonzini
        break;
660 ebddfcbe Gerd Hoffmann
661 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CACHING:
662 ebddfcbe Gerd Hoffmann
        p[0] = 8;
663 ebddfcbe Gerd Hoffmann
        p[1] = 0x12;
664 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
665 cfc606da Paolo Bonzini
            break;
666 282ab04e Bernhard Kohl
        }
667 428c149b Christoph Hellwig
        if (bdrv_enable_write_cache(s->bs)) {
668 ebddfcbe Gerd Hoffmann
            p[2] = 4; /* WCE */
669 ebddfcbe Gerd Hoffmann
        }
670 cfc606da Paolo Bonzini
        break;
671 ebddfcbe Gerd Hoffmann
672 67cc61e4 Paolo Bonzini
    case MODE_PAGE_CAPABILITIES:
673 cfc606da Paolo Bonzini
        if (s->qdev.type != TYPE_ROM) {
674 cfc606da Paolo Bonzini
            return -1;
675 cfc606da Paolo Bonzini
        }
676 ebddfcbe Gerd Hoffmann
        p[0] = 0x2a;
677 ebddfcbe Gerd Hoffmann
        p[1] = 0x14;
678 282ab04e Bernhard Kohl
        if (page_control == 1) { /* Changeable Values */
679 cfc606da Paolo Bonzini
            break;
680 282ab04e Bernhard Kohl
        }
681 ebddfcbe Gerd Hoffmann
        p[2] = 3; // CD-R & CD-RW read
682 ebddfcbe Gerd Hoffmann
        p[3] = 0; // Writing not supported
683 ebddfcbe Gerd Hoffmann
        p[4] = 0x7f; /* Audio, composite, digital out,
684 ebddfcbe Gerd Hoffmann
                        mode 2 form 1&2, multi session */
685 ebddfcbe Gerd Hoffmann
        p[5] = 0xff; /* CD DA, DA accurate, RW supported,
686 ebddfcbe Gerd Hoffmann
                        RW corrected, C2 errors, ISRC,
687 ebddfcbe Gerd Hoffmann
                        UPC, Bar code */
688 81b1008d Markus Armbruster
        p[6] = 0x2d | (s->tray_locked ? 2 : 0);
689 ebddfcbe Gerd Hoffmann
        /* Locking supported, jumper present, eject, tray */
690 ebddfcbe Gerd Hoffmann
        p[7] = 0; /* no volume & mute control, no
691 ebddfcbe Gerd Hoffmann
                     changer */
692 ebddfcbe Gerd Hoffmann
        p[8] = (50 * 176) >> 8; // 50x read speed
693 ebddfcbe Gerd Hoffmann
        p[9] = (50 * 176) & 0xff;
694 ebddfcbe Gerd Hoffmann
        p[10] = 0 >> 8; // No volume
695 ebddfcbe Gerd Hoffmann
        p[11] = 0 & 0xff;
696 ebddfcbe Gerd Hoffmann
        p[12] = 2048 >> 8; // 2M buffer
697 ebddfcbe Gerd Hoffmann
        p[13] = 2048 & 0xff;
698 ebddfcbe Gerd Hoffmann
        p[14] = (16 * 176) >> 8; // 16x read speed current
699 ebddfcbe Gerd Hoffmann
        p[15] = (16 * 176) & 0xff;
700 ebddfcbe Gerd Hoffmann
        p[18] = (16 * 176) >> 8; // 16x write speed
701 ebddfcbe Gerd Hoffmann
        p[19] = (16 * 176) & 0xff;
702 ebddfcbe Gerd Hoffmann
        p[20] = (16 * 176) >> 8; // 16x write speed current
703 ebddfcbe Gerd Hoffmann
        p[21] = (16 * 176) & 0xff;
704 cfc606da Paolo Bonzini
        break;
705 ebddfcbe Gerd Hoffmann
706 ebddfcbe Gerd Hoffmann
    default:
707 cfc606da Paolo Bonzini
        return -1;
708 ebddfcbe Gerd Hoffmann
    }
709 cfc606da Paolo Bonzini
710 cfc606da Paolo Bonzini
    *p_outbuf += p[1] + 2;
711 cfc606da Paolo Bonzini
    return p[1] + 2;
712 ebddfcbe Gerd Hoffmann
}
713 ebddfcbe Gerd Hoffmann
714 cfc606da Paolo Bonzini
static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
715 ebddfcbe Gerd Hoffmann
{
716 cfc606da Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
717 ebddfcbe Gerd Hoffmann
    uint64_t nb_sectors;
718 cfc606da Paolo Bonzini
    int page, dbd, buflen, ret, page_control;
719 ebddfcbe Gerd Hoffmann
    uint8_t *p;
720 ce512ee1 Bernhard Kohl
    uint8_t dev_specific_param;
721 ebddfcbe Gerd Hoffmann
722 cfc606da Paolo Bonzini
    dbd = r->req.cmd.buf[1]  & 0x8;
723 cfc606da Paolo Bonzini
    page = r->req.cmd.buf[2] & 0x3f;
724 cfc606da Paolo Bonzini
    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
725 aa2b1e89 Bernhard Kohl
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
726 cfc606da Paolo Bonzini
        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
727 cfc606da Paolo Bonzini
    memset(outbuf, 0, r->req.cmd.xfer);
728 ebddfcbe Gerd Hoffmann
    p = outbuf;
729 ebddfcbe Gerd Hoffmann
730 0056dcc1 Naphtali Sprei
    if (bdrv_is_read_only(s->bs)) {
731 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x80; /* Readonly.  */
732 ce512ee1 Bernhard Kohl
    } else {
733 ce512ee1 Bernhard Kohl
        dev_specific_param = 0x00;
734 ce512ee1 Bernhard Kohl
    }
735 ce512ee1 Bernhard Kohl
736 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
737 ce512ee1 Bernhard Kohl
        p[1] = 0; /* Default media type.  */
738 ce512ee1 Bernhard Kohl
        p[2] = dev_specific_param;
739 ce512ee1 Bernhard Kohl
        p[3] = 0; /* Block descriptor length.  */
740 ce512ee1 Bernhard Kohl
        p += 4;
741 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
742 ce512ee1 Bernhard Kohl
        p[2] = 0; /* Default media type.  */
743 ce512ee1 Bernhard Kohl
        p[3] = dev_specific_param;
744 ce512ee1 Bernhard Kohl
        p[6] = p[7] = 0; /* Block descriptor length.  */
745 ce512ee1 Bernhard Kohl
        p += 8;
746 ebddfcbe Gerd Hoffmann
    }
747 ebddfcbe Gerd Hoffmann
748 428c149b Christoph Hellwig
    bdrv_get_geometry(s->bs, &nb_sectors);
749 333d50fe Bernhard Kohl
    if (!dbd && nb_sectors) {
750 cfc606da Paolo Bonzini
        if (r->req.cmd.buf[0] == MODE_SENSE) {
751 ce512ee1 Bernhard Kohl
            outbuf[3] = 8; /* Block descriptor length  */
752 ce512ee1 Bernhard Kohl
        } else { /* MODE_SENSE_10 */
753 ce512ee1 Bernhard Kohl
            outbuf[7] = 8; /* Block descriptor length  */
754 ce512ee1 Bernhard Kohl
        }
755 ebddfcbe Gerd Hoffmann
        nb_sectors /= s->cluster_size;
756 f01b5931 Paolo Bonzini
        if (nb_sectors > 0xffffff) {
757 2488b740 Bernhard Kohl
            nb_sectors = 0;
758 f01b5931 Paolo Bonzini
        }
759 ebddfcbe Gerd Hoffmann
        p[0] = 0; /* media density code */
760 ebddfcbe Gerd Hoffmann
        p[1] = (nb_sectors >> 16) & 0xff;
761 ebddfcbe Gerd Hoffmann
        p[2] = (nb_sectors >> 8) & 0xff;
762 ebddfcbe Gerd Hoffmann
        p[3] = nb_sectors & 0xff;
763 ebddfcbe Gerd Hoffmann
        p[4] = 0; /* reserved */
764 ebddfcbe Gerd Hoffmann
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
765 ebddfcbe Gerd Hoffmann
        p[6] = s->cluster_size * 2;
766 ebddfcbe Gerd Hoffmann
        p[7] = 0;
767 ebddfcbe Gerd Hoffmann
        p += 8;
768 ebddfcbe Gerd Hoffmann
    }
769 ebddfcbe Gerd Hoffmann
770 cfc606da Paolo Bonzini
    if (page_control == 3) {
771 cfc606da Paolo Bonzini
        /* Saved Values */
772 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
773 cfc606da Paolo Bonzini
        return -1;
774 282ab04e Bernhard Kohl
    }
775 282ab04e Bernhard Kohl
776 cfc606da Paolo Bonzini
    if (page == 0x3f) {
777 cfc606da Paolo Bonzini
        for (page = 0; page <= 0x3e; page++) {
778 cfc606da Paolo Bonzini
            mode_sense_page(s, page, &p, page_control);
779 cfc606da Paolo Bonzini
        }
780 cfc606da Paolo Bonzini
    } else {
781 cfc606da Paolo Bonzini
        ret = mode_sense_page(s, page, &p, page_control);
782 cfc606da Paolo Bonzini
        if (ret == -1) {
783 cfc606da Paolo Bonzini
            return -1;
784 cfc606da Paolo Bonzini
        }
785 ebddfcbe Gerd Hoffmann
    }
786 ebddfcbe Gerd Hoffmann
787 ebddfcbe Gerd Hoffmann
    buflen = p - outbuf;
788 ce512ee1 Bernhard Kohl
    /*
789 ce512ee1 Bernhard Kohl
     * The mode data length field specifies the length in bytes of the
790 ce512ee1 Bernhard Kohl
     * following data that is available to be transferred. The mode data
791 ce512ee1 Bernhard Kohl
     * length does not include itself.
792 ce512ee1 Bernhard Kohl
     */
793 cfc606da Paolo Bonzini
    if (r->req.cmd.buf[0] == MODE_SENSE) {
794 ce512ee1 Bernhard Kohl
        outbuf[0] = buflen - 1;
795 ce512ee1 Bernhard Kohl
    } else { /* MODE_SENSE_10 */
796 ce512ee1 Bernhard Kohl
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
797 ce512ee1 Bernhard Kohl
        outbuf[1] = (buflen - 2) & 0xff;
798 ce512ee1 Bernhard Kohl
    }
799 f01b5931 Paolo Bonzini
    if (buflen > r->req.cmd.xfer) {
800 cfc606da Paolo Bonzini
        buflen = r->req.cmd.xfer;
801 f01b5931 Paolo Bonzini
    }
802 ebddfcbe Gerd Hoffmann
    return buflen;
803 ebddfcbe Gerd Hoffmann
}
804 ebddfcbe Gerd Hoffmann
805 02880f43 Gerd Hoffmann
static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
806 02880f43 Gerd Hoffmann
{
807 02880f43 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
808 02880f43 Gerd Hoffmann
    int start_track, format, msf, toclen;
809 02880f43 Gerd Hoffmann
    uint64_t nb_sectors;
810 02880f43 Gerd Hoffmann
811 02880f43 Gerd Hoffmann
    msf = req->cmd.buf[1] & 2;
812 02880f43 Gerd Hoffmann
    format = req->cmd.buf[2] & 0xf;
813 02880f43 Gerd Hoffmann
    start_track = req->cmd.buf[6];
814 428c149b Christoph Hellwig
    bdrv_get_geometry(s->bs, &nb_sectors);
815 02880f43 Gerd Hoffmann
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
816 02880f43 Gerd Hoffmann
    nb_sectors /= s->cluster_size;
817 02880f43 Gerd Hoffmann
    switch (format) {
818 02880f43 Gerd Hoffmann
    case 0:
819 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
820 02880f43 Gerd Hoffmann
        break;
821 02880f43 Gerd Hoffmann
    case 1:
822 02880f43 Gerd Hoffmann
        /* multi session : only a single session defined */
823 02880f43 Gerd Hoffmann
        toclen = 12;
824 02880f43 Gerd Hoffmann
        memset(outbuf, 0, 12);
825 02880f43 Gerd Hoffmann
        outbuf[1] = 0x0a;
826 02880f43 Gerd Hoffmann
        outbuf[2] = 0x01;
827 02880f43 Gerd Hoffmann
        outbuf[3] = 0x01;
828 02880f43 Gerd Hoffmann
        break;
829 02880f43 Gerd Hoffmann
    case 2:
830 02880f43 Gerd Hoffmann
        toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
831 02880f43 Gerd Hoffmann
        break;
832 02880f43 Gerd Hoffmann
    default:
833 02880f43 Gerd Hoffmann
        return -1;
834 02880f43 Gerd Hoffmann
    }
835 f01b5931 Paolo Bonzini
    if (toclen > req->cmd.xfer) {
836 02880f43 Gerd Hoffmann
        toclen = req->cmd.xfer;
837 f01b5931 Paolo Bonzini
    }
838 02880f43 Gerd Hoffmann
    return toclen;
839 02880f43 Gerd Hoffmann
}
840 02880f43 Gerd Hoffmann
841 68bb01f3 Markus Armbruster
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
842 bfd52647 Markus Armbruster
{
843 bfd52647 Markus Armbruster
    SCSIRequest *req = &r->req;
844 bfd52647 Markus Armbruster
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
845 bfd52647 Markus Armbruster
    bool start = req->cmd.buf[4] & 1;
846 bfd52647 Markus Armbruster
    bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
847 bfd52647 Markus Armbruster
848 bfd52647 Markus Armbruster
    if (s->qdev.type == TYPE_ROM && loej) {
849 68bb01f3 Markus Armbruster
        if (!start && !s->tray_open && s->tray_locked) {
850 68bb01f3 Markus Armbruster
            scsi_check_condition(r,
851 68bb01f3 Markus Armbruster
                                 bdrv_is_inserted(s->bs)
852 68bb01f3 Markus Armbruster
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
853 68bb01f3 Markus Armbruster
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
854 68bb01f3 Markus Armbruster
            return -1;
855 fdec4404 Markus Armbruster
        }
856 bfd52647 Markus Armbruster
        bdrv_eject(s->bs, !start);
857 ece0d5e9 Markus Armbruster
        s->tray_open = !start;
858 bfd52647 Markus Armbruster
    }
859 68bb01f3 Markus Armbruster
    return 0;
860 bfd52647 Markus Armbruster
}
861 bfd52647 Markus Armbruster
862 7285477a Paolo Bonzini
static int scsi_disk_emulate_command(SCSIDiskReq *r)
863 aa5dbdc1 Gerd Hoffmann
{
864 8af7a3ab Kevin Wolf
    SCSIRequest *req = &r->req;
865 e7e25e32 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
866 e7e25e32 Gerd Hoffmann
    uint64_t nb_sectors;
867 7285477a Paolo Bonzini
    uint8_t *outbuf;
868 aa5dbdc1 Gerd Hoffmann
    int buflen = 0;
869 aa5dbdc1 Gerd Hoffmann
870 7285477a Paolo Bonzini
    if (!r->iov.iov_base) {
871 7285477a Paolo Bonzini
        /*
872 7285477a Paolo Bonzini
         * FIXME: we shouldn't return anything bigger than 4k, but the code
873 7285477a Paolo Bonzini
         * requires the buffer to be as big as req->cmd.xfer in several
874 7285477a Paolo Bonzini
         * places.  So, do not allow CDBs with a very large ALLOCATION
875 7285477a Paolo Bonzini
         * LENGTH.  The real fix would be to modify scsi_read_data and
876 7285477a Paolo Bonzini
         * dma_buf_read, so that they return data beyond the buflen
877 7285477a Paolo Bonzini
         * as all zeros.
878 7285477a Paolo Bonzini
         */
879 7285477a Paolo Bonzini
        if (req->cmd.xfer > 65536) {
880 7285477a Paolo Bonzini
            goto illegal_request;
881 7285477a Paolo Bonzini
        }
882 7285477a Paolo Bonzini
        r->buflen = MAX(4096, req->cmd.xfer);
883 7285477a Paolo Bonzini
        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
884 7285477a Paolo Bonzini
    }
885 7285477a Paolo Bonzini
886 7285477a Paolo Bonzini
    outbuf = r->iov.iov_base;
887 aa5dbdc1 Gerd Hoffmann
    switch (req->cmd.buf[0]) {
888 aa5dbdc1 Gerd Hoffmann
    case TEST_UNIT_READY:
889 f01b5931 Paolo Bonzini
        if (s->tray_open || !bdrv_is_inserted(s->bs)) {
890 aa5dbdc1 Gerd Hoffmann
            goto not_ready;
891 f01b5931 Paolo Bonzini
        }
892 5f71d32f Hannes Reinecke
        break;
893 0b06c059 Gerd Hoffmann
    case INQUIRY:
894 0b06c059 Gerd Hoffmann
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
895 f01b5931 Paolo Bonzini
        if (buflen < 0) {
896 0b06c059 Gerd Hoffmann
            goto illegal_request;
897 f01b5931 Paolo Bonzini
        }
898 5f71d32f Hannes Reinecke
        break;
899 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
900 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
901 cfc606da Paolo Bonzini
        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
902 f01b5931 Paolo Bonzini
        if (buflen < 0) {
903 ebddfcbe Gerd Hoffmann
            goto illegal_request;
904 f01b5931 Paolo Bonzini
        }
905 ebddfcbe Gerd Hoffmann
        break;
906 02880f43 Gerd Hoffmann
    case READ_TOC:
907 02880f43 Gerd Hoffmann
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
908 f01b5931 Paolo Bonzini
        if (buflen < 0) {
909 02880f43 Gerd Hoffmann
            goto illegal_request;
910 f01b5931 Paolo Bonzini
        }
911 02880f43 Gerd Hoffmann
        break;
912 3d53ba18 Gerd Hoffmann
    case RESERVE:
913 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
914 3d53ba18 Gerd Hoffmann
            goto illegal_request;
915 f01b5931 Paolo Bonzini
        }
916 3d53ba18 Gerd Hoffmann
        break;
917 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
918 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
919 3d53ba18 Gerd Hoffmann
            goto illegal_request;
920 f01b5931 Paolo Bonzini
        }
921 3d53ba18 Gerd Hoffmann
        break;
922 3d53ba18 Gerd Hoffmann
    case RELEASE:
923 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 1) {
924 3d53ba18 Gerd Hoffmann
            goto illegal_request;
925 f01b5931 Paolo Bonzini
        }
926 3d53ba18 Gerd Hoffmann
        break;
927 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
928 f01b5931 Paolo Bonzini
        if (req->cmd.buf[1] & 3) {
929 3d53ba18 Gerd Hoffmann
            goto illegal_request;
930 f01b5931 Paolo Bonzini
        }
931 3d53ba18 Gerd Hoffmann
        break;
932 8d3628ff Gerd Hoffmann
    case START_STOP:
933 68bb01f3 Markus Armbruster
        if (scsi_disk_emulate_start_stop(r) < 0) {
934 68bb01f3 Markus Armbruster
            return -1;
935 68bb01f3 Markus Armbruster
        }
936 5f71d32f Hannes Reinecke
        break;
937 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
938 81b1008d Markus Armbruster
        s->tray_locked = req->cmd.buf[4] & 1;
939 025e849a Markus Armbruster
        bdrv_lock_medium(s->bs, req->cmd.buf[4] & 1);
940 5f71d32f Hannes Reinecke
        break;
941 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
942 e7e25e32 Gerd Hoffmann
        /* The normal LEN field for this command is zero.  */
943 5f71d32f Hannes Reinecke
        memset(outbuf, 0, 8);
944 5f71d32f Hannes Reinecke
        bdrv_get_geometry(s->bs, &nb_sectors);
945 f01b5931 Paolo Bonzini
        if (!nb_sectors) {
946 e7e25e32 Gerd Hoffmann
            goto not_ready;
947 f01b5931 Paolo Bonzini
        }
948 e7e25e32 Gerd Hoffmann
        nb_sectors /= s->cluster_size;
949 e7e25e32 Gerd Hoffmann
        /* Returned value is the address of the last sector.  */
950 e7e25e32 Gerd Hoffmann
        nb_sectors--;
951 e7e25e32 Gerd Hoffmann
        /* Remember the new size for read/write sanity checking. */
952 e7e25e32 Gerd Hoffmann
        s->max_lba = nb_sectors;
953 e7e25e32 Gerd Hoffmann
        /* Clip to 2TB, instead of returning capacity modulo 2TB. */
954 f01b5931 Paolo Bonzini
        if (nb_sectors > UINT32_MAX) {
955 e7e25e32 Gerd Hoffmann
            nb_sectors = UINT32_MAX;
956 f01b5931 Paolo Bonzini
        }
957 e7e25e32 Gerd Hoffmann
        outbuf[0] = (nb_sectors >> 24) & 0xff;
958 e7e25e32 Gerd Hoffmann
        outbuf[1] = (nb_sectors >> 16) & 0xff;
959 e7e25e32 Gerd Hoffmann
        outbuf[2] = (nb_sectors >> 8) & 0xff;
960 e7e25e32 Gerd Hoffmann
        outbuf[3] = nb_sectors & 0xff;
961 e7e25e32 Gerd Hoffmann
        outbuf[4] = 0;
962 e7e25e32 Gerd Hoffmann
        outbuf[5] = 0;
963 e7e25e32 Gerd Hoffmann
        outbuf[6] = s->cluster_size * 2;
964 e7e25e32 Gerd Hoffmann
        outbuf[7] = 0;
965 e7e25e32 Gerd Hoffmann
        buflen = 8;
966 5f71d32f Hannes Reinecke
        break;
967 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
968 38215553 Gerd Hoffmann
        memset(outbuf, 0, 8);
969 38215553 Gerd Hoffmann
        /* ??? This should probably return much more information.  For now
970 38215553 Gerd Hoffmann
           just return the basic header indicating the CD-ROM profile.  */
971 38215553 Gerd Hoffmann
        outbuf[7] = 8; // CD-ROM
972 38215553 Gerd Hoffmann
        buflen = 8;
973 38215553 Gerd Hoffmann
        break;
974 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
975 5dd90e2a Gerd Hoffmann
        /* Service Action In subcommands. */
976 f6515262 Paolo Bonzini
        if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
977 5dd90e2a Gerd Hoffmann
            DPRINTF("SAI READ CAPACITY(16)\n");
978 5dd90e2a Gerd Hoffmann
            memset(outbuf, 0, req->cmd.xfer);
979 428c149b Christoph Hellwig
            bdrv_get_geometry(s->bs, &nb_sectors);
980 f01b5931 Paolo Bonzini
            if (!nb_sectors) {
981 5dd90e2a Gerd Hoffmann
                goto not_ready;
982 f01b5931 Paolo Bonzini
            }
983 5dd90e2a Gerd Hoffmann
            nb_sectors /= s->cluster_size;
984 5dd90e2a Gerd Hoffmann
            /* Returned value is the address of the last sector.  */
985 5dd90e2a Gerd Hoffmann
            nb_sectors--;
986 5dd90e2a Gerd Hoffmann
            /* Remember the new size for read/write sanity checking. */
987 5dd90e2a Gerd Hoffmann
            s->max_lba = nb_sectors;
988 5dd90e2a Gerd Hoffmann
            outbuf[0] = (nb_sectors >> 56) & 0xff;
989 5dd90e2a Gerd Hoffmann
            outbuf[1] = (nb_sectors >> 48) & 0xff;
990 5dd90e2a Gerd Hoffmann
            outbuf[2] = (nb_sectors >> 40) & 0xff;
991 5dd90e2a Gerd Hoffmann
            outbuf[3] = (nb_sectors >> 32) & 0xff;
992 5dd90e2a Gerd Hoffmann
            outbuf[4] = (nb_sectors >> 24) & 0xff;
993 5dd90e2a Gerd Hoffmann
            outbuf[5] = (nb_sectors >> 16) & 0xff;
994 5dd90e2a Gerd Hoffmann
            outbuf[6] = (nb_sectors >> 8) & 0xff;
995 5dd90e2a Gerd Hoffmann
            outbuf[7] = nb_sectors & 0xff;
996 5dd90e2a Gerd Hoffmann
            outbuf[8] = 0;
997 5dd90e2a Gerd Hoffmann
            outbuf[9] = 0;
998 5dd90e2a Gerd Hoffmann
            outbuf[10] = s->cluster_size * 2;
999 5dd90e2a Gerd Hoffmann
            outbuf[11] = 0;
1000 ee3659e3 Christoph Hellwig
            outbuf[12] = 0;
1001 ee3659e3 Christoph Hellwig
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
1002 ea3bd56f Christoph Hellwig
1003 ea3bd56f Christoph Hellwig
            /* set TPE bit if the format supports discard */
1004 ea3bd56f Christoph Hellwig
            if (s->qdev.conf.discard_granularity) {
1005 ea3bd56f Christoph Hellwig
                outbuf[14] = 0x80;
1006 ea3bd56f Christoph Hellwig
            }
1007 ea3bd56f Christoph Hellwig
1008 5dd90e2a Gerd Hoffmann
            /* Protection, exponent and lowest lba field left blank. */
1009 5dd90e2a Gerd Hoffmann
            buflen = req->cmd.xfer;
1010 5dd90e2a Gerd Hoffmann
            break;
1011 5dd90e2a Gerd Hoffmann
        }
1012 5dd90e2a Gerd Hoffmann
        DPRINTF("Unsupported Service Action In\n");
1013 5dd90e2a Gerd Hoffmann
        goto illegal_request;
1014 5e30a07d Hannes Reinecke
    case VERIFY_10:
1015 88f8a5ed Gerd Hoffmann
        break;
1016 aa5dbdc1 Gerd Hoffmann
    default:
1017 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1018 a1f0cce2 Hannes Reinecke
        return -1;
1019 aa5dbdc1 Gerd Hoffmann
    }
1020 aa5dbdc1 Gerd Hoffmann
    return buflen;
1021 aa5dbdc1 Gerd Hoffmann
1022 aa5dbdc1 Gerd Hoffmann
not_ready:
1023 a1aff5bf Markus Armbruster
    if (s->tray_open || !bdrv_is_inserted(s->bs)) {
1024 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1025 a1f0cce2 Hannes Reinecke
    } else {
1026 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1027 a1f0cce2 Hannes Reinecke
    }
1028 8af7a3ab Kevin Wolf
    return -1;
1029 aa5dbdc1 Gerd Hoffmann
1030 aa5dbdc1 Gerd Hoffmann
illegal_request:
1031 cfc606da Paolo Bonzini
    if (r->req.status == -1) {
1032 cfc606da Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1033 cfc606da Paolo Bonzini
    }
1034 8af7a3ab Kevin Wolf
    return -1;
1035 aa5dbdc1 Gerd Hoffmann
}
1036 aa5dbdc1 Gerd Hoffmann
1037 2e5d83bb pbrook
/* Execute a scsi command.  Returns the length of the data expected by the
1038 2e5d83bb pbrook
   command.  This will be Positive for data transfers from the device
1039 2e5d83bb pbrook
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
1040 2e5d83bb pbrook
   and zero if the command does not transfer any data.  */
1041 2e5d83bb pbrook
1042 5c6c0e51 Hannes Reinecke
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
1043 2e5d83bb pbrook
{
1044 5c6c0e51 Hannes Reinecke
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1045 5c6c0e51 Hannes Reinecke
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1046 ad2d30f7 Paolo Bonzini
    int32_t len;
1047 a917d384 pbrook
    uint8_t command;
1048 aa5dbdc1 Gerd Hoffmann
    int rc;
1049 a917d384 pbrook
1050 a917d384 pbrook
    command = buf[0];
1051 653c1c3f Hannes Reinecke
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
1052 2dd791b6 Hannes Reinecke
1053 2e5d83bb pbrook
#ifdef DEBUG_SCSI
1054 2e5d83bb pbrook
    {
1055 2e5d83bb pbrook
        int i;
1056 2dd791b6 Hannes Reinecke
        for (i = 1; i < r->req.cmd.len; i++) {
1057 2e5d83bb pbrook
            printf(" 0x%02x", buf[i]);
1058 2e5d83bb pbrook
        }
1059 2e5d83bb pbrook
        printf("\n");
1060 2e5d83bb pbrook
    }
1061 2e5d83bb pbrook
#endif
1062 aa5dbdc1 Gerd Hoffmann
1063 a917d384 pbrook
    switch (command) {
1064 ebf46023 Gerd Hoffmann
    case TEST_UNIT_READY:
1065 0b06c059 Gerd Hoffmann
    case INQUIRY:
1066 ebddfcbe Gerd Hoffmann
    case MODE_SENSE:
1067 ebddfcbe Gerd Hoffmann
    case MODE_SENSE_10:
1068 3d53ba18 Gerd Hoffmann
    case RESERVE:
1069 3d53ba18 Gerd Hoffmann
    case RESERVE_10:
1070 3d53ba18 Gerd Hoffmann
    case RELEASE:
1071 3d53ba18 Gerd Hoffmann
    case RELEASE_10:
1072 8d3628ff Gerd Hoffmann
    case START_STOP:
1073 c68b9f34 Gerd Hoffmann
    case ALLOW_MEDIUM_REMOVAL:
1074 5e30a07d Hannes Reinecke
    case READ_CAPACITY_10:
1075 02880f43 Gerd Hoffmann
    case READ_TOC:
1076 38215553 Gerd Hoffmann
    case GET_CONFIGURATION:
1077 f6515262 Paolo Bonzini
    case SERVICE_ACTION_IN_16:
1078 5e30a07d Hannes Reinecke
    case VERIFY_10:
1079 7285477a Paolo Bonzini
        rc = scsi_disk_emulate_command(r);
1080 8af7a3ab Kevin Wolf
        if (rc < 0) {
1081 0b06c059 Gerd Hoffmann
            return 0;
1082 aa5dbdc1 Gerd Hoffmann
        }
1083 8af7a3ab Kevin Wolf
1084 8af7a3ab Kevin Wolf
        r->iov.iov_len = rc;
1085 0b06c059 Gerd Hoffmann
        break;
1086 0a4ac106 Paolo Bonzini
    case SYNCHRONIZE_CACHE:
1087 0a4ac106 Paolo Bonzini
        bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1088 0a4ac106 Paolo Bonzini
        r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r);
1089 0a4ac106 Paolo Bonzini
        if (r->req.aiocb == NULL) {
1090 0a4ac106 Paolo Bonzini
            scsi_flush_complete(r, -EIO);
1091 0a4ac106 Paolo Bonzini
        }
1092 0a4ac106 Paolo Bonzini
        return 0;
1093 ebf46023 Gerd Hoffmann
    case READ_6:
1094 ebf46023 Gerd Hoffmann
    case READ_10:
1095 bd536cf3 Gerd Hoffmann
    case READ_12:
1096 bd536cf3 Gerd Hoffmann
    case READ_16:
1097 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1098 2dd791b6 Hannes Reinecke
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
1099 f01b5931 Paolo Bonzini
        if (r->req.cmd.lba > s->max_lba) {
1100 274fb0e1 aliguori
            goto illegal_lba;
1101 f01b5931 Paolo Bonzini
        }
1102 2dd791b6 Hannes Reinecke
        r->sector = r->req.cmd.lba * s->cluster_size;
1103 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
1104 2e5d83bb pbrook
        break;
1105 ebf46023 Gerd Hoffmann
    case WRITE_6:
1106 ebf46023 Gerd Hoffmann
    case WRITE_10:
1107 bd536cf3 Gerd Hoffmann
    case WRITE_12:
1108 bd536cf3 Gerd Hoffmann
    case WRITE_16:
1109 5e30a07d Hannes Reinecke
    case WRITE_VERIFY_10:
1110 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_12:
1111 ebef0bbb Bernhard Kohl
    case WRITE_VERIFY_16:
1112 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1113 ebef0bbb Bernhard Kohl
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1114 2dd791b6 Hannes Reinecke
                (command & 0xe) == 0xe ? "And Verify " : "",
1115 2dd791b6 Hannes Reinecke
                r->req.cmd.lba, len);
1116 f01b5931 Paolo Bonzini
        if (r->req.cmd.lba > s->max_lba) {
1117 274fb0e1 aliguori
            goto illegal_lba;
1118 f01b5931 Paolo Bonzini
        }
1119 2dd791b6 Hannes Reinecke
        r->sector = r->req.cmd.lba * s->cluster_size;
1120 a917d384 pbrook
        r->sector_count = len * s->cluster_size;
1121 2e5d83bb pbrook
        break;
1122 ebef0bbb Bernhard Kohl
    case MODE_SELECT:
1123 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1124 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1125 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1126 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 12) {
1127 ebef0bbb Bernhard Kohl
            goto fail;
1128 ebef0bbb Bernhard Kohl
        }
1129 ebef0bbb Bernhard Kohl
        break;
1130 ebef0bbb Bernhard Kohl
    case MODE_SELECT_10:
1131 2dd791b6 Hannes Reinecke
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1132 ebef0bbb Bernhard Kohl
        /* We don't support mode parameter changes.
1133 ebef0bbb Bernhard Kohl
           Allow the mode parameter header + block descriptors only. */
1134 2dd791b6 Hannes Reinecke
        if (r->req.cmd.xfer > 16) {
1135 ebef0bbb Bernhard Kohl
            goto fail;
1136 ebef0bbb Bernhard Kohl
        }
1137 ebef0bbb Bernhard Kohl
        break;
1138 ebef0bbb Bernhard Kohl
    case SEEK_6:
1139 ebef0bbb Bernhard Kohl
    case SEEK_10:
1140 2dd791b6 Hannes Reinecke
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
1141 2dd791b6 Hannes Reinecke
                r->req.cmd.lba);
1142 2dd791b6 Hannes Reinecke
        if (r->req.cmd.lba > s->max_lba) {
1143 ebef0bbb Bernhard Kohl
            goto illegal_lba;
1144 ebef0bbb Bernhard Kohl
        }
1145 ebef0bbb Bernhard Kohl
        break;
1146 ea3bd56f Christoph Hellwig
    case WRITE_SAME_16:
1147 5c6c0e51 Hannes Reinecke
        len = r->req.cmd.xfer / s->qdev.blocksize;
1148 ea3bd56f Christoph Hellwig
1149 ea3bd56f Christoph Hellwig
        DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
1150 ea3bd56f Christoph Hellwig
                r->req.cmd.lba, len);
1151 ea3bd56f Christoph Hellwig
1152 ea3bd56f Christoph Hellwig
        if (r->req.cmd.lba > s->max_lba) {
1153 ea3bd56f Christoph Hellwig
            goto illegal_lba;
1154 ea3bd56f Christoph Hellwig
        }
1155 ea3bd56f Christoph Hellwig
1156 ea3bd56f Christoph Hellwig
        /*
1157 ea3bd56f Christoph Hellwig
         * We only support WRITE SAME with the unmap bit set for now.
1158 ea3bd56f Christoph Hellwig
         */
1159 ea3bd56f Christoph Hellwig
        if (!(buf[1] & 0x8)) {
1160 ea3bd56f Christoph Hellwig
            goto fail;
1161 ea3bd56f Christoph Hellwig
        }
1162 ea3bd56f Christoph Hellwig
1163 ea3bd56f Christoph Hellwig
        rc = bdrv_discard(s->bs, r->req.cmd.lba * s->cluster_size,
1164 ea3bd56f Christoph Hellwig
                          len * s->cluster_size);
1165 ea3bd56f Christoph Hellwig
        if (rc < 0) {
1166 ea3bd56f Christoph Hellwig
            /* XXX: better error code ?*/
1167 ea3bd56f Christoph Hellwig
            goto fail;
1168 ea3bd56f Christoph Hellwig
        }
1169 ea3bd56f Christoph Hellwig
1170 ea3bd56f Christoph Hellwig
        break;
1171 739df215 Paolo Bonzini
    case REQUEST_SENSE:
1172 739df215 Paolo Bonzini
        abort();
1173 2e5d83bb pbrook
    default:
1174 2dd791b6 Hannes Reinecke
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1175 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1176 a1f0cce2 Hannes Reinecke
        return 0;
1177 2e5d83bb pbrook
    fail:
1178 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1179 2dd791b6 Hannes Reinecke
        return 0;
1180 274fb0e1 aliguori
    illegal_lba:
1181 b45ef674 Paolo Bonzini
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1182 274fb0e1 aliguori
        return 0;
1183 2e5d83bb pbrook
    }
1184 c87c0672 aliguori
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1185 b45ef674 Paolo Bonzini
        scsi_req_complete(&r->req, GOOD);
1186 a917d384 pbrook
    }
1187 c87c0672 aliguori
    len = r->sector_count * 512 + r->iov.iov_len;
1188 efb9ee02 Hannes Reinecke
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1189 efb9ee02 Hannes Reinecke
        return -len;
1190 a917d384 pbrook
    } else {
1191 f01b5931 Paolo Bonzini
        if (!r->sector_count) {
1192 a917d384 pbrook
            r->sector_count = -1;
1193 f01b5931 Paolo Bonzini
        }
1194 efb9ee02 Hannes Reinecke
        return len;
1195 2e5d83bb pbrook
    }
1196 2e5d83bb pbrook
}
1197 2e5d83bb pbrook
1198 e9447f35 Jan Kiszka
static void scsi_disk_reset(DeviceState *dev)
1199 e9447f35 Jan Kiszka
{
1200 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1201 e9447f35 Jan Kiszka
    uint64_t nb_sectors;
1202 e9447f35 Jan Kiszka
1203 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
1204 e9447f35 Jan Kiszka
1205 e9447f35 Jan Kiszka
    bdrv_get_geometry(s->bs, &nb_sectors);
1206 e9447f35 Jan Kiszka
    nb_sectors /= s->cluster_size;
1207 e9447f35 Jan Kiszka
    if (nb_sectors) {
1208 e9447f35 Jan Kiszka
        nb_sectors--;
1209 e9447f35 Jan Kiszka
    }
1210 e9447f35 Jan Kiszka
    s->max_lba = nb_sectors;
1211 e9447f35 Jan Kiszka
}
1212 e9447f35 Jan Kiszka
1213 e9447f35 Jan Kiszka
static void scsi_destroy(SCSIDevice *dev)
1214 e9447f35 Jan Kiszka
{
1215 e9447f35 Jan Kiszka
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1216 e9447f35 Jan Kiszka
1217 c7b48872 Paolo Bonzini
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1218 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(s->qdev.conf.bs);
1219 56a14938 Gerd Hoffmann
}
1220 56a14938 Gerd Hoffmann
1221 7d4b4ba5 Markus Armbruster
static void scsi_cd_change_media_cb(void *opaque, bool load)
1222 2c6942fa Markus Armbruster
{
1223 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = opaque;
1224 8a9c16f6 Paolo Bonzini
1225 8a9c16f6 Paolo Bonzini
    /*
1226 8a9c16f6 Paolo Bonzini
     * When a CD gets changed, we have to report an ejected state and
1227 8a9c16f6 Paolo Bonzini
     * then a loaded state to guests so that they detect tray
1228 8a9c16f6 Paolo Bonzini
     * open/close and media change events.  Guests that do not use
1229 8a9c16f6 Paolo Bonzini
     * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1230 8a9c16f6 Paolo Bonzini
     * states rely on this behavior.
1231 8a9c16f6 Paolo Bonzini
     *
1232 8a9c16f6 Paolo Bonzini
     * media_changed governs the state machine used for unit attention
1233 8a9c16f6 Paolo Bonzini
     * report.  media_event is used by GET EVENT STATUS NOTIFICATION.
1234 8a9c16f6 Paolo Bonzini
     */
1235 8a9c16f6 Paolo Bonzini
    s->media_changed = load;
1236 8a9c16f6 Paolo Bonzini
    s->tray_open = !load;
1237 8a9c16f6 Paolo Bonzini
    s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
1238 2c6942fa Markus Armbruster
}
1239 2c6942fa Markus Armbruster
1240 e4def80b Markus Armbruster
static bool scsi_cd_is_tray_open(void *opaque)
1241 e4def80b Markus Armbruster
{
1242 e4def80b Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_open;
1243 e4def80b Markus Armbruster
}
1244 e4def80b Markus Armbruster
1245 f107639a Markus Armbruster
static bool scsi_cd_is_medium_locked(void *opaque)
1246 f107639a Markus Armbruster
{
1247 f107639a Markus Armbruster
    return ((SCSIDiskState *)opaque)->tray_locked;
1248 f107639a Markus Armbruster
}
1249 f107639a Markus Armbruster
1250 f107639a Markus Armbruster
static const BlockDevOps scsi_cd_block_ops = {
1251 2c6942fa Markus Armbruster
    .change_media_cb = scsi_cd_change_media_cb,
1252 e4def80b Markus Armbruster
    .is_tray_open = scsi_cd_is_tray_open,
1253 f107639a Markus Armbruster
    .is_medium_locked = scsi_cd_is_medium_locked,
1254 f107639a Markus Armbruster
};
1255 f107639a Markus Armbruster
1256 8a9c16f6 Paolo Bonzini
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
1257 8a9c16f6 Paolo Bonzini
{
1258 8a9c16f6 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1259 8a9c16f6 Paolo Bonzini
    if (s->media_changed) {
1260 8a9c16f6 Paolo Bonzini
        s->media_changed = false;
1261 8a9c16f6 Paolo Bonzini
        s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
1262 8a9c16f6 Paolo Bonzini
    }
1263 8a9c16f6 Paolo Bonzini
}
1264 8a9c16f6 Paolo Bonzini
1265 f37bd73b Hannes Reinecke
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
1266 2e5d83bb pbrook
{
1267 d52affa7 Gerd Hoffmann
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1268 f8b6cc00 Markus Armbruster
    DriveInfo *dinfo;
1269 2e5d83bb pbrook
1270 f8b6cc00 Markus Armbruster
    if (!s->qdev.conf.bs) {
1271 1ecda02b Markus Armbruster
        error_report("scsi-disk: drive property not set");
1272 d52affa7 Gerd Hoffmann
        return -1;
1273 d52affa7 Gerd Hoffmann
    }
1274 f8b6cc00 Markus Armbruster
    s->bs = s->qdev.conf.bs;
1275 d52affa7 Gerd Hoffmann
1276 f37bd73b Hannes Reinecke
    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
1277 98f28ad7 Markus Armbruster
        error_report("Device needs media, but drive is empty");
1278 98f28ad7 Markus Armbruster
        return -1;
1279 98f28ad7 Markus Armbruster
    }
1280 98f28ad7 Markus Armbruster
1281 a0fef654 Markus Armbruster
    if (!s->serial) {
1282 f8b6cc00 Markus Armbruster
        /* try to fall back to value set with legacy -drive serial=... */
1283 f8b6cc00 Markus Armbruster
        dinfo = drive_get_by_blockdev(s->bs);
1284 3e1c0c9a Hannes Reinecke
        if (*dinfo->serial) {
1285 7267c094 Anthony Liguori
            s->serial = g_strdup(dinfo->serial);
1286 3e1c0c9a Hannes Reinecke
        }
1287 a0fef654 Markus Armbruster
    }
1288 a0fef654 Markus Armbruster
1289 552fee93 Markus Armbruster
    if (!s->version) {
1290 7267c094 Anthony Liguori
        s->version = g_strdup(QEMU_VERSION);
1291 552fee93 Markus Armbruster
    }
1292 552fee93 Markus Armbruster
1293 32bb404a Markus Armbruster
    if (bdrv_is_sg(s->bs)) {
1294 1ecda02b Markus Armbruster
        error_report("scsi-disk: unwanted /dev/sg*");
1295 32bb404a Markus Armbruster
        return -1;
1296 32bb404a Markus Armbruster
    }
1297 32bb404a Markus Armbruster
1298 f37bd73b Hannes Reinecke
    if (scsi_type == TYPE_ROM) {
1299 f107639a Markus Armbruster
        bdrv_set_dev_ops(s->bs, &scsi_cd_block_ops, s);
1300 8cfacf07 Christoph Hellwig
        s->qdev.blocksize = 2048;
1301 f37bd73b Hannes Reinecke
    } else if (scsi_type == TYPE_DISK) {
1302 8cfacf07 Christoph Hellwig
        s->qdev.blocksize = s->qdev.conf.logical_block_size;
1303 f37bd73b Hannes Reinecke
    } else {
1304 f37bd73b Hannes Reinecke
        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
1305 f37bd73b Hannes Reinecke
        return -1;
1306 2e5d83bb pbrook
    }
1307 8cfacf07 Christoph Hellwig
    s->cluster_size = s->qdev.blocksize / 512;
1308 7b6f9300 Markus Armbruster
    bdrv_set_buffer_alignment(s->bs, s->qdev.blocksize);
1309 8cfacf07 Christoph Hellwig
1310 f37bd73b Hannes Reinecke
    s->qdev.type = scsi_type;
1311 ea8a5d7f aliguori
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
1312 9fb118e6 Luiz Capitulino
    bdrv_iostatus_enable(s->bs);
1313 1ca4d09a Gleb Natapov
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
1314 d52affa7 Gerd Hoffmann
    return 0;
1315 d52affa7 Gerd Hoffmann
}
1316 d52affa7 Gerd Hoffmann
1317 b443ae67 Markus Armbruster
static int scsi_hd_initfn(SCSIDevice *dev)
1318 b443ae67 Markus Armbruster
{
1319 f37bd73b Hannes Reinecke
    return scsi_initfn(dev, TYPE_DISK);
1320 b443ae67 Markus Armbruster
}
1321 b443ae67 Markus Armbruster
1322 b443ae67 Markus Armbruster
static int scsi_cd_initfn(SCSIDevice *dev)
1323 b443ae67 Markus Armbruster
{
1324 f37bd73b Hannes Reinecke
    return scsi_initfn(dev, TYPE_ROM);
1325 b443ae67 Markus Armbruster
}
1326 b443ae67 Markus Armbruster
1327 b443ae67 Markus Armbruster
static int scsi_disk_initfn(SCSIDevice *dev)
1328 b443ae67 Markus Armbruster
{
1329 95b5edcd Markus Armbruster
    DriveInfo *dinfo;
1330 f37bd73b Hannes Reinecke
    uint8_t scsi_type;
1331 b443ae67 Markus Armbruster
1332 b443ae67 Markus Armbruster
    if (!dev->conf.bs) {
1333 f37bd73b Hannes Reinecke
        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
1334 b443ae67 Markus Armbruster
    } else {
1335 95b5edcd Markus Armbruster
        dinfo = drive_get_by_blockdev(dev->conf.bs);
1336 f37bd73b Hannes Reinecke
        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
1337 b443ae67 Markus Armbruster
    }
1338 b443ae67 Markus Armbruster
1339 f37bd73b Hannes Reinecke
    return scsi_initfn(dev, scsi_type);
1340 b443ae67 Markus Armbruster
}
1341 b443ae67 Markus Armbruster
1342 8dbd4574 Paolo Bonzini
static SCSIReqOps scsi_disk_reqops = {
1343 8dbd4574 Paolo Bonzini
    .size         = sizeof(SCSIDiskReq),
1344 12010e7b Paolo Bonzini
    .free_req     = scsi_free_request,
1345 12010e7b Paolo Bonzini
    .send_command = scsi_send_command,
1346 12010e7b Paolo Bonzini
    .read_data    = scsi_read_data,
1347 12010e7b Paolo Bonzini
    .write_data   = scsi_write_data,
1348 12010e7b Paolo Bonzini
    .cancel_io    = scsi_cancel_io,
1349 12010e7b Paolo Bonzini
    .get_buf      = scsi_get_buf,
1350 8dbd4574 Paolo Bonzini
};
1351 8dbd4574 Paolo Bonzini
1352 8dbd4574 Paolo Bonzini
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
1353 8dbd4574 Paolo Bonzini
                                     uint32_t lun, void *hba_private)
1354 8dbd4574 Paolo Bonzini
{
1355 8dbd4574 Paolo Bonzini
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1356 8dbd4574 Paolo Bonzini
    SCSIRequest *req;
1357 8dbd4574 Paolo Bonzini
1358 8dbd4574 Paolo Bonzini
    req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
1359 8dbd4574 Paolo Bonzini
    return req;
1360 8dbd4574 Paolo Bonzini
}
1361 8dbd4574 Paolo Bonzini
1362 b443ae67 Markus Armbruster
#define DEFINE_SCSI_DISK_PROPERTIES()                           \
1363 b443ae67 Markus Armbruster
    DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),          \
1364 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
1365 b443ae67 Markus Armbruster
    DEFINE_PROP_STRING("serial",  SCSIDiskState, serial)
1366 b443ae67 Markus Armbruster
1367 b443ae67 Markus Armbruster
static SCSIDeviceInfo scsi_disk_info[] = {
1368 b443ae67 Markus Armbruster
    {
1369 b443ae67 Markus Armbruster
        .qdev.name    = "scsi-hd",
1370 b443ae67 Markus Armbruster
        .qdev.fw_name = "disk",
1371 b443ae67 Markus Armbruster
        .qdev.desc    = "virtual SCSI disk",
1372 b443ae67 Markus Armbruster
        .qdev.size    = sizeof(SCSIDiskState),
1373 b443ae67 Markus Armbruster
        .qdev.reset   = scsi_disk_reset,
1374 b443ae67 Markus Armbruster
        .init         = scsi_hd_initfn,
1375 b443ae67 Markus Armbruster
        .destroy      = scsi_destroy,
1376 5c6c0e51 Hannes Reinecke
        .alloc_req    = scsi_new_request,
1377 8a9c16f6 Paolo Bonzini
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1378 b443ae67 Markus Armbruster
        .qdev.props   = (Property[]) {
1379 b443ae67 Markus Armbruster
            DEFINE_SCSI_DISK_PROPERTIES(),
1380 b443ae67 Markus Armbruster
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1381 b443ae67 Markus Armbruster
            DEFINE_PROP_END_OF_LIST(),
1382 b443ae67 Markus Armbruster
        }
1383 b443ae67 Markus Armbruster
    },{
1384 b443ae67 Markus Armbruster
        .qdev.name    = "scsi-cd",
1385 b443ae67 Markus Armbruster
        .qdev.fw_name = "disk",
1386 b443ae67 Markus Armbruster
        .qdev.desc    = "virtual SCSI CD-ROM",
1387 b443ae67 Markus Armbruster
        .qdev.size    = sizeof(SCSIDiskState),
1388 b443ae67 Markus Armbruster
        .qdev.reset   = scsi_disk_reset,
1389 b443ae67 Markus Armbruster
        .init         = scsi_cd_initfn,
1390 b443ae67 Markus Armbruster
        .destroy      = scsi_destroy,
1391 5c6c0e51 Hannes Reinecke
        .alloc_req    = scsi_new_request,
1392 8a9c16f6 Paolo Bonzini
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1393 b443ae67 Markus Armbruster
        .qdev.props   = (Property[]) {
1394 b443ae67 Markus Armbruster
            DEFINE_SCSI_DISK_PROPERTIES(),
1395 b443ae67 Markus Armbruster
            DEFINE_PROP_END_OF_LIST(),
1396 b443ae67 Markus Armbruster
        },
1397 b443ae67 Markus Armbruster
    },{
1398 b443ae67 Markus Armbruster
        .qdev.name    = "scsi-disk", /* legacy -device scsi-disk */
1399 b443ae67 Markus Armbruster
        .qdev.fw_name = "disk",
1400 b443ae67 Markus Armbruster
        .qdev.desc    = "virtual SCSI disk or CD-ROM (legacy)",
1401 b443ae67 Markus Armbruster
        .qdev.size    = sizeof(SCSIDiskState),
1402 b443ae67 Markus Armbruster
        .qdev.reset   = scsi_disk_reset,
1403 b443ae67 Markus Armbruster
        .init         = scsi_disk_initfn,
1404 b443ae67 Markus Armbruster
        .destroy      = scsi_destroy,
1405 5c6c0e51 Hannes Reinecke
        .alloc_req    = scsi_new_request,
1406 8a9c16f6 Paolo Bonzini
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1407 b443ae67 Markus Armbruster
        .qdev.props   = (Property[]) {
1408 b443ae67 Markus Armbruster
            DEFINE_SCSI_DISK_PROPERTIES(),
1409 b443ae67 Markus Armbruster
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1410 b443ae67 Markus Armbruster
            DEFINE_PROP_END_OF_LIST(),
1411 b443ae67 Markus Armbruster
        }
1412 b443ae67 Markus Armbruster
    }
1413 d52affa7 Gerd Hoffmann
};
1414 d52affa7 Gerd Hoffmann
1415 d52affa7 Gerd Hoffmann
static void scsi_disk_register_devices(void)
1416 d52affa7 Gerd Hoffmann
{
1417 b443ae67 Markus Armbruster
    int i;
1418 b443ae67 Markus Armbruster
1419 b443ae67 Markus Armbruster
    for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) {
1420 b443ae67 Markus Armbruster
        scsi_qdev_register(&scsi_disk_info[i]);
1421 b443ae67 Markus Armbruster
    }
1422 8ccc2ace ths
}
1423 d52affa7 Gerd Hoffmann
device_init(scsi_disk_register_devices)