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