]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/scsi-generic.c
hw: Convert from BlockDriverState to BlockBackend, mostly
[mirror_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 <Laurent.Vivier@bull.net>
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
TS
90/* Helper function for command completion. */
91static void scsi_command_complete(void *opaque, int ret)
92{
682a9b21 93 int status;
4c41d2ef 94 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2 95
d33e0ce2 96 r->req.aiocb = NULL;
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
4be74634 145static int execute_command(BlockBackend *blk,
4c41d2ef 146 SCSIGenericReq *r, int direction,
097310b5 147 BlockCompletionFunc *complete)
2cc977e2 148{
2cc977e2
TS
149 r->io_header.interface_id = 'S';
150 r->io_header.dxfer_direction = direction;
151 r->io_header.dxferp = r->buf;
152 r->io_header.dxfer_len = r->buflen;
29362ebe
GH
153 r->io_header.cmdp = r->req.cmd.buf;
154 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
155 r->io_header.mx_sb_len = sizeof(r->req.sense);
156 r->io_header.sbp = r->req.sense;
2cc977e2
TS
157 r->io_header.timeout = MAX_UINT;
158 r->io_header.usr_ptr = r;
159 r->io_header.flags |= SG_FLAG_DIRECT_IO;
160
4be74634 161 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
d836f8d3
PH
162 if (r->req.aiocb == NULL) {
163 return -EIO;
164 }
2cc977e2
TS
165
166 return 0;
167}
168
169static void scsi_read_complete(void * opaque, int ret)
170{
4c41d2ef 171 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
9b6eef8a 172 SCSIDevice *s = r->req.dev;
2cc977e2
TS
173 int len;
174
d33e0ce2 175 r->req.aiocb = NULL;
6c25fa6c 176 if (ret || r->req.io_canceled) {
2cc977e2
TS
177 scsi_command_complete(r, ret);
178 return;
179 }
180 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 181 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
182
183 r->len = -1;
40f16dd1 184 if (len == 0) {
89c0f643 185 scsi_command_complete(r, 0);
40f16dd1 186 } else {
9b6eef8a 187 /* Snoop READ CAPACITY output to set the blocksize. */
53254e56
PB
188 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
189 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
9b6eef8a 190 s->blocksize = ldl_be_p(&r->buf[4]);
53254e56 191 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
9b6eef8a
PB
192 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
193 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
194 s->blocksize = ldl_be_p(&r->buf[8]);
7877903a 195 s->max_lba = ldq_be_p(&r->buf[0]);
9b6eef8a 196 }
4be74634 197 blk_set_guest_block_size(s->conf.blk, s->blocksize);
9b6eef8a 198
ab9adc88 199 scsi_req_data(&r->req, len);
3df9caf8 200 scsi_req_unref(&r->req);
40f16dd1 201 }
2cc977e2
TS
202}
203
204/* Read more data from scsi device into buffer. */
5c6c0e51 205static void scsi_read_data(SCSIRequest *req)
2cc977e2 206{
5c6c0e51 207 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 208 SCSIDevice *s = r->req.dev;
2cc977e2
TS
209 int ret;
210
5c6c0e51 211 DPRINTF("scsi_read_data 0x%x\n", req->tag);
c9501c95
PB
212
213 /* The request is used as the AIO opaque value, so add a ref. */
214 scsi_req_ref(&r->req);
2cc977e2
TS
215 if (r->len == -1) {
216 scsi_command_complete(r, 0);
217 return;
218 }
219
4be74634
MA
220 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
221 scsi_read_complete);
a1f0cce2
HR
222 if (ret < 0) {
223 scsi_command_complete(r, ret);
2cc977e2
TS
224 }
225}
226
227static void scsi_write_complete(void * opaque, int ret)
228{
4c41d2ef 229 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
8869e103 230 SCSIDevice *s = r->req.dev;
2cc977e2
TS
231
232 DPRINTF("scsi_write_complete() ret = %d\n", ret);
d33e0ce2 233 r->req.aiocb = NULL;
6c25fa6c 234 if (ret || r->req.io_canceled) {
2cc977e2
TS
235 scsi_command_complete(r, ret);
236 return;
237 }
238
29362ebe 239 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
8869e103
PB
240 s->type == TYPE_TAPE) {
241 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
242 DPRINTF("block size %d\n", s->blocksize);
89c0f643
AJ
243 }
244
2cc977e2
TS
245 scsi_command_complete(r, ret);
246}
247
248/* Write data to a scsi device. Returns nonzero on failure.
249 The transfer may complete asynchronously. */
42741212 250static void scsi_write_data(SCSIRequest *req)
2cc977e2 251{
5c6c0e51 252 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 253 SCSIDevice *s = r->req.dev;
2cc977e2
TS
254 int ret;
255
5c6c0e51 256 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
257 if (r->len == 0) {
258 r->len = r->buflen;
ab9adc88 259 scsi_req_data(&r->req, r->len);
42741212 260 return;
2cc977e2
TS
261 }
262
c9501c95
PB
263 /* The request is used as the AIO opaque value, so add a ref. */
264 scsi_req_ref(&r->req);
4be74634 265 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2
HR
266 if (ret < 0) {
267 scsi_command_complete(r, ret);
2cc977e2 268 }
2cc977e2
TS
269}
270
271/* Return a pointer to the data buffer. */
5c6c0e51 272static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 273{
5c6c0e51
HR
274 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
275
2cc977e2
TS
276 return r->buf;
277}
278
2cc977e2
TS
279/* Execute a scsi command. Returns the length of the data expected by the
280 command. This will be Positive for data transfers from the device
281 (eg. disk reads), negative for transfers to the device (eg. disk writes),
282 and zero if the command does not transfer any data. */
283
5c6c0e51 284static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 285{
5c6c0e51 286 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 287 SCSIDevice *s = r->req.dev;
2cc977e2
TS
288 int ret;
289
aa2b1e89
BK
290#ifdef DEBUG_SCSI
291 {
292 int i;
293 for (i = 1; i < r->req.cmd.len; i++) {
294 printf(" 0x%02x", cmd[i]);
295 }
296 printf("\n");
297 }
298#endif
2cc977e2 299
2ec749cb 300 if (r->req.cmd.xfer == 0) {
2cc977e2 301 if (r->buf != NULL)
7267c094 302 g_free(r->buf);
2cc977e2
TS
303 r->buflen = 0;
304 r->buf = NULL;
c9501c95
PB
305 /* The request is used as the AIO opaque value, so add a ref. */
306 scsi_req_ref(&r->req);
4be74634
MA
307 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
308 scsi_command_complete);
a1f0cce2
HR
309 if (ret < 0) {
310 scsi_command_complete(r, ret);
311 return 0;
2cc977e2
TS
312 }
313 return 0;
314 }
315
2ec749cb 316 if (r->buflen != r->req.cmd.xfer) {
2cc977e2 317 if (r->buf != NULL)
7267c094
AL
318 g_free(r->buf);
319 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 320 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
321 }
322
323 memset(r->buf, 0, r->buflen);
2ec749cb 324 r->len = r->req.cmd.xfer;
97a06435 325 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 326 r->len = 0;
5c6c0e51 327 return -r->req.cmd.xfer;
ad2d30f7 328 } else {
5c6c0e51 329 return r->req.cmd.xfer;
2cc977e2 330 }
2cc977e2
TS
331}
332
4be74634 333static int get_stream_blocksize(BlockBackend *blk)
89c0f643
AJ
334{
335 uint8_t cmd[6];
336 uint8_t buf[12];
337 uint8_t sensebuf[8];
338 sg_io_hdr_t io_header;
339 int ret;
340
341 memset(cmd, 0, sizeof(cmd));
342 memset(buf, 0, sizeof(buf));
343 cmd[0] = MODE_SENSE;
344 cmd[4] = sizeof(buf);
345
346 memset(&io_header, 0, sizeof(io_header));
347 io_header.interface_id = 'S';
348 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
349 io_header.dxfer_len = sizeof(buf);
350 io_header.dxferp = buf;
351 io_header.cmdp = cmd;
352 io_header.cmd_len = sizeof(cmd);
353 io_header.mx_sb_len = sizeof(sensebuf);
354 io_header.sbp = sensebuf;
355 io_header.timeout = 6000; /* XXX */
356
4be74634 357 ret = blk_ioctl(blk, SG_IO, &io_header);
fe0ed712 358 if (ret < 0 || io_header.driver_status || io_header.host_status) {
89c0f643 359 return -1;
fe0ed712 360 }
89c0f643
AJ
361 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
362}
363
f8b6d672
BK
364static void scsi_generic_reset(DeviceState *dev)
365{
b9eea3e6 366 SCSIDevice *s = SCSI_DEVICE(dev);
f8b6d672 367
8869e103 368 scsi_device_purge_requests(s, SENSE_CODE(RESET));
f8b6d672
BK
369}
370
a818a4b6 371static void scsi_unrealize(SCSIDevice *s, Error **errp)
f8b6d672 372{
8869e103 373 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
4be74634 374 blockdev_mark_auto_del(s->conf.blk);
2cc977e2
TS
375}
376
a818a4b6 377static void scsi_generic_realize(SCSIDevice *s, Error **errp)
2cc977e2 378{
6ee143a0 379 int rc;
2cc977e2 380 int sg_version;
2cc977e2
TS
381 struct sg_scsi_id scsiid;
382
4be74634 383 if (!s->conf.blk) {
a818a4b6
FZ
384 error_setg(errp, "drive property not set");
385 return;
d52affa7 386 }
2cc977e2 387
4be74634 388 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
a818a4b6
FZ
389 error_setg(errp, "Device doesn't support drive option werror");
390 return;
620f862e 391 }
4be74634 392 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
a818a4b6
FZ
393 error_setg(errp, "Device doesn't support drive option rerror");
394 return;
620f862e
MA
395 }
396
2cc977e2 397 /* check we are using a driver managing SG_IO (version 3 and after */
4be74634 398 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
6ee143a0 399 if (rc < 0) {
a818a4b6
FZ
400 error_setg(errp, "cannot get SG_IO version number: %s. "
401 "Is this a SCSI device?",
402 strerror(-rc));
403 return;
98392453
RS
404 }
405 if (sg_version < 30000) {
a818a4b6
FZ
406 error_setg(errp, "scsi generic interface too old");
407 return;
d52affa7 408 }
2cc977e2
TS
409
410 /* get LUN of the /dev/sg? */
4be74634 411 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
a818a4b6
FZ
412 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
413 return;
d52affa7 414 }
2cc977e2
TS
415
416 /* define device state */
8869e103
PB
417 s->type = scsiid.scsi_type;
418 DPRINTF("device type %d\n", s->type);
28b77657 419
9b6eef8a
PB
420 switch (s->type) {
421 case TYPE_TAPE:
4be74634 422 s->blocksize = get_stream_blocksize(s->conf.blk);
8869e103
PB
423 if (s->blocksize == -1) {
424 s->blocksize = 0;
425 }
9b6eef8a
PB
426 break;
427
428 /* Make a guess for block devices, we'll fix it when the guest sends.
429 * READ CAPACITY. If they don't, they likely would assume these sizes
430 * anyway. (TODO: they could also send MODE SENSE).
431 */
432 case TYPE_ROM:
433 case TYPE_WORM:
434 s->blocksize = 2048;
435 break;
436 default:
437 s->blocksize = 512;
438 break;
89c0f643 439 }
8869e103
PB
440
441 DPRINTF("block size %d\n", s->blocksize);
d52affa7 442}
2cc977e2 443
765d1525 444const SCSIReqOps scsi_generic_req_ops = {
8dbd4574 445 .size = sizeof(SCSIGenericReq),
12010e7b
PB
446 .free_req = scsi_free_request,
447 .send_command = scsi_send_command,
448 .read_data = scsi_read_data,
449 .write_data = scsi_write_data,
12010e7b 450 .get_buf = scsi_get_buf,
56b1fc48
PB
451 .load_request = scsi_generic_load_request,
452 .save_request = scsi_generic_save_request,
8dbd4574
PB
453};
454
455static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
63db0f0e 456 uint8_t *buf, void *hba_private)
8dbd4574
PB
457{
458 SCSIRequest *req;
459
460 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
461 return req;
462}
463
39bffca2 464static Property scsi_generic_properties[] = {
4be74634 465 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
39bffca2
AL
466 DEFINE_PROP_END_OF_LIST(),
467};
468
3e7e180a
PB
469static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
470 uint8_t *buf, void *hba_private)
471{
472 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
473}
474
b9eea3e6
AL
475static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
476{
39bffca2 477 DeviceClass *dc = DEVICE_CLASS(klass);
b9eea3e6
AL
478 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
479
a818a4b6
FZ
480 sc->realize = scsi_generic_realize;
481 sc->unrealize = scsi_unrealize;
b9eea3e6 482 sc->alloc_req = scsi_new_request;
3e7e180a 483 sc->parse_cdb = scsi_generic_parse_cdb;
39bffca2
AL
484 dc->fw_name = "disk";
485 dc->desc = "pass through generic scsi device (/dev/sg*)";
486 dc->reset = scsi_generic_reset;
487 dc->props = scsi_generic_properties;
56b1fc48 488 dc->vmsd = &vmstate_scsi_device;
b9eea3e6
AL
489}
490
8c43a6f0 491static const TypeInfo scsi_generic_info = {
39bffca2
AL
492 .name = "scsi-generic",
493 .parent = TYPE_SCSI_DEVICE,
494 .instance_size = sizeof(SCSIDevice),
495 .class_init = scsi_generic_class_initfn,
d52affa7 496};
2cc977e2 497
83f7d43a 498static void scsi_generic_register_types(void)
d52affa7 499{
39bffca2 500 type_register_static(&scsi_generic_info);
2cc977e2 501}
83f7d43a
AF
502
503type_init(scsi_generic_register_types)
d52affa7 504
2cc977e2 505#endif /* __linux__ */