]> Git Repo - qemu.git/blame - hw/scsi/scsi-generic.c
ivshmem: limit maximum number of peers to G_MAXUINT16
[qemu.git] / hw / scsi / scsi-generic.c
CommitLineData
2cc977e2
TS
1/*
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 <[email protected]>
9 *
8e31bf38 10 * This code is licensed under the LGPL.
2cc977e2
TS
11 *
12 */
13
14#include "qemu-common.h"
1de7afc9 15#include "qemu/error-report.h"
0d09e41a 16#include "hw/scsi/scsi.h"
4be74634 17#include "sysemu/block-backend.h"
9c17d615 18#include "sysemu/blockdev.h"
2cc977e2 19
d52affa7 20#ifdef __linux__
2cc977e2
TS
21
22//#define DEBUG_SCSI
23
24#ifdef DEBUG_SCSI
001faf32
BS
25#define DPRINTF(fmt, ...) \
26do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2 27#else
001faf32 28#define DPRINTF(fmt, ...) do {} while(0)
2cc977e2
TS
29#endif
30
001faf32
BS
31#define BADF(fmt, ...) \
32do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2
TS
33
34#include <stdio.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <unistd.h>
38#include <scsi/sg.h>
0d09e41a 39#include "block/scsi.h"
2cc977e2 40
a3b16e71
PB
41#define SG_ERR_DRIVER_TIMEOUT 0x06
42#define SG_ERR_DRIVER_SENSE 0x08
43
44#define SG_ERR_DID_OK 0x00
45#define SG_ERR_DID_NO_CONNECT 0x01
46#define SG_ERR_DID_BUS_BUSY 0x02
47#define SG_ERR_DID_TIME_OUT 0x03
2cc977e2
TS
48
49#ifndef MAX_UINT
50#define MAX_UINT ((unsigned int)-1)
51#endif
52
4c41d2ef
GH
53typedef struct SCSIGenericReq {
54 SCSIRequest req;
2cc977e2
TS
55 uint8_t *buf;
56 int buflen;
57 int len;
58 sg_io_hdr_t io_header;
4c41d2ef 59} SCSIGenericReq;
2cc977e2 60
56b1fc48
PB
61static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
62{
63 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
64
65 qemu_put_sbe32s(f, &r->buflen);
66 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
67 assert(!r->req.sg);
68 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
69 }
70}
71
72static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
73{
74 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
75
76 qemu_get_sbe32s(f, &r->buflen);
77 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
78 assert(!r->req.sg);
79 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
80 }
81}
82
ad2d30f7 83static void scsi_free_request(SCSIRequest *req)
2cc977e2 84{
ad2d30f7
PB
85 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
86
7267c094 87 g_free(r->buf);
2cc977e2
TS
88}
89
2cc977e2 90/* Helper function for command completion. */
fa0d653b 91static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
2cc977e2 92{
682a9b21 93 int status;
2cc977e2 94
fa0d653b
PB
95 assert(r->req.aiocb == NULL);
96
6c25fa6c 97 if (r->req.io_canceled) {
d5776465 98 scsi_req_cancel_complete(&r->req);
6c25fa6c
FZ
99 goto done;
100 }
a3b16e71 101 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
b45ef674 102 r->req.sense_len = r->io_header.sb_len_wr;
a3b16e71 103 }
89c0f643 104
a1f0cce2
HR
105 if (ret != 0) {
106 switch (ret) {
2e7cc4d6 107 case -EDOM:
682a9b21 108 status = TASK_SET_FULL;
2e7cc4d6 109 break;
a1f0cce2 110 case -ENOMEM:
682a9b21 111 status = CHECK_CONDITION;
b45ef674 112 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
a1f0cce2
HR
113 break;
114 default:
682a9b21 115 status = CHECK_CONDITION;
b45ef674 116 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
a1f0cce2
HR
117 break;
118 }
119 } else {
a3b16e71
PB
120 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
121 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
122 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
123 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
682a9b21 124 status = BUSY;
2cc977e2 125 BADF("Driver Timeout\n");
a3b16e71
PB
126 } else if (r->io_header.host_status) {
127 status = CHECK_CONDITION;
128 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
682a9b21
PB
129 } else if (r->io_header.status) {
130 status = r->io_header.status;
b45ef674 131 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
682a9b21
PB
132 status = CHECK_CONDITION;
133 } else {
134 status = GOOD;
135 }
2cc977e2 136 }
89c0f643 137 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
682a9b21 138 r, r->req.tag, status);
ed3a34a3 139
682a9b21 140 scsi_req_complete(&r->req, status);
6c25fa6c 141done:
3df9caf8 142 scsi_req_unref(&r->req);
2cc977e2
TS
143}
144
fa0d653b
PB
145static void scsi_command_complete(void *opaque, int ret)
146{
147 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
148
149 assert(r->req.aiocb != NULL);
150 r->req.aiocb = NULL;
151 scsi_command_complete_noio(r, ret);
152}
153
4be74634 154static int execute_command(BlockBackend *blk,
4c41d2ef 155 SCSIGenericReq *r, int direction,
097310b5 156 BlockCompletionFunc *complete)
2cc977e2 157{
2cc977e2
TS
158 r->io_header.interface_id = 'S';
159 r->io_header.dxfer_direction = direction;
160 r->io_header.dxferp = r->buf;
161 r->io_header.dxfer_len = r->buflen;
29362ebe
GH
162 r->io_header.cmdp = r->req.cmd.buf;
163 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
164 r->io_header.mx_sb_len = sizeof(r->req.sense);
165 r->io_header.sbp = r->req.sense;
2cc977e2
TS
166 r->io_header.timeout = MAX_UINT;
167 r->io_header.usr_ptr = r;
168 r->io_header.flags |= SG_FLAG_DIRECT_IO;
169
4be74634 170 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
d836f8d3
PH
171 if (r->req.aiocb == NULL) {
172 return -EIO;
173 }
2cc977e2
TS
174
175 return 0;
176}
177
178static void scsi_read_complete(void * opaque, int ret)
179{
4c41d2ef 180 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
9b6eef8a 181 SCSIDevice *s = r->req.dev;
2cc977e2
TS
182 int len;
183
fa0d653b 184 assert(r->req.aiocb != NULL);
d33e0ce2 185 r->req.aiocb = NULL;
fa0d653b 186
6c25fa6c 187 if (ret || r->req.io_canceled) {
fa0d653b 188 scsi_command_complete_noio(r, ret);
2cc977e2
TS
189 return;
190 }
fa0d653b 191
2cc977e2 192 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 193 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
194
195 r->len = -1;
40f16dd1 196 if (len == 0) {
fa0d653b
PB
197 scsi_command_complete_noio(r, 0);
198 return;
199 }
9b6eef8a 200
fa0d653b
PB
201 /* Snoop READ CAPACITY output to set the blocksize. */
202 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
203 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
204 s->blocksize = ldl_be_p(&r->buf[4]);
205 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
206 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
207 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
208 s->blocksize = ldl_be_p(&r->buf[8]);
209 s->max_lba = ldq_be_p(&r->buf[0]);
40f16dd1 210 }
fa0d653b
PB
211 blk_set_guest_block_size(s->conf.blk, s->blocksize);
212
0eb2baeb
PB
213 /* Patch MODE SENSE device specific parameters if the BDS is opened
214 * readonly.
215 */
216 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) &&
217 blk_is_read_only(s->conf.blk) &&
218 (r->req.cmd.buf[0] == MODE_SENSE ||
219 r->req.cmd.buf[0] == MODE_SENSE_10) &&
220 (r->req.cmd.buf[1] & 0x8) == 0) {
221 if (r->req.cmd.buf[0] == MODE_SENSE) {
222 r->buf[2] |= 0x80;
223 } else {
224 r->buf[3] |= 0x80;
225 }
226 }
fa0d653b
PB
227 scsi_req_data(&r->req, len);
228 scsi_req_unref(&r->req);
2cc977e2
TS
229}
230
231/* Read more data from scsi device into buffer. */
5c6c0e51 232static void scsi_read_data(SCSIRequest *req)
2cc977e2 233{
5c6c0e51 234 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 235 SCSIDevice *s = r->req.dev;
2cc977e2
TS
236 int ret;
237
5c6c0e51 238 DPRINTF("scsi_read_data 0x%x\n", req->tag);
c9501c95
PB
239
240 /* The request is used as the AIO opaque value, so add a ref. */
241 scsi_req_ref(&r->req);
2cc977e2 242 if (r->len == -1) {
fa0d653b 243 scsi_command_complete_noio(r, 0);
2cc977e2
TS
244 return;
245 }
246
4be74634
MA
247 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
248 scsi_read_complete);
a1f0cce2 249 if (ret < 0) {
fa0d653b 250 scsi_command_complete_noio(r, ret);
2cc977e2
TS
251 }
252}
253
254static void scsi_write_complete(void * opaque, int ret)
255{
4c41d2ef 256 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
8869e103 257 SCSIDevice *s = r->req.dev;
2cc977e2
TS
258
259 DPRINTF("scsi_write_complete() ret = %d\n", ret);
fa0d653b
PB
260
261 assert(r->req.aiocb != NULL);
d33e0ce2 262 r->req.aiocb = NULL;
fa0d653b 263
6c25fa6c 264 if (ret || r->req.io_canceled) {
fa0d653b 265 scsi_command_complete_noio(r, ret);
2cc977e2
TS
266 return;
267 }
268
29362ebe 269 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
8869e103
PB
270 s->type == TYPE_TAPE) {
271 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
272 DPRINTF("block size %d\n", s->blocksize);
89c0f643
AJ
273 }
274
fa0d653b 275 scsi_command_complete_noio(r, ret);
2cc977e2
TS
276}
277
278/* Write data to a scsi device. Returns nonzero on failure.
279 The transfer may complete asynchronously. */
42741212 280static void scsi_write_data(SCSIRequest *req)
2cc977e2 281{
5c6c0e51 282 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 283 SCSIDevice *s = r->req.dev;
2cc977e2
TS
284 int ret;
285
5c6c0e51 286 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
287 if (r->len == 0) {
288 r->len = r->buflen;
ab9adc88 289 scsi_req_data(&r->req, r->len);
42741212 290 return;
2cc977e2
TS
291 }
292
c9501c95
PB
293 /* The request is used as the AIO opaque value, so add a ref. */
294 scsi_req_ref(&r->req);
4be74634 295 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2 296 if (ret < 0) {
fa0d653b 297 scsi_command_complete_noio(r, ret);
2cc977e2 298 }
2cc977e2
TS
299}
300
301/* Return a pointer to the data buffer. */
5c6c0e51 302static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 303{
5c6c0e51
HR
304 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
305
2cc977e2
TS
306 return r->buf;
307}
308
2cc977e2
TS
309/* Execute a scsi command. Returns the length of the data expected by the
310 command. This will be Positive for data transfers from the device
311 (eg. disk reads), negative for transfers to the device (eg. disk writes),
312 and zero if the command does not transfer any data. */
313
5c6c0e51 314static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 315{
5c6c0e51 316 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 317 SCSIDevice *s = r->req.dev;
2cc977e2
TS
318 int ret;
319
aa2b1e89
BK
320#ifdef DEBUG_SCSI
321 {
322 int i;
323 for (i = 1; i < r->req.cmd.len; i++) {
324 printf(" 0x%02x", cmd[i]);
325 }
326 printf("\n");
327 }
328#endif
2cc977e2 329
2ec749cb 330 if (r->req.cmd.xfer == 0) {
1c3381af 331 g_free(r->buf);
2cc977e2
TS
332 r->buflen = 0;
333 r->buf = NULL;
c9501c95
PB
334 /* The request is used as the AIO opaque value, so add a ref. */
335 scsi_req_ref(&r->req);
4be74634
MA
336 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
337 scsi_command_complete);
a1f0cce2 338 if (ret < 0) {
fa0d653b 339 scsi_command_complete_noio(r, ret);
a1f0cce2 340 return 0;
2cc977e2
TS
341 }
342 return 0;
343 }
344
2ec749cb 345 if (r->buflen != r->req.cmd.xfer) {
1c3381af 346 g_free(r->buf);
7267c094 347 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 348 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
349 }
350
351 memset(r->buf, 0, r->buflen);
2ec749cb 352 r->len = r->req.cmd.xfer;
97a06435 353 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 354 r->len = 0;
5c6c0e51 355 return -r->req.cmd.xfer;
ad2d30f7 356 } else {
5c6c0e51 357 return r->req.cmd.xfer;
2cc977e2 358 }
2cc977e2
TS
359}
360
4be74634 361static int get_stream_blocksize(BlockBackend *blk)
89c0f643
AJ
362{
363 uint8_t cmd[6];
364 uint8_t buf[12];
365 uint8_t sensebuf[8];
366 sg_io_hdr_t io_header;
367 int ret;
368
369 memset(cmd, 0, sizeof(cmd));
370 memset(buf, 0, sizeof(buf));
371 cmd[0] = MODE_SENSE;
372 cmd[4] = sizeof(buf);
373
374 memset(&io_header, 0, sizeof(io_header));
375 io_header.interface_id = 'S';
376 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
377 io_header.dxfer_len = sizeof(buf);
378 io_header.dxferp = buf;
379 io_header.cmdp = cmd;
380 io_header.cmd_len = sizeof(cmd);
381 io_header.mx_sb_len = sizeof(sensebuf);
382 io_header.sbp = sensebuf;
383 io_header.timeout = 6000; /* XXX */
384
4be74634 385 ret = blk_ioctl(blk, SG_IO, &io_header);
fe0ed712 386 if (ret < 0 || io_header.driver_status || io_header.host_status) {
89c0f643 387 return -1;
fe0ed712 388 }
89c0f643
AJ
389 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
390}
391
f8b6d672
BK
392static void scsi_generic_reset(DeviceState *dev)
393{
b9eea3e6 394 SCSIDevice *s = SCSI_DEVICE(dev);
f8b6d672 395
8869e103 396 scsi_device_purge_requests(s, SENSE_CODE(RESET));
f8b6d672
BK
397}
398
a818a4b6 399static void scsi_generic_realize(SCSIDevice *s, Error **errp)
2cc977e2 400{
6ee143a0 401 int rc;
2cc977e2 402 int sg_version;
2cc977e2
TS
403 struct sg_scsi_id scsiid;
404
4be74634 405 if (!s->conf.blk) {
a818a4b6
FZ
406 error_setg(errp, "drive property not set");
407 return;
d52affa7 408 }
2cc977e2 409
4be74634 410 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
a818a4b6
FZ
411 error_setg(errp, "Device doesn't support drive option werror");
412 return;
620f862e 413 }
4be74634 414 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
a818a4b6
FZ
415 error_setg(errp, "Device doesn't support drive option rerror");
416 return;
620f862e
MA
417 }
418
2cc977e2 419 /* check we are using a driver managing SG_IO (version 3 and after */
4be74634 420 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
6ee143a0 421 if (rc < 0) {
a818a4b6
FZ
422 error_setg(errp, "cannot get SG_IO version number: %s. "
423 "Is this a SCSI device?",
424 strerror(-rc));
425 return;
98392453
RS
426 }
427 if (sg_version < 30000) {
a818a4b6
FZ
428 error_setg(errp, "scsi generic interface too old");
429 return;
d52affa7 430 }
2cc977e2
TS
431
432 /* get LUN of the /dev/sg? */
4be74634 433 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
a818a4b6
FZ
434 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
435 return;
d52affa7 436 }
2cc977e2
TS
437
438 /* define device state */
8869e103
PB
439 s->type = scsiid.scsi_type;
440 DPRINTF("device type %d\n", s->type);
28b77657 441
9b6eef8a
PB
442 switch (s->type) {
443 case TYPE_TAPE:
4be74634 444 s->blocksize = get_stream_blocksize(s->conf.blk);
8869e103
PB
445 if (s->blocksize == -1) {
446 s->blocksize = 0;
447 }
9b6eef8a
PB
448 break;
449
450 /* Make a guess for block devices, we'll fix it when the guest sends.
451 * READ CAPACITY. If they don't, they likely would assume these sizes
452 * anyway. (TODO: they could also send MODE SENSE).
453 */
454 case TYPE_ROM:
455 case TYPE_WORM:
456 s->blocksize = 2048;
457 break;
458 default:
459 s->blocksize = 512;
460 break;
89c0f643 461 }
8869e103
PB
462
463 DPRINTF("block size %d\n", s->blocksize);
d52affa7 464}
2cc977e2 465
765d1525 466const SCSIReqOps scsi_generic_req_ops = {
8dbd4574 467 .size = sizeof(SCSIGenericReq),
12010e7b
PB
468 .free_req = scsi_free_request,
469 .send_command = scsi_send_command,
470 .read_data = scsi_read_data,
471 .write_data = scsi_write_data,
12010e7b 472 .get_buf = scsi_get_buf,
56b1fc48
PB
473 .load_request = scsi_generic_load_request,
474 .save_request = scsi_generic_save_request,
8dbd4574
PB
475};
476
477static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
63db0f0e 478 uint8_t *buf, void *hba_private)
8dbd4574
PB
479{
480 SCSIRequest *req;
481
482 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
483 return req;
484}
485
39bffca2 486static Property scsi_generic_properties[] = {
4be74634 487 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
39bffca2
AL
488 DEFINE_PROP_END_OF_LIST(),
489};
490
3e7e180a
PB
491static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
492 uint8_t *buf, void *hba_private)
493{
494 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
495}
496
b9eea3e6
AL
497static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
498{
39bffca2 499 DeviceClass *dc = DEVICE_CLASS(klass);
b9eea3e6
AL
500 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
501
a818a4b6 502 sc->realize = scsi_generic_realize;
b9eea3e6 503 sc->alloc_req = scsi_new_request;
3e7e180a 504 sc->parse_cdb = scsi_generic_parse_cdb;
39bffca2
AL
505 dc->fw_name = "disk";
506 dc->desc = "pass through generic scsi device (/dev/sg*)";
507 dc->reset = scsi_generic_reset;
508 dc->props = scsi_generic_properties;
56b1fc48 509 dc->vmsd = &vmstate_scsi_device;
b9eea3e6
AL
510}
511
8c43a6f0 512static const TypeInfo scsi_generic_info = {
39bffca2
AL
513 .name = "scsi-generic",
514 .parent = TYPE_SCSI_DEVICE,
515 .instance_size = sizeof(SCSIDevice),
516 .class_init = scsi_generic_class_initfn,
d52affa7 517};
2cc977e2 518
83f7d43a 519static void scsi_generic_register_types(void)
d52affa7 520{
39bffca2 521 type_register_static(&scsi_generic_info);
2cc977e2 522}
83f7d43a
AF
523
524type_init(scsi_generic_register_types)
d52affa7 525
2cc977e2 526#endif /* __linux__ */
This page took 0.902302 seconds and 4 git commands to generate.