blob: 7a588a7ad43f0d5a4d0e071ff6159549b6b397ec [file] [log] [blame]
ths2cc977e2007-12-24 16:11:51 +00001/*
2 * Generic SCSI Device support
3 *
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
7 *
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
9 *
Matthew Fernandez8e31bf32011-06-26 12:21:35 +100010 * This code is licensed under the LGPL.
ths2cc977e2007-12-24 16:11:51 +000011 *
12 */
13
Peter Maydella4ab4792016-01-26 18:17:16 +000014#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010015#include "qapi/error.h"
ths2cc977e2007-12-24 16:11:51 +000016#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010017#include "qemu/error-report.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010018#include "hw/scsi/scsi.h"
Markus Armbruster4be74632014-10-07 13:59:18 +020019#include "sysemu/block-backend.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010020#include "sysemu/blockdev.h"
ths2cc977e2007-12-24 16:11:51 +000021
Gerd Hoffmannd52affa2009-08-31 14:24:04 +020022#ifdef __linux__
ths2cc977e2007-12-24 16:11:51 +000023
24//#define DEBUG_SCSI
25
26#ifdef DEBUG_SCSI
Blue Swirl001faf32009-05-13 17:53:17 +000027#define DPRINTF(fmt, ...) \
28do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
ths2cc977e2007-12-24 16:11:51 +000029#else
Blue Swirl001faf32009-05-13 17:53:17 +000030#define DPRINTF(fmt, ...) do {} while(0)
ths2cc977e2007-12-24 16:11:51 +000031#endif
32
Blue Swirl001faf32009-05-13 17:53:17 +000033#define BADF(fmt, ...) \
34do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
ths2cc977e2007-12-24 16:11:51 +000035
ths2cc977e2007-12-24 16:11:51 +000036#include <scsi/sg.h>
Paolo Bonzini0d09e412013-02-05 17:06:20 +010037#include "block/scsi.h"
ths2cc977e2007-12-24 16:11:51 +000038
Paolo Bonzinia3b16e72011-10-12 14:53:43 +020039#define SG_ERR_DRIVER_TIMEOUT 0x06
40#define SG_ERR_DRIVER_SENSE 0x08
41
42#define SG_ERR_DID_OK 0x00
43#define SG_ERR_DID_NO_CONNECT 0x01
44#define SG_ERR_DID_BUS_BUSY 0x02
45#define SG_ERR_DID_TIME_OUT 0x03
ths2cc977e2007-12-24 16:11:51 +000046
47#ifndef MAX_UINT
48#define MAX_UINT ((unsigned int)-1)
49#endif
50
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010051typedef struct SCSIGenericReq {
52 SCSIRequest req;
ths2cc977e2007-12-24 16:11:51 +000053 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010057} SCSIGenericReq;
ths2cc977e2007-12-24 16:11:51 +000058
Paolo Bonzini56b1fc42011-12-15 07:24:30 -050059static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
60{
61 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
62
63 qemu_put_sbe32s(f, &r->buflen);
64 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
65 assert(!r->req.sg);
66 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
67 }
68}
69
70static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
71{
72 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
73
74 qemu_get_sbe32s(f, &r->buflen);
75 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
76 assert(!r->req.sg);
77 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
78 }
79}
80
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020081static void scsi_free_request(SCSIRequest *req)
ths2cc977e2007-12-24 16:11:51 +000082{
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020083 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
84
Anthony Liguori7267c092011-08-20 22:09:37 -050085 g_free(r->buf);
ths2cc977e2007-12-24 16:11:51 +000086}
87
ths2cc977e2007-12-24 16:11:51 +000088/* Helper function for command completion. */
Paolo Bonzinifa0d6532015-07-19 19:15:26 +020089static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
ths2cc977e2007-12-24 16:11:51 +000090{
Paolo Bonzini682a9b22011-08-03 10:49:06 +020091 int status;
ths2cc977e2007-12-24 16:11:51 +000092
Paolo Bonzinifa0d6532015-07-19 19:15:26 +020093 assert(r->req.aiocb == NULL);
94
Fam Zheng6c25fa62014-09-24 16:27:53 +080095 if (r->req.io_canceled) {
Fam Zhengd5776462014-09-25 10:20:47 +080096 scsi_req_cancel_complete(&r->req);
Fam Zheng6c25fa62014-09-24 16:27:53 +080097 goto done;
98 }
Paolo Bonzinia3b16e72011-10-12 14:53:43 +020099 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200100 r->req.sense_len = r->io_header.sb_len_wr;
Paolo Bonzinia3b16e72011-10-12 14:53:43 +0200101 }
aurel3289c0f642008-10-17 08:08:56 +0000102
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200103 if (ret != 0) {
104 switch (ret) {
Paolo Bonzini2e7cc4d2011-04-18 14:29:16 +0200105 case -EDOM:
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200106 status = TASK_SET_FULL;
Paolo Bonzini2e7cc4d2011-04-18 14:29:16 +0200107 break;
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200108 case -ENOMEM:
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200109 status = CHECK_CONDITION;
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200110 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200111 break;
112 default:
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200113 status = CHECK_CONDITION;
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200114 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200115 break;
116 }
117 } else {
Paolo Bonzinia3b16e72011-10-12 14:53:43 +0200118 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
119 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
120 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
121 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200122 status = BUSY;
ths2cc977e2007-12-24 16:11:51 +0000123 BADF("Driver Timeout\n");
Paolo Bonzinia3b16e72011-10-12 14:53:43 +0200124 } else if (r->io_header.host_status) {
125 status = CHECK_CONDITION;
126 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200127 } else if (r->io_header.status) {
128 status = r->io_header.status;
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200129 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200130 status = CHECK_CONDITION;
131 } else {
132 status = GOOD;
133 }
ths2cc977e2007-12-24 16:11:51 +0000134 }
aurel3289c0f642008-10-17 08:08:56 +0000135 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200136 r, r->req.tag, status);
Gerd Hoffmanned3a34a2009-11-26 15:34:00 +0100137
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200138 scsi_req_complete(&r->req, status);
Fam Zheng6c25fa62014-09-24 16:27:53 +0800139done:
Fam Zheng3df9caf2014-09-24 16:27:54 +0800140 scsi_req_unref(&r->req);
ths2cc977e2007-12-24 16:11:51 +0000141}
142
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200143static void scsi_command_complete(void *opaque, int ret)
144{
145 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
146
147 assert(r->req.aiocb != NULL);
148 r->req.aiocb = NULL;
149 scsi_command_complete_noio(r, ret);
150}
151
Markus Armbruster4be74632014-10-07 13:59:18 +0200152static int execute_command(BlockBackend *blk,
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100153 SCSIGenericReq *r, int direction,
Markus Armbruster097310b2014-10-07 13:59:15 +0200154 BlockCompletionFunc *complete)
ths2cc977e2007-12-24 16:11:51 +0000155{
ths2cc977e2007-12-24 16:11:51 +0000156 r->io_header.interface_id = 'S';
157 r->io_header.dxfer_direction = direction;
158 r->io_header.dxferp = r->buf;
159 r->io_header.dxfer_len = r->buflen;
Gerd Hoffmann29362eb2009-11-26 15:33:51 +0100160 r->io_header.cmdp = r->req.cmd.buf;
161 r->io_header.cmd_len = r->req.cmd.len;
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200162 r->io_header.mx_sb_len = sizeof(r->req.sense);
163 r->io_header.sbp = r->req.sense;
ths2cc977e2007-12-24 16:11:51 +0000164 r->io_header.timeout = MAX_UINT;
165 r->io_header.usr_ptr = r;
166 r->io_header.flags |= SG_FLAG_DIRECT_IO;
167
Markus Armbruster4be74632014-10-07 13:59:18 +0200168 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
Pavel Hrdinad836f8d2013-05-29 14:12:10 +0200169 if (r->req.aiocb == NULL) {
170 return -EIO;
171 }
ths2cc977e2007-12-24 16:11:51 +0000172
173 return 0;
174}
175
176static void scsi_read_complete(void * opaque, int ret)
177{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100178 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
Paolo Bonzini9b6eef82011-10-13 10:36:27 +0200179 SCSIDevice *s = r->req.dev;
ths2cc977e2007-12-24 16:11:51 +0000180 int len;
181
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200182 assert(r->req.aiocb != NULL);
Paolo Bonzinid33e0ce2011-05-25 16:53:46 +0200183 r->req.aiocb = NULL;
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200184
Fam Zheng6c25fa62014-09-24 16:27:53 +0800185 if (ret || r->req.io_canceled) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200186 scsi_command_complete_noio(r, ret);
ths2cc977e2007-12-24 16:11:51 +0000187 return;
188 }
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200189
ths2cc977e2007-12-24 16:11:51 +0000190 len = r->io_header.dxfer_len - r->io_header.resid;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100191 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
ths2cc977e2007-12-24 16:11:51 +0000192
193 r->len = -1;
Paolo Bonzini40f16dd2011-05-03 14:15:59 +0200194 if (len == 0) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200195 scsi_command_complete_noio(r, 0);
196 return;
Paolo Bonzini40f16dd2011-05-03 14:15:59 +0200197 }
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200198
199 /* Snoop READ CAPACITY output to set the blocksize. */
200 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
201 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
202 s->blocksize = ldl_be_p(&r->buf[4]);
203 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
204 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
205 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
206 s->blocksize = ldl_be_p(&r->buf[8]);
207 s->max_lba = ldq_be_p(&r->buf[0]);
208 }
209 blk_set_guest_block_size(s->conf.blk, s->blocksize);
210
Paolo Bonzini0eb2bae2015-09-16 17:26:16 +0200211 /* Patch MODE SENSE device specific parameters if the BDS is opened
212 * readonly.
213 */
214 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) &&
215 blk_is_read_only(s->conf.blk) &&
216 (r->req.cmd.buf[0] == MODE_SENSE ||
217 r->req.cmd.buf[0] == MODE_SENSE_10) &&
218 (r->req.cmd.buf[1] & 0x8) == 0) {
219 if (r->req.cmd.buf[0] == MODE_SENSE) {
220 r->buf[2] |= 0x80;
221 } else {
222 r->buf[3] |= 0x80;
223 }
224 }
Fam Zheng063143d2016-05-26 14:15:05 +0800225 if (s->type == TYPE_DISK &&
226 r->req.cmd.buf[0] == INQUIRY &&
227 r->req.cmd.buf[2] == 0xb0) {
Eric Blake5def6b82016-06-23 16:37:19 -0600228 uint32_t max_transfer =
229 blk_get_max_transfer(s->conf.blk) / s->blocksize;
Eric Blake24ce9a22016-06-23 16:37:12 -0600230
Eric Blake5def6b82016-06-23 16:37:19 -0600231 assert(max_transfer);
232 stl_be_p(&r->buf[8], max_transfer);
Eric Blake24ce9a22016-06-23 16:37:12 -0600233 /* Also take care of the opt xfer len. */
Eric Blake5def6b82016-06-23 16:37:19 -0600234 if (ldl_be_p(&r->buf[12]) > max_transfer) {
235 stl_be_p(&r->buf[12], max_transfer);
Fam Zheng063143d2016-05-26 14:15:05 +0800236 }
237 }
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200238 scsi_req_data(&r->req, len);
239 scsi_req_unref(&r->req);
ths2cc977e2007-12-24 16:11:51 +0000240}
241
242/* Read more data from scsi device into buffer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200243static void scsi_read_data(SCSIRequest *req)
ths2cc977e2007-12-24 16:11:51 +0000244{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200245 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
Paolo Bonzini8869e102011-10-12 12:49:35 +0200246 SCSIDevice *s = r->req.dev;
ths2cc977e2007-12-24 16:11:51 +0000247 int ret;
248
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200249 DPRINTF("scsi_read_data 0x%x\n", req->tag);
Paolo Bonzinic9501c92011-10-25 12:53:35 +0200250
251 /* The request is used as the AIO opaque value, so add a ref. */
252 scsi_req_ref(&r->req);
ths2cc977e2007-12-24 16:11:51 +0000253 if (r->len == -1) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200254 scsi_command_complete_noio(r, 0);
ths2cc977e2007-12-24 16:11:51 +0000255 return;
256 }
257
Markus Armbruster4be74632014-10-07 13:59:18 +0200258 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
259 scsi_read_complete);
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200260 if (ret < 0) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200261 scsi_command_complete_noio(r, ret);
ths2cc977e2007-12-24 16:11:51 +0000262 }
263}
264
265static void scsi_write_complete(void * opaque, int ret)
266{
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +0100267 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
Paolo Bonzini8869e102011-10-12 12:49:35 +0200268 SCSIDevice *s = r->req.dev;
ths2cc977e2007-12-24 16:11:51 +0000269
270 DPRINTF("scsi_write_complete() ret = %d\n", ret);
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200271
272 assert(r->req.aiocb != NULL);
Paolo Bonzinid33e0ce2011-05-25 16:53:46 +0200273 r->req.aiocb = NULL;
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200274
Fam Zheng6c25fa62014-09-24 16:27:53 +0800275 if (ret || r->req.io_canceled) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200276 scsi_command_complete_noio(r, ret);
ths2cc977e2007-12-24 16:11:51 +0000277 return;
278 }
279
Gerd Hoffmann29362eb2009-11-26 15:33:51 +0100280 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
Paolo Bonzini8869e102011-10-12 12:49:35 +0200281 s->type == TYPE_TAPE) {
282 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
283 DPRINTF("block size %d\n", s->blocksize);
aurel3289c0f642008-10-17 08:08:56 +0000284 }
285
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200286 scsi_command_complete_noio(r, ret);
ths2cc977e2007-12-24 16:11:51 +0000287}
288
289/* Write data to a scsi device. Returns nonzero on failure.
290 The transfer may complete asynchronously. */
Paolo Bonzini42741212011-04-22 09:39:16 +0200291static void scsi_write_data(SCSIRequest *req)
ths2cc977e2007-12-24 16:11:51 +0000292{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200293 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
Paolo Bonzini8869e102011-10-12 12:49:35 +0200294 SCSIDevice *s = r->req.dev;
ths2cc977e2007-12-24 16:11:51 +0000295 int ret;
296
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200297 DPRINTF("scsi_write_data 0x%x\n", req->tag);
ths2cc977e2007-12-24 16:11:51 +0000298 if (r->len == 0) {
299 r->len = r->buflen;
Paolo Bonziniab9adc82011-04-18 14:59:13 +0200300 scsi_req_data(&r->req, r->len);
Paolo Bonzini42741212011-04-22 09:39:16 +0200301 return;
ths2cc977e2007-12-24 16:11:51 +0000302 }
303
Paolo Bonzinic9501c92011-10-25 12:53:35 +0200304 /* The request is used as the AIO opaque value, so add a ref. */
305 scsi_req_ref(&r->req);
Markus Armbruster4be74632014-10-07 13:59:18 +0200306 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200307 if (ret < 0) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200308 scsi_command_complete_noio(r, ret);
ths2cc977e2007-12-24 16:11:51 +0000309 }
ths2cc977e2007-12-24 16:11:51 +0000310}
311
312/* Return a pointer to the data buffer. */
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200313static uint8_t *scsi_get_buf(SCSIRequest *req)
ths2cc977e2007-12-24 16:11:51 +0000314{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200315 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
316
ths2cc977e2007-12-24 16:11:51 +0000317 return r->buf;
318}
319
ths2cc977e2007-12-24 16:11:51 +0000320/* Execute a scsi command. Returns the length of the data expected by the
321 command. This will be Positive for data transfers from the device
322 (eg. disk reads), negative for transfers to the device (eg. disk writes),
323 and zero if the command does not transfer any data. */
324
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200325static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
ths2cc977e2007-12-24 16:11:51 +0000326{
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200327 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
Paolo Bonzini8869e102011-10-12 12:49:35 +0200328 SCSIDevice *s = r->req.dev;
ths2cc977e2007-12-24 16:11:51 +0000329 int ret;
330
Bernhard Kohlaa2b1e82010-09-01 16:33:21 +0200331#ifdef DEBUG_SCSI
332 {
333 int i;
334 for (i = 1; i < r->req.cmd.len; i++) {
335 printf(" 0x%02x", cmd[i]);
336 }
337 printf("\n");
338 }
339#endif
Gerd Hoffmann2ec749c2009-11-26 15:33:55 +0100340
341 if (r->req.cmd.xfer == 0) {
Markus Armbruster1c3381a2014-12-04 14:12:43 +0100342 g_free(r->buf);
ths2cc977e2007-12-24 16:11:51 +0000343 r->buflen = 0;
344 r->buf = NULL;
Paolo Bonzinic9501c92011-10-25 12:53:35 +0200345 /* The request is used as the AIO opaque value, so add a ref. */
346 scsi_req_ref(&r->req);
Markus Armbruster4be74632014-10-07 13:59:18 +0200347 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
348 scsi_command_complete);
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200349 if (ret < 0) {
Paolo Bonzinifa0d6532015-07-19 19:15:26 +0200350 scsi_command_complete_noio(r, ret);
Hannes Reineckea1f0cce2011-04-18 12:53:14 +0200351 return 0;
ths2cc977e2007-12-24 16:11:51 +0000352 }
353 return 0;
354 }
355
Gerd Hoffmann2ec749c2009-11-26 15:33:55 +0100356 if (r->buflen != r->req.cmd.xfer) {
Markus Armbruster1c3381a2014-12-04 14:12:43 +0100357 g_free(r->buf);
Anthony Liguori7267c092011-08-20 22:09:37 -0500358 r->buf = g_malloc(r->req.cmd.xfer);
Gerd Hoffmann2ec749c2009-11-26 15:33:55 +0100359 r->buflen = r->req.cmd.xfer;
ths2cc977e2007-12-24 16:11:51 +0000360 }
361
362 memset(r->buf, 0, r->buflen);
Gerd Hoffmann2ec749c2009-11-26 15:33:55 +0100363 r->len = r->req.cmd.xfer;
Gerd Hoffmann97a06432009-11-26 15:33:57 +0100364 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
ths2cc977e2007-12-24 16:11:51 +0000365 r->len = 0;
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200366 return -r->req.cmd.xfer;
Paolo Bonziniad2d30f2011-04-18 16:01:56 +0200367 } else {
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +0200368 return r->req.cmd.xfer;
ths2cc977e2007-12-24 16:11:51 +0000369 }
ths2cc977e2007-12-24 16:11:51 +0000370}
371
Paolo Bonzini9fd7e852016-01-12 12:29:57 +0100372static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
373{
374 int i;
375
376 if ((p[1] & 0xF) == 3) {
377 /* NAA designator type */
378 if (p[3] != 8) {
379 return -EINVAL;
380 }
381 *p_wwn = ldq_be_p(p + 4);
382 return 0;
383 }
384
385 if ((p[1] & 0xF) == 8) {
386 /* SCSI name string designator type */
387 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
388 return -EINVAL;
389 }
390 if (p[3] > 20 && p[24] != ',') {
391 return -EINVAL;
392 }
393 *p_wwn = 0;
394 for (i = 8; i < 24; i++) {
395 char c = toupper(p[i]);
396 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
397 *p_wwn = (*p_wwn << 4) | c;
398 }
399 return 0;
400 }
401
402 return -EINVAL;
403}
404
405void scsi_generic_read_device_identification(SCSIDevice *s)
406{
407 uint8_t cmd[6];
408 uint8_t buf[250];
409 uint8_t sensebuf[8];
410 sg_io_hdr_t io_header;
411 int ret;
412 int i, len;
413
414 memset(cmd, 0, sizeof(cmd));
415 memset(buf, 0, sizeof(buf));
416 cmd[0] = INQUIRY;
417 cmd[1] = 1;
418 cmd[2] = 0x83;
419 cmd[4] = sizeof(buf);
420
421 memset(&io_header, 0, sizeof(io_header));
422 io_header.interface_id = 'S';
423 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
424 io_header.dxfer_len = sizeof(buf);
425 io_header.dxferp = buf;
426 io_header.cmdp = cmd;
427 io_header.cmd_len = sizeof(cmd);
428 io_header.mx_sb_len = sizeof(sensebuf);
429 io_header.sbp = sensebuf;
430 io_header.timeout = 6000; /* XXX */
431
432 ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
433 if (ret < 0 || io_header.driver_status || io_header.host_status) {
434 return;
435 }
436
437 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
438 for (i = 0; i + 3 <= len; ) {
439 const uint8_t *p = &buf[i + 4];
440 uint64_t wwn;
441
442 if (i + (p[3] + 4) > len) {
443 break;
444 }
445
446 if ((p[1] & 0x10) == 0) {
447 /* Associated with the logical unit */
448 if (read_naa_id(p, &wwn) == 0) {
449 s->wwn = wwn;
450 }
451 } else if ((p[1] & 0x10) == 0x10) {
452 /* Associated with the target port */
453 if (read_naa_id(p, &wwn) == 0) {
454 s->port_wwn = wwn;
455 }
456 }
457
458 i += p[3] + 4;
459 }
460}
461
Markus Armbruster4be74632014-10-07 13:59:18 +0200462static int get_stream_blocksize(BlockBackend *blk)
aurel3289c0f642008-10-17 08:08:56 +0000463{
464 uint8_t cmd[6];
465 uint8_t buf[12];
466 uint8_t sensebuf[8];
467 sg_io_hdr_t io_header;
468 int ret;
469
470 memset(cmd, 0, sizeof(cmd));
471 memset(buf, 0, sizeof(buf));
472 cmd[0] = MODE_SENSE;
473 cmd[4] = sizeof(buf);
474
475 memset(&io_header, 0, sizeof(io_header));
476 io_header.interface_id = 'S';
477 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
478 io_header.dxfer_len = sizeof(buf);
479 io_header.dxferp = buf;
480 io_header.cmdp = cmd;
481 io_header.cmd_len = sizeof(cmd);
482 io_header.mx_sb_len = sizeof(sensebuf);
483 io_header.sbp = sensebuf;
484 io_header.timeout = 6000; /* XXX */
485
Markus Armbruster4be74632014-10-07 13:59:18 +0200486 ret = blk_ioctl(blk, SG_IO, &io_header);
Paolo Bonzinife0ed712011-10-12 14:49:48 +0200487 if (ret < 0 || io_header.driver_status || io_header.host_status) {
aurel3289c0f642008-10-17 08:08:56 +0000488 return -1;
Paolo Bonzinife0ed712011-10-12 14:49:48 +0200489 }
aurel3289c0f642008-10-17 08:08:56 +0000490 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
491}
492
Bernhard Kohlf8b6d672010-09-06 16:07:33 +0200493static void scsi_generic_reset(DeviceState *dev)
494{
Anthony Liguorib9eea3e2011-12-15 14:50:08 -0600495 SCSIDevice *s = SCSI_DEVICE(dev);
Bernhard Kohlf8b6d672010-09-06 16:07:33 +0200496
Paolo Bonzini8869e102011-10-12 12:49:35 +0200497 scsi_device_purge_requests(s, SENSE_CODE(RESET));
Bernhard Kohlf8b6d672010-09-06 16:07:33 +0200498}
499
Fam Zhenga818a4b2014-08-12 10:12:55 +0800500static void scsi_generic_realize(SCSIDevice *s, Error **errp)
ths2cc977e2007-12-24 16:11:51 +0000501{
Paolo Bonzini6ee143a2014-04-28 12:14:57 +0200502 int rc;
ths2cc977e2007-12-24 16:11:51 +0000503 int sg_version;
ths2cc977e2007-12-24 16:11:51 +0000504 struct sg_scsi_id scsiid;
505
Markus Armbruster4be74632014-10-07 13:59:18 +0200506 if (!s->conf.blk) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800507 error_setg(errp, "drive property not set");
508 return;
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200509 }
ths2cc977e2007-12-24 16:11:51 +0000510
Markus Armbruster4be74632014-10-07 13:59:18 +0200511 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800512 error_setg(errp, "Device doesn't support drive option werror");
513 return;
Markus Armbruster620f8622010-05-27 20:02:28 +0200514 }
Markus Armbruster4be74632014-10-07 13:59:18 +0200515 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800516 error_setg(errp, "Device doesn't support drive option rerror");
517 return;
Markus Armbruster620f8622010-05-27 20:02:28 +0200518 }
519
ths2cc977e2007-12-24 16:11:51 +0000520 /* check we are using a driver managing SG_IO (version 3 and after */
Markus Armbruster4be74632014-10-07 13:59:18 +0200521 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
Paolo Bonzini6ee143a2014-04-28 12:14:57 +0200522 if (rc < 0) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800523 error_setg(errp, "cannot get SG_IO version number: %s. "
524 "Is this a SCSI device?",
525 strerror(-rc));
526 return;
Ronnie Sahlberg98392452012-05-25 21:59:01 +1000527 }
528 if (sg_version < 30000) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800529 error_setg(errp, "scsi generic interface too old");
530 return;
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200531 }
ths2cc977e2007-12-24 16:11:51 +0000532
533 /* get LUN of the /dev/sg? */
Markus Armbruster4be74632014-10-07 13:59:18 +0200534 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
Fam Zhenga818a4b2014-08-12 10:12:55 +0800535 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
536 return;
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200537 }
ths2cc977e2007-12-24 16:11:51 +0000538
539 /* define device state */
Paolo Bonzini8869e102011-10-12 12:49:35 +0200540 s->type = scsiid.scsi_type;
541 DPRINTF("device type %d\n", s->type);
Paolo Bonzini28b77652011-11-18 16:32:02 +0100542
Paolo Bonzini9b6eef82011-10-13 10:36:27 +0200543 switch (s->type) {
544 case TYPE_TAPE:
Markus Armbruster4be74632014-10-07 13:59:18 +0200545 s->blocksize = get_stream_blocksize(s->conf.blk);
Paolo Bonzini8869e102011-10-12 12:49:35 +0200546 if (s->blocksize == -1) {
547 s->blocksize = 0;
548 }
Paolo Bonzini9b6eef82011-10-13 10:36:27 +0200549 break;
550
551 /* Make a guess for block devices, we'll fix it when the guest sends.
552 * READ CAPACITY. If they don't, they likely would assume these sizes
553 * anyway. (TODO: they could also send MODE SENSE).
554 */
555 case TYPE_ROM:
556 case TYPE_WORM:
557 s->blocksize = 2048;
558 break;
559 default:
560 s->blocksize = 512;
561 break;
aurel3289c0f642008-10-17 08:08:56 +0000562 }
Paolo Bonzini8869e102011-10-12 12:49:35 +0200563
564 DPRINTF("block size %d\n", s->blocksize);
Paolo Bonzini9fd7e852016-01-12 12:29:57 +0100565
566 scsi_generic_read_device_identification(s);
ths2cc977e2007-12-24 16:11:51 +0000567}
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200568
Paolo Bonzini765d1522011-10-12 12:54:31 +0200569const SCSIReqOps scsi_generic_req_ops = {
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200570 .size = sizeof(SCSIGenericReq),
Paolo Bonzini12010e72011-08-03 10:49:09 +0200571 .free_req = scsi_free_request,
572 .send_command = scsi_send_command,
573 .read_data = scsi_read_data,
574 .write_data = scsi_write_data,
Paolo Bonzini12010e72011-08-03 10:49:09 +0200575 .get_buf = scsi_get_buf,
Paolo Bonzini56b1fc42011-12-15 07:24:30 -0500576 .load_request = scsi_generic_load_request,
577 .save_request = scsi_generic_save_request,
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200578};
579
580static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
Paolo Bonzini63db0f02011-10-12 12:58:31 +0200581 uint8_t *buf, void *hba_private)
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200582{
Eduardo Habkost9be38592016-06-13 18:57:58 -0300583 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200584}
585
Anthony Liguori39bffca2011-12-07 21:34:16 -0600586static Property scsi_generic_properties[] = {
Markus Armbruster4be74632014-10-07 13:59:18 +0200587 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
Anthony Liguori39bffca2011-12-07 21:34:16 -0600588 DEFINE_PROP_END_OF_LIST(),
589};
590
Paolo Bonzini3e7e1802014-07-16 12:22:26 +0200591static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
592 uint8_t *buf, void *hba_private)
593{
594 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
595}
596
Anthony Liguorib9eea3e2011-12-15 14:50:08 -0600597static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
598{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600599 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -0600600 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
601
Fam Zhenga818a4b2014-08-12 10:12:55 +0800602 sc->realize = scsi_generic_realize;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -0600603 sc->alloc_req = scsi_new_request;
Paolo Bonzini3e7e1802014-07-16 12:22:26 +0200604 sc->parse_cdb = scsi_generic_parse_cdb;
Anthony Liguori39bffca2011-12-07 21:34:16 -0600605 dc->fw_name = "disk";
606 dc->desc = "pass through generic scsi device (/dev/sg*)";
607 dc->reset = scsi_generic_reset;
608 dc->props = scsi_generic_properties;
Paolo Bonzini56b1fc42011-12-15 07:24:30 -0500609 dc->vmsd = &vmstate_scsi_device;
Anthony Liguorib9eea3e2011-12-15 14:50:08 -0600610}
611
Andreas Färber8c43a6f2013-01-10 16:19:07 +0100612static const TypeInfo scsi_generic_info = {
Anthony Liguori39bffca2011-12-07 21:34:16 -0600613 .name = "scsi-generic",
614 .parent = TYPE_SCSI_DEVICE,
615 .instance_size = sizeof(SCSIDevice),
616 .class_init = scsi_generic_class_initfn,
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200617};
618
Andreas Färber83f7d432012-02-09 15:20:55 +0100619static void scsi_generic_register_types(void)
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200620{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600621 type_register_static(&scsi_generic_info);
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200622}
Andreas Färber83f7d432012-02-09 15:20:55 +0100623
624type_init(scsi_generic_register_types)
Gerd Hoffmannd52affa2009-08-31 14:24:04 +0200625
ths2cc977e2007-12-24 16:11:51 +0000626#endif /* __linux__ */