blob: ae2519458cc88c7a7be32057e7e602c2b9b15f5a [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"
Paolo Bonzini5d0d2462011-10-12 15:12:14 +020037#include "dma.h"
blueswir122864252008-10-11 09:33:03 +000038
Paolo Bonzini336a6912011-10-25 12:53:37 +020039#ifdef __linux
40#include <scsi/sg.h>
41#endif
42
aurel32f0f72ff2008-10-01 21:46:23 +000043#define SCSI_DMA_BUF_SIZE 131072
balrog57575052008-12-07 03:12:54 +000044#define SCSI_MAX_INQUIRY_LEN 256
pbrooka917d382006-08-29 04:52:16 +000045
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020046typedef struct SCSIDiskState SCSIDiskState;
47
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010048typedef struct SCSIDiskReq {
49 SCSIRequest req;
pbrooka917d382006-08-29 04:52:16 +000050 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
aliguorie035b432009-01-28 21:58:22 +000051 uint64_t sector;
52 uint32_t sector_count;
Paolo Bonzini72854772011-09-16 16:40:04 +020053 uint32_t buflen;
Paolo Bonzinia0e66a62012-04-19 11:51:42 +020054 bool started;
aliguoric87c0672009-04-07 18:43:20 +000055 struct iovec iov;
56 QEMUIOVector qiov;
Christoph Hellwiga597e792011-08-25 08:26:01 +020057 BlockAcctCookie acct;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010058} SCSIDiskReq;
pbrooka917d382006-08-29 04:52:16 +000059
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020060#define SCSI_DISK_F_REMOVABLE 0
Paolo Bonzinida8365d2012-05-01 10:25:16 +020061#define SCSI_DISK_F_DPOFUA 1
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020062
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020063struct SCSIDiskState
pbrook2e5d83b2006-05-25 23:58:51 +000064{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020065 SCSIDevice qdev;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +020066 uint32_t features;
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +020067 bool media_changed;
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +020068 bool media_event;
Paolo Bonzini4480de12011-10-25 12:53:40 +020069 bool eject_request;
Markus Armbruster213189a2009-07-28 14:33:41 -040070 QEMUBH *bh;
Gerd Hoffmann383b4d92010-01-14 14:44:13 +010071 char *version;
Markus Armbrustera0fef652010-06-01 20:32:34 +020072 char *serial;
Markus Armbrusterece0d5e2011-09-06 18:58:40 +020073 bool tray_open;
Markus Armbruster81b10082011-09-06 18:58:44 +020074 bool tray_locked;
pbrook2e5d83b2006-05-25 23:58:51 +000075};
76
Paolo Bonzini71544d32011-10-25 12:53:36 +020077static int scsi_handle_rw_error(SCSIDiskReq *r, int error);
Kevin Wolf5dba48a2010-10-25 14:52:21 +020078
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020079static void scsi_free_request(SCSIRequest *req)
pbrook4d611c92006-08-12 01:04:27 +000080{
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020081 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
82
Paolo Bonzini72854772011-09-16 16:40:04 +020083 if (r->iov.iov_base) {
84 qemu_vfree(r->iov.iov_base);
85 }
pbrooka917d382006-08-29 04:52:16 +000086}
87
Paolo Bonzinib45ef672011-08-03 10:49:07 +020088/* Helper function for command completion with sense. */
89static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
Gerd Hoffmanned3a34a2009-11-26 15:34:00 +010090{
Blue Swirl02fa69b2011-08-20 09:21:42 +000091 DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
92 r->req.tag, sense.key, sense.asc, sense.ascq);
Paolo Bonzinib45ef672011-08-03 10:49:07 +020093 scsi_req_build_sense(&r->req, sense);
94 scsi_req_complete(&r->req, CHECK_CONDITION);
pbrooka917d382006-08-29 04:52:16 +000095}
96
97/* Cancel a pending data transfer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020098static void scsi_cancel_io(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +000099{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200100 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
101
102 DPRINTF("Cancel tag=0x%x\n", req->tag);
103 if (r->req.aiocb) {
104 bdrv_aio_cancel(r->req.aiocb);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200105
106 /* This reference was left in by scsi_*_data. We take ownership of
107 * it the moment scsi_req_cancel is called, independent of whether
108 * bdrv_aio_cancel completes the request or not. */
109 scsi_req_unref(&r->req);
pbrooka917d382006-08-29 04:52:16 +0000110 }
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200111 r->req.aiocb = NULL;
pbrook4d611c92006-08-12 01:04:27 +0000112}
113
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500114static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200115{
Paolo Bonzini72854772011-09-16 16:40:04 +0200116 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
117
118 if (!r->iov.iov_base) {
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500119 r->buflen = size;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200120 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +0200121 }
122 r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200123 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
124 return r->qiov.size / 512;
125}
126
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500127static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
128{
129 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
130
131 qemu_put_be64s(f, &r->sector);
132 qemu_put_be32s(f, &r->sector_count);
133 qemu_put_be32s(f, &r->buflen);
Gerd Hoffmann18eef3b2012-05-16 14:20:03 +0200134 if (r->buflen) {
135 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
136 qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
137 } else if (!req->retry) {
138 uint32_t len = r->iov.iov_len;
139 qemu_put_be32s(f, &len);
140 qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
141 }
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500142 }
143}
144
145static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
146{
147 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
148
149 qemu_get_be64s(f, &r->sector);
150 qemu_get_be32s(f, &r->sector_count);
151 qemu_get_be32s(f, &r->buflen);
152 if (r->buflen) {
153 scsi_init_iovec(r, r->buflen);
154 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
155 qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
Gerd Hoffmann18eef3b2012-05-16 14:20:03 +0200156 } else if (!r->req.retry) {
157 uint32_t len;
158 qemu_get_be32s(f, &len);
159 r->iov.iov_len = len;
160 assert(r->iov.iov_len <= r->buflen);
161 qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500162 }
163 }
164
165 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
166}
167
Paolo Bonzinib77912a2012-04-19 10:05:04 +0200168static void scsi_flush_complete(void * opaque, int ret)
169{
170 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
171 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
172
173 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
174
175 if (ret < 0) {
176 if (scsi_handle_rw_error(r, -ret)) {
177 goto done;
178 }
179 }
180
181 scsi_req_complete(&r->req, GOOD);
182
183done:
184 if (!r->req.io_canceled) {
185 scsi_req_unref(&r->req);
186 }
187}
188
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200189static bool scsi_is_cmd_fua(SCSICommand *cmd)
190{
191 switch (cmd->buf[0]) {
192 case READ_10:
193 case READ_12:
194 case READ_16:
195 case WRITE_10:
196 case WRITE_12:
197 case WRITE_16:
198 return (cmd->buf[1] & 8) != 0;
199
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +0200200 case VERIFY_10:
201 case VERIFY_12:
202 case VERIFY_16:
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200203 case WRITE_VERIFY_10:
204 case WRITE_VERIFY_12:
205 case WRITE_VERIFY_16:
206 return true;
207
208 case READ_6:
209 case WRITE_6:
210 default:
211 return false;
212 }
213}
214
215static void scsi_write_do_fua(SCSIDiskReq *r)
216{
217 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
218
219 if (scsi_is_cmd_fua(&r->req.cmd)) {
220 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
221 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
222 return;
223 }
224
225 scsi_req_complete(&r->req, GOOD);
226 if (!r->req.io_canceled) {
227 scsi_req_unref(&r->req);
228 }
229}
230
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200231static void scsi_dma_complete(void *opaque, int ret)
232{
233 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
234 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
235
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +0200236 if (r->req.aiocb != NULL) {
237 r->req.aiocb = NULL;
238 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
239 }
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200240
Paolo Bonzini80624c92012-04-19 14:00:24 +0200241 if (ret < 0) {
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200242 if (scsi_handle_rw_error(r, -ret)) {
243 goto done;
244 }
245 }
246
247 r->sector += r->sector_count;
248 r->sector_count = 0;
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200249 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
250 scsi_write_do_fua(r);
251 return;
252 } else {
253 scsi_req_complete(&r->req, GOOD);
254 }
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200255
256done:
Paolo Bonzinib8aba8d2012-04-19 10:09:49 +0200257 if (!r->req.io_canceled) {
258 scsi_req_unref(&r->req);
259 }
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200260}
261
pbrook4d611c92006-08-12 01:04:27 +0000262static void scsi_read_complete(void * opaque, int ret)
263{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100264 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200265 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200266 int n;
pbrook4d611c92006-08-12 01:04:27 +0000267
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200268 if (r->req.aiocb != NULL) {
269 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200270 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200271 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200272
Paolo Bonzini80624c92012-04-19 14:00:24 +0200273 if (ret < 0) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200274 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200275 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200276 }
pbrook4d611c92006-08-12 01:04:27 +0000277 }
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200278
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200279 DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
pbrooka917d382006-08-29 04:52:16 +0000280
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200281 n = r->qiov.size / 512;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200282 r->sector += n;
283 r->sector_count -= n;
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200284 scsi_req_data(&r->req, r->qiov.size);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200285
286done:
287 if (!r->req.io_canceled) {
288 scsi_req_unref(&r->req);
289 }
pbrook4d611c92006-08-12 01:04:27 +0000290}
291
Paolo Bonziniac668422012-04-19 11:55:28 +0200292/* Actually issue a read to the block device. */
293static void scsi_do_read(void *opaque, int ret)
294{
295 SCSIDiskReq *r = opaque;
296 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
297 uint32_t n;
298
299 if (r->req.aiocb != NULL) {
300 r->req.aiocb = NULL;
301 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
302 }
303
304 if (ret < 0) {
305 if (scsi_handle_rw_error(r, -ret)) {
306 goto done;
307 }
308 }
309
Paolo Bonzini31e8fd82012-04-24 08:41:04 +0200310 if (r->req.io_canceled) {
311 return;
312 }
313
314 /* The request is used as the AIO opaque value, so add a ref. */
315 scsi_req_ref(&r->req);
316
Paolo Bonziniac668422012-04-19 11:55:28 +0200317 if (r->req.sg) {
318 dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
319 r->req.resid -= r->req.sg->size;
320 r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
321 scsi_dma_complete, r);
322 } else {
323 n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
324 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
325 r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
326 scsi_read_complete, r);
327 }
328
329done:
330 if (!r->req.io_canceled) {
331 scsi_req_unref(&r->req);
332 }
333}
334
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200335/* Read more data from scsi device into buffer. */
336static void scsi_read_data(SCSIRequest *req)
pbrook2e5d83b2006-05-25 23:58:51 +0000337{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200338 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200339 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonziniac668422012-04-19 11:55:28 +0200340 bool first;
pbrook2e5d83b2006-05-25 23:58:51 +0000341
pbrooka917d382006-08-29 04:52:16 +0000342 if (r->sector_count == (uint32_t)-1) {
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +0200343 DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
pbrooka917d382006-08-29 04:52:16 +0000344 r->sector_count = 0;
Paolo Bonzinia0e66a62012-04-19 11:51:42 +0200345 r->started = true;
Paolo Bonziniab9adc82011-04-18 14:59:13 +0200346 scsi_req_data(&r->req, r->iov.iov_len);
pbrooka917d382006-08-29 04:52:16 +0000347 return;
348 }
349 DPRINTF("Read sector_count=%d\n", r->sector_count);
350 if (r->sector_count == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200351 /* This also clears the sense buffer for REQUEST SENSE. */
352 scsi_req_complete(&r->req, GOOD);
pbrooka917d382006-08-29 04:52:16 +0000353 return;
pbrook2e5d83b2006-05-25 23:58:51 +0000354 }
355
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000356 /* No data transfer may already be in progress */
357 assert(r->req.aiocb == NULL);
358
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200359 /* The request is used as the AIO opaque value, so add a ref. */
360 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200361 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
362 DPRINTF("Data transfer direction invalid\n");
363 scsi_read_complete(r, -EINVAL);
364 return;
365 }
366
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200367 if (s->tray_open) {
368 scsi_read_complete(r, -ENOMEDIUM);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200369 return;
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200370 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200371
Paolo Bonziniac668422012-04-19 11:55:28 +0200372 first = !r->started;
Paolo Bonzinia0e66a62012-04-19 11:51:42 +0200373 r->started = true;
Paolo Bonziniac668422012-04-19 11:55:28 +0200374 if (first && scsi_is_cmd_fua(&r->req.cmd)) {
375 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
376 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_do_read, r);
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200377 } else {
Paolo Bonziniac668422012-04-19 11:55:28 +0200378 scsi_do_read(r, 0);
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200379 }
pbrook2e5d83b2006-05-25 23:58:51 +0000380}
381
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200382/*
383 * scsi_handle_rw_error has two return values. 0 means that the error
384 * must be ignored, 1 means that the error has been processed and the
385 * caller should not do anything else for this request. Note that
386 * scsi_handle_rw_error always manages its reference counts, independent
387 * of the return value.
388 */
Paolo Bonzini71544d32011-10-25 12:53:36 +0200389static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200390{
Paolo Bonzini71544d32011-10-25 12:53:36 +0200391 int is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100392 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonzini44740c32011-10-12 12:54:16 +0200393 BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000394
Luiz Capitulino380f6402010-02-03 12:41:03 -0200395 if (action == BLOCK_ERR_IGNORE) {
Luiz Capitulino329c0a42012-01-25 16:59:43 -0200396 bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000397 return 0;
Luiz Capitulino380f6402010-02-03 12:41:03 -0200398 }
aliguoriea8a5d72009-01-22 19:52:21 +0000399
400 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
401 || action == BLOCK_ERR_STOP_ANY) {
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200402
Luiz Capitulino329c0a42012-01-25 16:59:43 -0200403 bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
Luiz Capitulino0461d5a2011-09-30 14:45:27 -0300404 vm_stop(RUN_STATE_IO_ERROR);
Paolo Bonzini44740c32011-10-12 12:54:16 +0200405 bdrv_iostatus_set_err(s->qdev.conf.bs, error);
Paolo Bonzini71544d32011-10-25 12:53:36 +0200406 scsi_req_retry(&r->req);
aliguoriea8a5d72009-01-22 19:52:21 +0000407 } else {
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200408 switch (error) {
Paolo Bonzini7e218df2011-09-19 17:19:21 +0200409 case ENOMEDIUM:
410 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
411 break;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200412 case ENOMEM:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200413 scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200414 break;
415 case EINVAL:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200416 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200417 break;
418 default:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200419 scsi_check_condition(r, SENSE_CODE(IO_ERROR));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200420 break;
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200421 }
Luiz Capitulino329c0a42012-01-25 16:59:43 -0200422 bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000423 }
aliguoriea8a5d72009-01-22 19:52:21 +0000424 return 1;
425}
426
pbrook4d611c92006-08-12 01:04:27 +0000427static void scsi_write_complete(void * opaque, int ret)
428{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100429 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200430 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000431 uint32_t n;
pbrook4d611c92006-08-12 01:04:27 +0000432
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200433 if (r->req.aiocb != NULL) {
434 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200435 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200436 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200437
Paolo Bonzini80624c92012-04-19 14:00:24 +0200438 if (ret < 0) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200439 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200440 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200441 }
aliguoriea8a5d72009-01-22 19:52:21 +0000442 }
443
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200444 n = r->qiov.size / 512;
aliguoriea8a5d72009-01-22 19:52:21 +0000445 r->sector += n;
446 r->sector_count -= n;
pbrooka917d382006-08-29 04:52:16 +0000447 if (r->sector_count == 0) {
Paolo Bonzini7e8c49c2012-04-19 10:10:54 +0200448 scsi_write_do_fua(r);
449 return;
pbrooka917d382006-08-29 04:52:16 +0000450 } else {
Paolo Bonzini43b978b2011-12-15 07:24:47 -0500451 scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200452 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
453 scsi_req_data(&r->req, r->qiov.size);
pbrook4d611c92006-08-12 01:04:27 +0000454 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200455
456done:
457 if (!r->req.io_canceled) {
458 scsi_req_unref(&r->req);
459 }
pbrook4d611c92006-08-12 01:04:27 +0000460}
461
Paolo Bonzini42741212011-04-22 09:39:16 +0200462static void scsi_write_data(SCSIRequest *req)
aliguoriea8a5d72009-01-22 19:52:21 +0000463{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200464 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100465 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000466 uint32_t n;
467
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000468 /* No data transfer may already be in progress */
469 assert(r->req.aiocb == NULL);
470
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200471 /* The request is used as the AIO opaque value, so add a ref. */
472 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200473 if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
474 DPRINTF("Data transfer direction invalid\n");
475 scsi_write_complete(r, -EINVAL);
Paolo Bonzini42741212011-04-22 09:39:16 +0200476 return;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200477 }
478
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200479 if (!r->req.sg && !r->qiov.size) {
480 /* Called for the first time. Ask the driver to send us more data. */
Paolo Bonzinia0e66a62012-04-19 11:51:42 +0200481 r->started = true;
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200482 scsi_write_complete(r, 0);
483 return;
484 }
485 if (s->tray_open) {
486 scsi_write_complete(r, -ENOMEDIUM);
487 return;
488 }
489
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +0200490 if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 ||
491 r->req.cmd.buf[0] == VERIFY_16) {
492 if (r->req.sg) {
493 scsi_dma_complete(r, 0);
494 } else {
495 scsi_write_complete(r, 0);
496 }
497 return;
498 }
499
Paolo Bonzini5d0d2462011-10-12 15:12:14 +0200500 if (r->req.sg) {
501 dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
502 r->req.resid -= r->req.sg->size;
503 r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
504 scsi_dma_complete, r);
505 } else {
506 n = r->qiov.size / 512;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200507 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
508 r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200509 scsi_write_complete, r);
aliguoriea8a5d72009-01-22 19:52:21 +0000510 }
pbrook2e5d83b2006-05-25 23:58:51 +0000511}
512
pbrooka917d382006-08-29 04:52:16 +0000513/* Return a pointer to the data buffer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200514static uint8_t *scsi_get_buf(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +0000515{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200516 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
pbrooka917d382006-08-29 04:52:16 +0000517
blueswir13f4cb3d2009-04-13 16:31:01 +0000518 return (uint8_t *)r->iov.iov_base;
pbrooka917d382006-08-29 04:52:16 +0000519}
520
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100521static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
522{
Gerd Hoffmann383b4d92010-01-14 14:44:13 +0100523 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100524 int buflen = 0;
525
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100526 if (req->cmd.buf[1] & 0x1) {
527 /* Vital product data */
528 uint8_t page_code = req->cmd.buf[2];
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100529
Paolo Bonzinie39be482011-10-12 14:27:40 +0200530 outbuf[buflen++] = s->qdev.type & 0x1f;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100531 outbuf[buflen++] = page_code ; // this page
532 outbuf[buflen++] = 0x00;
533
534 switch (page_code) {
535 case 0x00: /* Supported page codes, mandatory */
Hannes Reinecke39d98982010-11-24 12:15:58 +0100536 {
537 int pages;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100538 DPRINTF("Inquiry EVPD[Supported pages] "
539 "buffer size %zd\n", req->cmd.xfer);
Hannes Reinecke39d98982010-11-24 12:15:58 +0100540 pages = buflen++;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100541 outbuf[buflen++] = 0x00; // list of supported pages (this page)
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200542 if (s->serial) {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200543 outbuf[buflen++] = 0x80; // unit serial number
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200544 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100545 outbuf[buflen++] = 0x83; // device identification
Hannes Reineckef37bd732011-07-22 16:44:46 +0200546 if (s->qdev.type == TYPE_DISK) {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100547 outbuf[buflen++] = 0xb0; // block limits
548 outbuf[buflen++] = 0xb2; // thin provisioning
Hannes Reinecke39d98982010-11-24 12:15:58 +0100549 }
550 outbuf[pages] = buflen - pages - 1; // number of pages
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100551 break;
Hannes Reinecke39d98982010-11-24 12:15:58 +0100552 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100553 case 0x80: /* Device serial number, optional */
554 {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200555 int l;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100556
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200557 if (!s->serial) {
558 DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
559 return -1;
560 }
561
562 l = strlen(s->serial);
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200563 if (l > 20) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100564 l = 20;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200565 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100566
567 DPRINTF("Inquiry EVPD[Serial number] "
568 "buffer size %zd\n", req->cmd.xfer);
569 outbuf[buflen++] = l;
Markus Armbrustera0fef652010-06-01 20:32:34 +0200570 memcpy(outbuf+buflen, s->serial, l);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100571 buflen += l;
572 break;
573 }
574
575 case 0x83: /* Device identification page, mandatory */
576 {
Paolo Bonzinifd930792012-03-16 19:12:43 +0100577 const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
578 int max_len = s->serial ? 20 : 255 - 8;
579 int id_len = strlen(str);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100580
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200581 if (id_len > max_len) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100582 id_len = max_len;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200583 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100584 DPRINTF("Inquiry EVPD[Device identification] "
585 "buffer size %zd\n", req->cmd.xfer);
586
Hannes Reinecke39d98982010-11-24 12:15:58 +0100587 outbuf[buflen++] = 4 + id_len;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100588 outbuf[buflen++] = 0x2; // ASCII
589 outbuf[buflen++] = 0; // not officially assigned
590 outbuf[buflen++] = 0; // reserved
591 outbuf[buflen++] = id_len; // length of data following
592
Paolo Bonzinifd930792012-03-16 19:12:43 +0100593 memcpy(outbuf+buflen, str, id_len);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100594 buflen += id_len;
595 break;
596 }
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100597 case 0xb0: /* block limits */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100598 {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100599 unsigned int unmap_sectors =
600 s->qdev.conf.discard_granularity / s->qdev.blocksize;
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100601 unsigned int min_io_size =
602 s->qdev.conf.min_io_size / s->qdev.blocksize;
603 unsigned int opt_io_size =
604 s->qdev.conf.opt_io_size / s->qdev.blocksize;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100605
Hannes Reineckef37bd732011-07-22 16:44:46 +0200606 if (s->qdev.type == TYPE_ROM) {
Hannes Reinecke39d98982010-11-24 12:15:58 +0100607 DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
608 page_code);
609 return -1;
610 }
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100611 /* required VPD size with unmap support */
612 outbuf[3] = buflen = 0x3c;
613
614 memset(outbuf + 4, 0, buflen - 4);
615
616 /* optimal transfer length granularity */
617 outbuf[6] = (min_io_size >> 8) & 0xff;
618 outbuf[7] = min_io_size & 0xff;
619
620 /* optimal transfer length */
621 outbuf[12] = (opt_io_size >> 24) & 0xff;
622 outbuf[13] = (opt_io_size >> 16) & 0xff;
623 outbuf[14] = (opt_io_size >> 8) & 0xff;
624 outbuf[15] = opt_io_size & 0xff;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100625
626 /* optimal unmap granularity */
627 outbuf[28] = (unmap_sectors >> 24) & 0xff;
628 outbuf[29] = (unmap_sectors >> 16) & 0xff;
629 outbuf[30] = (unmap_sectors >> 8) & 0xff;
630 outbuf[31] = unmap_sectors & 0xff;
631 break;
632 }
633 case 0xb2: /* thin provisioning */
634 {
635 outbuf[3] = buflen = 8;
636 outbuf[4] = 0;
Ronnie Sahlbergc9e4d822012-04-19 20:41:16 +1000637 outbuf[5] = 0x60; /* write_same 10/16 supported */
Ronnie Sahlbergf644a292012-04-19 20:41:17 +1000638 outbuf[6] = s->qdev.conf.discard_granularity ? 2 : 1;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100639 outbuf[7] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100640 break;
641 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100642 default:
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100643 return -1;
644 }
645 /* done with EVPD */
646 return buflen;
647 }
648
649 /* Standard INQUIRY data */
650 if (req->cmd.buf[2] != 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100651 return -1;
652 }
653
654 /* PAGE CODE == 0 */
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100655 buflen = req->cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200656 if (buflen > SCSI_MAX_INQUIRY_LEN) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100657 buflen = SCSI_MAX_INQUIRY_LEN;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200658 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100659 memset(outbuf, 0, buflen);
660
Hannes Reineckef37bd732011-07-22 16:44:46 +0200661 outbuf[0] = s->qdev.type & 0x1f;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +0200662 outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0;
Hannes Reineckef37bd732011-07-22 16:44:46 +0200663 if (s->qdev.type == TYPE_ROM) {
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100664 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100665 } else {
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100666 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100667 }
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100668 memcpy(&outbuf[8], "QEMU ", 8);
Gerd Hoffmann314b1812010-03-10 17:47:17 +0100669 memset(&outbuf[32], 0, 4);
Markus Armbruster552fee92010-06-01 20:32:35 +0200670 memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
Christoph Hellwig99aba0c2010-03-04 14:45:44 +0100671 /*
672 * We claim conformance to SPC-3, which is required for guests
673 * to ask for modern features like READ CAPACITY(16) or the
674 * block characteristics VPD page by default. Not all of SPC-3
675 * is actually implemented, but we're good enough.
676 */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100677 outbuf[2] = 5;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100678 outbuf[3] = 2; /* Format 2 */
Artyom Tarasenkoad3cea42009-12-13 11:32:36 +0100679
680 if (buflen > 36) {
681 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
682 } else {
683 /* If the allocation length of CDB is too small,
684 the additional length is not adjusted */
685 outbuf[4] = 36 - 5;
686 }
687
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100688 /* Sync data transfer and TCQ. */
Paolo Bonziniafd40302011-08-13 15:44:45 +0200689 outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100690 return buflen;
691}
692
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200693static inline bool media_is_dvd(SCSIDiskState *s)
694{
695 uint64_t nb_sectors;
696 if (s->qdev.type != TYPE_ROM) {
697 return false;
698 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200699 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200700 return false;
701 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200702 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200703 return nb_sectors > CD_MAX_SECTORS;
704}
705
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200706static inline bool media_is_cd(SCSIDiskState *s)
707{
708 uint64_t nb_sectors;
709 if (s->qdev.type != TYPE_ROM) {
710 return false;
711 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200712 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200713 return false;
714 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200715 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200716 return nb_sectors <= CD_MAX_SECTORS;
717}
718
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200719static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
720 uint8_t *outbuf)
721{
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200722 static const int rds_caps_size[5] = {
723 [0] = 2048 + 4,
724 [1] = 4 + 4,
725 [3] = 188 + 4,
726 [4] = 2048 + 4,
727 };
728
729 uint8_t media = r->req.cmd.buf[1];
730 uint8_t layer = r->req.cmd.buf[6];
731 uint8_t format = r->req.cmd.buf[7];
732 int size = -1;
733
734 if (s->qdev.type != TYPE_ROM) {
735 return -1;
736 }
737 if (media != 0) {
738 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
739 return -1;
740 }
741
742 if (format != 0xff) {
Paolo Bonzini44740c32011-10-12 12:54:16 +0200743 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200744 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
745 return -1;
746 }
747 if (media_is_cd(s)) {
748 scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
749 return -1;
750 }
751 if (format >= ARRAY_SIZE(rds_caps_size)) {
752 return -1;
753 }
754 size = rds_caps_size[format];
755 memset(outbuf, 0, size);
756 }
757
758 switch (format) {
759 case 0x00: {
760 /* Physical format information */
761 uint64_t nb_sectors;
762 if (layer != 0) {
763 goto fail;
764 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200765 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200766
767 outbuf[4] = 1; /* DVD-ROM, part version 1 */
768 outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
769 outbuf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
770 outbuf[7] = 0; /* default densities */
771
772 stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
773 stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
774 break;
775 }
776
777 case 0x01: /* DVD copyright information, all zeros */
778 break;
779
780 case 0x03: /* BCA information - invalid field for no BCA info */
781 return -1;
782
783 case 0x04: /* DVD disc manufacturing information, all zeros */
784 break;
785
786 case 0xff: { /* List capabilities */
787 int i;
788 size = 4;
789 for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
790 if (!rds_caps_size[i]) {
791 continue;
792 }
793 outbuf[size] = i;
794 outbuf[size + 1] = 0x40; /* Not writable, readable */
795 stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
796 size += 4;
797 }
798 break;
799 }
800
801 default:
802 return -1;
803 }
804
805 /* Size of buffer, not including 2 byte size field */
806 stw_be_p(outbuf, size - 2);
807 return size;
808
809fail:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200810 return -1;
811}
812
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200813static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200814{
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200815 uint8_t event_code, media_status;
816
817 media_status = 0;
818 if (s->tray_open) {
819 media_status = MS_TRAY_OPEN;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200820 } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200821 media_status = MS_MEDIA_PRESENT;
822 }
823
824 /* Event notification descriptor */
825 event_code = MEC_NO_CHANGE;
Paolo Bonzini4480de12011-10-25 12:53:40 +0200826 if (media_status != MS_TRAY_OPEN) {
827 if (s->media_event) {
828 event_code = MEC_NEW_MEDIA;
829 s->media_event = false;
830 } else if (s->eject_request) {
831 event_code = MEC_EJECT_REQUESTED;
832 s->eject_request = false;
833 }
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200834 }
835
836 outbuf[0] = event_code;
837 outbuf[1] = media_status;
838
839 /* These fields are reserved, just clear them. */
840 outbuf[2] = 0;
841 outbuf[3] = 0;
842 return 4;
843}
844
845static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
846 uint8_t *outbuf)
847{
848 int size;
849 uint8_t *buf = r->req.cmd.buf;
850 uint8_t notification_class_request = buf[4];
851 if (s->qdev.type != TYPE_ROM) {
852 return -1;
853 }
854 if ((buf[1] & 1) == 0) {
855 /* asynchronous */
856 return -1;
857 }
858
859 size = 4;
860 outbuf[0] = outbuf[1] = 0;
861 outbuf[3] = 1 << GESN_MEDIA; /* supported events */
862 if (notification_class_request & (1 << GESN_MEDIA)) {
863 outbuf[2] = GESN_MEDIA;
864 size += scsi_event_status_media(s, &outbuf[size]);
865 } else {
866 outbuf[2] = 0x80;
867 }
868 stw_be_p(outbuf, size - 4);
869 return size;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200870}
871
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200872static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200873{
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200874 int current;
875
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200876 if (s->qdev.type != TYPE_ROM) {
877 return -1;
878 }
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200879 current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
880 memset(outbuf, 0, 40);
881 stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
882 stw_be_p(&outbuf[6], current);
883 /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
884 outbuf[10] = 0x03; /* persistent, current */
885 outbuf[11] = 8; /* two profiles */
886 stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
887 outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
888 stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
889 outbuf[18] = (current == MMC_PROFILE_CD_ROM);
890 /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
891 stw_be_p(&outbuf[20], 1);
892 outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
893 outbuf[23] = 8;
894 stl_be_p(&outbuf[24], 1); /* SCSI */
895 outbuf[28] = 1; /* DBE = 1, mandatory */
896 /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
897 stw_be_p(&outbuf[32], 3);
898 outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
899 outbuf[35] = 4;
900 outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
901 /* TODO: Random readable, CD read, DVD read, drive serial number,
902 power management */
903 return 40;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200904}
905
906static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
907{
908 if (s->qdev.type != TYPE_ROM) {
909 return -1;
910 }
911 memset(outbuf, 0, 8);
912 outbuf[5] = 1; /* CD-ROM */
913 return 8;
914}
915
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200916static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
Bernhard Kohl282ab042010-08-31 14:08:24 +0200917 int page_control)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100918{
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200919 static const int mode_sense_valid[0x3f] = {
920 [MODE_PAGE_HD_GEOMETRY] = (1 << TYPE_DISK),
921 [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
922 [MODE_PAGE_CACHING] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200923 [MODE_PAGE_R_W_ERROR] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
924 [MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200925 [MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
926 };
927
Paolo Bonzini44740c32011-10-12 12:54:16 +0200928 BlockDriverState *bdrv = s->qdev.conf.bs;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100929 int cylinders, heads, secs;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200930 uint8_t *p = *p_outbuf;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100931
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200932 if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
933 return -1;
934 }
935
936 p[0] = page;
937
Bernhard Kohl282ab042010-08-31 14:08:24 +0200938 /*
939 * If Changeable Values are requested, a mask denoting those mode parameters
940 * that are changeable shall be returned. As we currently don't support
941 * parameter changes via MODE_SELECT all bits are returned set to zero.
942 * The buffer was already menset to zero by the caller of this function.
943 */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100944 switch (page) {
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200945 case MODE_PAGE_HD_GEOMETRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100946 p[1] = 0x16;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200947 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200948 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200949 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100950 /* if a geometry hint is available, use it */
Paolo Bonzini245d0042011-11-15 16:57:50 +0100951 bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100952 p[2] = (cylinders >> 16) & 0xff;
953 p[3] = (cylinders >> 8) & 0xff;
954 p[4] = cylinders & 0xff;
955 p[5] = heads & 0xff;
956 /* Write precomp start cylinder, disabled */
957 p[6] = (cylinders >> 16) & 0xff;
958 p[7] = (cylinders >> 8) & 0xff;
959 p[8] = cylinders & 0xff;
960 /* Reduced current start cylinder, disabled */
961 p[9] = (cylinders >> 16) & 0xff;
962 p[10] = (cylinders >> 8) & 0xff;
963 p[11] = cylinders & 0xff;
964 /* Device step rate [ns], 200ns */
965 p[12] = 0;
966 p[13] = 200;
967 /* Landing zone cylinder */
968 p[14] = 0xff;
969 p[15] = 0xff;
970 p[16] = 0xff;
971 /* Medium rotation rate [rpm], 5400 rpm */
972 p[20] = (5400 >> 8) & 0xff;
973 p[21] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200974 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100975
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200976 case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100977 p[1] = 0x1e;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200978 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200979 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200980 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100981 /* Transfer rate [kbit/s], 5Mbit/s */
982 p[2] = 5000 >> 8;
983 p[3] = 5000 & 0xff;
984 /* if a geometry hint is available, use it */
Paolo Bonzini245d0042011-11-15 16:57:50 +0100985 bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100986 p[4] = heads & 0xff;
987 p[5] = secs & 0xff;
Paolo Bonzini69377302011-10-13 10:35:46 +0200988 p[6] = s->qdev.blocksize >> 8;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100989 p[8] = (cylinders >> 8) & 0xff;
990 p[9] = cylinders & 0xff;
991 /* Write precomp start cylinder, disabled */
992 p[10] = (cylinders >> 8) & 0xff;
993 p[11] = cylinders & 0xff;
994 /* Reduced current start cylinder, disabled */
995 p[12] = (cylinders >> 8) & 0xff;
996 p[13] = cylinders & 0xff;
997 /* Device step rate [100us], 100us */
998 p[14] = 0;
999 p[15] = 1;
1000 /* Device step pulse width [us], 1us */
1001 p[16] = 1;
1002 /* Device head settle delay [100us], 100us */
1003 p[17] = 0;
1004 p[18] = 1;
1005 /* Motor on delay [0.1s], 0.1s */
1006 p[19] = 1;
1007 /* Motor off delay [0.1s], 0.1s */
1008 p[20] = 1;
1009 /* Medium rotation rate [rpm], 5400 rpm */
1010 p[28] = (5400 >> 8) & 0xff;
1011 p[29] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001012 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001013
Paolo Bonzini67cc61e2011-09-13 14:41:56 +02001014 case MODE_PAGE_CACHING:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001015 p[0] = 8;
1016 p[1] = 0x12;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001017 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001018 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001019 }
Paolo Bonzini44740c32011-10-12 12:54:16 +02001020 if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001021 p[2] = 4; /* WCE */
1022 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001023 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001024
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001025 case MODE_PAGE_R_W_ERROR:
1026 p[1] = 10;
1027 p[2] = 0x80; /* Automatic Write Reallocation Enabled */
1028 if (s->qdev.type == TYPE_ROM) {
1029 p[3] = 0x20; /* Read Retry Count */
1030 }
1031 break;
1032
1033 case MODE_PAGE_AUDIO_CTL:
1034 p[1] = 14;
1035 break;
1036
Paolo Bonzini67cc61e2011-09-13 14:41:56 +02001037 case MODE_PAGE_CAPABILITIES:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001038 p[1] = 0x14;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001039 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001040 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001041 }
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001042
1043 p[2] = 0x3b; /* CD-R & CD-RW read */
1044 p[3] = 0; /* Writing not supported */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001045 p[4] = 0x7f; /* Audio, composite, digital out,
1046 mode 2 form 1&2, multi session */
1047 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
1048 RW corrected, C2 errors, ISRC,
1049 UPC, Bar code */
Markus Armbruster81b10082011-09-06 18:58:44 +02001050 p[6] = 0x2d | (s->tray_locked ? 2 : 0);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001051 /* Locking supported, jumper present, eject, tray */
1052 p[7] = 0; /* no volume & mute control, no
1053 changer */
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001054 p[8] = (50 * 176) >> 8; /* 50x read speed */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001055 p[9] = (50 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001056 p[10] = 2 >> 8; /* Two volume levels */
1057 p[11] = 2 & 0xff;
1058 p[12] = 2048 >> 8; /* 2M buffer */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001059 p[13] = 2048 & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001060 p[14] = (16 * 176) >> 8; /* 16x read speed current */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001061 p[15] = (16 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001062 p[18] = (16 * 176) >> 8; /* 16x write speed */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001063 p[19] = (16 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +02001064 p[20] = (16 * 176) >> 8; /* 16x write speed current */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001065 p[21] = (16 * 176) & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001066 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001067
1068 default:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001069 return -1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001070 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001071
1072 *p_outbuf += p[1] + 2;
1073 return p[1] + 2;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001074}
1075
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001076static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001077{
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001078 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001079 uint64_t nb_sectors;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001080 bool dbd;
1081 int page, buflen, ret, page_control;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001082 uint8_t *p;
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001083 uint8_t dev_specific_param;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001084
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001085 dbd = (r->req.cmd.buf[1] & 0x8) != 0;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001086 page = r->req.cmd.buf[2] & 0x3f;
1087 page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +02001088 DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001089 (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
1090 memset(outbuf, 0, r->req.cmd.xfer);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001091 p = outbuf;
1092
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001093 if (s->qdev.type == TYPE_DISK) {
Paolo Bonzinida8365d2012-05-01 10:25:16 +02001094 dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001095 if (bdrv_is_read_only(s->qdev.conf.bs)) {
1096 dev_specific_param |= 0x80; /* Readonly. */
1097 }
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001098 } else {
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001099 /* MMC prescribes that CD/DVD drives have no block descriptors,
1100 * and defines no device-specific parameter. */
Paolo Bonzini6a2de0f2012-04-19 10:28:15 +02001101 dev_specific_param = 0x00;
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001102 dbd = true;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001103 }
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001104
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001105 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001106 p[1] = 0; /* Default media type. */
1107 p[2] = dev_specific_param;
1108 p[3] = 0; /* Block descriptor length. */
1109 p += 4;
1110 } else { /* MODE_SENSE_10 */
1111 p[2] = 0; /* Default media type. */
1112 p[3] = dev_specific_param;
1113 p[6] = p[7] = 0; /* Block descriptor length. */
1114 p += 8;
1115 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001116
Paolo Bonzini44740c32011-10-12 12:54:16 +02001117 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinie590ecb2012-04-19 10:24:18 +02001118 if (!dbd && nb_sectors) {
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001119 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001120 outbuf[3] = 8; /* Block descriptor length */
1121 } else { /* MODE_SENSE_10 */
1122 outbuf[7] = 8; /* Block descriptor length */
1123 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001124 nb_sectors /= (s->qdev.blocksize / 512);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001125 if (nb_sectors > 0xffffff) {
Bernhard Kohl2488b742010-08-31 14:08:25 +02001126 nb_sectors = 0;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001127 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001128 p[0] = 0; /* media density code */
1129 p[1] = (nb_sectors >> 16) & 0xff;
1130 p[2] = (nb_sectors >> 8) & 0xff;
1131 p[3] = nb_sectors & 0xff;
1132 p[4] = 0; /* reserved */
1133 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
Paolo Bonzini69377302011-10-13 10:35:46 +02001134 p[6] = s->qdev.blocksize >> 8;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001135 p[7] = 0;
1136 p += 8;
1137 }
1138
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001139 if (page_control == 3) {
1140 /* Saved Values */
1141 scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
1142 return -1;
Bernhard Kohl282ab042010-08-31 14:08:24 +02001143 }
1144
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001145 if (page == 0x3f) {
1146 for (page = 0; page <= 0x3e; page++) {
1147 mode_sense_page(s, page, &p, page_control);
1148 }
1149 } else {
1150 ret = mode_sense_page(s, page, &p, page_control);
1151 if (ret == -1) {
1152 return -1;
1153 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001154 }
1155
1156 buflen = p - outbuf;
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001157 /*
1158 * The mode data length field specifies the length in bytes of the
1159 * following data that is available to be transferred. The mode data
1160 * length does not include itself.
1161 */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001162 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001163 outbuf[0] = buflen - 1;
1164 } else { /* MODE_SENSE_10 */
1165 outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1166 outbuf[1] = (buflen - 2) & 0xff;
1167 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001168 return buflen;
1169}
1170
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001171static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1172{
1173 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001174 int start_track, format, msf, toclen;
1175 uint64_t nb_sectors;
1176
1177 msf = req->cmd.buf[1] & 2;
1178 format = req->cmd.buf[2] & 0xf;
1179 start_track = req->cmd.buf[6];
Paolo Bonzini44740c32011-10-12 12:54:16 +02001180 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001181 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
Paolo Bonzini69377302011-10-13 10:35:46 +02001182 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001183 switch (format) {
1184 case 0:
1185 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1186 break;
1187 case 1:
1188 /* multi session : only a single session defined */
1189 toclen = 12;
1190 memset(outbuf, 0, 12);
1191 outbuf[1] = 0x0a;
1192 outbuf[2] = 0x01;
1193 outbuf[3] = 0x01;
1194 break;
1195 case 2:
1196 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1197 break;
1198 default:
1199 return -1;
1200 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001201 return toclen;
1202}
1203
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001204static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001205{
1206 SCSIRequest *req = &r->req;
1207 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1208 bool start = req->cmd.buf[4] & 1;
1209 bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
1210
1211 if (s->qdev.type == TYPE_ROM && loej) {
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001212 if (!start && !s->tray_open && s->tray_locked) {
1213 scsi_check_condition(r,
Paolo Bonzini44740c32011-10-12 12:54:16 +02001214 bdrv_is_inserted(s->qdev.conf.bs)
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001215 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1216 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1217 return -1;
Markus Armbrusterfdec4402011-09-06 18:58:45 +02001218 }
Luiz Capitulinod88b1812012-02-17 11:05:21 -02001219
1220 if (s->tray_open != !start) {
1221 bdrv_eject(s->qdev.conf.bs, !start);
1222 s->tray_open = !start;
1223 }
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001224 }
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001225 return 0;
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001226}
1227
Paolo Bonzini72854772011-09-16 16:40:04 +02001228static int scsi_disk_emulate_command(SCSIDiskReq *r)
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001229{
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001230 SCSIRequest *req = &r->req;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001231 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001232 uint64_t nb_sectors;
Paolo Bonzini72854772011-09-16 16:40:04 +02001233 uint8_t *outbuf;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001234 int buflen = 0;
1235
Paolo Bonzini72854772011-09-16 16:40:04 +02001236 if (!r->iov.iov_base) {
1237 /*
1238 * FIXME: we shouldn't return anything bigger than 4k, but the code
1239 * requires the buffer to be as big as req->cmd.xfer in several
1240 * places. So, do not allow CDBs with a very large ALLOCATION
1241 * LENGTH. The real fix would be to modify scsi_read_data and
1242 * dma_buf_read, so that they return data beyond the buflen
1243 * as all zeros.
1244 */
1245 if (req->cmd.xfer > 65536) {
1246 goto illegal_request;
1247 }
1248 r->buflen = MAX(4096, req->cmd.xfer);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001249 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +02001250 }
1251
1252 outbuf = r->iov.iov_base;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001253 switch (req->cmd.buf[0]) {
1254 case TEST_UNIT_READY:
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001255 assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001256 break;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001257 case INQUIRY:
1258 buflen = scsi_disk_emulate_inquiry(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001259 if (buflen < 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001260 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001261 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001262 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001263 case MODE_SENSE:
1264 case MODE_SENSE_10:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001265 buflen = scsi_disk_emulate_mode_sense(r, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001266 if (buflen < 0) {
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001267 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001268 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001269 break;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001270 case READ_TOC:
1271 buflen = scsi_disk_emulate_read_toc(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001272 if (buflen < 0) {
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001273 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001274 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001275 break;
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001276 case RESERVE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001277 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001278 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001279 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001280 break;
1281 case RESERVE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001282 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001283 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001284 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001285 break;
1286 case RELEASE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001287 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001288 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001289 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001290 break;
1291 case RELEASE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001292 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001293 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001294 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001295 break;
Gerd Hoffmann8d3628f2009-11-26 15:34:07 +01001296 case START_STOP:
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001297 if (scsi_disk_emulate_start_stop(r) < 0) {
1298 return -1;
1299 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001300 break;
Gerd Hoffmannc68b9f32009-11-26 15:34:08 +01001301 case ALLOW_MEDIUM_REMOVAL:
Markus Armbruster81b10082011-09-06 18:58:44 +02001302 s->tray_locked = req->cmd.buf[4] & 1;
Paolo Bonzini44740c32011-10-12 12:54:16 +02001303 bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001304 break;
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001305 case READ_CAPACITY_10:
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001306 /* The normal LEN field for this command is zero. */
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001307 memset(outbuf, 0, 8);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001308 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001309 if (!nb_sectors) {
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001310 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1311 return -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001312 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001313 if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
1314 goto illegal_request;
1315 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001316 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001317 /* Returned value is the address of the last sector. */
1318 nb_sectors--;
1319 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001320 s->qdev.max_lba = nb_sectors;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001321 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001322 if (nb_sectors > UINT32_MAX) {
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001323 nb_sectors = UINT32_MAX;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001324 }
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001325 outbuf[0] = (nb_sectors >> 24) & 0xff;
1326 outbuf[1] = (nb_sectors >> 16) & 0xff;
1327 outbuf[2] = (nb_sectors >> 8) & 0xff;
1328 outbuf[3] = nb_sectors & 0xff;
1329 outbuf[4] = 0;
1330 outbuf[5] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001331 outbuf[6] = s->qdev.blocksize >> 8;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001332 outbuf[7] = 0;
1333 buflen = 8;
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001334 break;
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001335 case REQUEST_SENSE:
1336 /* Just return "NO SENSE". */
1337 buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
1338 (req->cmd.buf[1] & 1) == 0);
1339 break;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001340 case MECHANISM_STATUS:
1341 buflen = scsi_emulate_mechanism_status(s, outbuf);
1342 if (buflen < 0) {
1343 goto illegal_request;
1344 }
1345 break;
Gerd Hoffmann38215552009-11-26 15:34:12 +01001346 case GET_CONFIGURATION:
Paolo Bonzini430ee2f2011-09-13 15:22:31 +02001347 buflen = scsi_get_configuration(s, outbuf);
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001348 if (buflen < 0) {
1349 goto illegal_request;
1350 }
1351 break;
1352 case GET_EVENT_STATUS_NOTIFICATION:
1353 buflen = scsi_get_event_status_notification(s, r, outbuf);
1354 if (buflen < 0) {
1355 goto illegal_request;
1356 }
1357 break;
1358 case READ_DVD_STRUCTURE:
1359 buflen = scsi_read_dvd_structure(s, r, outbuf);
1360 if (buflen < 0) {
1361 goto illegal_request;
1362 }
Gerd Hoffmann38215552009-11-26 15:34:12 +01001363 break;
Paolo Bonzinif6515262011-09-06 12:31:42 +02001364 case SERVICE_ACTION_IN_16:
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001365 /* Service Action In subcommands. */
Paolo Bonzinif6515262011-09-06 12:31:42 +02001366 if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001367 DPRINTF("SAI READ CAPACITY(16)\n");
1368 memset(outbuf, 0, req->cmd.xfer);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001369 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001370 if (!nb_sectors) {
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001371 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1372 return -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001373 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001374 if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1375 goto illegal_request;
1376 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001377 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001378 /* Returned value is the address of the last sector. */
1379 nb_sectors--;
1380 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001381 s->qdev.max_lba = nb_sectors;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001382 outbuf[0] = (nb_sectors >> 56) & 0xff;
1383 outbuf[1] = (nb_sectors >> 48) & 0xff;
1384 outbuf[2] = (nb_sectors >> 40) & 0xff;
1385 outbuf[3] = (nb_sectors >> 32) & 0xff;
1386 outbuf[4] = (nb_sectors >> 24) & 0xff;
1387 outbuf[5] = (nb_sectors >> 16) & 0xff;
1388 outbuf[6] = (nb_sectors >> 8) & 0xff;
1389 outbuf[7] = nb_sectors & 0xff;
1390 outbuf[8] = 0;
1391 outbuf[9] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001392 outbuf[10] = s->qdev.blocksize >> 8;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001393 outbuf[11] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +01001394 outbuf[12] = 0;
1395 outbuf[13] = get_physical_block_exp(&s->qdev.conf);
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001396
1397 /* set TPE bit if the format supports discard */
1398 if (s->qdev.conf.discard_granularity) {
1399 outbuf[14] = 0x80;
1400 }
1401
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001402 /* Protection, exponent and lowest lba field left blank. */
1403 buflen = req->cmd.xfer;
1404 break;
1405 }
1406 DPRINTF("Unsupported Service Action In\n");
1407 goto illegal_request;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001408 default:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001409 scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +02001410 return -1;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001411 }
Thomas Higdone2f0c492012-01-24 12:19:44 -05001412 buflen = MIN(buflen, req->cmd.xfer);
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001413 return buflen;
1414
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001415illegal_request:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001416 if (r->req.status == -1) {
1417 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1418 }
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001419 return -1;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001420}
1421
pbrook2e5d83b2006-05-25 23:58:51 +00001422/* Execute a scsi command. Returns the length of the data expected by the
1423 command. This will be Positive for data transfers from the device
1424 (eg. disk reads), negative for transfers to the device (eg. disk writes),
1425 and zero if the command does not transfer any data. */
1426
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001427static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
pbrook2e5d83b2006-05-25 23:58:51 +00001428{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001429 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1430 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Paolo Bonziniad2d30f2011-04-18 16:01:56 +02001431 int32_t len;
pbrooka917d382006-08-29 04:52:16 +00001432 uint8_t command;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001433 int rc;
pbrook2e5d83b2006-05-25 23:58:51 +00001434
pbrooka917d382006-08-29 04:52:16 +00001435 command = buf[0];
Hannes Reinecke653c1c32011-07-11 15:02:25 +02001436 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001437
pbrook2e5d83b2006-05-25 23:58:51 +00001438#ifdef DEBUG_SCSI
1439 {
1440 int i;
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001441 for (i = 1; i < r->req.cmd.len; i++) {
pbrook2e5d83b2006-05-25 23:58:51 +00001442 printf(" 0x%02x", buf[i]);
1443 }
1444 printf("\n");
1445 }
1446#endif
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001447
pbrooka917d382006-08-29 04:52:16 +00001448 switch (command) {
Paolo Bonzini9bcaf4f2012-03-16 19:11:43 +01001449 case INQUIRY:
1450 case MODE_SENSE:
1451 case MODE_SENSE_10:
1452 case RESERVE:
1453 case RESERVE_10:
1454 case RELEASE:
1455 case RELEASE_10:
1456 case START_STOP:
1457 case ALLOW_MEDIUM_REMOVAL:
1458 case GET_CONFIGURATION:
1459 case GET_EVENT_STATUS_NOTIFICATION:
1460 case MECHANISM_STATUS:
1461 case REQUEST_SENSE:
1462 break;
1463
1464 default:
1465 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1466 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1467 return 0;
1468 }
1469 break;
1470 }
1471
1472 switch (command) {
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001473 case TEST_UNIT_READY:
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001474 case INQUIRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001475 case MODE_SENSE:
1476 case MODE_SENSE_10:
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001477 case RESERVE:
1478 case RESERVE_10:
1479 case RELEASE:
1480 case RELEASE_10:
Gerd Hoffmann8d3628f2009-11-26 15:34:07 +01001481 case START_STOP:
Gerd Hoffmannc68b9f32009-11-26 15:34:08 +01001482 case ALLOW_MEDIUM_REMOVAL:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001483 case READ_CAPACITY_10:
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001484 case READ_TOC:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001485 case READ_DVD_STRUCTURE:
Gerd Hoffmann38215552009-11-26 15:34:12 +01001486 case GET_CONFIGURATION:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001487 case GET_EVENT_STATUS_NOTIFICATION:
1488 case MECHANISM_STATUS:
Paolo Bonzinif6515262011-09-06 12:31:42 +02001489 case SERVICE_ACTION_IN_16:
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001490 case REQUEST_SENSE:
Paolo Bonzini72854772011-09-16 16:40:04 +02001491 rc = scsi_disk_emulate_command(r);
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001492 if (rc < 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001493 return 0;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001494 }
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001495
1496 r->iov.iov_len = rc;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001497 break;
Paolo Bonzini0a4ac102011-09-06 09:08:34 +02001498 case SYNCHRONIZE_CACHE:
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +02001499 /* The request is used as the AIO opaque value, so add a ref. */
1500 scsi_req_ref(&r->req);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001501 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1502 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
Paolo Bonzini0a4ac102011-09-06 09:08:34 +02001503 return 0;
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001504 case READ_6:
1505 case READ_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001506 case READ_12:
1507 case READ_16:
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001508 len = r->req.cmd.xfer / s->qdev.blocksize;
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001509 DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
Paolo Bonzini78779032011-10-13 10:39:50 +02001510 if (r->req.cmd.lba > s->qdev.max_lba) {
aliguori274fb0e2009-01-29 19:59:04 +00001511 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001512 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001513 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1514 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001515 break;
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +02001516 case VERIFY_10:
1517 case VERIFY_12:
1518 case VERIFY_16:
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001519 case WRITE_6:
1520 case WRITE_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001521 case WRITE_12:
1522 case WRITE_16:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001523 case WRITE_VERIFY_10:
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001524 case WRITE_VERIFY_12:
1525 case WRITE_VERIFY_16:
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001526 len = r->req.cmd.xfer / s->qdev.blocksize;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001527 DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001528 (command & 0xe) == 0xe ? "And Verify " : "",
1529 r->req.cmd.lba, len);
Paolo Bonzini78779032011-10-13 10:39:50 +02001530 if (r->req.cmd.lba > s->qdev.max_lba) {
aliguori274fb0e2009-01-29 19:59:04 +00001531 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001532 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001533 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1534 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001535 break;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001536 case MODE_SELECT:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001537 DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001538 /* We don't support mode parameter changes.
1539 Allow the mode parameter header + block descriptors only. */
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001540 if (r->req.cmd.xfer > 12) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001541 goto fail;
1542 }
1543 break;
1544 case MODE_SELECT_10:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001545 DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001546 /* We don't support mode parameter changes.
1547 Allow the mode parameter header + block descriptors only. */
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001548 if (r->req.cmd.xfer > 16) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001549 goto fail;
1550 }
1551 break;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001552 case SEEK_10:
Paolo Bonzini00a01ad2011-11-14 14:31:48 +01001553 DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
Paolo Bonzini78779032011-10-13 10:39:50 +02001554 if (r->req.cmd.lba > s->qdev.max_lba) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001555 goto illegal_lba;
1556 }
1557 break;
Ronnie Sahlbergc9e4d822012-04-19 20:41:16 +10001558 case WRITE_SAME_10:
Paolo Bonzinia5ee9082012-02-08 10:40:37 +01001559 len = lduw_be_p(&buf[7]);
1560 goto write_same;
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001561 case WRITE_SAME_16:
Paolo Bonzinia5ee9082012-02-08 10:40:37 +01001562 len = ldl_be_p(&buf[10]) & 0xffffffffULL;
1563 write_same:
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001564
Ronnie Sahlbergc9e4d822012-04-19 20:41:16 +10001565 DPRINTF("WRITE SAME() (sector %" PRId64 ", count %d)\n",
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001566 r->req.cmd.lba, len);
1567
Paolo Bonzini78779032011-10-13 10:39:50 +02001568 if (r->req.cmd.lba > s->qdev.max_lba) {
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001569 goto illegal_lba;
1570 }
1571
1572 /*
1573 * We only support WRITE SAME with the unmap bit set for now.
1574 */
1575 if (!(buf[1] & 0x8)) {
1576 goto fail;
1577 }
1578
Paolo Bonzini69377302011-10-13 10:35:46 +02001579 rc = bdrv_discard(s->qdev.conf.bs,
1580 r->req.cmd.lba * (s->qdev.blocksize / 512),
1581 len * (s->qdev.blocksize / 512));
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001582 if (rc < 0) {
1583 /* XXX: better error code ?*/
1584 goto fail;
1585 }
1586
1587 break;
pbrook2e5d83b2006-05-25 23:58:51 +00001588 default:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001589 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001590 scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +02001591 return 0;
pbrook2e5d83b2006-05-25 23:58:51 +00001592 fail:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001593 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001594 return 0;
aliguori274fb0e2009-01-29 19:59:04 +00001595 illegal_lba:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001596 scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
aliguori274fb0e2009-01-29 19:59:04 +00001597 return 0;
pbrook2e5d83b2006-05-25 23:58:51 +00001598 }
aliguoric87c0672009-04-07 18:43:20 +00001599 if (r->sector_count == 0 && r->iov.iov_len == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001600 scsi_req_complete(&r->req, GOOD);
pbrook2e5d83b2006-05-25 23:58:51 +00001601 }
aliguoric87c0672009-04-07 18:43:20 +00001602 len = r->sector_count * 512 + r->iov.iov_len;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +02001603 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1604 return -len;
pbrooka917d382006-08-29 04:52:16 +00001605 } else {
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001606 if (!r->sector_count) {
pbrooka917d382006-08-29 04:52:16 +00001607 r->sector_count = -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001608 }
Hannes Reineckeefb9ee02011-04-18 12:57:22 +02001609 return len;
pbrooka917d382006-08-29 04:52:16 +00001610 }
pbrook2e5d83b2006-05-25 23:58:51 +00001611}
1612
Jan Kiszkae9447f32010-05-04 14:20:59 +02001613static void scsi_disk_reset(DeviceState *dev)
1614{
1615 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1616 uint64_t nb_sectors;
1617
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001618 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
Jan Kiszkae9447f32010-05-04 14:20:59 +02001619
Paolo Bonzini44740c32011-10-12 12:54:16 +02001620 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini69377302011-10-13 10:35:46 +02001621 nb_sectors /= s->qdev.blocksize / 512;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001622 if (nb_sectors) {
1623 nb_sectors--;
1624 }
Paolo Bonzini78779032011-10-13 10:39:50 +02001625 s->qdev.max_lba = nb_sectors;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001626}
1627
1628static void scsi_destroy(SCSIDevice *dev)
1629{
1630 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1631
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001632 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001633 blockdev_mark_auto_del(s->qdev.conf.bs);
Gerd Hoffmann56a14932009-09-25 21:42:46 +02001634}
1635
Markus Armbruster7d4b4ba2011-09-06 18:58:59 +02001636static void scsi_cd_change_media_cb(void *opaque, bool load)
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001637{
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001638 SCSIDiskState *s = opaque;
1639
1640 /*
1641 * When a CD gets changed, we have to report an ejected state and
1642 * then a loaded state to guests so that they detect tray
1643 * open/close and media change events. Guests that do not use
1644 * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1645 * states rely on this behavior.
1646 *
1647 * media_changed governs the state machine used for unit attention
1648 * report. media_event is used by GET EVENT STATUS NOTIFICATION.
1649 */
1650 s->media_changed = load;
1651 s->tray_open = !load;
1652 s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +02001653 s->media_event = true;
Paolo Bonzini4480de12011-10-25 12:53:40 +02001654 s->eject_request = false;
1655}
1656
1657static void scsi_cd_eject_request_cb(void *opaque, bool force)
1658{
1659 SCSIDiskState *s = opaque;
1660
1661 s->eject_request = true;
1662 if (force) {
1663 s->tray_locked = false;
1664 }
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001665}
1666
Markus Armbrustere4def802011-09-06 18:58:53 +02001667static bool scsi_cd_is_tray_open(void *opaque)
1668{
1669 return ((SCSIDiskState *)opaque)->tray_open;
1670}
1671
Markus Armbrusterf1076392011-09-06 18:58:46 +02001672static bool scsi_cd_is_medium_locked(void *opaque)
1673{
1674 return ((SCSIDiskState *)opaque)->tray_locked;
1675}
1676
1677static const BlockDevOps scsi_cd_block_ops = {
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001678 .change_media_cb = scsi_cd_change_media_cb,
Paolo Bonzini4480de12011-10-25 12:53:40 +02001679 .eject_request_cb = scsi_cd_eject_request_cb,
Markus Armbrustere4def802011-09-06 18:58:53 +02001680 .is_tray_open = scsi_cd_is_tray_open,
Markus Armbrusterf1076392011-09-06 18:58:46 +02001681 .is_medium_locked = scsi_cd_is_medium_locked,
1682};
1683
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001684static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
1685{
1686 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1687 if (s->media_changed) {
1688 s->media_changed = false;
1689 s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
1690 }
1691}
1692
Paolo Bonzinie39be482011-10-12 14:27:40 +02001693static int scsi_initfn(SCSIDevice *dev)
pbrook2e5d83b2006-05-25 23:58:51 +00001694{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001695 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001696 DriveInfo *dinfo;
pbrook2e5d83b2006-05-25 23:58:51 +00001697
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001698 if (!s->qdev.conf.bs) {
Markus Armbruster6a84cb12011-12-21 11:37:57 +01001699 error_report("drive property not set");
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001700 return -1;
1701 }
1702
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02001703 if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
1704 !bdrv_is_inserted(s->qdev.conf.bs)) {
Markus Armbruster98f28ad2010-07-06 14:37:44 +02001705 error_report("Device needs media, but drive is empty");
1706 return -1;
1707 }
1708
Markus Armbrustera0fef652010-06-01 20:32:34 +02001709 if (!s->serial) {
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001710 /* try to fall back to value set with legacy -drive serial=... */
Paolo Bonzini44740c32011-10-12 12:54:16 +02001711 dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +02001712 if (*dinfo->serial) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001713 s->serial = g_strdup(dinfo->serial);
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +02001714 }
Markus Armbrustera0fef652010-06-01 20:32:34 +02001715 }
1716
Markus Armbruster552fee92010-06-01 20:32:35 +02001717 if (!s->version) {
Crístian Viana93bfef42012-05-30 00:35:51 -03001718 s->version = g_strdup(qemu_get_version());
Markus Armbruster552fee92010-06-01 20:32:35 +02001719 }
1720
Paolo Bonzini44740c32011-10-12 12:54:16 +02001721 if (bdrv_is_sg(s->qdev.conf.bs)) {
Markus Armbruster6a84cb12011-12-21 11:37:57 +01001722 error_report("unwanted /dev/sg*");
Markus Armbruster32bb4042010-02-25 11:23:52 +01001723 return -1;
1724 }
1725
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02001726 if (s->features & (1 << SCSI_DISK_F_REMOVABLE)) {
Paolo Bonzini44740c32011-10-12 12:54:16 +02001727 bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
pbrook2e5d83b2006-05-25 23:58:51 +00001728 }
Paolo Bonzini44740c32011-10-12 12:54:16 +02001729 bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
Christoph Hellwig8cfacf02010-03-04 14:20:17 +01001730
Paolo Bonzini44740c32011-10-12 12:54:16 +02001731 bdrv_iostatus_enable(s->qdev.conf.bs);
Paolo Bonzini70828262011-11-15 17:36:38 +01001732 add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001733 return 0;
ths8ccc2ac2007-12-10 02:58:34 +00001734}
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001735
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001736static int scsi_hd_initfn(SCSIDevice *dev)
1737{
Paolo Bonzinie39be482011-10-12 14:27:40 +02001738 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1739 s->qdev.blocksize = s->qdev.conf.logical_block_size;
1740 s->qdev.type = TYPE_DISK;
1741 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001742}
1743
1744static int scsi_cd_initfn(SCSIDevice *dev)
1745{
Paolo Bonzinie39be482011-10-12 14:27:40 +02001746 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1747 s->qdev.blocksize = 2048;
1748 s->qdev.type = TYPE_ROM;
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02001749 s->features |= 1 << SCSI_DISK_F_REMOVABLE;
Paolo Bonzinie39be482011-10-12 14:27:40 +02001750 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001751}
1752
1753static int scsi_disk_initfn(SCSIDevice *dev)
1754{
Markus Armbruster95b5edc2011-05-16 15:04:56 +02001755 DriveInfo *dinfo;
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001756
1757 if (!dev->conf.bs) {
Paolo Bonzinie39be482011-10-12 14:27:40 +02001758 return scsi_initfn(dev); /* ... and die there */
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001759 }
1760
Paolo Bonzinie39be482011-10-12 14:27:40 +02001761 dinfo = drive_get_by_blockdev(dev->conf.bs);
1762 if (dinfo->media_cd) {
1763 return scsi_cd_initfn(dev);
1764 } else {
1765 return scsi_hd_initfn(dev);
1766 }
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001767}
1768
Paolo Bonziniadcf2752011-10-12 12:57:59 +02001769static const SCSIReqOps scsi_disk_reqops = {
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001770 .size = sizeof(SCSIDiskReq),
Paolo Bonzini12010e72011-08-03 10:49:09 +02001771 .free_req = scsi_free_request,
1772 .send_command = scsi_send_command,
1773 .read_data = scsi_read_data,
1774 .write_data = scsi_write_data,
1775 .cancel_io = scsi_cancel_io,
1776 .get_buf = scsi_get_buf,
Paolo Bonzini43b978b2011-12-15 07:24:47 -05001777 .load_request = scsi_disk_load_request,
1778 .save_request = scsi_disk_save_request,
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001779};
1780
Paolo Bonzini63db0f02011-10-12 12:58:31 +02001781static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
1782 uint8_t *buf, void *hba_private)
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001783{
1784 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1785 SCSIRequest *req;
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001786
1787 req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001788 return req;
1789}
1790
Paolo Bonzini336a6912011-10-25 12:53:37 +02001791#ifdef __linux__
1792static int get_device_type(SCSIDiskState *s)
1793{
1794 BlockDriverState *bdrv = s->qdev.conf.bs;
1795 uint8_t cmd[16];
1796 uint8_t buf[36];
1797 uint8_t sensebuf[8];
1798 sg_io_hdr_t io_header;
1799 int ret;
1800
1801 memset(cmd, 0, sizeof(cmd));
1802 memset(buf, 0, sizeof(buf));
1803 cmd[0] = INQUIRY;
1804 cmd[4] = sizeof(buf);
1805
1806 memset(&io_header, 0, sizeof(io_header));
1807 io_header.interface_id = 'S';
1808 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
1809 io_header.dxfer_len = sizeof(buf);
1810 io_header.dxferp = buf;
1811 io_header.cmdp = cmd;
1812 io_header.cmd_len = sizeof(cmd);
1813 io_header.mx_sb_len = sizeof(sensebuf);
1814 io_header.sbp = sensebuf;
1815 io_header.timeout = 6000; /* XXX */
1816
1817 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
1818 if (ret < 0 || io_header.driver_status || io_header.host_status) {
1819 return -1;
1820 }
1821 s->qdev.type = buf[0];
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02001822 if (buf[1] & 0x80) {
1823 s->features |= 1 << SCSI_DISK_F_REMOVABLE;
1824 }
Paolo Bonzini336a6912011-10-25 12:53:37 +02001825 return 0;
1826}
1827
1828static int scsi_block_initfn(SCSIDevice *dev)
1829{
1830 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1831 int sg_version;
1832 int rc;
1833
1834 if (!s->qdev.conf.bs) {
1835 error_report("scsi-block: drive property not set");
1836 return -1;
1837 }
1838
1839 /* check we are using a driver managing SG_IO (version 3 and after) */
1840 if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
1841 sg_version < 30000) {
1842 error_report("scsi-block: scsi generic interface too old");
1843 return -1;
1844 }
1845
1846 /* get device type from INQUIRY data */
1847 rc = get_device_type(s);
1848 if (rc < 0) {
1849 error_report("scsi-block: INQUIRY failed");
1850 return -1;
1851 }
1852
1853 /* Make a guess for the block size, we'll fix it when the guest sends.
1854 * READ CAPACITY. If they don't, they likely would assume these sizes
1855 * anyway. (TODO: check in /sys).
1856 */
1857 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
1858 s->qdev.blocksize = 2048;
1859 } else {
1860 s->qdev.blocksize = 512;
1861 }
1862 return scsi_initfn(&s->qdev);
1863}
1864
1865static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
1866 uint32_t lun, uint8_t *buf,
1867 void *hba_private)
1868{
1869 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1870
1871 switch (buf[0]) {
1872 case READ_6:
1873 case READ_10:
1874 case READ_12:
1875 case READ_16:
Paolo Bonzini7f64f8e2012-04-19 11:46:13 +02001876 case VERIFY_10:
1877 case VERIFY_12:
1878 case VERIFY_16:
Paolo Bonzini336a6912011-10-25 12:53:37 +02001879 case WRITE_6:
1880 case WRITE_10:
1881 case WRITE_12:
1882 case WRITE_16:
1883 case WRITE_VERIFY_10:
1884 case WRITE_VERIFY_12:
1885 case WRITE_VERIFY_16:
Paolo Bonzinieaccf492012-02-15 14:11:22 +01001886 /* If we are not using O_DIRECT, we might read stale data from the
1887 * host cache if writes were made using other commands than these
1888 * ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without
1889 * O_DIRECT everything must go through SG_IO.
1890 */
Markus Armbruster137745c2012-06-05 16:49:25 +02001891 if (bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE) {
Paolo Bonzinieaccf492012-02-15 14:11:22 +01001892 break;
1893 }
1894
Paolo Bonzini33ebad12011-11-14 14:31:52 +01001895 /* MMC writing cannot be done via pread/pwrite, because it sometimes
1896 * involves writing beyond the maximum LBA or to negative LBA (lead-in).
1897 * And once you do these writes, reading from the block device is
1898 * unreliable, too. It is even possible that reads deliver random data
1899 * from the host page cache (this is probably a Linux bug).
1900 *
1901 * We might use scsi_disk_reqops as long as no writing commands are
1902 * seen, but performance usually isn't paramount on optical media. So,
1903 * just make scsi-block operate the same as scsi-generic for them.
1904 */
Paolo Bonzinieaccf492012-02-15 14:11:22 +01001905 if (s->qdev.type == TYPE_ROM) {
1906 break;
1907 }
1908 return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
1909 hba_private);
Paolo Bonzini336a6912011-10-25 12:53:37 +02001910 }
1911
1912 return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
1913 hba_private);
1914}
1915#endif
1916
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001917#define DEFINE_SCSI_DISK_PROPERTIES() \
1918 DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \
1919 DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
1920 DEFINE_PROP_STRING("serial", SCSIDiskState, serial)
1921
Anthony Liguori39bffca2011-12-07 21:34:16 -06001922static Property scsi_hd_properties[] = {
1923 DEFINE_SCSI_DISK_PROPERTIES(),
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02001924 DEFINE_PROP_BIT("removable", SCSIDiskState, features,
1925 SCSI_DISK_F_REMOVABLE, false),
Paolo Bonzinida8365d2012-05-01 10:25:16 +02001926 DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
1927 SCSI_DISK_F_DPOFUA, false),
Anthony Liguori39bffca2011-12-07 21:34:16 -06001928 DEFINE_PROP_END_OF_LIST(),
1929};
1930
Paolo Bonzini43b978b2011-12-15 07:24:47 -05001931static const VMStateDescription vmstate_scsi_disk_state = {
1932 .name = "scsi-disk",
1933 .version_id = 1,
1934 .minimum_version_id = 1,
1935 .minimum_version_id_old = 1,
1936 .fields = (VMStateField[]) {
1937 VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
1938 VMSTATE_BOOL(media_changed, SCSIDiskState),
1939 VMSTATE_BOOL(media_event, SCSIDiskState),
1940 VMSTATE_BOOL(eject_request, SCSIDiskState),
1941 VMSTATE_BOOL(tray_open, SCSIDiskState),
1942 VMSTATE_BOOL(tray_locked, SCSIDiskState),
1943 VMSTATE_END_OF_LIST()
1944 }
1945};
1946
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001947static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
1948{
Anthony Liguori39bffca2011-12-07 21:34:16 -06001949 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001950 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1951
1952 sc->init = scsi_hd_initfn;
1953 sc->destroy = scsi_destroy;
1954 sc->alloc_req = scsi_new_request;
1955 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06001956 dc->fw_name = "disk";
1957 dc->desc = "virtual SCSI disk";
1958 dc->reset = scsi_disk_reset;
1959 dc->props = scsi_hd_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05001960 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001961}
1962
Anthony Liguori39bffca2011-12-07 21:34:16 -06001963static TypeInfo scsi_hd_info = {
1964 .name = "scsi-hd",
1965 .parent = TYPE_SCSI_DEVICE,
1966 .instance_size = sizeof(SCSIDiskState),
1967 .class_init = scsi_hd_class_initfn,
1968};
1969
1970static Property scsi_cd_properties[] = {
1971 DEFINE_SCSI_DISK_PROPERTIES(),
1972 DEFINE_PROP_END_OF_LIST(),
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001973};
1974
1975static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
1976{
Anthony Liguori39bffca2011-12-07 21:34:16 -06001977 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001978 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
1979
1980 sc->init = scsi_cd_initfn;
1981 sc->destroy = scsi_destroy;
1982 sc->alloc_req = scsi_new_request;
1983 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06001984 dc->fw_name = "disk";
1985 dc->desc = "virtual SCSI CD-ROM";
1986 dc->reset = scsi_disk_reset;
1987 dc->props = scsi_cd_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05001988 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001989}
1990
Anthony Liguori39bffca2011-12-07 21:34:16 -06001991static TypeInfo scsi_cd_info = {
1992 .name = "scsi-cd",
1993 .parent = TYPE_SCSI_DEVICE,
1994 .instance_size = sizeof(SCSIDiskState),
1995 .class_init = scsi_cd_class_initfn,
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06001996};
1997
Paolo Bonzini336a6912011-10-25 12:53:37 +02001998#ifdef __linux__
Anthony Liguori39bffca2011-12-07 21:34:16 -06001999static Property scsi_block_properties[] = {
2000 DEFINE_SCSI_DISK_PROPERTIES(),
2001 DEFINE_PROP_END_OF_LIST(),
2002};
2003
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002004static void scsi_block_class_initfn(ObjectClass *klass, void *data)
2005{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002006 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002007 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2008
2009 sc->init = scsi_block_initfn;
2010 sc->destroy = scsi_destroy;
2011 sc->alloc_req = scsi_block_new_request;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002012 dc->fw_name = "disk";
2013 dc->desc = "SCSI block device passthrough";
2014 dc->reset = scsi_disk_reset;
2015 dc->props = scsi_block_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002016 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002017}
2018
Anthony Liguori39bffca2011-12-07 21:34:16 -06002019static TypeInfo scsi_block_info = {
2020 .name = "scsi-block",
2021 .parent = TYPE_SCSI_DEVICE,
2022 .instance_size = sizeof(SCSIDiskState),
2023 .class_init = scsi_block_class_initfn,
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002024};
Paolo Bonzini336a6912011-10-25 12:53:37 +02002025#endif
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002026
Anthony Liguori39bffca2011-12-07 21:34:16 -06002027static Property scsi_disk_properties[] = {
2028 DEFINE_SCSI_DISK_PROPERTIES(),
Paolo Bonzinibfe3d7a2012-05-01 10:23:54 +02002029 DEFINE_PROP_BIT("removable", SCSIDiskState, features,
2030 SCSI_DISK_F_REMOVABLE, false),
Paolo Bonzinida8365d2012-05-01 10:25:16 +02002031 DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
2032 SCSI_DISK_F_DPOFUA, false),
Anthony Liguori39bffca2011-12-07 21:34:16 -06002033 DEFINE_PROP_END_OF_LIST(),
2034};
2035
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002036static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
2037{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002038 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002039 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
2040
2041 sc->init = scsi_disk_initfn;
2042 sc->destroy = scsi_destroy;
2043 sc->alloc_req = scsi_new_request;
2044 sc->unit_attention_reported = scsi_disk_unit_attention_reported;
Anthony Liguori39bffca2011-12-07 21:34:16 -06002045 dc->fw_name = "disk";
2046 dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
2047 dc->reset = scsi_disk_reset;
2048 dc->props = scsi_disk_properties;
Paolo Bonzini43b978b2011-12-15 07:24:47 -05002049 dc->vmsd = &vmstate_scsi_disk_state;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002050}
2051
Anthony Liguori39bffca2011-12-07 21:34:16 -06002052static TypeInfo scsi_disk_info = {
2053 .name = "scsi-disk",
2054 .parent = TYPE_SCSI_DEVICE,
2055 .instance_size = sizeof(SCSIDiskState),
2056 .class_init = scsi_disk_class_initfn,
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002057};
2058
Andreas Färber83f7d432012-02-09 15:20:55 +01002059static void scsi_disk_register_types(void)
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002060{
Anthony Liguori39bffca2011-12-07 21:34:16 -06002061 type_register_static(&scsi_hd_info);
2062 type_register_static(&scsi_cd_info);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002063#ifdef __linux__
Anthony Liguori39bffca2011-12-07 21:34:16 -06002064 type_register_static(&scsi_block_info);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -06002065#endif
Anthony Liguori39bffca2011-12-07 21:34:16 -06002066 type_register_static(&scsi_disk_info);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02002067}
Andreas Färber83f7d432012-02-09 15:20:55 +01002068
2069type_init(scsi_disk_register_types)