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