blob: 505accdde5373596e74063467ab4bb961ada15bc [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
Blue Swirl001faf32009-05-13 17:53:17 +000031#define BADF(fmt, ...) \
32do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
pbrook2e5d83b2006-05-25 23:58:51 +000033
pbrook87ecb682007-11-17 17:14:51 +000034#include "qemu-common.h"
Markus Armbruster2f792012010-02-18 16:24:31 +010035#include "qemu-error.h"
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010036#include "scsi.h"
Gerd Hoffmann0d65e1f2009-11-26 15:33:53 +010037#include "scsi-defs.h"
Markus Armbruster666daa62010-06-02 18:48:27 +020038#include "sysemu.h"
Blue Swirl24463332010-08-24 15:22:24 +000039#include "blockdev.h"
Markus Armbrusterd1a07392011-09-06 18:58:54 +020040#include "block_int.h"
blueswir122864252008-10-11 09:33:03 +000041
Paolo Bonzini336a6912011-10-25 12:53:37 +020042#ifdef __linux
43#include <scsi/sg.h>
44#endif
45
aurel32f0f72ff2008-10-01 21:46:23 +000046#define SCSI_DMA_BUF_SIZE 131072
balrog57575052008-12-07 03:12:54 +000047#define SCSI_MAX_INQUIRY_LEN 256
pbrooka917d382006-08-29 04:52:16 +000048
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020049typedef struct SCSIDiskState SCSIDiskState;
50
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010051typedef struct SCSIDiskReq {
52 SCSIRequest req;
pbrooka917d382006-08-29 04:52:16 +000053 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
aliguorie035b432009-01-28 21:58:22 +000054 uint64_t sector;
55 uint32_t sector_count;
Paolo Bonzini72854772011-09-16 16:40:04 +020056 uint32_t buflen;
aliguoric87c0672009-04-07 18:43:20 +000057 struct iovec iov;
58 QEMUIOVector qiov;
Christoph Hellwiga597e792011-08-25 08:26:01 +020059 BlockAcctCookie acct;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010060} SCSIDiskReq;
pbrooka917d382006-08-29 04:52:16 +000061
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020062struct SCSIDiskState
pbrook2e5d83b2006-05-25 23:58:51 +000063{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020064 SCSIDevice qdev;
Stefan Hajnoczi419e6912011-01-24 15:34:58 +000065 uint32_t removable;
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +020066 bool media_changed;
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +020067 bool media_event;
Paolo Bonzini4480de12011-10-25 12:53:40 +020068 bool eject_request;
Markus Armbruster213189a2009-07-28 14:33:41 -040069 QEMUBH *bh;
Gerd Hoffmann383b4d92010-01-14 14:44:13 +010070 char *version;
Markus Armbrustera0fef652010-06-01 20:32:34 +020071 char *serial;
Markus Armbrusterece0d5e2011-09-06 18:58:40 +020072 bool tray_open;
Markus Armbruster81b10082011-09-06 18:58:44 +020073 bool tray_locked;
pbrook2e5d83b2006-05-25 23:58:51 +000074};
75
Paolo Bonzini71544d32011-10-25 12:53:36 +020076static int scsi_handle_rw_error(SCSIDiskReq *r, int error);
Kevin Wolf5dba48a2010-10-25 14:52:21 +020077
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020078static void scsi_free_request(SCSIRequest *req)
pbrook4d611c92006-08-12 01:04:27 +000079{
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020080 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
81
Paolo Bonzini72854772011-09-16 16:40:04 +020082 if (r->iov.iov_base) {
83 qemu_vfree(r->iov.iov_base);
84 }
pbrooka917d382006-08-29 04:52:16 +000085}
86
Paolo Bonzinib45ef672011-08-03 10:49:07 +020087/* Helper function for command completion with sense. */
88static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
Gerd Hoffmanned3a34a2009-11-26 15:34:00 +010089{
Blue Swirl02fa69b2011-08-20 09:21:42 +000090 DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
91 r->req.tag, sense.key, sense.asc, sense.ascq);
Paolo Bonzinib45ef672011-08-03 10:49:07 +020092 scsi_req_build_sense(&r->req, sense);
93 scsi_req_complete(&r->req, CHECK_CONDITION);
pbrooka917d382006-08-29 04:52:16 +000094}
95
96/* Cancel a pending data transfer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020097static void scsi_cancel_io(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +000098{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020099 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
100
101 DPRINTF("Cancel tag=0x%x\n", req->tag);
102 if (r->req.aiocb) {
103 bdrv_aio_cancel(r->req.aiocb);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200104
105 /* This reference was left in by scsi_*_data. We take ownership of
106 * it the moment scsi_req_cancel is called, independent of whether
107 * bdrv_aio_cancel completes the request or not. */
108 scsi_req_unref(&r->req);
pbrooka917d382006-08-29 04:52:16 +0000109 }
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200110 r->req.aiocb = NULL;
pbrook4d611c92006-08-12 01:04:27 +0000111}
112
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200113static uint32_t scsi_init_iovec(SCSIDiskReq *r)
114{
Paolo Bonzini72854772011-09-16 16:40:04 +0200115 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
116
117 if (!r->iov.iov_base) {
118 r->buflen = SCSI_DMA_BUF_SIZE;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200119 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +0200120 }
121 r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200122 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
123 return r->qiov.size / 512;
124}
125
pbrook4d611c92006-08-12 01:04:27 +0000126static void scsi_read_complete(void * opaque, int ret)
127{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100128 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200129 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200130 int n;
pbrook4d611c92006-08-12 01:04:27 +0000131
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200132 if (r->req.aiocb != NULL) {
133 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200134 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200135 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200136
pbrook4d611c92006-08-12 01:04:27 +0000137 if (ret) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200138 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200139 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200140 }
pbrook4d611c92006-08-12 01:04:27 +0000141 }
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200142
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200143 DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
pbrooka917d382006-08-29 04:52:16 +0000144
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200145 n = r->qiov.size / 512;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200146 r->sector += n;
147 r->sector_count -= n;
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200148 scsi_req_data(&r->req, r->qiov.size);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200149
150done:
151 if (!r->req.io_canceled) {
152 scsi_req_unref(&r->req);
153 }
pbrook4d611c92006-08-12 01:04:27 +0000154}
155
Paolo Bonzini0a4ac102011-09-06 09:08:34 +0200156static void scsi_flush_complete(void * opaque, int ret)
157{
158 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
159 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
160
161 if (r->req.aiocb != NULL) {
162 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200163 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini0a4ac102011-09-06 09:08:34 +0200164 }
165
166 if (ret < 0) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200167 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200168 goto done;
Paolo Bonzini0a4ac102011-09-06 09:08:34 +0200169 }
170 }
171
172 scsi_req_complete(&r->req, GOOD);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200173
174done:
175 if (!r->req.io_canceled) {
176 scsi_req_unref(&r->req);
177 }
Paolo Bonzini0a4ac102011-09-06 09:08:34 +0200178}
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200179
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200180/* Read more data from scsi device into buffer. */
181static void scsi_read_data(SCSIRequest *req)
pbrook2e5d83b2006-05-25 23:58:51 +0000182{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200183 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200184 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
pbrook2e5d83b2006-05-25 23:58:51 +0000185 uint32_t n;
186
pbrooka917d382006-08-29 04:52:16 +0000187 if (r->sector_count == (uint32_t)-1) {
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +0200188 DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
pbrooka917d382006-08-29 04:52:16 +0000189 r->sector_count = 0;
Paolo Bonziniab9adc82011-04-18 14:59:13 +0200190 scsi_req_data(&r->req, r->iov.iov_len);
pbrooka917d382006-08-29 04:52:16 +0000191 return;
192 }
193 DPRINTF("Read sector_count=%d\n", r->sector_count);
194 if (r->sector_count == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200195 /* This also clears the sense buffer for REQUEST SENSE. */
196 scsi_req_complete(&r->req, GOOD);
pbrooka917d382006-08-29 04:52:16 +0000197 return;
pbrook2e5d83b2006-05-25 23:58:51 +0000198 }
199
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000200 /* No data transfer may already be in progress */
201 assert(r->req.aiocb == NULL);
202
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200203 /* The request is used as the AIO opaque value, so add a ref. */
204 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200205 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
206 DPRINTF("Data transfer direction invalid\n");
207 scsi_read_complete(r, -EINVAL);
208 return;
209 }
210
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200211 if (s->tray_open) {
212 scsi_read_complete(r, -ENOMEDIUM);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200213 return;
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200214 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200215
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200216 n = scsi_init_iovec(r);
Paolo Bonzini44740c32011-10-12 12:54:16 +0200217 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
218 r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
aliguoric87c0672009-04-07 18:43:20 +0000219 scsi_read_complete, r);
pbrook2e5d83b2006-05-25 23:58:51 +0000220}
221
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200222/*
223 * scsi_handle_rw_error has two return values. 0 means that the error
224 * must be ignored, 1 means that the error has been processed and the
225 * caller should not do anything else for this request. Note that
226 * scsi_handle_rw_error always manages its reference counts, independent
227 * of the return value.
228 */
Paolo Bonzini71544d32011-10-25 12:53:36 +0200229static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200230{
Paolo Bonzini71544d32011-10-25 12:53:36 +0200231 int is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100232 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Paolo Bonzini44740c32011-10-12 12:54:16 +0200233 BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000234
Luiz Capitulino380f6402010-02-03 12:41:03 -0200235 if (action == BLOCK_ERR_IGNORE) {
Paolo Bonzini44740c32011-10-12 12:54:16 +0200236 bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000237 return 0;
Luiz Capitulino380f6402010-02-03 12:41:03 -0200238 }
aliguoriea8a5d72009-01-22 19:52:21 +0000239
240 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
241 || action == BLOCK_ERR_STOP_ANY) {
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200242
Paolo Bonzini44740c32011-10-12 12:54:16 +0200243 bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
Luiz Capitulino0461d5a2011-09-30 14:45:27 -0300244 vm_stop(RUN_STATE_IO_ERROR);
Paolo Bonzini44740c32011-10-12 12:54:16 +0200245 bdrv_iostatus_set_err(s->qdev.conf.bs, error);
Paolo Bonzini71544d32011-10-25 12:53:36 +0200246 scsi_req_retry(&r->req);
aliguoriea8a5d72009-01-22 19:52:21 +0000247 } else {
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200248 switch (error) {
Paolo Bonzini7e218df2011-09-19 17:19:21 +0200249 case ENOMEDIUM:
250 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
251 break;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200252 case ENOMEM:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200253 scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200254 break;
255 case EINVAL:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200256 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200257 break;
258 default:
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200259 scsi_check_condition(r, SENSE_CODE(IO_ERROR));
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200260 break;
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200261 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200262 bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read);
aliguoriea8a5d72009-01-22 19:52:21 +0000263 }
aliguoriea8a5d72009-01-22 19:52:21 +0000264 return 1;
265}
266
pbrook4d611c92006-08-12 01:04:27 +0000267static void scsi_write_complete(void * opaque, int ret)
268{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100269 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
Christoph Hellwiga597e792011-08-25 08:26:01 +0200270 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000271 uint32_t n;
pbrook4d611c92006-08-12 01:04:27 +0000272
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200273 if (r->req.aiocb != NULL) {
274 r->req.aiocb = NULL;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200275 bdrv_acct_done(s->qdev.conf.bs, &r->acct);
Paolo Bonzini8e321cc2011-09-05 18:11:51 +0200276 }
Christoph Hellwiga597e792011-08-25 08:26:01 +0200277
aliguoriea8a5d72009-01-22 19:52:21 +0000278 if (ret) {
Paolo Bonzini71544d32011-10-25 12:53:36 +0200279 if (scsi_handle_rw_error(r, -ret)) {
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200280 goto done;
Kevin Wolf5dba48a2010-10-25 14:52:21 +0200281 }
aliguoriea8a5d72009-01-22 19:52:21 +0000282 }
283
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200284 n = r->qiov.size / 512;
aliguoriea8a5d72009-01-22 19:52:21 +0000285 r->sector += n;
286 r->sector_count -= n;
pbrooka917d382006-08-29 04:52:16 +0000287 if (r->sector_count == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200288 scsi_req_complete(&r->req, GOOD);
pbrooka917d382006-08-29 04:52:16 +0000289 } else {
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200290 scsi_init_iovec(r);
291 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
292 scsi_req_data(&r->req, r->qiov.size);
pbrook4d611c92006-08-12 01:04:27 +0000293 }
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200294
295done:
296 if (!r->req.io_canceled) {
297 scsi_req_unref(&r->req);
298 }
pbrook4d611c92006-08-12 01:04:27 +0000299}
300
Paolo Bonzini42741212011-04-22 09:39:16 +0200301static void scsi_write_data(SCSIRequest *req)
aliguoriea8a5d72009-01-22 19:52:21 +0000302{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200303 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100304 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
aliguoriea8a5d72009-01-22 19:52:21 +0000305 uint32_t n;
306
Stefan Hajnoczi6fa2c952010-11-12 09:57:11 +0000307 /* No data transfer may already be in progress */
308 assert(r->req.aiocb == NULL);
309
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200310 /* The request is used as the AIO opaque value, so add a ref. */
311 scsi_req_ref(&r->req);
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200312 if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
313 DPRINTF("Data transfer direction invalid\n");
314 scsi_write_complete(r, -EINVAL);
Paolo Bonzini42741212011-04-22 09:39:16 +0200315 return;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +0200316 }
317
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200318 n = r->qiov.size / 512;
aliguoriea8a5d72009-01-22 19:52:21 +0000319 if (n) {
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200320 if (s->tray_open) {
321 scsi_write_complete(r, -ENOMEDIUM);
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +0200322 return;
Markus Armbrustera1aff5b2011-09-06 18:58:41 +0200323 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200324 bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
325 r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200326 scsi_write_complete, r);
aliguoriea8a5d72009-01-22 19:52:21 +0000327 } else {
Paolo Bonzini103b40f2011-09-16 16:40:03 +0200328 /* Called for the first time. Ask the driver to send us more data. */
aliguoriea8a5d72009-01-22 19:52:21 +0000329 scsi_write_complete(r, 0);
330 }
pbrook2e5d83b2006-05-25 23:58:51 +0000331}
332
pbrooka917d382006-08-29 04:52:16 +0000333/* Return a pointer to the data buffer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200334static uint8_t *scsi_get_buf(SCSIRequest *req)
pbrooka917d382006-08-29 04:52:16 +0000335{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200336 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
pbrooka917d382006-08-29 04:52:16 +0000337
blueswir13f4cb3d2009-04-13 16:31:01 +0000338 return (uint8_t *)r->iov.iov_base;
pbrooka917d382006-08-29 04:52:16 +0000339}
340
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100341static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
342{
Gerd Hoffmann383b4d92010-01-14 14:44:13 +0100343 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100344 int buflen = 0;
345
346 if (req->cmd.buf[1] & 0x2) {
347 /* Command support data - optional, not implemented */
348 BADF("optional INQUIRY command support request not implemented\n");
349 return -1;
350 }
351
352 if (req->cmd.buf[1] & 0x1) {
353 /* Vital product data */
354 uint8_t page_code = req->cmd.buf[2];
355 if (req->cmd.xfer < 4) {
356 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
357 "less than 4\n", page_code, req->cmd.xfer);
358 return -1;
359 }
360
Paolo Bonzinie39be482011-10-12 14:27:40 +0200361 outbuf[buflen++] = s->qdev.type & 0x1f;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100362 outbuf[buflen++] = page_code ; // this page
363 outbuf[buflen++] = 0x00;
364
365 switch (page_code) {
366 case 0x00: /* Supported page codes, mandatory */
Hannes Reinecke39d98982010-11-24 12:15:58 +0100367 {
368 int pages;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100369 DPRINTF("Inquiry EVPD[Supported pages] "
370 "buffer size %zd\n", req->cmd.xfer);
Hannes Reinecke39d98982010-11-24 12:15:58 +0100371 pages = buflen++;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100372 outbuf[buflen++] = 0x00; // list of supported pages (this page)
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200373 if (s->serial) {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200374 outbuf[buflen++] = 0x80; // unit serial number
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200375 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100376 outbuf[buflen++] = 0x83; // device identification
Hannes Reineckef37bd732011-07-22 16:44:46 +0200377 if (s->qdev.type == TYPE_DISK) {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100378 outbuf[buflen++] = 0xb0; // block limits
379 outbuf[buflen++] = 0xb2; // thin provisioning
Hannes Reinecke39d98982010-11-24 12:15:58 +0100380 }
381 outbuf[pages] = buflen - pages - 1; // number of pages
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100382 break;
Hannes Reinecke39d98982010-11-24 12:15:58 +0100383 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100384 case 0x80: /* Device serial number, optional */
385 {
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200386 int l;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100387
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +0200388 if (!s->serial) {
389 DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
390 return -1;
391 }
392
393 l = strlen(s->serial);
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200394 if (l > req->cmd.xfer) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100395 l = req->cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200396 }
397 if (l > 20) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100398 l = 20;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200399 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100400
401 DPRINTF("Inquiry EVPD[Serial number] "
402 "buffer size %zd\n", req->cmd.xfer);
403 outbuf[buflen++] = l;
Markus Armbrustera0fef652010-06-01 20:32:34 +0200404 memcpy(outbuf+buflen, s->serial, l);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100405 buflen += l;
406 break;
407 }
408
409 case 0x83: /* Device identification page, mandatory */
410 {
411 int max_len = 255 - 8;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200412 int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100413
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200414 if (id_len > max_len) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100415 id_len = max_len;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200416 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100417 DPRINTF("Inquiry EVPD[Device identification] "
418 "buffer size %zd\n", req->cmd.xfer);
419
Hannes Reinecke39d98982010-11-24 12:15:58 +0100420 outbuf[buflen++] = 4 + id_len;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100421 outbuf[buflen++] = 0x2; // ASCII
422 outbuf[buflen++] = 0; // not officially assigned
423 outbuf[buflen++] = 0; // reserved
424 outbuf[buflen++] = id_len; // length of data following
425
Paolo Bonzini44740c32011-10-12 12:54:16 +0200426 memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100427 buflen += id_len;
428 break;
429 }
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100430 case 0xb0: /* block limits */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100431 {
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100432 unsigned int unmap_sectors =
433 s->qdev.conf.discard_granularity / s->qdev.blocksize;
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100434 unsigned int min_io_size =
435 s->qdev.conf.min_io_size / s->qdev.blocksize;
436 unsigned int opt_io_size =
437 s->qdev.conf.opt_io_size / s->qdev.blocksize;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100438
Hannes Reineckef37bd732011-07-22 16:44:46 +0200439 if (s->qdev.type == TYPE_ROM) {
Hannes Reinecke39d98982010-11-24 12:15:58 +0100440 DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
441 page_code);
442 return -1;
443 }
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100444 /* required VPD size with unmap support */
445 outbuf[3] = buflen = 0x3c;
446
447 memset(outbuf + 4, 0, buflen - 4);
448
449 /* optimal transfer length granularity */
450 outbuf[6] = (min_io_size >> 8) & 0xff;
451 outbuf[7] = min_io_size & 0xff;
452
453 /* optimal transfer length */
454 outbuf[12] = (opt_io_size >> 24) & 0xff;
455 outbuf[13] = (opt_io_size >> 16) & 0xff;
456 outbuf[14] = (opt_io_size >> 8) & 0xff;
457 outbuf[15] = opt_io_size & 0xff;
Christoph Hellwigea3bd562010-12-16 19:36:43 +0100458
459 /* optimal unmap granularity */
460 outbuf[28] = (unmap_sectors >> 24) & 0xff;
461 outbuf[29] = (unmap_sectors >> 16) & 0xff;
462 outbuf[30] = (unmap_sectors >> 8) & 0xff;
463 outbuf[31] = unmap_sectors & 0xff;
464 break;
465 }
466 case 0xb2: /* thin provisioning */
467 {
468 outbuf[3] = buflen = 8;
469 outbuf[4] = 0;
470 outbuf[5] = 0x40; /* write same with unmap supported */
471 outbuf[6] = 0;
472 outbuf[7] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100473 break;
474 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100475 default:
476 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
477 "buffer size %zd\n", page_code, req->cmd.xfer);
478 return -1;
479 }
480 /* done with EVPD */
481 return buflen;
482 }
483
484 /* Standard INQUIRY data */
485 if (req->cmd.buf[2] != 0) {
486 BADF("Error: Inquiry (STANDARD) page or code "
487 "is non-zero [%02X]\n", req->cmd.buf[2]);
488 return -1;
489 }
490
491 /* PAGE CODE == 0 */
492 if (req->cmd.xfer < 5) {
493 BADF("Error: Inquiry (STANDARD) buffer size %zd "
494 "is less than 5\n", req->cmd.xfer);
495 return -1;
496 }
497
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100498 buflen = req->cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200499 if (buflen > SCSI_MAX_INQUIRY_LEN) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100500 buflen = SCSI_MAX_INQUIRY_LEN;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200501 }
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100502 memset(outbuf, 0, buflen);
503
Hannes Reineckef37bd732011-07-22 16:44:46 +0200504 outbuf[0] = s->qdev.type & 0x1f;
Paolo Bonzinie39be482011-10-12 14:27:40 +0200505 outbuf[1] = s->removable ? 0x80 : 0;
Hannes Reineckef37bd732011-07-22 16:44:46 +0200506 if (s->qdev.type == TYPE_ROM) {
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100507 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100508 } else {
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100509 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100510 }
Laszlo Ast550fe6c2009-11-19 11:07:12 +0100511 memcpy(&outbuf[8], "QEMU ", 8);
Gerd Hoffmann314b1812010-03-10 17:47:17 +0100512 memset(&outbuf[32], 0, 4);
Markus Armbruster552fee92010-06-01 20:32:35 +0200513 memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
Christoph Hellwig99aba0c2010-03-04 14:45:44 +0100514 /*
515 * We claim conformance to SPC-3, which is required for guests
516 * to ask for modern features like READ CAPACITY(16) or the
517 * block characteristics VPD page by default. Not all of SPC-3
518 * is actually implemented, but we're good enough.
519 */
Christoph Hellwigee3659e2010-02-10 23:37:37 +0100520 outbuf[2] = 5;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100521 outbuf[3] = 2; /* Format 2 */
Artyom Tarasenkoad3cea42009-12-13 11:32:36 +0100522
523 if (buflen > 36) {
524 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
525 } else {
526 /* If the allocation length of CDB is too small,
527 the additional length is not adjusted */
528 outbuf[4] = 36 - 5;
529 }
530
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100531 /* Sync data transfer and TCQ. */
Paolo Bonziniafd40302011-08-13 15:44:45 +0200532 outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
Gerd Hoffmann0b06c052009-11-26 15:34:04 +0100533 return buflen;
534}
535
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200536static inline bool media_is_dvd(SCSIDiskState *s)
537{
538 uint64_t nb_sectors;
539 if (s->qdev.type != TYPE_ROM) {
540 return false;
541 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200542 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200543 return false;
544 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200545 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200546 return nb_sectors > CD_MAX_SECTORS;
547}
548
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200549static inline bool media_is_cd(SCSIDiskState *s)
550{
551 uint64_t nb_sectors;
552 if (s->qdev.type != TYPE_ROM) {
553 return false;
554 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200555 if (!bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200556 return false;
557 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200558 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200559 return nb_sectors <= CD_MAX_SECTORS;
560}
561
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200562static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
563 uint8_t *outbuf)
564{
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200565 static const int rds_caps_size[5] = {
566 [0] = 2048 + 4,
567 [1] = 4 + 4,
568 [3] = 188 + 4,
569 [4] = 2048 + 4,
570 };
571
572 uint8_t media = r->req.cmd.buf[1];
573 uint8_t layer = r->req.cmd.buf[6];
574 uint8_t format = r->req.cmd.buf[7];
575 int size = -1;
576
577 if (s->qdev.type != TYPE_ROM) {
578 return -1;
579 }
580 if (media != 0) {
581 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
582 return -1;
583 }
584
585 if (format != 0xff) {
Paolo Bonzini44740c32011-10-12 12:54:16 +0200586 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200587 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
588 return -1;
589 }
590 if (media_is_cd(s)) {
591 scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
592 return -1;
593 }
594 if (format >= ARRAY_SIZE(rds_caps_size)) {
595 return -1;
596 }
597 size = rds_caps_size[format];
598 memset(outbuf, 0, size);
599 }
600
601 switch (format) {
602 case 0x00: {
603 /* Physical format information */
604 uint64_t nb_sectors;
605 if (layer != 0) {
606 goto fail;
607 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200608 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonziniceb792e2011-09-13 15:57:15 +0200609
610 outbuf[4] = 1; /* DVD-ROM, part version 1 */
611 outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
612 outbuf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
613 outbuf[7] = 0; /* default densities */
614
615 stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
616 stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
617 break;
618 }
619
620 case 0x01: /* DVD copyright information, all zeros */
621 break;
622
623 case 0x03: /* BCA information - invalid field for no BCA info */
624 return -1;
625
626 case 0x04: /* DVD disc manufacturing information, all zeros */
627 break;
628
629 case 0xff: { /* List capabilities */
630 int i;
631 size = 4;
632 for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
633 if (!rds_caps_size[i]) {
634 continue;
635 }
636 outbuf[size] = i;
637 outbuf[size + 1] = 0x40; /* Not writable, readable */
638 stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
639 size += 4;
640 }
641 break;
642 }
643
644 default:
645 return -1;
646 }
647
648 /* Size of buffer, not including 2 byte size field */
649 stw_be_p(outbuf, size - 2);
650 return size;
651
652fail:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200653 return -1;
654}
655
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200656static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200657{
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200658 uint8_t event_code, media_status;
659
660 media_status = 0;
661 if (s->tray_open) {
662 media_status = MS_TRAY_OPEN;
Paolo Bonzini44740c32011-10-12 12:54:16 +0200663 } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200664 media_status = MS_MEDIA_PRESENT;
665 }
666
667 /* Event notification descriptor */
668 event_code = MEC_NO_CHANGE;
Paolo Bonzini4480de12011-10-25 12:53:40 +0200669 if (media_status != MS_TRAY_OPEN) {
670 if (s->media_event) {
671 event_code = MEC_NEW_MEDIA;
672 s->media_event = false;
673 } else if (s->eject_request) {
674 event_code = MEC_EJECT_REQUESTED;
675 s->eject_request = false;
676 }
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +0200677 }
678
679 outbuf[0] = event_code;
680 outbuf[1] = media_status;
681
682 /* These fields are reserved, just clear them. */
683 outbuf[2] = 0;
684 outbuf[3] = 0;
685 return 4;
686}
687
688static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
689 uint8_t *outbuf)
690{
691 int size;
692 uint8_t *buf = r->req.cmd.buf;
693 uint8_t notification_class_request = buf[4];
694 if (s->qdev.type != TYPE_ROM) {
695 return -1;
696 }
697 if ((buf[1] & 1) == 0) {
698 /* asynchronous */
699 return -1;
700 }
701
702 size = 4;
703 outbuf[0] = outbuf[1] = 0;
704 outbuf[3] = 1 << GESN_MEDIA; /* supported events */
705 if (notification_class_request & (1 << GESN_MEDIA)) {
706 outbuf[2] = GESN_MEDIA;
707 size += scsi_event_status_media(s, &outbuf[size]);
708 } else {
709 outbuf[2] = 0x80;
710 }
711 stw_be_p(outbuf, size - 4);
712 return size;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200713}
714
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200715static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200716{
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200717 int current;
718
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200719 if (s->qdev.type != TYPE_ROM) {
720 return -1;
721 }
Paolo Bonzini430ee2f2011-09-13 15:22:31 +0200722 current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
723 memset(outbuf, 0, 40);
724 stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
725 stw_be_p(&outbuf[6], current);
726 /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
727 outbuf[10] = 0x03; /* persistent, current */
728 outbuf[11] = 8; /* two profiles */
729 stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
730 outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
731 stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
732 outbuf[18] = (current == MMC_PROFILE_CD_ROM);
733 /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
734 stw_be_p(&outbuf[20], 1);
735 outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
736 outbuf[23] = 8;
737 stl_be_p(&outbuf[24], 1); /* SCSI */
738 outbuf[28] = 1; /* DBE = 1, mandatory */
739 /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
740 stw_be_p(&outbuf[32], 3);
741 outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
742 outbuf[35] = 4;
743 outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
744 /* TODO: Random readable, CD read, DVD read, drive serial number,
745 power management */
746 return 40;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +0200747}
748
749static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
750{
751 if (s->qdev.type != TYPE_ROM) {
752 return -1;
753 }
754 memset(outbuf, 0, 8);
755 outbuf[5] = 1; /* CD-ROM */
756 return 8;
757}
758
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200759static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
Bernhard Kohl282ab042010-08-31 14:08:24 +0200760 int page_control)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100761{
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200762 static const int mode_sense_valid[0x3f] = {
763 [MODE_PAGE_HD_GEOMETRY] = (1 << TYPE_DISK),
764 [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
765 [MODE_PAGE_CACHING] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200766 [MODE_PAGE_R_W_ERROR] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
767 [MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200768 [MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
769 };
770
Paolo Bonzini44740c32011-10-12 12:54:16 +0200771 BlockDriverState *bdrv = s->qdev.conf.bs;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100772 int cylinders, heads, secs;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200773 uint8_t *p = *p_outbuf;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100774
Paolo Bonzinia8f4bbe2011-09-13 14:50:15 +0200775 if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
776 return -1;
777 }
778
779 p[0] = page;
780
Bernhard Kohl282ab042010-08-31 14:08:24 +0200781 /*
782 * If Changeable Values are requested, a mask denoting those mode parameters
783 * that are changeable shall be returned. As we currently don't support
784 * parameter changes via MODE_SELECT all bits are returned set to zero.
785 * The buffer was already menset to zero by the caller of this function.
786 */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100787 switch (page) {
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200788 case MODE_PAGE_HD_GEOMETRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100789 p[1] = 0x16;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200790 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200791 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200792 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100793 /* if a geometry hint is available, use it */
Paolo Bonzini245d0042011-11-15 16:57:50 +0100794 bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100795 p[2] = (cylinders >> 16) & 0xff;
796 p[3] = (cylinders >> 8) & 0xff;
797 p[4] = cylinders & 0xff;
798 p[5] = heads & 0xff;
799 /* Write precomp start cylinder, disabled */
800 p[6] = (cylinders >> 16) & 0xff;
801 p[7] = (cylinders >> 8) & 0xff;
802 p[8] = cylinders & 0xff;
803 /* Reduced current start cylinder, disabled */
804 p[9] = (cylinders >> 16) & 0xff;
805 p[10] = (cylinders >> 8) & 0xff;
806 p[11] = cylinders & 0xff;
807 /* Device step rate [ns], 200ns */
808 p[12] = 0;
809 p[13] = 200;
810 /* Landing zone cylinder */
811 p[14] = 0xff;
812 p[15] = 0xff;
813 p[16] = 0xff;
814 /* Medium rotation rate [rpm], 5400 rpm */
815 p[20] = (5400 >> 8) & 0xff;
816 p[21] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200817 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100818
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200819 case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100820 p[1] = 0x1e;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200821 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200822 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200823 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100824 /* Transfer rate [kbit/s], 5Mbit/s */
825 p[2] = 5000 >> 8;
826 p[3] = 5000 & 0xff;
827 /* if a geometry hint is available, use it */
Paolo Bonzini245d0042011-11-15 16:57:50 +0100828 bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100829 p[4] = heads & 0xff;
830 p[5] = secs & 0xff;
Paolo Bonzini69377302011-10-13 10:35:46 +0200831 p[6] = s->qdev.blocksize >> 8;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100832 p[8] = (cylinders >> 8) & 0xff;
833 p[9] = cylinders & 0xff;
834 /* Write precomp start cylinder, disabled */
835 p[10] = (cylinders >> 8) & 0xff;
836 p[11] = cylinders & 0xff;
837 /* Reduced current start cylinder, disabled */
838 p[12] = (cylinders >> 8) & 0xff;
839 p[13] = cylinders & 0xff;
840 /* Device step rate [100us], 100us */
841 p[14] = 0;
842 p[15] = 1;
843 /* Device step pulse width [us], 1us */
844 p[16] = 1;
845 /* Device head settle delay [100us], 100us */
846 p[17] = 0;
847 p[18] = 1;
848 /* Motor on delay [0.1s], 0.1s */
849 p[19] = 1;
850 /* Motor off delay [0.1s], 0.1s */
851 p[20] = 1;
852 /* Medium rotation rate [rpm], 5400 rpm */
853 p[28] = (5400 >> 8) & 0xff;
854 p[29] = 5400 & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200855 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100856
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200857 case MODE_PAGE_CACHING:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100858 p[0] = 8;
859 p[1] = 0x12;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200860 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200861 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200862 }
Paolo Bonzini44740c32011-10-12 12:54:16 +0200863 if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100864 p[2] = 4; /* WCE */
865 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200866 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100867
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200868 case MODE_PAGE_R_W_ERROR:
869 p[1] = 10;
870 p[2] = 0x80; /* Automatic Write Reallocation Enabled */
871 if (s->qdev.type == TYPE_ROM) {
872 p[3] = 0x20; /* Read Retry Count */
873 }
874 break;
875
876 case MODE_PAGE_AUDIO_CTL:
877 p[1] = 14;
878 break;
879
Paolo Bonzini67cc61e2011-09-13 14:41:56 +0200880 case MODE_PAGE_CAPABILITIES:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100881 p[1] = 0x14;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200882 if (page_control == 1) { /* Changeable Values */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200883 break;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200884 }
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200885
886 p[2] = 0x3b; /* CD-R & CD-RW read */
887 p[3] = 0; /* Writing not supported */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100888 p[4] = 0x7f; /* Audio, composite, digital out,
889 mode 2 form 1&2, multi session */
890 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
891 RW corrected, C2 errors, ISRC,
892 UPC, Bar code */
Markus Armbruster81b10082011-09-06 18:58:44 +0200893 p[6] = 0x2d | (s->tray_locked ? 2 : 0);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100894 /* Locking supported, jumper present, eject, tray */
895 p[7] = 0; /* no volume & mute control, no
896 changer */
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200897 p[8] = (50 * 176) >> 8; /* 50x read speed */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100898 p[9] = (50 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200899 p[10] = 2 >> 8; /* Two volume levels */
900 p[11] = 2 & 0xff;
901 p[12] = 2048 >> 8; /* 2M buffer */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100902 p[13] = 2048 & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200903 p[14] = (16 * 176) >> 8; /* 16x read speed current */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100904 p[15] = (16 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200905 p[18] = (16 * 176) >> 8; /* 16x write speed */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100906 p[19] = (16 * 176) & 0xff;
Paolo Bonzinia07c7dc2011-09-13 15:08:22 +0200907 p[20] = (16 * 176) >> 8; /* 16x write speed current */
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100908 p[21] = (16 * 176) & 0xff;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200909 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100910
911 default:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200912 return -1;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100913 }
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200914
915 *p_outbuf += p[1] + 2;
916 return p[1] + 2;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100917}
918
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200919static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100920{
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200921 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100922 uint64_t nb_sectors;
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200923 int page, dbd, buflen, ret, page_control;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100924 uint8_t *p;
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200925 uint8_t dev_specific_param;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100926
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200927 dbd = r->req.cmd.buf[1] & 0x8;
928 page = r->req.cmd.buf[2] & 0x3f;
929 page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +0200930 DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200931 (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
932 memset(outbuf, 0, r->req.cmd.xfer);
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100933 p = outbuf;
934
Paolo Bonzini44740c32011-10-12 12:54:16 +0200935 if (bdrv_is_read_only(s->qdev.conf.bs)) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200936 dev_specific_param = 0x80; /* Readonly. */
937 } else {
938 dev_specific_param = 0x00;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100939 }
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200940
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200941 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200942 p[1] = 0; /* Default media type. */
943 p[2] = dev_specific_param;
944 p[3] = 0; /* Block descriptor length. */
945 p += 4;
946 } else { /* MODE_SENSE_10 */
947 p[2] = 0; /* Default media type. */
948 p[3] = dev_specific_param;
949 p[6] = p[7] = 0; /* Block descriptor length. */
950 p += 8;
951 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100952
Paolo Bonzini0fd76ff2011-11-14 14:31:50 +0100953 /* MMC prescribes that CD/DVD drives have no block descriptors. */
Paolo Bonzini44740c32011-10-12 12:54:16 +0200954 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini0fd76ff2011-11-14 14:31:50 +0100955 if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200956 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200957 outbuf[3] = 8; /* Block descriptor length */
958 } else { /* MODE_SENSE_10 */
959 outbuf[7] = 8; /* Block descriptor length */
960 }
Paolo Bonzini69377302011-10-13 10:35:46 +0200961 nb_sectors /= (s->qdev.blocksize / 512);
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200962 if (nb_sectors > 0xffffff) {
Bernhard Kohl2488b742010-08-31 14:08:25 +0200963 nb_sectors = 0;
Paolo Bonzinif01b5932011-10-17 16:39:27 +0200964 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100965 p[0] = 0; /* media density code */
966 p[1] = (nb_sectors >> 16) & 0xff;
967 p[2] = (nb_sectors >> 8) & 0xff;
968 p[3] = nb_sectors & 0xff;
969 p[4] = 0; /* reserved */
970 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
Paolo Bonzini69377302011-10-13 10:35:46 +0200971 p[6] = s->qdev.blocksize >> 8;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100972 p[7] = 0;
973 p += 8;
974 }
975
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200976 if (page_control == 3) {
977 /* Saved Values */
978 scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
979 return -1;
Bernhard Kohl282ab042010-08-31 14:08:24 +0200980 }
981
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200982 if (page == 0x3f) {
983 for (page = 0; page <= 0x3e; page++) {
984 mode_sense_page(s, page, &p, page_control);
985 }
986 } else {
987 ret = mode_sense_page(s, page, &p, page_control);
988 if (ret == -1) {
989 return -1;
990 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +0100991 }
992
993 buflen = p - outbuf;
Bernhard Kohlce512ee2010-08-31 14:08:23 +0200994 /*
995 * The mode data length field specifies the length in bytes of the
996 * following data that is available to be transferred. The mode data
997 * length does not include itself.
998 */
Paolo Bonzinicfc606d2011-09-06 12:31:44 +0200999 if (r->req.cmd.buf[0] == MODE_SENSE) {
Bernhard Kohlce512ee2010-08-31 14:08:23 +02001000 outbuf[0] = buflen - 1;
1001 } else { /* MODE_SENSE_10 */
1002 outbuf[0] = ((buflen - 2) >> 8) & 0xff;
1003 outbuf[1] = (buflen - 2) & 0xff;
1004 }
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001005 if (buflen > r->req.cmd.xfer) {
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001006 buflen = r->req.cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001007 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001008 return buflen;
1009}
1010
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001011static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
1012{
1013 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001014 int start_track, format, msf, toclen;
1015 uint64_t nb_sectors;
1016
1017 msf = req->cmd.buf[1] & 2;
1018 format = req->cmd.buf[2] & 0xf;
1019 start_track = req->cmd.buf[6];
Paolo Bonzini44740c32011-10-12 12:54:16 +02001020 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001021 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
Paolo Bonzini69377302011-10-13 10:35:46 +02001022 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001023 switch (format) {
1024 case 0:
1025 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
1026 break;
1027 case 1:
1028 /* multi session : only a single session defined */
1029 toclen = 12;
1030 memset(outbuf, 0, 12);
1031 outbuf[1] = 0x0a;
1032 outbuf[2] = 0x01;
1033 outbuf[3] = 0x01;
1034 break;
1035 case 2:
1036 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
1037 break;
1038 default:
1039 return -1;
1040 }
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001041 if (toclen > req->cmd.xfer) {
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001042 toclen = req->cmd.xfer;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001043 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001044 return toclen;
1045}
1046
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001047static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001048{
1049 SCSIRequest *req = &r->req;
1050 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
1051 bool start = req->cmd.buf[4] & 1;
1052 bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */
1053
1054 if (s->qdev.type == TYPE_ROM && loej) {
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001055 if (!start && !s->tray_open && s->tray_locked) {
1056 scsi_check_condition(r,
Paolo Bonzini44740c32011-10-12 12:54:16 +02001057 bdrv_is_inserted(s->qdev.conf.bs)
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001058 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
1059 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
1060 return -1;
Markus Armbrusterfdec4402011-09-06 18:58:45 +02001061 }
Paolo Bonzini44740c32011-10-12 12:54:16 +02001062 bdrv_eject(s->qdev.conf.bs, !start);
Markus Armbrusterece0d5e2011-09-06 18:58:40 +02001063 s->tray_open = !start;
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001064 }
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001065 return 0;
Markus Armbrusterbfd52642011-09-06 18:58:39 +02001066}
1067
Paolo Bonzini72854772011-09-16 16:40:04 +02001068static int scsi_disk_emulate_command(SCSIDiskReq *r)
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001069{
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001070 SCSIRequest *req = &r->req;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001071 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001072 uint64_t nb_sectors;
Paolo Bonzini72854772011-09-16 16:40:04 +02001073 uint8_t *outbuf;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001074 int buflen = 0;
1075
Paolo Bonzini72854772011-09-16 16:40:04 +02001076 if (!r->iov.iov_base) {
1077 /*
1078 * FIXME: we shouldn't return anything bigger than 4k, but the code
1079 * requires the buffer to be as big as req->cmd.xfer in several
1080 * places. So, do not allow CDBs with a very large ALLOCATION
1081 * LENGTH. The real fix would be to modify scsi_read_data and
1082 * dma_buf_read, so that they return data beyond the buflen
1083 * as all zeros.
1084 */
1085 if (req->cmd.xfer > 65536) {
1086 goto illegal_request;
1087 }
1088 r->buflen = MAX(4096, req->cmd.xfer);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001089 r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
Paolo Bonzini72854772011-09-16 16:40:04 +02001090 }
1091
1092 outbuf = r->iov.iov_base;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001093 switch (req->cmd.buf[0]) {
1094 case TEST_UNIT_READY:
Paolo Bonzini44740c32011-10-12 12:54:16 +02001095 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001096 goto not_ready;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001097 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001098 break;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001099 case INQUIRY:
1100 buflen = scsi_disk_emulate_inquiry(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001101 if (buflen < 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001102 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001103 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001104 break;
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001105 case MODE_SENSE:
1106 case MODE_SENSE_10:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001107 buflen = scsi_disk_emulate_mode_sense(r, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001108 if (buflen < 0) {
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001109 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001110 }
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001111 break;
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001112 case READ_TOC:
1113 buflen = scsi_disk_emulate_read_toc(req, outbuf);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001114 if (buflen < 0) {
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001115 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001116 }
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001117 break;
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001118 case RESERVE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001119 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001120 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001121 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001122 break;
1123 case RESERVE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001124 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001125 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001126 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001127 break;
1128 case RELEASE:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001129 if (req->cmd.buf[1] & 1) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001130 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001131 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001132 break;
1133 case RELEASE_10:
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001134 if (req->cmd.buf[1] & 3) {
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001135 goto illegal_request;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001136 }
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001137 break;
Gerd Hoffmann8d3628f2009-11-26 15:34:07 +01001138 case START_STOP:
Markus Armbruster68bb01f2011-09-06 18:58:49 +02001139 if (scsi_disk_emulate_start_stop(r) < 0) {
1140 return -1;
1141 }
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001142 break;
Gerd Hoffmannc68b9f32009-11-26 15:34:08 +01001143 case ALLOW_MEDIUM_REMOVAL:
Markus Armbruster81b10082011-09-06 18:58:44 +02001144 s->tray_locked = req->cmd.buf[4] & 1;
Paolo Bonzini44740c32011-10-12 12:54:16 +02001145 bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001146 break;
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001147 case READ_CAPACITY_10:
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001148 /* The normal LEN field for this command is zero. */
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001149 memset(outbuf, 0, 8);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001150 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001151 if (!nb_sectors) {
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001152 goto not_ready;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001153 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001154 if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
1155 goto illegal_request;
1156 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001157 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001158 /* Returned value is the address of the last sector. */
1159 nb_sectors--;
1160 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001161 s->qdev.max_lba = nb_sectors;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001162 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001163 if (nb_sectors > UINT32_MAX) {
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001164 nb_sectors = UINT32_MAX;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001165 }
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001166 outbuf[0] = (nb_sectors >> 24) & 0xff;
1167 outbuf[1] = (nb_sectors >> 16) & 0xff;
1168 outbuf[2] = (nb_sectors >> 8) & 0xff;
1169 outbuf[3] = nb_sectors & 0xff;
1170 outbuf[4] = 0;
1171 outbuf[5] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001172 outbuf[6] = s->qdev.blocksize >> 8;
Gerd Hoffmanne7e25e32009-11-26 15:34:09 +01001173 outbuf[7] = 0;
1174 buflen = 8;
Hannes Reinecke5f71d322011-07-22 16:51:12 +02001175 break;
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001176 case REQUEST_SENSE:
1177 /* Just return "NO SENSE". */
1178 buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
1179 (req->cmd.buf[1] & 1) == 0);
1180 break;
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001181 case MECHANISM_STATUS:
1182 buflen = scsi_emulate_mechanism_status(s, outbuf);
1183 if (buflen < 0) {
1184 goto illegal_request;
1185 }
1186 break;
Gerd Hoffmann38215552009-11-26 15:34:12 +01001187 case GET_CONFIGURATION:
Paolo Bonzini430ee2f2011-09-13 15:22:31 +02001188 buflen = scsi_get_configuration(s, outbuf);
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001189 if (buflen < 0) {
1190 goto illegal_request;
1191 }
1192 break;
1193 case GET_EVENT_STATUS_NOTIFICATION:
1194 buflen = scsi_get_event_status_notification(s, r, outbuf);
1195 if (buflen < 0) {
1196 goto illegal_request;
1197 }
1198 break;
1199 case READ_DVD_STRUCTURE:
1200 buflen = scsi_read_dvd_structure(s, r, outbuf);
1201 if (buflen < 0) {
1202 goto illegal_request;
1203 }
Gerd Hoffmann38215552009-11-26 15:34:12 +01001204 break;
Paolo Bonzinif6515262011-09-06 12:31:42 +02001205 case SERVICE_ACTION_IN_16:
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001206 /* Service Action In subcommands. */
Paolo Bonzinif6515262011-09-06 12:31:42 +02001207 if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001208 DPRINTF("SAI READ CAPACITY(16)\n");
1209 memset(outbuf, 0, req->cmd.xfer);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001210 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001211 if (!nb_sectors) {
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001212 goto not_ready;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001213 }
Paolo Bonzini7cec78b2011-10-03 13:57:06 +02001214 if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
1215 goto illegal_request;
1216 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001217 nb_sectors /= s->qdev.blocksize / 512;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001218 /* Returned value is the address of the last sector. */
1219 nb_sectors--;
1220 /* Remember the new size for read/write sanity checking. */
Paolo Bonzini78779032011-10-13 10:39:50 +02001221 s->qdev.max_lba = nb_sectors;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001222 outbuf[0] = (nb_sectors >> 56) & 0xff;
1223 outbuf[1] = (nb_sectors >> 48) & 0xff;
1224 outbuf[2] = (nb_sectors >> 40) & 0xff;
1225 outbuf[3] = (nb_sectors >> 32) & 0xff;
1226 outbuf[4] = (nb_sectors >> 24) & 0xff;
1227 outbuf[5] = (nb_sectors >> 16) & 0xff;
1228 outbuf[6] = (nb_sectors >> 8) & 0xff;
1229 outbuf[7] = nb_sectors & 0xff;
1230 outbuf[8] = 0;
1231 outbuf[9] = 0;
Paolo Bonzini69377302011-10-13 10:35:46 +02001232 outbuf[10] = s->qdev.blocksize >> 8;
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001233 outbuf[11] = 0;
Christoph Hellwigee3659e2010-02-10 23:37:37 +01001234 outbuf[12] = 0;
1235 outbuf[13] = get_physical_block_exp(&s->qdev.conf);
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001236
1237 /* set TPE bit if the format supports discard */
1238 if (s->qdev.conf.discard_granularity) {
1239 outbuf[14] = 0x80;
1240 }
1241
Gerd Hoffmann5dd90e22009-11-26 15:34:13 +01001242 /* Protection, exponent and lowest lba field left blank. */
1243 buflen = req->cmd.xfer;
1244 break;
1245 }
1246 DPRINTF("Unsupported Service Action In\n");
1247 goto illegal_request;
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001248 case VERIFY_10:
Gerd Hoffmann88f8a5e2009-11-26 15:34:15 +01001249 break;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001250 default:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001251 scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +02001252 return -1;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001253 }
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001254 return buflen;
1255
1256not_ready:
Paolo Bonzini44740c32011-10-12 12:54:16 +02001257 if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001258 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +02001259 } else {
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001260 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +02001261 }
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001262 return -1;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001263
1264illegal_request:
Paolo Bonzinicfc606d2011-09-06 12:31:44 +02001265 if (r->req.status == -1) {
1266 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1267 }
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001268 return -1;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001269}
1270
pbrook2e5d83b2006-05-25 23:58:51 +00001271/* Execute a scsi command. Returns the length of the data expected by the
1272 command. This will be Positive for data transfers from the device
1273 (eg. disk reads), negative for transfers to the device (eg. disk writes),
1274 and zero if the command does not transfer any data. */
1275
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001276static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
pbrook2e5d83b2006-05-25 23:58:51 +00001277{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001278 SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
1279 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
Paolo Bonziniad2d30f2011-04-18 16:01:56 +02001280 int32_t len;
pbrooka917d382006-08-29 04:52:16 +00001281 uint8_t command;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001282 int rc;
pbrook2e5d83b2006-05-25 23:58:51 +00001283
pbrooka917d382006-08-29 04:52:16 +00001284 command = buf[0];
Hannes Reinecke653c1c32011-07-11 15:02:25 +02001285 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001286
pbrook2e5d83b2006-05-25 23:58:51 +00001287#ifdef DEBUG_SCSI
1288 {
1289 int i;
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001290 for (i = 1; i < r->req.cmd.len; i++) {
pbrook2e5d83b2006-05-25 23:58:51 +00001291 printf(" 0x%02x", buf[i]);
1292 }
1293 printf("\n");
1294 }
1295#endif
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001296
pbrooka917d382006-08-29 04:52:16 +00001297 switch (command) {
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001298 case TEST_UNIT_READY:
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001299 case INQUIRY:
Gerd Hoffmannebddfcb2009-11-26 15:34:06 +01001300 case MODE_SENSE:
1301 case MODE_SENSE_10:
Gerd Hoffmann3d53ba12009-11-26 15:34:05 +01001302 case RESERVE:
1303 case RESERVE_10:
1304 case RELEASE:
1305 case RELEASE_10:
Gerd Hoffmann8d3628f2009-11-26 15:34:07 +01001306 case START_STOP:
Gerd Hoffmannc68b9f32009-11-26 15:34:08 +01001307 case ALLOW_MEDIUM_REMOVAL:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001308 case READ_CAPACITY_10:
Gerd Hoffmann02880f42009-11-26 15:34:11 +01001309 case READ_TOC:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001310 case READ_DVD_STRUCTURE:
Gerd Hoffmann38215552009-11-26 15:34:12 +01001311 case GET_CONFIGURATION:
Paolo Bonzinib6c251a2011-09-13 14:33:47 +02001312 case GET_EVENT_STATUS_NOTIFICATION:
1313 case MECHANISM_STATUS:
Paolo Bonzinif6515262011-09-06 12:31:42 +02001314 case SERVICE_ACTION_IN_16:
Paolo Bonzinif3b338e2011-11-14 14:31:51 +01001315 case REQUEST_SENSE:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001316 case VERIFY_10:
Paolo Bonzini72854772011-09-16 16:40:04 +02001317 rc = scsi_disk_emulate_command(r);
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001318 if (rc < 0) {
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001319 return 0;
Gerd Hoffmannaa5dbdc2009-11-26 15:34:02 +01001320 }
Kevin Wolf8af7a3a2010-10-25 12:43:22 +02001321
1322 r->iov.iov_len = rc;
Gerd Hoffmann0b06c052009-11-26 15:34:04 +01001323 break;
Paolo Bonzini0a4ac102011-09-06 09:08:34 +02001324 case SYNCHRONIZE_CACHE:
Paolo Bonzinic7bae6a2011-10-25 12:53:34 +02001325 /* The request is used as the AIO opaque value, so add a ref. */
1326 scsi_req_ref(&r->req);
Paolo Bonzini44740c32011-10-12 12:54:16 +02001327 bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
1328 r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
Paolo Bonzini0a4ac102011-09-06 09:08:34 +02001329 return 0;
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001330 case READ_6:
1331 case READ_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001332 case READ_12:
1333 case READ_16:
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001334 len = r->req.cmd.xfer / s->qdev.blocksize;
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001335 DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
Paolo Bonzini78779032011-10-13 10:39:50 +02001336 if (r->req.cmd.lba > s->qdev.max_lba) {
aliguori274fb0e2009-01-29 19:59:04 +00001337 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001338 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001339 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1340 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001341 break;
Gerd Hoffmannebf46022009-11-26 15:33:56 +01001342 case WRITE_6:
1343 case WRITE_10:
Gerd Hoffmannbd536cf2009-11-26 15:34:16 +01001344 case WRITE_12:
1345 case WRITE_16:
Hannes Reinecke5e30a072011-07-22 16:51:15 +02001346 case WRITE_VERIFY_10:
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001347 case WRITE_VERIFY_12:
1348 case WRITE_VERIFY_16:
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001349 len = r->req.cmd.xfer / s->qdev.blocksize;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001350 DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001351 (command & 0xe) == 0xe ? "And Verify " : "",
1352 r->req.cmd.lba, len);
Paolo Bonzini78779032011-10-13 10:39:50 +02001353 if (r->req.cmd.lba > s->qdev.max_lba) {
aliguori274fb0e2009-01-29 19:59:04 +00001354 goto illegal_lba;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001355 }
Paolo Bonzini69377302011-10-13 10:35:46 +02001356 r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
1357 r->sector_count = len * (s->qdev.blocksize / 512);
pbrook2e5d83b2006-05-25 23:58:51 +00001358 break;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001359 case MODE_SELECT:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001360 DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001361 /* We don't support mode parameter changes.
1362 Allow the mode parameter header + block descriptors only. */
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001363 if (r->req.cmd.xfer > 12) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001364 goto fail;
1365 }
1366 break;
1367 case MODE_SELECT_10:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001368 DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001369 /* We don't support mode parameter changes.
1370 Allow the mode parameter header + block descriptors only. */
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001371 if (r->req.cmd.xfer > 16) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001372 goto fail;
1373 }
1374 break;
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001375 case SEEK_10:
Paolo Bonzini00a01ad2011-11-14 14:31:48 +01001376 DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
Paolo Bonzini78779032011-10-13 10:39:50 +02001377 if (r->req.cmd.lba > s->qdev.max_lba) {
Bernhard Kohlebef0bb2010-09-06 11:50:55 +02001378 goto illegal_lba;
1379 }
1380 break;
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001381 case WRITE_SAME_16:
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001382 len = r->req.cmd.xfer / s->qdev.blocksize;
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001383
1384 DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
1385 r->req.cmd.lba, len);
1386
Paolo Bonzini78779032011-10-13 10:39:50 +02001387 if (r->req.cmd.lba > s->qdev.max_lba) {
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001388 goto illegal_lba;
1389 }
1390
1391 /*
1392 * We only support WRITE SAME with the unmap bit set for now.
1393 */
1394 if (!(buf[1] & 0x8)) {
1395 goto fail;
1396 }
1397
Paolo Bonzini69377302011-10-13 10:35:46 +02001398 rc = bdrv_discard(s->qdev.conf.bs,
1399 r->req.cmd.lba * (s->qdev.blocksize / 512),
1400 len * (s->qdev.blocksize / 512));
Christoph Hellwigea3bd562010-12-16 19:36:43 +01001401 if (rc < 0) {
1402 /* XXX: better error code ?*/
1403 goto fail;
1404 }
1405
1406 break;
pbrook2e5d83b2006-05-25 23:58:51 +00001407 default:
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001408 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
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 0;
pbrook2e5d83b2006-05-25 23:58:51 +00001411 fail:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001412 scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
Hannes Reinecke2dd791b2010-11-24 12:16:00 +01001413 return 0;
aliguori274fb0e2009-01-29 19:59:04 +00001414 illegal_lba:
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001415 scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
aliguori274fb0e2009-01-29 19:59:04 +00001416 return 0;
pbrook2e5d83b2006-05-25 23:58:51 +00001417 }
aliguoric87c0672009-04-07 18:43:20 +00001418 if (r->sector_count == 0 && r->iov.iov_len == 0) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +02001419 scsi_req_complete(&r->req, GOOD);
pbrook2e5d83b2006-05-25 23:58:51 +00001420 }
aliguoric87c0672009-04-07 18:43:20 +00001421 len = r->sector_count * 512 + r->iov.iov_len;
Hannes Reineckeefb9ee02011-04-18 12:57:22 +02001422 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
1423 return -len;
pbrooka917d382006-08-29 04:52:16 +00001424 } else {
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001425 if (!r->sector_count) {
pbrooka917d382006-08-29 04:52:16 +00001426 r->sector_count = -1;
Paolo Bonzinif01b5932011-10-17 16:39:27 +02001427 }
Hannes Reineckeefb9ee02011-04-18 12:57:22 +02001428 return len;
pbrooka917d382006-08-29 04:52:16 +00001429 }
pbrook2e5d83b2006-05-25 23:58:51 +00001430}
1431
Jan Kiszkae9447f32010-05-04 14:20:59 +02001432static void scsi_disk_reset(DeviceState *dev)
1433{
1434 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1435 uint64_t nb_sectors;
1436
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001437 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
Jan Kiszkae9447f32010-05-04 14:20:59 +02001438
Paolo Bonzini44740c32011-10-12 12:54:16 +02001439 bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
Paolo Bonzini69377302011-10-13 10:35:46 +02001440 nb_sectors /= s->qdev.blocksize / 512;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001441 if (nb_sectors) {
1442 nb_sectors--;
1443 }
Paolo Bonzini78779032011-10-13 10:39:50 +02001444 s->qdev.max_lba = nb_sectors;
Jan Kiszkae9447f32010-05-04 14:20:59 +02001445}
1446
1447static void scsi_destroy(SCSIDevice *dev)
1448{
1449 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1450
Paolo Bonzinic7b48872011-08-03 10:49:18 +02001451 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001452 blockdev_mark_auto_del(s->qdev.conf.bs);
Gerd Hoffmann56a14932009-09-25 21:42:46 +02001453}
1454
Markus Armbruster7d4b4ba2011-09-06 18:58:59 +02001455static void scsi_cd_change_media_cb(void *opaque, bool load)
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001456{
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001457 SCSIDiskState *s = opaque;
1458
1459 /*
1460 * When a CD gets changed, we have to report an ejected state and
1461 * then a loaded state to guests so that they detect tray
1462 * open/close and media change events. Guests that do not use
1463 * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
1464 * states rely on this behavior.
1465 *
1466 * media_changed governs the state machine used for unit attention
1467 * report. media_event is used by GET EVENT STATUS NOTIFICATION.
1468 */
1469 s->media_changed = load;
1470 s->tray_open = !load;
1471 s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
Paolo Bonzini3c2f7c12011-09-13 16:26:51 +02001472 s->media_event = true;
Paolo Bonzini4480de12011-10-25 12:53:40 +02001473 s->eject_request = false;
1474}
1475
1476static void scsi_cd_eject_request_cb(void *opaque, bool force)
1477{
1478 SCSIDiskState *s = opaque;
1479
1480 s->eject_request = true;
1481 if (force) {
1482 s->tray_locked = false;
1483 }
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001484}
1485
Markus Armbrustere4def802011-09-06 18:58:53 +02001486static bool scsi_cd_is_tray_open(void *opaque)
1487{
1488 return ((SCSIDiskState *)opaque)->tray_open;
1489}
1490
Markus Armbrusterf1076392011-09-06 18:58:46 +02001491static bool scsi_cd_is_medium_locked(void *opaque)
1492{
1493 return ((SCSIDiskState *)opaque)->tray_locked;
1494}
1495
1496static const BlockDevOps scsi_cd_block_ops = {
Markus Armbruster2c6942f2011-09-06 18:58:51 +02001497 .change_media_cb = scsi_cd_change_media_cb,
Paolo Bonzini4480de12011-10-25 12:53:40 +02001498 .eject_request_cb = scsi_cd_eject_request_cb,
Markus Armbrustere4def802011-09-06 18:58:53 +02001499 .is_tray_open = scsi_cd_is_tray_open,
Markus Armbrusterf1076392011-09-06 18:58:46 +02001500 .is_medium_locked = scsi_cd_is_medium_locked,
1501};
1502
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001503static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
1504{
1505 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1506 if (s->media_changed) {
1507 s->media_changed = false;
1508 s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
1509 }
1510}
1511
Paolo Bonzinie39be482011-10-12 14:27:40 +02001512static int scsi_initfn(SCSIDevice *dev)
pbrook2e5d83b2006-05-25 23:58:51 +00001513{
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001514 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001515 DriveInfo *dinfo;
pbrook2e5d83b2006-05-25 23:58:51 +00001516
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001517 if (!s->qdev.conf.bs) {
Markus Armbruster1ecda022010-02-18 17:25:24 +01001518 error_report("scsi-disk: drive property not set");
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001519 return -1;
1520 }
1521
Paolo Bonzinie39be482011-10-12 14:27:40 +02001522 if (!s->removable && !bdrv_is_inserted(s->qdev.conf.bs)) {
Markus Armbruster98f28ad2010-07-06 14:37:44 +02001523 error_report("Device needs media, but drive is empty");
1524 return -1;
1525 }
1526
Markus Armbrustera0fef652010-06-01 20:32:34 +02001527 if (!s->serial) {
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +02001528 /* try to fall back to value set with legacy -drive serial=... */
Paolo Bonzini44740c32011-10-12 12:54:16 +02001529 dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +02001530 if (*dinfo->serial) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001531 s->serial = g_strdup(dinfo->serial);
Hannes Reinecke3e1c0c92011-07-11 15:02:26 +02001532 }
Markus Armbrustera0fef652010-06-01 20:32:34 +02001533 }
1534
Markus Armbruster552fee92010-06-01 20:32:35 +02001535 if (!s->version) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001536 s->version = g_strdup(QEMU_VERSION);
Markus Armbruster552fee92010-06-01 20:32:35 +02001537 }
1538
Paolo Bonzini44740c32011-10-12 12:54:16 +02001539 if (bdrv_is_sg(s->qdev.conf.bs)) {
Markus Armbruster1ecda022010-02-18 17:25:24 +01001540 error_report("scsi-disk: unwanted /dev/sg*");
Markus Armbruster32bb4042010-02-25 11:23:52 +01001541 return -1;
1542 }
1543
Paolo Bonzinie39be482011-10-12 14:27:40 +02001544 if (s->removable) {
Paolo Bonzini44740c32011-10-12 12:54:16 +02001545 bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
pbrook2e5d83b2006-05-25 23:58:51 +00001546 }
Paolo Bonzini44740c32011-10-12 12:54:16 +02001547 bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
Christoph Hellwig8cfacf02010-03-04 14:20:17 +01001548
Paolo Bonzini44740c32011-10-12 12:54:16 +02001549 bdrv_iostatus_enable(s->qdev.conf.bs);
Paolo Bonzini70828262011-11-15 17:36:38 +01001550 add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001551 return 0;
ths8ccc2ac2007-12-10 02:58:34 +00001552}
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001553
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001554static int scsi_hd_initfn(SCSIDevice *dev)
1555{
Paolo Bonzinie39be482011-10-12 14:27:40 +02001556 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1557 s->qdev.blocksize = s->qdev.conf.logical_block_size;
1558 s->qdev.type = TYPE_DISK;
1559 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001560}
1561
1562static int scsi_cd_initfn(SCSIDevice *dev)
1563{
Paolo Bonzinie39be482011-10-12 14:27:40 +02001564 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1565 s->qdev.blocksize = 2048;
1566 s->qdev.type = TYPE_ROM;
1567 s->removable = true;
1568 return scsi_initfn(&s->qdev);
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001569}
1570
1571static int scsi_disk_initfn(SCSIDevice *dev)
1572{
Markus Armbruster95b5edc2011-05-16 15:04:56 +02001573 DriveInfo *dinfo;
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001574
1575 if (!dev->conf.bs) {
Paolo Bonzinie39be482011-10-12 14:27:40 +02001576 return scsi_initfn(dev); /* ... and die there */
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001577 }
1578
Paolo Bonzinie39be482011-10-12 14:27:40 +02001579 dinfo = drive_get_by_blockdev(dev->conf.bs);
1580 if (dinfo->media_cd) {
1581 return scsi_cd_initfn(dev);
1582 } else {
1583 return scsi_hd_initfn(dev);
1584 }
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001585}
1586
Paolo Bonziniadcf2752011-10-12 12:57:59 +02001587static const SCSIReqOps scsi_disk_reqops = {
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001588 .size = sizeof(SCSIDiskReq),
Paolo Bonzini12010e72011-08-03 10:49:09 +02001589 .free_req = scsi_free_request,
1590 .send_command = scsi_send_command,
1591 .read_data = scsi_read_data,
1592 .write_data = scsi_write_data,
1593 .cancel_io = scsi_cancel_io,
1594 .get_buf = scsi_get_buf,
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001595};
1596
Paolo Bonzini63db0f02011-10-12 12:58:31 +02001597static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
1598 uint8_t *buf, void *hba_private)
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001599{
1600 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1601 SCSIRequest *req;
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001602
1603 req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
Paolo Bonzini8dbd4572011-08-03 10:49:08 +02001604 return req;
1605}
1606
Paolo Bonzini336a6912011-10-25 12:53:37 +02001607#ifdef __linux__
1608static int get_device_type(SCSIDiskState *s)
1609{
1610 BlockDriverState *bdrv = s->qdev.conf.bs;
1611 uint8_t cmd[16];
1612 uint8_t buf[36];
1613 uint8_t sensebuf[8];
1614 sg_io_hdr_t io_header;
1615 int ret;
1616
1617 memset(cmd, 0, sizeof(cmd));
1618 memset(buf, 0, sizeof(buf));
1619 cmd[0] = INQUIRY;
1620 cmd[4] = sizeof(buf);
1621
1622 memset(&io_header, 0, sizeof(io_header));
1623 io_header.interface_id = 'S';
1624 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
1625 io_header.dxfer_len = sizeof(buf);
1626 io_header.dxferp = buf;
1627 io_header.cmdp = cmd;
1628 io_header.cmd_len = sizeof(cmd);
1629 io_header.mx_sb_len = sizeof(sensebuf);
1630 io_header.sbp = sensebuf;
1631 io_header.timeout = 6000; /* XXX */
1632
1633 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
1634 if (ret < 0 || io_header.driver_status || io_header.host_status) {
1635 return -1;
1636 }
1637 s->qdev.type = buf[0];
1638 s->removable = (buf[1] & 0x80) != 0;
1639 return 0;
1640}
1641
1642static int scsi_block_initfn(SCSIDevice *dev)
1643{
1644 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1645 int sg_version;
1646 int rc;
1647
1648 if (!s->qdev.conf.bs) {
1649 error_report("scsi-block: drive property not set");
1650 return -1;
1651 }
1652
1653 /* check we are using a driver managing SG_IO (version 3 and after) */
1654 if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
1655 sg_version < 30000) {
1656 error_report("scsi-block: scsi generic interface too old");
1657 return -1;
1658 }
1659
1660 /* get device type from INQUIRY data */
1661 rc = get_device_type(s);
1662 if (rc < 0) {
1663 error_report("scsi-block: INQUIRY failed");
1664 return -1;
1665 }
1666
1667 /* Make a guess for the block size, we'll fix it when the guest sends.
1668 * READ CAPACITY. If they don't, they likely would assume these sizes
1669 * anyway. (TODO: check in /sys).
1670 */
1671 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM) {
1672 s->qdev.blocksize = 2048;
1673 } else {
1674 s->qdev.blocksize = 512;
1675 }
1676 return scsi_initfn(&s->qdev);
1677}
1678
1679static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
1680 uint32_t lun, uint8_t *buf,
1681 void *hba_private)
1682{
1683 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
1684
1685 switch (buf[0]) {
1686 case READ_6:
1687 case READ_10:
1688 case READ_12:
1689 case READ_16:
1690 case WRITE_6:
1691 case WRITE_10:
1692 case WRITE_12:
1693 case WRITE_16:
1694 case WRITE_VERIFY_10:
1695 case WRITE_VERIFY_12:
1696 case WRITE_VERIFY_16:
Paolo Bonzini33ebad12011-11-14 14:31:52 +01001697 /* MMC writing cannot be done via pread/pwrite, because it sometimes
1698 * involves writing beyond the maximum LBA or to negative LBA (lead-in).
1699 * And once you do these writes, reading from the block device is
1700 * unreliable, too. It is even possible that reads deliver random data
1701 * from the host page cache (this is probably a Linux bug).
1702 *
1703 * We might use scsi_disk_reqops as long as no writing commands are
1704 * seen, but performance usually isn't paramount on optical media. So,
1705 * just make scsi-block operate the same as scsi-generic for them.
1706 */
1707 if (s->qdev.type != TYPE_ROM) {
1708 return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
1709 hba_private);
1710 }
Paolo Bonzini336a6912011-10-25 12:53:37 +02001711 }
1712
1713 return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
1714 hba_private);
1715}
1716#endif
1717
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001718#define DEFINE_SCSI_DISK_PROPERTIES() \
1719 DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \
1720 DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
1721 DEFINE_PROP_STRING("serial", SCSIDiskState, serial)
1722
1723static SCSIDeviceInfo scsi_disk_info[] = {
1724 {
1725 .qdev.name = "scsi-hd",
1726 .qdev.fw_name = "disk",
1727 .qdev.desc = "virtual SCSI disk",
1728 .qdev.size = sizeof(SCSIDiskState),
1729 .qdev.reset = scsi_disk_reset,
1730 .init = scsi_hd_initfn,
1731 .destroy = scsi_destroy,
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001732 .alloc_req = scsi_new_request,
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001733 .unit_attention_reported = scsi_disk_unit_attention_reported,
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001734 .qdev.props = (Property[]) {
1735 DEFINE_SCSI_DISK_PROPERTIES(),
1736 DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1737 DEFINE_PROP_END_OF_LIST(),
1738 }
1739 },{
1740 .qdev.name = "scsi-cd",
1741 .qdev.fw_name = "disk",
1742 .qdev.desc = "virtual SCSI CD-ROM",
1743 .qdev.size = sizeof(SCSIDiskState),
1744 .qdev.reset = scsi_disk_reset,
1745 .init = scsi_cd_initfn,
1746 .destroy = scsi_destroy,
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001747 .alloc_req = scsi_new_request,
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001748 .unit_attention_reported = scsi_disk_unit_attention_reported,
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001749 .qdev.props = (Property[]) {
1750 DEFINE_SCSI_DISK_PROPERTIES(),
1751 DEFINE_PROP_END_OF_LIST(),
1752 },
Paolo Bonzini336a6912011-10-25 12:53:37 +02001753#ifdef __linux__
1754 },{
1755 .qdev.name = "scsi-block",
1756 .qdev.fw_name = "disk",
1757 .qdev.desc = "SCSI block device passthrough",
1758 .qdev.size = sizeof(SCSIDiskState),
1759 .qdev.reset = scsi_disk_reset,
1760 .init = scsi_block_initfn,
1761 .destroy = scsi_destroy,
1762 .alloc_req = scsi_block_new_request,
1763 .qdev.props = (Property[]) {
1764 DEFINE_SCSI_DISK_PROPERTIES(),
1765 DEFINE_PROP_END_OF_LIST(),
1766 },
1767#endif
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001768 },{
1769 .qdev.name = "scsi-disk", /* legacy -device scsi-disk */
1770 .qdev.fw_name = "disk",
1771 .qdev.desc = "virtual SCSI disk or CD-ROM (legacy)",
1772 .qdev.size = sizeof(SCSIDiskState),
1773 .qdev.reset = scsi_disk_reset,
1774 .init = scsi_disk_initfn,
1775 .destroy = scsi_destroy,
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +02001776 .alloc_req = scsi_new_request,
Paolo Bonzini8a9c16f2011-09-13 16:26:06 +02001777 .unit_attention_reported = scsi_disk_unit_attention_reported,
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001778 .qdev.props = (Property[]) {
1779 DEFINE_SCSI_DISK_PROPERTIES(),
1780 DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
1781 DEFINE_PROP_END_OF_LIST(),
1782 }
1783 }
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001784};
1785
1786static void scsi_disk_register_devices(void)
1787{
Markus Armbrusterb443ae62011-05-16 15:04:53 +02001788 int i;
1789
1790 for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) {
1791 scsi_qdev_register(&scsi_disk_info[i]);
1792 }
Gerd Hoffmannd52affa2009-08-31 14:24:04 +02001793}
1794device_init(scsi_disk_register_devices)