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