]> git.proxmox.com Git - qemu.git/blob - hw/scsi/scsi-generic.c
scsi-generic: check the return value of bdrv_aio_ioctl in execute_command
[qemu.git] / hw / scsi / scsi-generic.c
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 *
10 * This code is licensed under the LGPL.
11 *
12 */
13
14 #include "qemu-common.h"
15 #include "qemu/error-report.h"
16 #include "hw/scsi/scsi.h"
17 #include "sysemu/blockdev.h"
18
19 #ifdef __linux__
20
21 //#define DEBUG_SCSI
22
23 #ifdef DEBUG_SCSI
24 #define DPRINTF(fmt, ...) \
25 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26 #else
27 #define DPRINTF(fmt, ...) do {} while(0)
28 #endif
29
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
32
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <scsi/sg.h>
38 #include "block/scsi.h"
39
40 #define SCSI_SENSE_BUF_SIZE 96
41
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
49
50 #ifndef MAX_UINT
51 #define MAX_UINT ((unsigned int)-1)
52 #endif
53
54 typedef struct SCSIGenericReq {
55 SCSIRequest req;
56 uint8_t *buf;
57 int buflen;
58 int len;
59 sg_io_hdr_t io_header;
60 } SCSIGenericReq;
61
62 static 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
73 static 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
84 static void scsi_free_request(SCSIRequest *req)
85 {
86 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
87
88 g_free(r->buf);
89 }
90
91 /* Helper function for command completion. */
92 static void scsi_command_complete(void *opaque, int ret)
93 {
94 int status;
95 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
96
97 r->req.aiocb = NULL;
98 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
99 r->req.sense_len = r->io_header.sb_len_wr;
100 }
101
102 if (ret != 0) {
103 switch (ret) {
104 case -EDOM:
105 status = TASK_SET_FULL;
106 break;
107 case -ENOMEM:
108 status = CHECK_CONDITION;
109 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
110 break;
111 default:
112 status = CHECK_CONDITION;
113 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
114 break;
115 }
116 } else {
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)) {
121 status = BUSY;
122 BADF("Driver Timeout\n");
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));
126 } else if (r->io_header.status) {
127 status = r->io_header.status;
128 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
129 status = CHECK_CONDITION;
130 } else {
131 status = GOOD;
132 }
133 }
134 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135 r, r->req.tag, status);
136
137 scsi_req_complete(&r->req, status);
138 if (!r->req.io_canceled) {
139 scsi_req_unref(&r->req);
140 }
141 }
142
143 /* Cancel a pending data transfer. */
144 static void scsi_cancel_io(SCSIRequest *req)
145 {
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);
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);
156 }
157 r->req.aiocb = NULL;
158 }
159
160 static int execute_command(BlockDriverState *bdrv,
161 SCSIGenericReq *r, int direction,
162 BlockDriverCompletionFunc *complete)
163 {
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;
168 r->io_header.cmdp = r->req.cmd.buf;
169 r->io_header.cmd_len = r->req.cmd.len;
170 r->io_header.mx_sb_len = sizeof(r->req.sense);
171 r->io_header.sbp = r->req.sense;
172 r->io_header.timeout = MAX_UINT;
173 r->io_header.usr_ptr = r;
174 r->io_header.flags |= SG_FLAG_DIRECT_IO;
175
176 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
177 if (r->req.aiocb == NULL) {
178 return -EIO;
179 }
180
181 return 0;
182 }
183
184 static void scsi_read_complete(void * opaque, int ret)
185 {
186 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
187 SCSIDevice *s = r->req.dev;
188 int len;
189
190 r->req.aiocb = NULL;
191 if (ret) {
192 DPRINTF("IO error ret %d\n", ret);
193 scsi_command_complete(r, ret);
194 return;
195 }
196 len = r->io_header.dxfer_len - r->io_header.resid;
197 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
198
199 r->len = -1;
200 if (len == 0) {
201 scsi_command_complete(r, 0);
202 } else {
203 /* Snoop READ CAPACITY output to set the blocksize. */
204 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
205 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
206 s->blocksize = ldl_be_p(&r->buf[4]);
207 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
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]);
211 s->max_lba = ldq_be_p(&r->buf[0]);
212 }
213 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
214
215 scsi_req_data(&r->req, len);
216 if (!r->req.io_canceled) {
217 scsi_req_unref(&r->req);
218 }
219 }
220 }
221
222 /* Read more data from scsi device into buffer. */
223 static void scsi_read_data(SCSIRequest *req)
224 {
225 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
226 SCSIDevice *s = r->req.dev;
227 int ret;
228
229 DPRINTF("scsi_read_data 0x%x\n", req->tag);
230
231 /* The request is used as the AIO opaque value, so add a ref. */
232 scsi_req_ref(&r->req);
233 if (r->len == -1) {
234 scsi_command_complete(r, 0);
235 return;
236 }
237
238 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
239 if (ret < 0) {
240 scsi_command_complete(r, ret);
241 }
242 }
243
244 static void scsi_write_complete(void * opaque, int ret)
245 {
246 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
247 SCSIDevice *s = r->req.dev;
248
249 DPRINTF("scsi_write_complete() ret = %d\n", ret);
250 r->req.aiocb = NULL;
251 if (ret) {
252 DPRINTF("IO error\n");
253 scsi_command_complete(r, ret);
254 return;
255 }
256
257 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
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);
261 }
262
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. */
268 static void scsi_write_data(SCSIRequest *req)
269 {
270 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271 SCSIDevice *s = r->req.dev;
272 int ret;
273
274 DPRINTF("scsi_write_data 0x%x\n", req->tag);
275 if (r->len == 0) {
276 r->len = r->buflen;
277 scsi_req_data(&r->req, r->len);
278 return;
279 }
280
281 /* The request is used as the AIO opaque value, so add a ref. */
282 scsi_req_ref(&r->req);
283 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
284 if (ret < 0) {
285 scsi_command_complete(r, ret);
286 }
287 }
288
289 /* Return a pointer to the data buffer. */
290 static uint8_t *scsi_get_buf(SCSIRequest *req)
291 {
292 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
293
294 return r->buf;
295 }
296
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
302 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
303 {
304 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
305 SCSIDevice *s = r->req.dev;
306 int ret;
307
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
320
321 if (r->req.cmd.xfer == 0) {
322 if (r->buf != NULL)
323 g_free(r->buf);
324 r->buflen = 0;
325 r->buf = NULL;
326 /* The request is used as the AIO opaque value, so add a ref. */
327 scsi_req_ref(&r->req);
328 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
329 if (ret < 0) {
330 scsi_command_complete(r, ret);
331 return 0;
332 }
333 return 0;
334 }
335
336 if (r->buflen != r->req.cmd.xfer) {
337 if (r->buf != NULL)
338 g_free(r->buf);
339 r->buf = g_malloc(r->req.cmd.xfer);
340 r->buflen = r->req.cmd.xfer;
341 }
342
343 memset(r->buf, 0, r->buflen);
344 r->len = r->req.cmd.xfer;
345 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
346 r->len = 0;
347 return -r->req.cmd.xfer;
348 } else {
349 return r->req.cmd.xfer;
350 }
351 }
352
353 static 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
377 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
378 if (ret < 0 || io_header.driver_status || io_header.host_status) {
379 return -1;
380 }
381 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
382 }
383
384 static void scsi_generic_reset(DeviceState *dev)
385 {
386 SCSIDevice *s = SCSI_DEVICE(dev);
387
388 scsi_device_purge_requests(s, SENSE_CODE(RESET));
389 }
390
391 static void scsi_destroy(SCSIDevice *s)
392 {
393 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
394 blockdev_mark_auto_del(s->conf.bs);
395 }
396
397 static int scsi_generic_initfn(SCSIDevice *s)
398 {
399 int sg_version;
400 struct sg_scsi_id scsiid;
401
402 if (!s->conf.bs) {
403 error_report("drive property not set");
404 return -1;
405 }
406
407 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
408 error_report("Device doesn't support drive option werror");
409 return -1;
410 }
411 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
412 error_report("Device doesn't support drive option rerror");
413 return -1;
414 }
415
416 /* check we are using a driver managing SG_IO (version 3 and after */
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) {
422 error_report("scsi generic interface too old");
423 return -1;
424 }
425
426 /* get LUN of the /dev/sg? */
427 if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
428 error_report("SG_GET_SCSI_ID ioctl failed");
429 return -1;
430 }
431
432 /* define device state */
433 s->type = scsiid.scsi_type;
434 DPRINTF("device type %d\n", s->type);
435 if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
436 add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
437 }
438
439 switch (s->type) {
440 case TYPE_TAPE:
441 s->blocksize = get_stream_blocksize(s->conf.bs);
442 if (s->blocksize == -1) {
443 s->blocksize = 0;
444 }
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;
458 }
459
460 DPRINTF("block size %d\n", s->blocksize);
461 return 0;
462 }
463
464 const SCSIReqOps scsi_generic_req_ops = {
465 .size = sizeof(SCSIGenericReq),
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,
472 .load_request = scsi_generic_load_request,
473 .save_request = scsi_generic_save_request,
474 };
475
476 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
477 uint8_t *buf, void *hba_private)
478 {
479 SCSIRequest *req;
480
481 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
482 return req;
483 }
484
485 static Property scsi_generic_properties[] = {
486 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
487 DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
488 DEFINE_PROP_END_OF_LIST(),
489 };
490
491 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
492 {
493 DeviceClass *dc = DEVICE_CLASS(klass);
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;
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;
503 dc->vmsd = &vmstate_scsi_device;
504 }
505
506 static const TypeInfo scsi_generic_info = {
507 .name = "scsi-generic",
508 .parent = TYPE_SCSI_DEVICE,
509 .instance_size = sizeof(SCSIDevice),
510 .class_init = scsi_generic_class_initfn,
511 };
512
513 static void scsi_generic_register_types(void)
514 {
515 type_register_static(&scsi_generic_info);
516 }
517
518 type_init(scsi_generic_register_types)
519
520 #endif /* __linux__ */