blob: 49b5686a92fab515b4ab73a17637f89be93d88ce [file] [log] [blame]
pbrook2e5d83b2006-05-25 23:58:51 +00001/*
2 * SCSI Device emulation
3 *
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
6 *
7 * Written by Paul Brook
Artyom Tarasenkoad3cea42009-12-13 11:32:36 +01008 * Modifications:
9 * 2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
10 * when the allocation length of CDB is smaller
11 * than 36.
12 * 2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
13 * MODE SENSE response.
pbrook2e5d83b2006-05-25 23:58:51 +000014 *
Matthew Fernandez8e31bf32011-06-26 12:21:35 +100015 * This code is licensed under the LGPL.
pbrooka917d382006-08-29 04:52:16 +000016 *
17 * Note that this file only handles the SCSI architecture model and device
balrog1d4db892008-02-03 04:05:50 +000018 * commands. Emulation of interface/link layer protocols is handled by
19 * the host adapter emulator.
pbrook2e5d83b2006-05-25 23:58:51 +000020 */
21
22//#define DEBUG_SCSI
23
24#ifdef DEBUG_SCSI
Blue Swirl001faf32009-05-13 17:53:17 +000025#define DPRINTF(fmt, ...) \
26do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
pbrook2e5d83b2006-05-25 23:58:51 +000027#else
Blue Swirl001faf32009-05-13 17:53:17 +000028#define DPRINTF(fmt, ...) do {} while(0)
pbrook2e5d83b2006-05-25 23:58:51 +000029#endif
30
pbrook87ecb682007-11-17 17:14:51 +000031#include "qemu-common.h"
Markus Armbruster2f792012010-02-18 16:24:31 +010032#include "qemu-error.h"
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010033#include "scsi.h"
Gerd Hoffmann0d65e1f2009-11-26 15:33:53 +010034#include "scsi-defs.h"
Markus Armbruster666daa62010-06-02 18:48:27 +020035#include "sysemu.h"
Blue Swirl24463332010-08-24 15:22:24 +000036#include "blockdev.h"
Markus Armbruster9db1c0f2012-07-10 11:12:31 +020037#include "hw/block-common.h"
Paolo Bonzini5d0d2462011-10-12 15:12:14 +020038#include "dma.h"
blueswir122864252008-10-11 09:33:03 +000039
Paolo Bonzini336a6912011-10-25 12:53:37 +020040#ifdef __linux
41#include <scsi/sg.h>
42#endif
43
aurel32f0f72ff2008-10-01 21:46:23 +000044#define SCSI_DMA_BUF_SIZE 131072
balrog57575052008-12-07 03:12:54 +000045#define SCSI_MAX_INQUIRY_LEN 256
Paolo Bonzini380feaf2012-07-10 15:02:55 +020046#define SCSI_MAX_MODE_LEN 256
pbrooka917d382006-08-29 04:52:16 +000047
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020048typedef struct SCSIDiskState SCSIDiskState;
49
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010050typedef struct SCSIDiskReq {
51 SCSIRequest req;
pbrooka917d382006-08-29 04:52:16 +000052 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
aliguorie035b432009-01-28 21:58:22 +000053 uint64_t sector;
54 uint32_t sector_count;
Paolo Bonzini72854772011-09-16 16:40:04 +020055 uint32_t buflen;
Paolo Bonzinia0e66a62012-04-19 11:51:42 +020056 bool started;
aliguoric87c0672009-04-07 18:43:20 +000057 struct iovec iov;
58 QEMUIOVector qiov;
Christoph Hellwiga597e792011-08-25 08:26:01 +020059 BlockAcctCookie acct;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010060} SCSIDiskReq;
pbrooka917d382006-08-29 04:52:16 +000061
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020062#define SCSI_DISK_F_REMOVABLE 0
Paolo Bonzinida8365d2012-05-01 10:25:16 +020063#define SCSI_DISK_F_DPOFUA 1
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020064
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020065struct SCSIDiskState
pbrook2e5d83b2006-05-25 23:58:51 +000066{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020067 SCSIDevice qdev;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020068 uint32_t features;
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +020069 bool media_changed;
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +020070 bool media_event;
Paolo Bonzini4480de12011-10-25 12:53:40 +020071 bool eject_request;
Paolo Bonzini27395ad2012-05-15 12:46:09 +020072 uint64_t wwn;
Markus Armbruster213189a2009-07-28 14:33:41 -040073 QEMUBH *bh;
Gerd Hoffmann383b4d92010-01-14 14:44:13 +010074 char *version;
Markus Armbrustera0fef652010-06-01 20:32:34 +020075 char *serial;
Dmitry Fleytman353815a2012-07-06 22:03:35 -070076 char *vendor;
77 char *product;
Markus Armbrusterece0d5e2011-09-06 18:58:40 +020078 bool tray_open;
Markus Armbruster81b10082011-09-06 18:58:44 +020079 bool tray_locked;
pbrook2e5d83b2006-05-25 23:58:51 +000080};
81
Paolo Bonzini71544d32011-10-25 12:53:36 +020082static int scsi_handle_rw_error(SCSIDiskReq *r, int error);
Kevin Wolf5dba48a2010-10-25 14:52:21 +020083
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020084static void scsi_free_request(SCSIRequest *req)
pbrook4d611c92006-08-12 01:04:27 +000085{
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020086 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
87
Paolo Bonzini72854772011-09-16 16:40:04 +020088 if (r->iov.iov_base) {
89 qemu_vfree(r->iov.iov_base);
90 }
pbrooka917d382006-08-29 04:52:16 +000091}
92
Paolo Bonzinib45ef672011-08-03 10:49:07 +020093/* Helper function for command completion with sense. */
94static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
Gerd Hoffmanned3a34a2009-11-26 15:34:00 +010095{
Blue Swirl02fa69b2011-08-20 09:21:42 +000096 DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
97 r->req.tag, sense.key, sense.asc, sense.ascq);
Paolo Bonzinib45ef672011-08-03 10:49:07 +020098 scsi_req_build_sense(&r->req, sense);
99 scsi_req_complete(&r->req, CHECK_CONDITION);
pbrooka917d382006-08-29 04:52:16 +0000100}
101
102/* Cancel a pending data transfer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200103static void scsi_cancel_io(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +0000104{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200105 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
106
107 DPRINTF("Cancel tag=0x%x\n", req->tag);
108 if (r->req.aiocb) {
109 bdrv_aio_cancel(r->req.aiocb);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200110
111 /* This reference was left in by scsi_*_data. We take ownership of
112 * it the moment scsi_req_cancel is called, independent of whether
113 * bdrv_aio_cancel completes the request or not. */
114 scsi_req_unref(&r->req);
pbrooka917d382006-08-29 04:52:16 +0000115 }
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200116 r->req.aiocb = NULL;
pbrook4d611c92006-08-12 01:04:27 +0000117}
118
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500119static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200120{
Paolo Bonzini72854772011-09-16 16:40:04 +0200121 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
122
123 if (!r->iov.iov_base) {
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500124 r->buflen = size;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200125 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +0200126 }
127 r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200128 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
129 return r->qiov.size / 512;
130}
131
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500132static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
133{
134 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
135
136 qemu_put_be64s(f, &r->sector);
137 qemu_put_be32s(f, &r->sector_count);
138 qemu_put_be32s(f, &r->buflen);
Gerd Hoffmann18eef3b2012-05-16 14:20:03 +0200139 if (r->buflen) {
140 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
141 qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
142 } else if (!req->retry) {
143 uint32_t len = r->iov.iov_len;
144 qemu_put_be32s(f, &len);
145 qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
146 }
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500147 }
148}
149
150static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
151{
152 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
153
154 qemu_get_be64s(f, &r->sector);
155 qemu_get_be32s(f, &r->sector_count);
156 qemu_get_be32s(f, &r->buflen);
157 if (r->buflen) {
158 scsi_init_iovec(r, r->buflen);
159 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
160 qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
Gerd Hoffmann18eef3b2012-05-16 14:20:03 +0200161 } else if (!r->req.retry) {
162 uint32_t len;
163 qemu_get_be32s(f, &len);
164 r->iov.iov_len = len;
165 assert(r->iov.iov_len <= r->buflen);
166 qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500167 }
168 }
169
170 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
171}
172
Paolo Bonzinic1b35242012-02-08 10:37:48 +0100173static void scsi_aio_complete(void *opaque, int ret)
Paolo Bonzinib77912a2012-04-19 10:05:04 +0200174{
175 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
176 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
177
Paolo Bonzini46e3f302012-08-09 11:33:26 +0200178 assert(r->req.aiocb != NULL);
179 r->req.aiocb = NULL;
Paolo Bonzinib77912a2012-04-19 10:05:04 +0200180 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
181
182 if (ret < 0) {
183 if (scsi_handle_rw_error(r, -ret)) {
184 goto done;
185 }
186 }
187
188 scsi_req_complete(&r->req, GOOD);
189
190done:
191 if (!r->req.io_canceled) {
192 scsi_req_unref(&r->req);
193 }
194}
195
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200196static bool scsi_is_cmd_fua(SCSICommand *cmd)
197{
198 switch (cmd->buf[0]) {
199 case READ_10:
200 case READ_12:
201 case READ_16:
202 case WRITE_10:
203 case WRITE_12:
204 case WRITE_16:
205 return (cmd->buf[1] & 8) != 0;
206
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +0200207 case VERIFY_10:
208 case VERIFY_12:
209 case VERIFY_16:
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200210 case WRITE_VERIFY_10:
211 case WRITE_VERIFY_12:
212 case WRITE_VERIFY_16:
213 return true;
214
215 case READ_6:
216 case WRITE_6:
217 default:
218 return false;
219 }
220}
221
222static void scsi_write_do_fua(SCSIDiskReq *r)
223{
224 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
225
226 if (scsi_is_cmd_fua(&r->req.cmd)) {
227 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
Paolo Bonzinic1b35242012-02-08 10:37:48 +0100228 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200229 return;
230 }
231
232 scsi_req_complete(&r->req, GOOD);
233 if (!r->req.io_canceled) {
234 scsi_req_unref(&r->req);
235 }
236}
237
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200238static void scsi_dma_complete(void *opaque, int ret)
239{
240 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
241 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
242
Paolo Bonzini46e3f302012-08-09 11:33:26 +0200243 assert(r->req.aiocb != NULL);
244 r->req.aiocb = NULL;
245 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200246
Paolo Bonzini80624c92012-04-19 14:00:24 +0200247 if (ret < 0) {
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200248 if (scsi_handle_rw_error(r, -ret)) {
249 goto done;
250 }
251 }
252
253 r->sector += r->sector_count;
254 r->sector_count = 0;
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200255 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
256 scsi_write_do_fua(r);
257 return;
258 } else {
259 scsi_req_complete(&r->req, GOOD);
260 }
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200261
262done:
Paolo Bonzinib8aba8d2012-04-19 10:09:49 +0200263 if (!r->req.io_canceled) {
264 scsi_req_unref(&r->req);
265 }
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200266}
267
pbrook4d611c92006-08-12 01:04:27 +0000268static void scsi_read_complete(void * opaque, int ret)
269{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100270 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200271 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200272 int n;
pbrook4d611c92006-08-12 01:04:27 +0000273
Paolo Bonzini46e3f302012-08-09 11:33:26 +0200274 assert(r->req.aiocb != NULL);
275 r->req.aiocb = NULL;
276 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200277
Paolo Bonzini80624c92012-04-19 14:00:24 +0200278 if (ret < 0) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200279 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200280 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200281 }
pbrook4d611c92006-08-12 01:04:27 +0000282 }
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200283
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200284 DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
pbrooka917d382006-08-29 04:52:16 +0000285
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200286 n = r->qiov.size / 512;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200287 r->sector += n;
288 r->sector_count -= n;
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200289 scsi_req_data(&r->req, r->qiov.size);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200290
291done:
292 if (!r->req.io_canceled) {
293 scsi_req_unref(&r->req);
294 }
pbrook4d611c92006-08-12 01:04:27 +0000295}
296
Paolo Bonziniac668422012-04-19 11:55:28 +0200297/* Actually issue a read to the block device. */
298static void scsi_do_read(void *opaque, int ret)
299{
300 SCSIDiskReq *r = opaque;
301 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
302 uint32_t n;
303
304 if (r->req.aiocb != NULL) {
305 r->req.aiocb = NULL;
306 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
307 }
308
309 if (ret < 0) {
310 if (scsi_handle_rw_error(r, -ret)) {
311 goto done;
312 }
313 }
314
Paolo Bonzini31e8fd82012-04-24 08:41:04 +0200315 if (r->req.io_canceled) {
316 return;
317 }
318
319 /* The request is used as the AIO opaque value, so add a ref. */
320 scsi_req_ref(&r->req);
321
Paolo Bonziniac668422012-04-19 11:55:28 +0200322 if (r->req.sg) {
323 dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
324 r->req.resid -= r->req.sg->size;
325 r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
326 scsi_dma_complete, r);
327 } else {
328 n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
329 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
330 r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
331 scsi_read_complete, r);
332 }
333
334done:
335 if (!r->req.io_canceled) {
336 scsi_req_unref(&r->req);
337 }
338}
339
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200340/* Read more data from scsi device into buffer. */
341static void scsi_read_data(SCSIRequest *req)
pbrook2e5d83b2006-05-25 23:58:51 +0000342{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200343 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200344 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonziniac668422012-04-19 11:55:28 +0200345 bool first;
pbrook2e5d83b2006-05-25 23:58:51 +0000346
pbrooka917d382006-08-29 04:52:16 +0000347 DPRINTF("Read sector_count=%d\n", r->sector_count);
348 if (r->sector_count == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200349 /* This also clears the sense buffer for REQUEST SENSE. */
350 scsi_req_complete(&r->req, GOOD);
pbrooka917d382006-08-29 04:52:16 +0000351 return;
pbrook2e5d83b2006-05-25 23:58:51 +0000352 }
353
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000354 /* No data transfer may already be in progress */
355 assert(r->req.aiocb == NULL);
356
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200357 /* The request is used as the AIO opaque value, so add a ref. */
358 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200359 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
360 DPRINTF("Data transfer direction invalid\n");
361 scsi_read_complete(r, -EINVAL);
362 return;
363 }
364
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200365 if (s->tray_open) {
366 scsi_read_complete(r, -ENOMEDIUM);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200367 return;
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200368 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200369
Paolo Bonziniac668422012-04-19 11:55:28 +0200370 first = !r->started;
Paolo Bonzinia0e66a62012-04-19 11:51:42 +0200371 r->started = true;
Paolo Bonziniac668422012-04-19 11:55:28 +0200372 if (first && scsi_is_cmd_fua(&r->req.cmd)) {
373 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
374 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_do_read, r);
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200375 } else {
Paolo Bonziniac668422012-04-19 11:55:28 +0200376 scsi_do_read(r, 0);
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200377 }
pbrook2e5d83b2006-05-25 23:58:51 +0000378}
379
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200380/*
381 * scsi_handle_rw_error has two return values. 0 means that the error
382 * must be ignored, 1 means that the error has been processed and the
383 * caller should not do anything else for this request. Note that
384 * scsi_handle_rw_error always manages its reference counts, independent
385 * of the return value.
386 */
Paolo Bonzini71544d32011-10-25 12:53:36 +0200387static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200388{
Paolo Bonzini1ceee0d2012-09-28 17:22:56 +0200389 bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100390 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonzini3e1caa52012-09-28 17:22:57 +0200391 BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error);
aliguoriea8a5d72009-01-22 19:52:21 +0000392
Paolo Bonzini3e1caa52012-09-28 17:22:57 +0200393 if (action == BDRV_ACTION_REPORT) {
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200394 switch (error) {
Paolo Bonzini7e218df2011-09-19 17:19:21 +0200395 case ENOMEDIUM:
396 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
397 break;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200398 case ENOMEM:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200399 scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200400 break;
401 case EINVAL:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200402 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200403 break;
404 default:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200405 scsi_check_condition(r, SENSE_CODE(IO_ERROR));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200406 break;
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200407 }
aliguoriea8a5d72009-01-22 19:52:21 +0000408 }
Paolo Bonzini3e1caa52012-09-28 17:22:57 +0200409 bdrv_error_action(s->qdev.conf.bs, action, is_read, error);
410 if (action == BDRV_ACTION_STOP) {
411 scsi_req_retry(&r->req);
412 }
413 return action != BDRV_ACTION_IGNORE;
aliguoriea8a5d72009-01-22 19:52:21 +0000414}
415
pbrook4d611c92006-08-12 01:04:27 +0000416static void scsi_write_complete(void * opaque, int ret)
417{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100418 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200419 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000420 uint32_t n;
pbrook4d611c92006-08-12 01:04:27 +0000421
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200422 if (r->req.aiocb != NULL) {
423 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200424 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200425 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200426
Paolo Bonzini80624c92012-04-19 14:00:24 +0200427 if (ret < 0) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200428 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200429 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200430 }
aliguoriea8a5d72009-01-22 19:52:21 +0000431 }
432
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200433 n = r->qiov.size / 512;
aliguoriea8a5d72009-01-22 19:52:21 +0000434 r->sector += n;
435 r->sector_count -= n;
pbrooka917d382006-08-29 04:52:16 +0000436 if (r->sector_count == 0) {
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200437 scsi_write_do_fua(r);
438 return;
pbrooka917d382006-08-29 04:52:16 +0000439 } else {
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500440 scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
Paolo Bonzini79fb50b2012-07-31 16:10:23 +0200441 DPRINTF("Write complete tag=0x%x more=%zd\n", r->req.tag, r->qiov.size);
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200442 scsi_req_data(&r->req, r->qiov.size);
pbrook4d611c92006-08-12 01:04:27 +0000443 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200444
445done:
446 if (!r->req.io_canceled) {
447 scsi_req_unref(&r->req);
448 }
pbrook4d611c92006-08-12 01:04:27 +0000449}
450
Paolo Bonzini42741212011-04-22 09:39:16 +0200451static void scsi_write_data(SCSIRequest *req)
aliguoriea8a5d72009-01-22 19:52:21 +0000452{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200453 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100454 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000455 uint32_t n;
456
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000457 /* No data transfer may already be in progress */
458 assert(r->req.aiocb == NULL);
459
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200460 /* The request is used as the AIO opaque value, so add a ref. */
461 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200462 if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
463 DPRINTF("Data transfer direction invalid\n");
464 scsi_write_complete(r, -EINVAL);
Paolo Bonzini42741212011-04-22 09:39:16 +0200465 return;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200466 }
467
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200468 if (!r->req.sg && !r->qiov.size) {
469 /* Called for the first time. Ask the driver to send us more data. */
Paolo Bonzinia0e66a62012-04-19 11:51:42 +0200470 r->started = true;
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200471 scsi_write_complete(r, 0);
472 return;
473 }
474 if (s->tray_open) {
475 scsi_write_complete(r, -ENOMEDIUM);
476 return;
477 }
478
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +0200479 if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 ||
480 r->req.cmd.buf[0] == VERIFY_16) {
481 if (r->req.sg) {
482 scsi_dma_complete(r, 0);
483 } else {
484 scsi_write_complete(r, 0);
485 }
486 return;
487 }
488
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200489 if (r->req.sg) {
490 dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
491 r->req.resid -= r->req.sg->size;
492 r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
493 scsi_dma_complete, r);
494 } else {
495 n = r->qiov.size / 512;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200496 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
497 r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200498 scsi_write_complete, r);
aliguoriea8a5d72009-01-22 19:52:21 +0000499 }
pbrook2e5d83b2006-05-25 23:58:51 +0000500}
501
pbrooka917d382006-08-29 04:52:16 +0000502/* Return a pointer to the data buffer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200503static uint8_t *scsi_get_buf(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +0000504{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200505 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
pbrooka917d382006-08-29 04:52:16 +0000506
blueswir13f4cb3d2009-04-13 16:31:01 +0000507 return (uint8_t *)r->iov.iov_base;
pbrooka917d382006-08-29 04:52:16 +0000508}
509
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100510static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
511{
Gerd Hoffmann383b4d92010-01-14 14:44:13 +0100512 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100513 int buflen = 0;
Paolo Bonzini82579392012-05-15 12:45:20 +0200514 int start;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100515
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100516 if (req->cmd.buf[1] & 0x1) {
517 /* Vital product data */
518 uint8_t page_code = req->cmd.buf[2];
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100519
Paolo Bonzinie39be482011-10-12 14:27:40 +0200520 outbuf[buflen++] = s->qdev.type & 0x1f;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100521 outbuf[buflen++] = page_code ; // this page
522 outbuf[buflen++] = 0x00;
Paolo Bonzini82579392012-05-15 12:45:20 +0200523 outbuf[buflen++] = 0x00;
524 start = buflen;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100525
526 switch (page_code) {
527 case 0x00: /* Supported page codes, mandatory */
Hannes Reinecke39d98982010-11-24 12:15:58 +0100528 {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100529 DPRINTF("Inquiry EVPD[Supported pages] "
530 "buffer size %zd\n", req->cmd.xfer);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100531 outbuf[buflen++] = 0x00; // list of supported pages (this page)
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200532 if (s->serial) {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200533 outbuf[buflen++] = 0x80; // unit serial number
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200534 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100535 outbuf[buflen++] = 0x83; // device identification
Hannes Reineckef37bd732011-07-22 16:44:46 +0200536 if (s->qdev.type == TYPE_DISK) {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100537 outbuf[buflen++] = 0xb0; // block limits
538 outbuf[buflen++] = 0xb2; // thin provisioning
Hannes Reinecke39d98982010-11-24 12:15:58 +0100539 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100540 break;
Hannes Reinecke39d98982010-11-24 12:15:58 +0100541 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100542 case 0x80: /* Device serial number, optional */
543 {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200544 int l;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100545
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200546 if (!s->serial) {
547 DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
548 return -1;
549 }
550
551 l = strlen(s->serial);
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200552 if (l > 20) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100553 l = 20;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200554 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100555
556 DPRINTF("Inquiry EVPD[Serial number] "
557 "buffer size %zd\n", req->cmd.xfer);
Markus Armbrustera0fef652010-06-01 20:32:34 +0200558 memcpy(outbuf+buflen, s->serial, l);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100559 buflen += l;
560 break;
561 }
562
563 case 0x83: /* Device identification page, mandatory */
564 {
Paolo Bonzinifd930792012-03-16 19:12:43 +0100565 const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
566 int max_len = s->serial ? 20 : 255 - 8;
567 int id_len = strlen(str);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100568
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200569 if (id_len > max_len) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100570 id_len = max_len;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200571 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100572 DPRINTF("Inquiry EVPD[Device identification] "
573 "buffer size %zd\n", req->cmd.xfer);
574
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100575 outbuf[buflen++] = 0x2; // ASCII
576 outbuf[buflen++] = 0; // not officially assigned
577 outbuf[buflen++] = 0; // reserved
578 outbuf[buflen++] = id_len; // length of data following
Paolo Bonzinifd930792012-03-16 19:12:43 +0100579 memcpy(outbuf+buflen, str, id_len);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100580 buflen += id_len;
Paolo Bonzini27395ad2012-05-15 12:46:09 +0200581
582 if (s->wwn) {
583 outbuf[buflen++] = 0x1; // Binary
584 outbuf[buflen++] = 0x3; // NAA
585 outbuf[buflen++] = 0; // reserved
586 outbuf[buflen++] = 8;
587 stq_be_p(&outbuf[buflen], s->wwn);
588 buflen += 8;
589 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100590 break;
591 }
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100592 case 0xb0: /* block limits */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100593 {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100594 unsigned int unmap_sectors =
595 s->qdev.conf.discard_granularity / s->qdev.blocksize;
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100596 unsigned int min_io_size =
597 s->qdev.conf.min_io_size / s->qdev.blocksize;
598 unsigned int opt_io_size =
599 s->qdev.conf.opt_io_size / s->qdev.blocksize;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100600
Hannes Reineckef37bd732011-07-22 16:44:46 +0200601 if (s->qdev.type == TYPE_ROM) {
Hannes Reinecke39d98982010-11-24 12:15:58 +0100602 DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
603 page_code);
604 return -1;
605 }
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100606 /* required VPD size with unmap support */
Paolo Bonzini82579392012-05-15 12:45:20 +0200607 buflen = 0x40;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100608 memset(outbuf + 4, 0, buflen - 4);
609
610 /* optimal transfer length granularity */
611 outbuf[6] = (min_io_size >> 8) & 0xff;
612 outbuf[7] = min_io_size & 0xff;
613
614 /* optimal transfer length */
615 outbuf[12] = (opt_io_size >> 24) & 0xff;
616 outbuf[13] = (opt_io_size >> 16) & 0xff;
617 outbuf[14] = (opt_io_size >> 8) & 0xff;
618 outbuf[15] = opt_io_size & 0xff;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100619
620 /* optimal unmap granularity */
621 outbuf[28] = (unmap_sectors >> 24) & 0xff;
622 outbuf[29] = (unmap_sectors >> 16) & 0xff;
623 outbuf[30] = (unmap_sectors >> 8) & 0xff;
624 outbuf[31] = unmap_sectors & 0xff;
625 break;
626 }
627 case 0xb2: /* thin provisioning */
628 {
Paolo Bonzini82579392012-05-15 12:45:20 +0200629 buflen = 8;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100630 outbuf[4] = 0;
Paolo Bonzini5222aaf2012-08-09 11:00:22 +0200631 outbuf[5] = 0xe0; /* unmap & write_same 10/16 all supported */
Ronnie Sahlbergf644a292012-04-19 20:41:17 +1000632 outbuf[6] = s->qdev.conf.discard_granularity ? 2 : 1;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100633 outbuf[7] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100634 break;
635 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100636 default:
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100637 return -1;
638 }
639 /* done with EVPD */
Paolo Bonzini82579392012-05-15 12:45:20 +0200640 assert(buflen - start <= 255);
641 outbuf[start - 1] = buflen - start;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100642 return buflen;
643 }
644
645 /* Standard INQUIRY data */
646 if (req->cmd.buf[2] != 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100647 return -1;
648 }
649
650 /* PAGE CODE == 0 */
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100651 buflen = req->cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200652 if (buflen > SCSI_MAX_INQUIRY_LEN) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100653 buflen = SCSI_MAX_INQUIRY_LEN;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200654 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100655
Hannes Reineckef37bd732011-07-22 16:44:46 +0200656 outbuf[0] = s->qdev.type & 0x1f;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +0200657 outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0;
Dmitry Fleytman353815a2012-07-06 22:03:35 -0700658
659 strpadcpy((char *) &outbuf[16], 16, s->product, ' ');
660 strpadcpy((char *) &outbuf[8], 8, s->vendor, ' ');
661
Gerd Hoffmann314b1812010-03-10 17:47:17 +0100662 memset(&outbuf[32], 0, 4);
Markus Armbruster552fee92010-06-01 20:32:35 +0200663 memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
Christoph Hellwig99aba0c2010-03-04 14:45:44 +0100664 /*
665 * We claim conformance to SPC-3, which is required for guests
666 * to ask for modern features like READ CAPACITY(16) or the
667 * block characteristics VPD page by default. Not all of SPC-3
668 * is actually implemented, but we're good enough.
669 */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100670 outbuf[2] = 5;
Ronnie Sahlberg1109c892012-09-14 18:13:29 -0700671 outbuf[3] = 2 | 0x10; /* Format 2, HiSup */
Artyom Tarasenkoad3cea42009-12-13 11:32:36 +0100672
673 if (buflen > 36) {
674 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
675 } else {
676 /* If the allocation length of CDB is too small,
677 the additional length is not adjusted */
678 outbuf[4] = 36 - 5;
679 }
680
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100681 /* Sync data transfer and TCQ. */
Paolo Bonziniafd40302011-08-13 15:44:45 +0200682 outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100683 return buflen;
684}
685
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200686static inline bool media_is_dvd(SCSIDiskState *s)
687{
688 uint64_t nb_sectors;
689 if (s->qdev.type != TYPE_ROM) {
690 return false;
691 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200692 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200693 return false;
694 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200695 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200696 return nb_sectors > CD_MAX_SECTORS;
697}
698
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200699static inline bool media_is_cd(SCSIDiskState *s)
700{
701 uint64_t nb_sectors;
702 if (s->qdev.type != TYPE_ROM) {
703 return false;
704 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200705 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200706 return false;
707 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200708 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200709 return nb_sectors <= CD_MAX_SECTORS;
710}
711
Paolo Bonzini1a4f0c32012-05-25 12:59:55 +0200712static int scsi_read_disc_information(SCSIDiskState *s, SCSIDiskReq *r,
713 uint8_t *outbuf)
714{
715 uint8_t type = r->req.cmd.buf[1] & 7;
716
717 if (s->qdev.type != TYPE_ROM) {
718 return -1;
719 }
720
721 /* Types 1/2 are only defined for Blu-Ray. */
722 if (type != 0) {
723 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
724 return -1;
725 }
726
727 memset(outbuf, 0, 34);
728 outbuf[1] = 32;
729 outbuf[2] = 0xe; /* last session complete, disc finalized */
730 outbuf[3] = 1; /* first track on disc */
731 outbuf[4] = 1; /* # of sessions */
732 outbuf[5] = 1; /* first track of last session */
733 outbuf[6] = 1; /* last track of last session */
734 outbuf[7] = 0x20; /* unrestricted use */
735 outbuf[8] = 0x00; /* CD-ROM or DVD-ROM */
736 /* 9-10-11: most significant byte corresponding bytes 4-5-6 */
737 /* 12-23: not meaningful for CD-ROM or DVD-ROM */
738 /* 24-31: disc bar code */
739 /* 32: disc application code */
740 /* 33: number of OPC tables */
741
742 return 34;
743}
744
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200745static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
746 uint8_t *outbuf)
747{
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200748 static const int rds_caps_size[5] = {
749 [0] = 2048 + 4,
750 [1] = 4 + 4,
751 [3] = 188 + 4,
752 [4] = 2048 + 4,
753 };
754
755 uint8_t media = r->req.cmd.buf[1];
756 uint8_t layer = r->req.cmd.buf[6];
757 uint8_t format = r->req.cmd.buf[7];
758 int size = -1;
759
760 if (s->qdev.type != TYPE_ROM) {
761 return -1;
762 }
763 if (media != 0) {
764 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
765 return -1;
766 }
767
768 if (format != 0xff) {
Paolo Bonzini44740c32011-10-12 12:54:16 +0200769 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200770 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
771 return -1;
772 }
773 if (media_is_cd(s)) {
774 scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
775 return -1;
776 }
777 if (format >= ARRAY_SIZE(rds_caps_size)) {
778 return -1;
779 }
780 size = rds_caps_size[format];
781 memset(outbuf, 0, size);
782 }
783
784 switch (format) {
785 case 0x00: {
786 /* Physical format information */
787 uint64_t nb_sectors;
788 if (layer != 0) {
789 goto fail;
790 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200791 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200792
793 outbuf[4] = 1; /* DVD-ROM, part version 1 */
794 outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
795 outbuf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
796 outbuf[7] = 0; /* default densities */
797
798 stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
799 stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
800 break;
801 }
802
803 case 0x01: /* DVD copyright information, all zeros */
804 break;
805
806 case 0x03: /* BCA information - invalid field for no BCA info */
807 return -1;
808
809 case 0x04: /* DVD disc manufacturing information, all zeros */
810 break;
811
812 case 0xff: { /* List capabilities */
813 int i;
814 size = 4;
815 for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
816 if (!rds_caps_size[i]) {
817 continue;
818 }
819 outbuf[size] = i;
820 outbuf[size + 1] = 0x40; /* Not writable, readable */
821 stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
822 size += 4;
823 }
824 break;
825 }
826
827 default:
828 return -1;
829 }
830
831 /* Size of buffer, not including 2 byte size field */
832 stw_be_p(outbuf, size - 2);
833 return size;
834
835fail:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200836 return -1;
837}
838
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200839static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200840{
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200841 uint8_t event_code, media_status;
842
843 media_status = 0;
844 if (s->tray_open) {
845 media_status = MS_TRAY_OPEN;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200846 } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200847 media_status = MS_MEDIA_PRESENT;
848 }
849
850 /* Event notification descriptor */
851 event_code = MEC_NO_CHANGE;
Paolo Bonzini4480de12011-10-25 12:53:40 +0200852 if (media_status != MS_TRAY_OPEN) {
853 if (s->media_event) {
854 event_code = MEC_NEW_MEDIA;
855 s->media_event = false;
856 } else if (s->eject_request) {
857 event_code = MEC_EJECT_REQUESTED;
858 s->eject_request = false;
859 }
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200860 }
861
862 outbuf[0] = event_code;
863 outbuf[1] = media_status;
864
865 /* These fields are reserved, just clear them. */
866 outbuf[2] = 0;
867 outbuf[3] = 0;
868 return 4;
869}
870
871static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
872 uint8_t *outbuf)
873{
874 int size;
875 uint8_t *buf = r->req.cmd.buf;
876 uint8_t notification_class_request = buf[4];
877 if (s->qdev.type != TYPE_ROM) {
878 return -1;
879 }
880 if ((buf[1] & 1) == 0) {
881 /* asynchronous */
882 return -1;
883 }
884
885 size = 4;
886 outbuf[0] = outbuf[1] = 0;
887 outbuf[3] = 1 << GESN_MEDIA; /* supported events */
888 if (notification_class_request & (1 << GESN_MEDIA)) {
889 outbuf[2] = GESN_MEDIA;
890 size += scsi_event_status_media(s, &outbuf[size]);
891 } else {
892 outbuf[2] = 0x80;
893 }
894 stw_be_p(outbuf, size - 4);
895 return size;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200896}
897
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200898static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200899{
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200900 int current;
901
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200902 if (s->qdev.type != TYPE_ROM) {
903 return -1;
904 }
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200905 current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
906 memset(outbuf, 0, 40);
907 stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
908 stw_be_p(&outbuf[6], current);
909 /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
910 outbuf[10] = 0x03; /* persistent, current */
911 outbuf[11] = 8; /* two profiles */
912 stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
913 outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
914 stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
915 outbuf[18] = (current == MMC_PROFILE_CD_ROM);
916 /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
917 stw_be_p(&outbuf[20], 1);
918 outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
919 outbuf[23] = 8;
920 stl_be_p(&outbuf[24], 1); /* SCSI */
921 outbuf[28] = 1; /* DBE = 1, mandatory */
922 /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
923 stw_be_p(&outbuf[32], 3);
924 outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
925 outbuf[35] = 4;
926 outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
927 /* TODO: Random readable, CD read, DVD read, drive serial number,
928 power management */
929 return 40;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200930}
931
932static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
933{
934 if (s->qdev.type != TYPE_ROM) {
935 return -1;
936 }
937 memset(outbuf, 0, 8);
938 outbuf[5] = 1; /* CD-ROM */
939 return 8;
940}
941
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200942static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
Bernhard Kohl282ab042010-08-31 14:08:24 +0200943 int page_control)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100944{
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200945 static const int mode_sense_valid[0x3f] = {
946 [MODE_PAGE_HD_GEOMETRY] = (1 << TYPE_DISK),
947 [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
948 [MODE_PAGE_CACHING] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200949 [MODE_PAGE_R_W_ERROR] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
950 [MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200951 [MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
952 };
Paolo Bonzinief405612012-07-12 16:08:24 +0200953
954 uint8_t *p = *p_outbuf + 2;
955 int length;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100956
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200957 if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
958 return -1;
959 }
960
Bernhard Kohl282ab042010-08-31 14:08:24 +0200961 /*
962 * If Changeable Values are requested, a mask denoting those mode parameters
963 * that are changeable shall be returned. As we currently don't support
964 * parameter changes via MODE_SELECT all bits are returned set to zero.
965 * The buffer was already menset to zero by the caller of this function.
Paolo Bonzinief405612012-07-12 16:08:24 +0200966 *
967 * The offsets here are off by two compared to the descriptions in the
968 * SCSI specs, because those include a 2-byte header. This is unfortunate,
969 * but it is done so that offsets are consistent within our implementation
970 * of MODE SENSE and MODE SELECT. MODE SELECT has to deal with both
971 * 2-byte and 4-byte headers.
Bernhard Kohl282ab042010-08-31 14:08:24 +0200972 */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100973 switch (page) {
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200974 case MODE_PAGE_HD_GEOMETRY:
Paolo Bonzinief405612012-07-12 16:08:24 +0200975 length = 0x16;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200976 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200977 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200978 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100979 /* if a geometry hint is available, use it */
Paolo Bonzinief405612012-07-12 16:08:24 +0200980 p[0] = (s->qdev.conf.cyls >> 16) & 0xff;
981 p[1] = (s->qdev.conf.cyls >> 8) & 0xff;
982 p[2] = s->qdev.conf.cyls & 0xff;
983 p[3] = s->qdev.conf.heads & 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100984 /* Write precomp start cylinder, disabled */
Paolo Bonzinief405612012-07-12 16:08:24 +0200985 p[4] = (s->qdev.conf.cyls >> 16) & 0xff;
986 p[5] = (s->qdev.conf.cyls >> 8) & 0xff;
987 p[6] = s->qdev.conf.cyls & 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100988 /* Reduced current start cylinder, disabled */
Paolo Bonzinief405612012-07-12 16:08:24 +0200989 p[7] = (s->qdev.conf.cyls >> 16) & 0xff;
990 p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
991 p[9] = s->qdev.conf.cyls & 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100992 /* Device step rate [ns], 200ns */
Paolo Bonzinief405612012-07-12 16:08:24 +0200993 p[10] = 0;
994 p[11] = 200;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100995 /* Landing zone cylinder */
Paolo Bonzinief405612012-07-12 16:08:24 +0200996 p[12] = 0xff;
997 p[13] = 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100998 p[14] = 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100999 /* Medium rotation rate [rpm], 5400 rpm */
Paolo Bonzinief405612012-07-12 16:08:24 +02001000 p[18] = (5400 >> 8) & 0xff;
1001 p[19] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001002 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001003
Paolo Bonzini67cc61e2011-09-13 14:41:56 +02001004 case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
Paolo Bonzinief405612012-07-12 16:08:24 +02001005 length = 0x1e;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001006 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001007 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001008 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001009 /* Transfer rate [kbit/s], 5Mbit/s */
Paolo Bonzinief405612012-07-12 16:08:24 +02001010 p[0] = 5000 >> 8;
1011 p[1] = 5000 & 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001012 /* if a geometry hint is available, use it */
Paolo Bonzinief405612012-07-12 16:08:24 +02001013 p[2] = s->qdev.conf.heads & 0xff;
1014 p[3] = s->qdev.conf.secs & 0xff;
1015 p[4] = s->qdev.blocksize >> 8;
1016 p[6] = (s->qdev.conf.cyls >> 8) & 0xff;
1017 p[7] = s->qdev.conf.cyls & 0xff;
1018 /* Write precomp start cylinder, disabled */
Markus Armbrusterd252df42012-07-10 11:12:42 +02001019 p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
1020 p[9] = s->qdev.conf.cyls & 0xff;
Paolo Bonzinief405612012-07-12 16:08:24 +02001021 /* Reduced current start cylinder, disabled */
Markus Armbrusterd252df42012-07-10 11:12:42 +02001022 p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
1023 p[11] = s->qdev.conf.cyls & 0xff;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001024 /* Device step rate [100us], 100us */
Paolo Bonzinief405612012-07-12 16:08:24 +02001025 p[12] = 0;
1026 p[13] = 1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001027 /* Device step pulse width [us], 1us */
Paolo Bonzinief405612012-07-12 16:08:24 +02001028 p[14] = 1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001029 /* Device head settle delay [100us], 100us */
Paolo Bonzinief405612012-07-12 16:08:24 +02001030 p[15] = 0;
1031 p[16] = 1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001032 /* Motor on delay [0.1s], 0.1s */
Paolo Bonzinief405612012-07-12 16:08:24 +02001033 p[17] = 1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001034 /* Motor off delay [0.1s], 0.1s */
Paolo Bonzinief405612012-07-12 16:08:24 +02001035 p[18] = 1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001036 /* Medium rotation rate [rpm], 5400 rpm */
Paolo Bonzinief405612012-07-12 16:08:24 +02001037 p[26] = (5400 >> 8) & 0xff;
1038 p[27] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001039 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001040
Paolo Bonzini67cc61e2011-09-13 14:41:56 +02001041 case MODE_PAGE_CACHING:
Paolo Bonzinief405612012-07-12 16:08:24 +02001042 length = 0x12;
Paolo Bonzini96c91bb2012-07-10 15:03:17 +02001043 if (page_control == 1 || /* Changeable Values */
1044 bdrv_enable_write_cache(s->qdev.conf.bs)) {
Paolo Bonzinief405612012-07-12 16:08:24 +02001045 p[0] = 4; /* WCE */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001046 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001047 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001048
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001049 case MODE_PAGE_R_W_ERROR:
Paolo Bonzinief405612012-07-12 16:08:24 +02001050 length = 10;
Paolo Bonzini4f588b12012-07-10 14:04:51 +02001051 if (page_control == 1) { /* Changeable Values */
1052 break;
1053 }
Paolo Bonzinief405612012-07-12 16:08:24 +02001054 p[0] = 0x80; /* Automatic Write Reallocation Enabled */
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001055 if (s->qdev.type == TYPE_ROM) {
Paolo Bonzinief405612012-07-12 16:08:24 +02001056 p[1] = 0x20; /* Read Retry Count */
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001057 }
1058 break;
1059
1060 case MODE_PAGE_AUDIO_CTL:
Paolo Bonzinief405612012-07-12 16:08:24 +02001061 length = 14;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001062 break;
1063
Paolo Bonzini67cc61e2011-09-13 14:41:56 +02001064 case MODE_PAGE_CAPABILITIES:
Paolo Bonzinief405612012-07-12 16:08:24 +02001065 length = 0x14;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001066 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001067 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001068 }
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001069
Paolo Bonzinief405612012-07-12 16:08:24 +02001070 p[0] = 0x3b; /* CD-R & CD-RW read */
1071 p[1] = 0; /* Writing not supported */
1072 p[2] = 0x7f; /* Audio, composite, digital out,
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001073 mode 2 form 1&2, multi session */
Paolo Bonzinief405612012-07-12 16:08:24 +02001074 p[3] = 0xff; /* CD DA, DA accurate, RW supported,
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001075 RW corrected, C2 errors, ISRC,
1076 UPC, Bar code */
Paolo Bonzinief405612012-07-12 16:08:24 +02001077 p[4] = 0x2d | (s->tray_locked ? 2 : 0);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001078 /* Locking supported, jumper present, eject, tray */
Paolo Bonzinief405612012-07-12 16:08:24 +02001079 p[5] = 0; /* no volume & mute control, no
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001080 changer */
Paolo Bonzinief405612012-07-12 16:08:24 +02001081 p[6] = (50 * 176) >> 8; /* 50x read speed */
1082 p[7] = (50 * 176) & 0xff;
1083 p[8] = 2 >> 8; /* Two volume levels */
1084 p[9] = 2 & 0xff;
1085 p[10] = 2048 >> 8; /* 2M buffer */
1086 p[11] = 2048 & 0xff;
1087 p[12] = (16 * 176) >> 8; /* 16x read speed current */
1088 p[13] = (16 * 176) & 0xff;
1089 p[16] = (16 * 176) >> 8; /* 16x write speed */
1090 p[17] = (16 * 176) & 0xff;
1091 p[18] = (16 * 176) >> 8; /* 16x write speed current */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001092 p[19] = (16 * 176) & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001093 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001094
1095 default:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001096 return -1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001097 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001098
Paolo Bonzinief405612012-07-12 16:08:24 +02001099 assert(length < 256);
1100 (*p_outbuf)[0] = page;
1101 (*p_outbuf)[1] = length;
1102 *p_outbuf += length + 2;
1103 return length + 2;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001104}
1105
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001106static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001107{
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001108 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001109 uint64_t nb_sectors;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001110 bool dbd;
1111 int page, buflen, ret, page_control;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001112 uint8_t *p;
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001113 uint8_t dev_specific_param;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001114
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001115 dbd = (r->req.cmd.buf[1] & 0x8) != 0;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001116 page = r->req.cmd.buf[2] & 0x3f;
1117 page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +02001118 DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001119 (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
1120 memset(outbuf, 0, r->req.cmd.xfer);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001121 p = outbuf;
1122
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001123 if (s->qdev.type == TYPE_DISK) {
Paolo Bonzinida8365d2012-05-01 10:25:16 +02001124 dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001125 if (bdrv_is_read_only(s->qdev.conf.bs)) {
1126 dev_specific_param |= 0x80; /* Readonly. */
1127 }
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001128 } else {
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001129 /* MMC prescribes that CD/DVD drives have no block descriptors,
1130 * and defines no device-specific parameter. */
Paolo Bonzini6a2de0f2012-04-19 10:28:15 +02001131 dev_specific_param = 0x00;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001132 dbd = true;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001133 }
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001134
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001135 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001136 p[1] = 0; /* Default media type. */
1137 p[2] = dev_specific_param;
1138 p[3] = 0; /* Block descriptor length. */
1139 p += 4;
1140 } else { /* MODE_SENSE_10 */
1141 p[2] = 0; /* Default media type. */
1142 p[3] = dev_specific_param;
1143 p[6] = p[7] = 0; /* Block descriptor length. */
1144 p += 8;
1145 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001146
Paolo Bonzini44740c32011-10-12 12:54:16 +02001147 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001148 if (!dbd && nb_sectors) {
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001149 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001150 outbuf[3] = 8; /* Block descriptor length */
1151 } else { /* MODE_SENSE_10 */
1152 outbuf[7] = 8; /* Block descriptor length */
1153 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001154 nb_sectors /= (s->qdev.blocksize / 512);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001155 if (nb_sectors > 0xffffff) {
Bernhard Kohl2488b742010-08-31 14:08:25 +02001156 nb_sectors = 0;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001157 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001158 p[0] = 0; /* media density code */
1159 p[1] = (nb_sectors >> 16) & 0xff;
1160 p[2] = (nb_sectors >> 8) & 0xff;
1161 p[3] = nb_sectors & 0xff;
1162 p[4] = 0; /* reserved */
1163 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
Paolo Bonzini69377302011-10-13 10:35:46 +02001164 p[6] = s->qdev.blocksize >> 8;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001165 p[7] = 0;
1166 p += 8;
1167 }
1168
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001169 if (page_control == 3) {
1170 /* Saved Values */
1171 scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
1172 return -1;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001173 }
1174
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001175 if (page == 0x3f) {
1176 for (page = 0; page <= 0x3e; page++) {
1177 mode_sense_page(s, page, &p, page_control);
1178 }
1179 } else {
1180 ret = mode_sense_page(s, page, &p, page_control);
1181 if (ret == -1) {
1182 return -1;
1183 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001184 }
1185
1186 buflen = p - outbuf;
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001187 /*
1188 * The mode data length field specifies the length in bytes of the
1189 * following data that is available to be transferred. The mode data
1190 * length does not include itself.
1191 */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001192 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001193 outbuf[0] = buflen - 1;
1194 } else { /* MODE_SENSE_10 */
1195 outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1196 outbuf[1] = (buflen - 2) & 0xff;
1197 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001198 return buflen;
1199}
1200
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001201static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1202{
1203 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001204 int start_track, format, msf, toclen;
1205 uint64_t nb_sectors;
1206
1207 msf = req->cmd.buf[1] & 2;
1208 format = req->cmd.buf[2] & 0xf;
1209 start_track = req->cmd.buf[6];
Paolo Bonzini44740c32011-10-12 12:54:16 +02001210 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001211 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
Paolo Bonzini69377302011-10-13 10:35:46 +02001212 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001213 switch (format) {
1214 case 0:
1215 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1216 break;
1217 case 1:
1218 /* multi session : only a single session defined */
1219 toclen = 12;
1220 memset(outbuf, 0, 12);
1221 outbuf[1] = 0x0a;
1222 outbuf[2] = 0x01;
1223 outbuf[3] = 0x01;
1224 break;
1225 case 2:
1226 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1227 break;
1228 default:
1229 return -1;
1230 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001231 return toclen;
1232}
1233
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001234static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001235{
1236 SCSIRequest *req = &r->req;
1237 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1238 bool start = req->cmd.buf[4] & 1;
1239 bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
Ronnie Sahlbergae5708b2012-07-28 11:14:53 +10001240 int pwrcnd = req->cmd.buf[4] & 0xf0;
1241
1242 if (pwrcnd) {
1243 /* eject/load only happens for power condition == 0 */
1244 return 0;
1245 }
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001246
Paolo Bonzinib456a712012-07-16 15:59:57 +02001247 if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && loej) {
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001248 if (!start && !s->tray_open && s->tray_locked) {
1249 scsi_check_condition(r,
Paolo Bonzini44740c32011-10-12 12:54:16 +02001250 bdrv_is_inserted(s->qdev.conf.bs)
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001251 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1252 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1253 return -1;
Markus Armbrusterfdec4402011-09-06 18:58:45 +02001254 }
Luiz Capitulinod88b1812012-02-17 11:05:21 -02001255
1256 if (s->tray_open != !start) {
1257 bdrv_eject(s->qdev.conf.bs, !start);
1258 s->tray_open = !start;
1259 }
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001260 }
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001261 return 0;
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001262}
1263
Paolo Bonzini314a3292012-02-08 10:26:21 +01001264static void scsi_disk_emulate_read_data(SCSIRequest *req)
1265{
1266 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1267 int buflen = r->iov.iov_len;
1268
1269 if (buflen) {
Paolo Bonzini79fb50b2012-07-31 16:10:23 +02001270 DPRINTF("Read buf_len=%d\n", buflen);
Paolo Bonzini314a3292012-02-08 10:26:21 +01001271 r->iov.iov_len = 0;
1272 r->started = true;
1273 scsi_req_data(&r->req, buflen);
1274 return;
1275 }
1276
1277 /* This also clears the sense buffer for REQUEST SENSE. */
1278 scsi_req_complete(&r->req, GOOD);
1279}
1280
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001281static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
1282 uint8_t *inbuf, int inlen)
1283{
1284 uint8_t mode_current[SCSI_MAX_MODE_LEN];
1285 uint8_t mode_changeable[SCSI_MAX_MODE_LEN];
1286 uint8_t *p;
1287 int len, expected_len, changeable_len, i;
1288
1289 /* The input buffer does not include the page header, so it is
1290 * off by 2 bytes.
1291 */
1292 expected_len = inlen + 2;
1293 if (expected_len > SCSI_MAX_MODE_LEN) {
1294 return -1;
1295 }
1296
1297 p = mode_current;
1298 memset(mode_current, 0, inlen + 2);
1299 len = mode_sense_page(s, page, &p, 0);
1300 if (len < 0 || len != expected_len) {
1301 return -1;
1302 }
1303
1304 p = mode_changeable;
1305 memset(mode_changeable, 0, inlen + 2);
1306 changeable_len = mode_sense_page(s, page, &p, 1);
1307 assert(changeable_len == len);
1308
1309 /* Check that unchangeable bits are the same as what MODE SENSE
1310 * would return.
1311 */
1312 for (i = 2; i < len; i++) {
1313 if (((mode_current[i] ^ inbuf[i - 2]) & ~mode_changeable[i]) != 0) {
1314 return -1;
1315 }
1316 }
1317 return 0;
1318}
1319
1320static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page, uint8_t *p)
1321{
Paolo Bonzini96c91bb2012-07-10 15:03:17 +02001322 switch (page) {
1323 case MODE_PAGE_CACHING:
1324 bdrv_set_enable_write_cache(s->qdev.conf.bs, (p[0] & 4) != 0);
1325 break;
1326
1327 default:
1328 break;
1329 }
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001330}
1331
1332static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
1333{
1334 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
1335
1336 while (len > 0) {
1337 int page, subpage, page_len;
1338
1339 /* Parse both possible formats for the mode page headers. */
1340 page = p[0] & 0x3f;
1341 if (p[0] & 0x40) {
1342 if (len < 4) {
1343 goto invalid_param_len;
1344 }
1345 subpage = p[1];
1346 page_len = lduw_be_p(&p[2]);
1347 p += 4;
1348 len -= 4;
1349 } else {
1350 if (len < 2) {
1351 goto invalid_param_len;
1352 }
1353 subpage = 0;
1354 page_len = p[1];
1355 p += 2;
1356 len -= 2;
1357 }
1358
1359 if (subpage) {
1360 goto invalid_param;
1361 }
1362 if (page_len > len) {
1363 goto invalid_param_len;
1364 }
1365
1366 if (!change) {
1367 if (scsi_disk_check_mode_select(s, page, p, page_len) < 0) {
1368 goto invalid_param;
1369 }
1370 } else {
1371 scsi_disk_apply_mode_select(s, page, p);
1372 }
1373
1374 p += page_len;
1375 len -= page_len;
1376 }
1377 return 0;
1378
1379invalid_param:
1380 scsi_check_condition(r, SENSE_CODE(INVALID_PARAM));
1381 return -1;
1382
1383invalid_param_len:
1384 scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
1385 return -1;
1386}
1387
1388static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
1389{
Paolo Bonziniaccfeb22012-10-31 17:14:41 +01001390 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001391 uint8_t *p = inbuf;
1392 int cmd = r->req.cmd.buf[0];
1393 int len = r->req.cmd.xfer;
1394 int hdr_len = (cmd == MODE_SELECT ? 4 : 8);
1395 int bd_len;
1396 int pass;
1397
1398 /* We only support PF=1, SP=0. */
1399 if ((r->req.cmd.buf[1] & 0x11) != 0x10) {
1400 goto invalid_field;
1401 }
1402
1403 if (len < hdr_len) {
1404 goto invalid_param_len;
1405 }
1406
1407 bd_len = (cmd == MODE_SELECT ? p[3] : lduw_be_p(&p[6]));
1408 len -= hdr_len;
1409 p += hdr_len;
1410 if (len < bd_len) {
1411 goto invalid_param_len;
1412 }
1413 if (bd_len != 0 && bd_len != 8) {
1414 goto invalid_param;
1415 }
1416
1417 len -= bd_len;
1418 p += bd_len;
1419
1420 /* Ensure no change is made if there is an error! */
1421 for (pass = 0; pass < 2; pass++) {
1422 if (mode_select_pages(r, p, len, pass == 1) < 0) {
1423 assert(pass == 0);
1424 return;
1425 }
1426 }
Paolo Bonziniaccfeb22012-10-31 17:14:41 +01001427 if (!bdrv_enable_write_cache(s->qdev.conf.bs)) {
1428 /* The request is used as the AIO opaque value, so add a ref. */
1429 scsi_req_ref(&r->req);
1430 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1431 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
1432 return;
1433 }
1434
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001435 scsi_req_complete(&r->req, GOOD);
1436 return;
1437
1438invalid_param:
1439 scsi_check_condition(r, SENSE_CODE(INVALID_PARAM));
1440 return;
1441
1442invalid_param_len:
1443 scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
1444 return;
1445
1446invalid_field:
1447 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001448}
1449
Paolo Bonzini444bc902012-09-05 17:46:18 +02001450static inline bool check_lba_range(SCSIDiskState *s,
1451 uint64_t sector_num, uint32_t nb_sectors)
1452{
1453 /*
1454 * The first line tests that no overflow happens when computing the last
1455 * sector. The second line tests that the last accessed sector is in
1456 * range.
Paolo Bonzini12ca76f2012-09-05 17:54:36 +02001457 *
1458 * Careful, the computations should not underflow for nb_sectors == 0,
1459 * and a 0-block read to the first LBA beyond the end of device is
1460 * valid.
Paolo Bonzini444bc902012-09-05 17:46:18 +02001461 */
1462 return (sector_num <= sector_num + nb_sectors &&
Paolo Bonzini12ca76f2012-09-05 17:54:36 +02001463 sector_num + nb_sectors <= s->qdev.max_lba + 1);
Paolo Bonzini444bc902012-09-05 17:46:18 +02001464}
1465
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001466typedef struct UnmapCBData {
1467 SCSIDiskReq *r;
1468 uint8_t *inbuf;
1469 int count;
1470} UnmapCBData;
1471
1472static void scsi_unmap_complete(void *opaque, int ret)
1473{
1474 UnmapCBData *data = opaque;
1475 SCSIDiskReq *r = data->r;
1476 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
1477 uint64_t sector_num;
Stefan Weil5bb0b622012-08-29 20:39:25 +02001478 uint32_t nb_sectors;
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001479
1480 r->req.aiocb = NULL;
1481 if (ret < 0) {
1482 if (scsi_handle_rw_error(r, -ret)) {
1483 goto done;
1484 }
1485 }
1486
1487 if (data->count > 0 && !r->req.io_canceled) {
1488 sector_num = ldq_be_p(&data->inbuf[0]);
1489 nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
Paolo Bonzini444bc902012-09-05 17:46:18 +02001490 if (!check_lba_range(s, sector_num, nb_sectors)) {
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001491 scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1492 goto done;
1493 }
1494
1495 r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
1496 sector_num * (s->qdev.blocksize / 512),
1497 nb_sectors * (s->qdev.blocksize / 512),
1498 scsi_unmap_complete, data);
1499 data->count--;
1500 data->inbuf += 16;
1501 return;
1502 }
1503
1504done:
1505 if (data->count == 0) {
1506 scsi_req_complete(&r->req, GOOD);
1507 }
1508 if (!r->req.io_canceled) {
1509 scsi_req_unref(&r->req);
1510 }
1511 g_free(data);
1512}
1513
1514static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
1515{
1516 uint8_t *p = inbuf;
1517 int len = r->req.cmd.xfer;
1518 UnmapCBData *data;
1519
1520 if (len < 8) {
1521 goto invalid_param_len;
1522 }
1523 if (len < lduw_be_p(&p[0]) + 2) {
1524 goto invalid_param_len;
1525 }
1526 if (len < lduw_be_p(&p[2]) + 8) {
1527 goto invalid_param_len;
1528 }
1529 if (lduw_be_p(&p[2]) & 15) {
1530 goto invalid_param_len;
1531 }
1532
1533 data = g_new0(UnmapCBData, 1);
1534 data->r = r;
1535 data->inbuf = &p[8];
1536 data->count = lduw_be_p(&p[2]) >> 4;
1537
1538 /* The matching unref is in scsi_unmap_complete, before data is freed. */
1539 scsi_req_ref(&r->req);
1540 scsi_unmap_complete(data, 0);
1541 return;
1542
1543invalid_param_len:
1544 scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001545}
1546
Paolo Bonzini314a3292012-02-08 10:26:21 +01001547static void scsi_disk_emulate_write_data(SCSIRequest *req)
1548{
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001549 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1550
1551 if (r->iov.iov_len) {
1552 int buflen = r->iov.iov_len;
Paolo Bonzini79fb50b2012-07-31 16:10:23 +02001553 DPRINTF("Write buf_len=%d\n", buflen);
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001554 r->iov.iov_len = 0;
1555 scsi_req_data(&r->req, buflen);
1556 return;
1557 }
1558
1559 switch (req->cmd.buf[0]) {
1560 case MODE_SELECT:
1561 case MODE_SELECT_10:
1562 /* This also clears the sense buffer for REQUEST SENSE. */
Paolo Bonzini380feaf2012-07-10 15:02:55 +02001563 scsi_disk_emulate_mode_select(r, r->iov.iov_base);
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001564 break;
1565
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001566 case UNMAP:
1567 scsi_disk_emulate_unmap(r, r->iov.iov_base);
1568 break;
1569
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001570 default:
1571 abort();
1572 }
Paolo Bonzini314a3292012-02-08 10:26:21 +01001573}
1574
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001575static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001576{
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001577 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001578 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001579 uint64_t nb_sectors;
Paolo Bonzini72854772011-09-16 16:40:04 +02001580 uint8_t *outbuf;
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001581 int buflen;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001582
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001583 switch (req->cmd.buf[0]) {
1584 case INQUIRY:
1585 case MODE_SENSE:
1586 case MODE_SENSE_10:
1587 case RESERVE:
1588 case RESERVE_10:
1589 case RELEASE:
1590 case RELEASE_10:
1591 case START_STOP:
1592 case ALLOW_MEDIUM_REMOVAL:
1593 case GET_CONFIGURATION:
1594 case GET_EVENT_STATUS_NOTIFICATION:
1595 case MECHANISM_STATUS:
1596 case REQUEST_SENSE:
1597 break;
1598
1599 default:
1600 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1601 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1602 return 0;
1603 }
1604 break;
1605 }
1606
Paolo Bonzinic8dcb532012-10-10 12:18:03 +02001607 /*
1608 * FIXME: we shouldn't return anything bigger than 4k, but the code
1609 * requires the buffer to be as big as req->cmd.xfer in several
1610 * places. So, do not allow CDBs with a very large ALLOCATION
1611 * LENGTH. The real fix would be to modify scsi_read_data and
1612 * dma_buf_read, so that they return data beyond the buflen
1613 * as all zeros.
1614 */
1615 if (req->cmd.xfer > 65536) {
1616 goto illegal_request;
1617 }
1618 r->buflen = MAX(4096, req->cmd.xfer);
1619
Paolo Bonzini72854772011-09-16 16:40:04 +02001620 if (!r->iov.iov_base) {
Paolo Bonzini44740c32011-10-12 12:54:16 +02001621 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +02001622 }
1623
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001624 buflen = req->cmd.xfer;
Paolo Bonzini72854772011-09-16 16:40:04 +02001625 outbuf = r->iov.iov_base;
Paolo Bonzinic8dcb532012-10-10 12:18:03 +02001626 memset(outbuf, 0, r->buflen);
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001627 switch (req->cmd.buf[0]) {
1628 case TEST_UNIT_READY:
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001629 assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001630 break;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001631 case INQUIRY:
1632 buflen = scsi_disk_emulate_inquiry(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001633 if (buflen < 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001634 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001635 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001636 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001637 case MODE_SENSE:
1638 case MODE_SENSE_10:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001639 buflen = scsi_disk_emulate_mode_sense(r, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001640 if (buflen < 0) {
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001641 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001642 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001643 break;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001644 case READ_TOC:
1645 buflen = scsi_disk_emulate_read_toc(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001646 if (buflen < 0) {
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001647 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001648 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001649 break;
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001650 case RESERVE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001651 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001652 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001653 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001654 break;
1655 case RESERVE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001656 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001657 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001658 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001659 break;
1660 case RELEASE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001661 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001662 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001663 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001664 break;
1665 case RELEASE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001666 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001667 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001668 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001669 break;
Gerd Hoffmann8d3628f2009-11-26 15:34:07 +01001670 case START_STOP:
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001671 if (scsi_disk_emulate_start_stop(r) < 0) {
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001672 return 0;
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001673 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001674 break;
Gerd Hoffmannc68b9f32009-11-26 15:34:08 +01001675 case ALLOW_MEDIUM_REMOVAL:
Markus Armbruster81b10082011-09-06 18:58:44 +02001676 s->tray_locked = req->cmd.buf[4] & 1;
Paolo Bonzini44740c32011-10-12 12:54:16 +02001677 bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001678 break;
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001679 case READ_CAPACITY_10:
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001680 /* The normal LEN field for this command is zero. */
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001681 memset(outbuf, 0, 8);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001682 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001683 if (!nb_sectors) {
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001684 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1685 return -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001686 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001687 if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
1688 goto illegal_request;
1689 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001690 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001691 /* Returned value is the address of the last sector. */
1692 nb_sectors--;
1693 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001694 s->qdev.max_lba = nb_sectors;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001695 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001696 if (nb_sectors > UINT32_MAX) {
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001697 nb_sectors = UINT32_MAX;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001698 }
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001699 outbuf[0] = (nb_sectors >> 24) & 0xff;
1700 outbuf[1] = (nb_sectors >> 16) & 0xff;
1701 outbuf[2] = (nb_sectors >> 8) & 0xff;
1702 outbuf[3] = nb_sectors & 0xff;
1703 outbuf[4] = 0;
1704 outbuf[5] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001705 outbuf[6] = s->qdev.blocksize >> 8;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001706 outbuf[7] = 0;
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001707 break;
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001708 case REQUEST_SENSE:
1709 /* Just return "NO SENSE". */
1710 buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
1711 (req->cmd.buf[1] & 1) == 0);
Paolo Bonzinic8dcb532012-10-10 12:18:03 +02001712 if (buflen < 0) {
1713 goto illegal_request;
1714 }
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001715 break;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001716 case MECHANISM_STATUS:
1717 buflen = scsi_emulate_mechanism_status(s, outbuf);
1718 if (buflen < 0) {
1719 goto illegal_request;
1720 }
1721 break;
Gerd Hoffmann38215552009-11-26 15:34:12 +01001722 case GET_CONFIGURATION:
Paolo Bonzini430ee2f2011-09-13 15:22:31 +02001723 buflen = scsi_get_configuration(s, outbuf);
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001724 if (buflen < 0) {
1725 goto illegal_request;
1726 }
1727 break;
1728 case GET_EVENT_STATUS_NOTIFICATION:
1729 buflen = scsi_get_event_status_notification(s, r, outbuf);
1730 if (buflen < 0) {
1731 goto illegal_request;
1732 }
1733 break;
Paolo Bonzini1a4f0c32012-05-25 12:59:55 +02001734 case READ_DISC_INFORMATION:
1735 buflen = scsi_read_disc_information(s, r, outbuf);
1736 if (buflen < 0) {
1737 goto illegal_request;
1738 }
1739 break;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001740 case READ_DVD_STRUCTURE:
1741 buflen = scsi_read_dvd_structure(s, r, outbuf);
1742 if (buflen < 0) {
1743 goto illegal_request;
1744 }
Gerd Hoffmann38215552009-11-26 15:34:12 +01001745 break;
Paolo Bonzinif6515262011-09-06 12:31:42 +02001746 case SERVICE_ACTION_IN_16:
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001747 /* Service Action In subcommands. */
Paolo Bonzinif6515262011-09-06 12:31:42 +02001748 if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001749 DPRINTF("SAI READ CAPACITY(16)\n");
1750 memset(outbuf, 0, req->cmd.xfer);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001751 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001752 if (!nb_sectors) {
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001753 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1754 return -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001755 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001756 if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1757 goto illegal_request;
1758 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001759 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001760 /* Returned value is the address of the last sector. */
1761 nb_sectors--;
1762 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001763 s->qdev.max_lba = nb_sectors;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001764 outbuf[0] = (nb_sectors >> 56) & 0xff;
1765 outbuf[1] = (nb_sectors >> 48) & 0xff;
1766 outbuf[2] = (nb_sectors >> 40) & 0xff;
1767 outbuf[3] = (nb_sectors >> 32) & 0xff;
1768 outbuf[4] = (nb_sectors >> 24) & 0xff;
1769 outbuf[5] = (nb_sectors >> 16) & 0xff;
1770 outbuf[6] = (nb_sectors >> 8) & 0xff;
1771 outbuf[7] = nb_sectors & 0xff;
1772 outbuf[8] = 0;
1773 outbuf[9] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001774 outbuf[10] = s->qdev.blocksize >> 8;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001775 outbuf[11] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +01001776 outbuf[12] = 0;
1777 outbuf[13] = get_physical_block_exp(&s->qdev.conf);
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001778
1779 /* set TPE bit if the format supports discard */
1780 if (s->qdev.conf.discard_granularity) {
1781 outbuf[14] = 0x80;
1782 }
1783
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001784 /* Protection, exponent and lowest lba field left blank. */
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001785 break;
1786 }
1787 DPRINTF("Unsupported Service Action In\n");
1788 goto illegal_request;
Paolo Bonzini101aa852012-02-08 09:43:52 +01001789 case SYNCHRONIZE_CACHE:
1790 /* The request is used as the AIO opaque value, so add a ref. */
1791 scsi_req_ref(&r->req);
1792 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1793 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
1794 return 0;
1795 case SEEK_10:
1796 DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
1797 if (r->req.cmd.lba > s->qdev.max_lba) {
1798 goto illegal_lba;
1799 }
1800 break;
Paolo Bonzini101aa852012-02-08 09:43:52 +01001801 case MODE_SELECT:
1802 DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
Paolo Bonzini101aa852012-02-08 09:43:52 +01001803 break;
1804 case MODE_SELECT_10:
1805 DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
Paolo Bonzini101aa852012-02-08 09:43:52 +01001806 break;
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02001807 case UNMAP:
1808 DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer);
1809 break;
Paolo Bonzini101aa852012-02-08 09:43:52 +01001810 case WRITE_SAME_10:
Paolo Bonzini101aa852012-02-08 09:43:52 +01001811 case WRITE_SAME_16:
Paolo Bonzinie93176d2012-09-05 18:00:57 +02001812 nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
Ronnie Sahlberg6a8a6852012-07-16 08:53:28 +02001813 if (bdrv_is_read_only(s->qdev.conf.bs)) {
1814 scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
1815 return 0;
1816 }
Paolo Bonzini444bc902012-09-05 17:46:18 +02001817 if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) {
Paolo Bonzini101aa852012-02-08 09:43:52 +01001818 goto illegal_lba;
1819 }
1820
1821 /*
1822 * We only support WRITE SAME with the unmap bit set for now.
1823 */
1824 if (!(req->cmd.buf[1] & 0x8)) {
1825 goto illegal_request;
1826 }
1827
1828 /* The request is used as the AIO opaque value, so add a ref. */
1829 scsi_req_ref(&r->req);
1830 r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
1831 r->req.cmd.lba * (s->qdev.blocksize / 512),
1832 nb_sectors * (s->qdev.blocksize / 512),
1833 scsi_aio_complete, r);
1834 return 0;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001835 default:
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001836 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001837 scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001838 return 0;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001839 }
Paolo Bonzini314a3292012-02-08 10:26:21 +01001840 assert(!r->req.aiocb);
Paolo Bonzinic8dcb532012-10-10 12:18:03 +02001841 r->iov.iov_len = MIN(r->buflen, req->cmd.xfer);
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001842 if (r->iov.iov_len == 0) {
1843 scsi_req_complete(&r->req, GOOD);
1844 }
Paolo Bonziniaf6d5102012-02-08 10:32:55 +01001845 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1846 assert(r->iov.iov_len == req->cmd.xfer);
1847 return -r->iov.iov_len;
1848 } else {
1849 return r->iov.iov_len;
1850 }
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001851
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001852illegal_request:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001853 if (r->req.status == -1) {
1854 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1855 }
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001856 return 0;
Paolo Bonzini101aa852012-02-08 09:43:52 +01001857
1858illegal_lba:
1859 scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1860 return 0;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001861}
1862
pbrook2e5d83b2006-05-25 23:58:51 +00001863/* Execute a scsi command. Returns the length of the data expected by the
1864 command. This will be Positive for data transfers from the device
1865 (eg. disk reads), negative for transfers to the device (eg. disk writes),
1866 and zero if the command does not transfer any data. */
1867
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001868static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
pbrook2e5d83b2006-05-25 23:58:51 +00001869{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001870 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1871 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Paolo Bonzinie93176d2012-09-05 18:00:57 +02001872 uint32_t len;
pbrooka917d382006-08-29 04:52:16 +00001873 uint8_t command;
pbrook2e5d83b2006-05-25 23:58:51 +00001874
pbrooka917d382006-08-29 04:52:16 +00001875 command = buf[0];
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001876
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001877 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1878 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1879 return 0;
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001880 }
1881
Paolo Bonzinie93176d2012-09-05 18:00:57 +02001882 len = scsi_data_cdb_length(r->req.cmd.buf);
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001883 switch (command) {
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001884 case READ_6:
1885 case READ_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001886 case READ_12:
1887 case READ_16:
Paolo Bonzinie93176d2012-09-05 18:00:57 +02001888 DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len);
Ronnie Sahlberg96bdbba2012-07-12 10:19:38 +10001889 if (r->req.cmd.buf[1] & 0xe0) {
1890 goto illegal_request;
1891 }
Paolo Bonzini444bc902012-09-05 17:46:18 +02001892 if (!check_lba_range(s, r->req.cmd.lba, len)) {
aliguori274fb0e2009-01-29 19:59:04 +00001893 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001894 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001895 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1896 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001897 break;
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001898 case WRITE_6:
1899 case WRITE_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001900 case WRITE_12:
1901 case WRITE_16:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001902 case WRITE_VERIFY_10:
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001903 case WRITE_VERIFY_12:
1904 case WRITE_VERIFY_16:
Ronnie Sahlberg6a8a6852012-07-16 08:53:28 +02001905 if (bdrv_is_read_only(s->qdev.conf.bs)) {
1906 scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
1907 return 0;
1908 }
1909 /* fallthrough */
1910 case VERIFY_10:
1911 case VERIFY_12:
1912 case VERIFY_16:
Paolo Bonzinie93176d2012-09-05 18:00:57 +02001913 DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001914 (command & 0xe) == 0xe ? "And Verify " : "",
1915 r->req.cmd.lba, len);
Ronnie Sahlberg96bdbba2012-07-12 10:19:38 +10001916 if (r->req.cmd.buf[1] & 0xe0) {
1917 goto illegal_request;
1918 }
Paolo Bonzini444bc902012-09-05 17:46:18 +02001919 if (!check_lba_range(s, r->req.cmd.lba, len)) {
aliguori274fb0e2009-01-29 19:59:04 +00001920 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001921 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001922 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1923 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001924 break;
pbrook2e5d83b2006-05-25 23:58:51 +00001925 default:
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001926 abort();
Ronnie Sahlberg96bdbba2012-07-12 10:19:38 +10001927 illegal_request:
1928 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1929 return 0;
aliguori274fb0e2009-01-29 19:59:04 +00001930 illegal_lba:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001931 scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
aliguori274fb0e2009-01-29 19:59:04 +00001932 return 0;
pbrook2e5d83b2006-05-25 23:58:51 +00001933 }
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001934 if (r->sector_count == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001935 scsi_req_complete(&r->req, GOOD);
pbrook2e5d83b2006-05-25 23:58:51 +00001936 }
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001937 assert(r->iov.iov_len == 0);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +02001938 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001939 return -r->sector_count * 512;
pbrooka917d382006-08-29 04:52:16 +00001940 } else {
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01001941 return r->sector_count * 512;
pbrooka917d382006-08-29 04:52:16 +00001942 }
pbrook2e5d83b2006-05-25 23:58:51 +00001943}
1944
Jan Kiszkae9447f32010-05-04 14:20:59 +02001945static void scsi_disk_reset(DeviceState *dev)
1946{
1947 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1948 uint64_t nb_sectors;
1949
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001950 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
Jan Kiszkae9447f32010-05-04 14:20:59 +02001951
Paolo Bonzini44740c32011-10-12 12:54:16 +02001952 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini69377302011-10-13 10:35:46 +02001953 nb_sectors /= s->qdev.blocksize / 512;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001954 if (nb_sectors) {
1955 nb_sectors--;
1956 }
Paolo Bonzini78779032011-10-13 10:39:50 +02001957 s->qdev.max_lba = nb_sectors;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001958}
1959
1960static void scsi_destroy(SCSIDevice *dev)
1961{
1962 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1963
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001964 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001965 blockdev_mark_auto_del(s->qdev.conf.bs);
Gerd Hoffmann56a14932009-09-25 21:42:46 +02001966}
1967
Paolo Bonziniaaebace2012-07-16 14:07:55 +02001968static void scsi_disk_resize_cb(void *opaque)
1969{
1970 SCSIDiskState *s = opaque;
1971
1972 /* SPC lists this sense code as available only for
1973 * direct-access devices.
1974 */
1975 if (s->qdev.type == TYPE_DISK) {
Paolo Bonzini53200fa2012-07-16 14:22:36 +02001976 scsi_device_report_change(&s->qdev, SENSE_CODE(CAPACITY_CHANGED));
Paolo Bonziniaaebace2012-07-16 14:07:55 +02001977 }
1978}
1979
Markus Armbruster7d4b4ba2011-09-06 18:58:59 +02001980static void scsi_cd_change_media_cb(void *opaque, bool load)
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001981{
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001982 SCSIDiskState *s = opaque;
1983
1984 /*
1985 * When a CD gets changed, we have to report an ejected state and
1986 * then a loaded state to guests so that they detect tray
1987 * open/close and media change events. Guests that do not use
1988 * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1989 * states rely on this behavior.
1990 *
1991 * media_changed governs the state machine used for unit attention
1992 * report. media_event is used by GET EVENT STATUS NOTIFICATION.
1993 */
1994 s->media_changed = load;
1995 s->tray_open = !load;
Paolo Bonzinie48e84e2012-07-16 14:18:58 +02001996 scsi_device_set_ua(&s->qdev, SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM));
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +02001997 s->media_event = true;
Paolo Bonzini4480de12011-10-25 12:53:40 +02001998 s->eject_request = false;
1999}
2000
2001static void scsi_cd_eject_request_cb(void *opaque, bool force)
2002{
2003 SCSIDiskState *s = opaque;
2004
2005 s->eject_request = true;
2006 if (force) {
2007 s->tray_locked = false;
2008 }
Markus Armbruster2c6942f2011-09-06 18:58:51 +02002009}
2010
Markus Armbrustere4def802011-09-06 18:58:53 +02002011static bool scsi_cd_is_tray_open(void *opaque)
2012{
2013 return ((SCSIDiskState *)opaque)->tray_open;
2014}
2015
Markus Armbrusterf1076392011-09-06 18:58:46 +02002016static bool scsi_cd_is_medium_locked(void *opaque)
2017{
2018 return ((SCSIDiskState *)opaque)->tray_locked;
2019}
2020
Paolo Bonziniaaebace2012-07-16 14:07:55 +02002021static const BlockDevOps scsi_disk_removable_block_ops = {
Markus Armbruster2c6942f2011-09-06 18:58:51 +02002022 .change_media_cb = scsi_cd_change_media_cb,
Paolo Bonzini4480de12011-10-25 12:53:40 +02002023 .eject_request_cb = scsi_cd_eject_request_cb,
Markus Armbrustere4def802011-09-06 18:58:53 +02002024 .is_tray_open = scsi_cd_is_tray_open,
Markus Armbrusterf1076392011-09-06 18:58:46 +02002025 .is_medium_locked = scsi_cd_is_medium_locked,
Paolo Bonziniaaebace2012-07-16 14:07:55 +02002026
2027 .resize_cb = scsi_disk_resize_cb,
2028};
2029
2030static const BlockDevOps scsi_disk_block_ops = {
2031 .resize_cb = scsi_disk_resize_cb,
Markus Armbrusterf1076392011-09-06 18:58:46 +02002032};
2033
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02002034static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
2035{
2036 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2037 if (s->media_changed) {
2038 s->media_changed = false;
Paolo Bonzinie48e84e2012-07-16 14:18:58 +02002039 scsi_device_set_ua(&s->qdev, SENSE_CODE(MEDIUM_CHANGED));
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02002040 }
2041}
2042
Paolo Bonzinie39be482011-10-12 14:27:40 +02002043static int scsi_initfn(SCSIDevice *dev)
pbrook2e5d83b2006-05-25 23:58:51 +00002044{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002045 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
pbrook2e5d83b2006-05-25 23:58:51 +00002046
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02002047 if (!s->qdev.conf.bs) {
Markus Armbruster6a84cb12011-12-21 11:37:57 +01002048 error_report("drive property not set");
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002049 return -1;
2050 }
2051
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002052 if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
2053 !bdrv_is_inserted(s->qdev.conf.bs)) {
Markus Armbruster98f28ad2010-07-06 14:37:44 +02002054 error_report("Device needs media, but drive is empty");
2055 return -1;
2056 }
2057
Markus Armbruster911525d2012-07-11 15:08:37 +02002058 blkconf_serial(&s->qdev.conf, &s->serial);
Markus Armbrusterb2df4312012-07-12 18:52:31 +02002059 if (dev->type == TYPE_DISK
2060 && blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) {
Markus Armbrusterb7eb0c92012-07-11 15:08:39 +02002061 return -1;
2062 }
Markus Armbrustera0fef652010-06-01 20:32:34 +02002063
Markus Armbruster552fee92010-06-01 20:32:35 +02002064 if (!s->version) {
Crístian Viana93bfef42012-05-30 00:35:51 -03002065 s->version = g_strdup(qemu_get_version());
Markus Armbruster552fee92010-06-01 20:32:35 +02002066 }
Dmitry Fleytman353815a2012-07-06 22:03:35 -07002067 if (!s->vendor) {
2068 s->vendor = g_strdup("QEMU");
2069 }
Markus Armbruster552fee92010-06-01 20:32:35 +02002070
Paolo Bonzini44740c32011-10-12 12:54:16 +02002071 if (bdrv_is_sg(s->qdev.conf.bs)) {
Markus Armbruster6a84cb12011-12-21 11:37:57 +01002072 error_report("unwanted /dev/sg*");
Markus Armbruster32bb4042010-02-25 11:23:52 +01002073 return -1;
2074 }
2075
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002076 if (s->features & (1 << SCSI_DISK_F_REMOVABLE)) {
Paolo Bonziniaaebace2012-07-16 14:07:55 +02002077 bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_removable_block_ops, s);
2078 } else {
2079 bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_block_ops, s);
pbrook2e5d83b2006-05-25 23:58:51 +00002080 }
Paolo Bonzini44740c32011-10-12 12:54:16 +02002081 bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
Christoph Hellwig8cfacf02010-03-04 14:20:17 +01002082
Paolo Bonzini44740c32011-10-12 12:54:16 +02002083 bdrv_iostatus_enable(s->qdev.conf.bs);
Paolo Bonzini70828262011-11-15 17:36:38 +01002084 add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002085 return 0;
ths8ccc2ac2007-12-10 02:58:34 +00002086}
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002087
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002088static int scsi_hd_initfn(SCSIDevice *dev)
2089{
Paolo Bonzinie39be482011-10-12 14:27:40 +02002090 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2091 s->qdev.blocksize = s->qdev.conf.logical_block_size;
2092 s->qdev.type = TYPE_DISK;
Dmitry Fleytman353815a2012-07-06 22:03:35 -07002093 if (!s->product) {
2094 s->product = g_strdup("QEMU HARDDISK");
2095 }
Paolo Bonzinie39be482011-10-12 14:27:40 +02002096 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002097}
2098
2099static int scsi_cd_initfn(SCSIDevice *dev)
2100{
Paolo Bonzinie39be482011-10-12 14:27:40 +02002101 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2102 s->qdev.blocksize = 2048;
2103 s->qdev.type = TYPE_ROM;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002104 s->features |= 1 << SCSI_DISK_F_REMOVABLE;
Dmitry Fleytman353815a2012-07-06 22:03:35 -07002105 if (!s->product) {
2106 s->product = g_strdup("QEMU CD-ROM");
2107 }
Paolo Bonzinie39be482011-10-12 14:27:40 +02002108 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002109}
2110
2111static int scsi_disk_initfn(SCSIDevice *dev)
2112{
Markus Armbruster95b5edc2011-05-16 15:04:56 +02002113 DriveInfo *dinfo;
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002114
2115 if (!dev->conf.bs) {
Paolo Bonzinie39be482011-10-12 14:27:40 +02002116 return scsi_initfn(dev); /* ... and die there */
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002117 }
2118
Paolo Bonzinie39be482011-10-12 14:27:40 +02002119 dinfo = drive_get_by_blockdev(dev->conf.bs);
2120 if (dinfo->media_cd) {
2121 return scsi_cd_initfn(dev);
2122 } else {
2123 return scsi_hd_initfn(dev);
2124 }
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002125}
2126
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002127static const SCSIReqOps scsi_disk_emulate_reqops = {
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02002128 .size = sizeof(SCSIDiskReq),
Paolo Bonzini12010e72011-08-03 10:49:09 +02002129 .free_req = scsi_free_request,
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002130 .send_command = scsi_disk_emulate_command,
Paolo Bonzini314a3292012-02-08 10:26:21 +01002131 .read_data = scsi_disk_emulate_read_data,
2132 .write_data = scsi_disk_emulate_write_data,
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002133 .get_buf = scsi_get_buf,
2134};
2135
2136static const SCSIReqOps scsi_disk_dma_reqops = {
2137 .size = sizeof(SCSIDiskReq),
2138 .free_req = scsi_free_request,
2139 .send_command = scsi_disk_dma_command,
Paolo Bonzini12010e72011-08-03 10:49:09 +02002140 .read_data = scsi_read_data,
2141 .write_data = scsi_write_data,
2142 .cancel_io = scsi_cancel_io,
2143 .get_buf = scsi_get_buf,
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002144 .load_request = scsi_disk_load_request,
2145 .save_request = scsi_disk_save_request,
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02002146};
2147
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002148static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
2149 [TEST_UNIT_READY] = &scsi_disk_emulate_reqops,
2150 [INQUIRY] = &scsi_disk_emulate_reqops,
2151 [MODE_SENSE] = &scsi_disk_emulate_reqops,
2152 [MODE_SENSE_10] = &scsi_disk_emulate_reqops,
2153 [START_STOP] = &scsi_disk_emulate_reqops,
2154 [ALLOW_MEDIUM_REMOVAL] = &scsi_disk_emulate_reqops,
2155 [READ_CAPACITY_10] = &scsi_disk_emulate_reqops,
2156 [READ_TOC] = &scsi_disk_emulate_reqops,
2157 [READ_DVD_STRUCTURE] = &scsi_disk_emulate_reqops,
2158 [READ_DISC_INFORMATION] = &scsi_disk_emulate_reqops,
2159 [GET_CONFIGURATION] = &scsi_disk_emulate_reqops,
2160 [GET_EVENT_STATUS_NOTIFICATION] = &scsi_disk_emulate_reqops,
2161 [MECHANISM_STATUS] = &scsi_disk_emulate_reqops,
2162 [SERVICE_ACTION_IN_16] = &scsi_disk_emulate_reqops,
2163 [REQUEST_SENSE] = &scsi_disk_emulate_reqops,
2164 [SYNCHRONIZE_CACHE] = &scsi_disk_emulate_reqops,
2165 [SEEK_10] = &scsi_disk_emulate_reqops,
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002166 [MODE_SELECT] = &scsi_disk_emulate_reqops,
2167 [MODE_SELECT_10] = &scsi_disk_emulate_reqops,
Paolo Bonzini5222aaf2012-08-09 11:00:22 +02002168 [UNMAP] = &scsi_disk_emulate_reqops,
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002169 [WRITE_SAME_10] = &scsi_disk_emulate_reqops,
2170 [WRITE_SAME_16] = &scsi_disk_emulate_reqops,
2171
2172 [READ_6] = &scsi_disk_dma_reqops,
2173 [READ_10] = &scsi_disk_dma_reqops,
2174 [READ_12] = &scsi_disk_dma_reqops,
2175 [READ_16] = &scsi_disk_dma_reqops,
2176 [VERIFY_10] = &scsi_disk_dma_reqops,
2177 [VERIFY_12] = &scsi_disk_dma_reqops,
2178 [VERIFY_16] = &scsi_disk_dma_reqops,
2179 [WRITE_6] = &scsi_disk_dma_reqops,
2180 [WRITE_10] = &scsi_disk_dma_reqops,
2181 [WRITE_12] = &scsi_disk_dma_reqops,
2182 [WRITE_16] = &scsi_disk_dma_reqops,
2183 [WRITE_VERIFY_10] = &scsi_disk_dma_reqops,
2184 [WRITE_VERIFY_12] = &scsi_disk_dma_reqops,
2185 [WRITE_VERIFY_16] = &scsi_disk_dma_reqops,
2186};
2187
Paolo Bonzini63db0f02011-10-12 12:58:31 +02002188static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
2189 uint8_t *buf, void *hba_private)
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02002190{
2191 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
2192 SCSIRequest *req;
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002193 const SCSIReqOps *ops;
2194 uint8_t command;
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02002195
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002196 command = buf[0];
2197 ops = scsi_disk_reqops_dispatch[command];
2198 if (!ops) {
2199 ops = &scsi_disk_emulate_reqops;
2200 }
2201 req = scsi_req_alloc(ops, &s->qdev, tag, lun, hba_private);
Paolo Bonzini79fb50b2012-07-31 16:10:23 +02002202
2203#ifdef DEBUG_SCSI
2204 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
2205 {
2206 int i;
2207 for (i = 1; i < req->cmd.len; i++) {
2208 printf(" 0x%02x", buf[i]);
2209 }
2210 printf("\n");
2211 }
2212#endif
2213
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02002214 return req;
2215}
2216
Paolo Bonzini336a6912011-10-25 12:53:37 +02002217#ifdef __linux__
2218static int get_device_type(SCSIDiskState *s)
2219{
2220 BlockDriverState *bdrv = s->qdev.conf.bs;
2221 uint8_t cmd[16];
2222 uint8_t buf[36];
2223 uint8_t sensebuf[8];
2224 sg_io_hdr_t io_header;
2225 int ret;
2226
2227 memset(cmd, 0, sizeof(cmd));
2228 memset(buf, 0, sizeof(buf));
2229 cmd[0] = INQUIRY;
2230 cmd[4] = sizeof(buf);
2231
2232 memset(&io_header, 0, sizeof(io_header));
2233 io_header.interface_id = 'S';
2234 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
2235 io_header.dxfer_len = sizeof(buf);
2236 io_header.dxferp = buf;
2237 io_header.cmdp = cmd;
2238 io_header.cmd_len = sizeof(cmd);
2239 io_header.mx_sb_len = sizeof(sensebuf);
2240 io_header.sbp = sensebuf;
2241 io_header.timeout = 6000; /* XXX */
2242
2243 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
2244 if (ret < 0 || io_header.driver_status || io_header.host_status) {
2245 return -1;
2246 }
2247 s->qdev.type = buf[0];
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002248 if (buf[1] & 0x80) {
2249 s->features |= 1 << SCSI_DISK_F_REMOVABLE;
2250 }
Paolo Bonzini336a6912011-10-25 12:53:37 +02002251 return 0;
2252}
2253
2254static int scsi_block_initfn(SCSIDevice *dev)
2255{
2256 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
2257 int sg_version;
2258 int rc;
2259
2260 if (!s->qdev.conf.bs) {
2261 error_report("scsi-block: drive property not set");
2262 return -1;
2263 }
2264
2265 /* check we are using a driver managing SG_IO (version 3 and after) */
2266 if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
2267 sg_version < 30000) {
2268 error_report("scsi-block: scsi generic interface too old");
2269 return -1;
2270 }
2271
2272 /* get device type from INQUIRY data */
2273 rc = get_device_type(s);
2274 if (rc < 0) {
2275 error_report("scsi-block: INQUIRY failed");
2276 return -1;
2277 }
2278
2279 /* Make a guess for the block size, we'll fix it when the guest sends.
2280 * READ CAPACITY. If they don't, they likely would assume these sizes
2281 * anyway. (TODO: check in /sys).
2282 */
2283 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
2284 s->qdev.blocksize = 2048;
2285 } else {
2286 s->qdev.blocksize = 512;
2287 }
2288 return scsi_initfn(&s->qdev);
2289}
2290
2291static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
2292 uint32_t lun, uint8_t *buf,
2293 void *hba_private)
2294{
2295 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
2296
2297 switch (buf[0]) {
2298 case READ_6:
2299 case READ_10:
2300 case READ_12:
2301 case READ_16:
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +02002302 case VERIFY_10:
2303 case VERIFY_12:
2304 case VERIFY_16:
Paolo Bonzini336a6912011-10-25 12:53:37 +02002305 case WRITE_6:
2306 case WRITE_10:
2307 case WRITE_12:
2308 case WRITE_16:
2309 case WRITE_VERIFY_10:
2310 case WRITE_VERIFY_12:
2311 case WRITE_VERIFY_16:
Paolo Bonzinieaccf492012-02-15 14:11:22 +01002312 /* If we are not using O_DIRECT, we might read stale data from the
2313 * host cache if writes were made using other commands than these
2314 * ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without
2315 * O_DIRECT everything must go through SG_IO.
2316 */
Markus Armbruster137745c2012-06-05 16:49:25 +02002317 if (bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE) {
Paolo Bonzinieaccf492012-02-15 14:11:22 +01002318 break;
2319 }
2320
Paolo Bonzini33ebad12011-11-14 14:31:52 +01002321 /* MMC writing cannot be done via pread/pwrite, because it sometimes
2322 * involves writing beyond the maximum LBA or to negative LBA (lead-in).
2323 * And once you do these writes, reading from the block device is
2324 * unreliable, too. It is even possible that reads deliver random data
2325 * from the host page cache (this is probably a Linux bug).
2326 *
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002327 * We might use scsi_disk_dma_reqops as long as no writing commands are
Paolo Bonzini33ebad12011-11-14 14:31:52 +01002328 * seen, but performance usually isn't paramount on optical media. So,
2329 * just make scsi-block operate the same as scsi-generic for them.
2330 */
Paolo Bonzinib08d0ea2012-02-08 09:53:42 +01002331 if (s->qdev.type != TYPE_ROM) {
2332 return scsi_req_alloc(&scsi_disk_dma_reqops, &s->qdev, tag, lun,
2333 hba_private);
2334 }
Paolo Bonzini336a6912011-10-25 12:53:37 +02002335 }
2336
2337 return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
2338 hba_private);
2339}
2340#endif
2341
Dmitry Fleytman353815a2012-07-06 22:03:35 -07002342#define DEFINE_SCSI_DISK_PROPERTIES() \
2343 DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \
2344 DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
2345 DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
2346 DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
2347 DEFINE_PROP_STRING("product", SCSIDiskState, product)
Markus Armbrusterb443ae62011-05-16 15:04:53 +02002348
Anthony Liguori39bffca2011-12-07 21:34:16 -06002349static Property scsi_hd_properties[] = {
2350 DEFINE_SCSI_DISK_PROPERTIES(),
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002351 DEFINE_PROP_BIT("removable", SCSIDiskState, features,
2352 SCSI_DISK_F_REMOVABLE, false),
Paolo Bonzinida8365d2012-05-01 10:25:16 +02002353 DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
2354 SCSI_DISK_F_DPOFUA, false),
Paolo Bonzini27395ad2012-05-15 12:46:09 +02002355 DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
Markus Armbrusterd252df42012-07-10 11:12:42 +02002356 DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
Anthony Liguori39bffca2011-12-07 21:34:16 -06002357 DEFINE_PROP_END_OF_LIST(),
2358};
2359
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002360static const VMStateDescription vmstate_scsi_disk_state = {
2361 .name = "scsi-disk",
2362 .version_id = 1,
2363 .minimum_version_id = 1,
2364 .minimum_version_id_old = 1,
2365 .fields = (VMStateField[]) {
2366 VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
2367 VMSTATE_BOOL(media_changed, SCSIDiskState),
2368 VMSTATE_BOOL(media_event, SCSIDiskState),
2369 VMSTATE_BOOL(eject_request, SCSIDiskState),
2370 VMSTATE_BOOL(tray_open, SCSIDiskState),
2371 VMSTATE_BOOL(tray_locked, SCSIDiskState),
2372 VMSTATE_END_OF_LIST()
2373 }
2374};
2375
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002376static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
2377{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002378 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002379 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2380
2381 sc->init = scsi_hd_initfn;
2382 sc->destroy = scsi_destroy;
2383 sc->alloc_req = scsi_new_request;
2384 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002385 dc->fw_name = "disk";
2386 dc->desc = "virtual SCSI disk";
2387 dc->reset = scsi_disk_reset;
2388 dc->props = scsi_hd_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002389 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002390}
2391
Anthony Liguori39bffca2011-12-07 21:34:16 -06002392static TypeInfo scsi_hd_info = {
2393 .name = "scsi-hd",
2394 .parent = TYPE_SCSI_DEVICE,
2395 .instance_size = sizeof(SCSIDiskState),
2396 .class_init = scsi_hd_class_initfn,
2397};
2398
2399static Property scsi_cd_properties[] = {
2400 DEFINE_SCSI_DISK_PROPERTIES(),
Paolo Bonzini27395ad2012-05-15 12:46:09 +02002401 DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
Anthony Liguori39bffca2011-12-07 21:34:16 -06002402 DEFINE_PROP_END_OF_LIST(),
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002403};
2404
2405static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
2406{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002407 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002408 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2409
2410 sc->init = scsi_cd_initfn;
2411 sc->destroy = scsi_destroy;
2412 sc->alloc_req = scsi_new_request;
2413 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002414 dc->fw_name = "disk";
2415 dc->desc = "virtual SCSI CD-ROM";
2416 dc->reset = scsi_disk_reset;
2417 dc->props = scsi_cd_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002418 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002419}
2420
Anthony Liguori39bffca2011-12-07 21:34:16 -06002421static TypeInfo scsi_cd_info = {
2422 .name = "scsi-cd",
2423 .parent = TYPE_SCSI_DEVICE,
2424 .instance_size = sizeof(SCSIDiskState),
2425 .class_init = scsi_cd_class_initfn,
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002426};
2427
Paolo Bonzini336a6912011-10-25 12:53:37 +02002428#ifdef __linux__
Anthony Liguori39bffca2011-12-07 21:34:16 -06002429static Property scsi_block_properties[] = {
Paolo Bonzini03847832012-07-09 12:11:04 +02002430 DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
Paolo Bonzini0f1da442012-08-28 12:46:18 +02002431 DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
Anthony Liguori39bffca2011-12-07 21:34:16 -06002432 DEFINE_PROP_END_OF_LIST(),
2433};
2434
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002435static void scsi_block_class_initfn(ObjectClass *klass, void *data)
2436{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002437 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002438 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2439
2440 sc->init = scsi_block_initfn;
2441 sc->destroy = scsi_destroy;
2442 sc->alloc_req = scsi_block_new_request;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002443 dc->fw_name = "disk";
2444 dc->desc = "SCSI block device passthrough";
2445 dc->reset = scsi_disk_reset;
2446 dc->props = scsi_block_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002447 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002448}
2449
Anthony Liguori39bffca2011-12-07 21:34:16 -06002450static TypeInfo scsi_block_info = {
2451 .name = "scsi-block",
2452 .parent = TYPE_SCSI_DEVICE,
2453 .instance_size = sizeof(SCSIDiskState),
2454 .class_init = scsi_block_class_initfn,
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002455};
Paolo Bonzini336a6912011-10-25 12:53:37 +02002456#endif
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002457
Anthony Liguori39bffca2011-12-07 21:34:16 -06002458static Property scsi_disk_properties[] = {
2459 DEFINE_SCSI_DISK_PROPERTIES(),
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002460 DEFINE_PROP_BIT("removable", SCSIDiskState, features,
2461 SCSI_DISK_F_REMOVABLE, false),
Paolo Bonzinida8365d2012-05-01 10:25:16 +02002462 DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
2463 SCSI_DISK_F_DPOFUA, false),
Paolo Bonzini27395ad2012-05-15 12:46:09 +02002464 DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
Anthony Liguori39bffca2011-12-07 21:34:16 -06002465 DEFINE_PROP_END_OF_LIST(),
2466};
2467
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002468static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
2469{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002470 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002471 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2472
2473 sc->init = scsi_disk_initfn;
2474 sc->destroy = scsi_destroy;
2475 sc->alloc_req = scsi_new_request;
2476 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002477 dc->fw_name = "disk";
2478 dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
2479 dc->reset = scsi_disk_reset;
2480 dc->props = scsi_disk_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002481 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002482}
2483
Anthony Liguori39bffca2011-12-07 21:34:16 -06002484static TypeInfo scsi_disk_info = {
2485 .name = "scsi-disk",
2486 .parent = TYPE_SCSI_DEVICE,
2487 .instance_size = sizeof(SCSIDiskState),
2488 .class_init = scsi_disk_class_initfn,
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002489};
2490
Andreas Färber83f7d432012-02-09 15:20:55 +01002491static void scsi_disk_register_types(void)
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002492{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002493 type_register_static(&scsi_hd_info);
2494 type_register_static(&scsi_cd_info);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002495#ifdef __linux__
Anthony Liguori39bffca2011-12-07 21:34:16 -06002496 type_register_static(&scsi_block_info);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002497#endif
Anthony Liguori39bffca2011-12-07 21:34:16 -06002498 type_register_static(&scsi_disk_info);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002499}
Andreas Färber83f7d432012-02-09 15:20:55 +01002500
2501type_init(scsi_disk_register_types)