]> git.proxmox.com Git - mirror_qemu.git/blob - hw/scsi/scsi-generic.c
coccinelle: Remove unnecessary variables for function return value
[mirror_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/osdep.h"
15 #include "qapi/error.h"
16 #include "qemu-common.h"
17 #include "qemu/error-report.h"
18 #include "hw/scsi/scsi.h"
19 #include "sysemu/block-backend.h"
20 #include "sysemu/blockdev.h"
21
22 #ifdef __linux__
23
24 //#define DEBUG_SCSI
25
26 #ifdef DEBUG_SCSI
27 #define DPRINTF(fmt, ...) \
28 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
29 #else
30 #define DPRINTF(fmt, ...) do {} while(0)
31 #endif
32
33 #define BADF(fmt, ...) \
34 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
35
36 #include <scsi/sg.h>
37 #include "block/scsi.h"
38
39 #define SG_ERR_DRIVER_TIMEOUT 0x06
40 #define SG_ERR_DRIVER_SENSE 0x08
41
42 #define SG_ERR_DID_OK 0x00
43 #define SG_ERR_DID_NO_CONNECT 0x01
44 #define SG_ERR_DID_BUS_BUSY 0x02
45 #define SG_ERR_DID_TIME_OUT 0x03
46
47 #ifndef MAX_UINT
48 #define MAX_UINT ((unsigned int)-1)
49 #endif
50
51 typedef struct SCSIGenericReq {
52 SCSIRequest req;
53 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
57 } SCSIGenericReq;
58
59 static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
60 {
61 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
62
63 qemu_put_sbe32s(f, &r->buflen);
64 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
65 assert(!r->req.sg);
66 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
67 }
68 }
69
70 static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
71 {
72 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
73
74 qemu_get_sbe32s(f, &r->buflen);
75 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
76 assert(!r->req.sg);
77 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
78 }
79 }
80
81 static void scsi_free_request(SCSIRequest *req)
82 {
83 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
84
85 g_free(r->buf);
86 }
87
88 /* Helper function for command completion. */
89 static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
90 {
91 int status;
92
93 assert(r->req.aiocb == NULL);
94
95 if (r->req.io_canceled) {
96 scsi_req_cancel_complete(&r->req);
97 goto done;
98 }
99 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
100 r->req.sense_len = r->io_header.sb_len_wr;
101 }
102
103 if (ret != 0) {
104 switch (ret) {
105 case -EDOM:
106 status = TASK_SET_FULL;
107 break;
108 case -ENOMEM:
109 status = CHECK_CONDITION;
110 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
111 break;
112 default:
113 status = CHECK_CONDITION;
114 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
115 break;
116 }
117 } else {
118 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
119 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
120 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
121 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
122 status = BUSY;
123 BADF("Driver Timeout\n");
124 } else if (r->io_header.host_status) {
125 status = CHECK_CONDITION;
126 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
127 } else if (r->io_header.status) {
128 status = r->io_header.status;
129 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
130 status = CHECK_CONDITION;
131 } else {
132 status = GOOD;
133 }
134 }
135 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
136 r, r->req.tag, status);
137
138 scsi_req_complete(&r->req, status);
139 done:
140 scsi_req_unref(&r->req);
141 }
142
143 static void scsi_command_complete(void *opaque, int ret)
144 {
145 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
146
147 assert(r->req.aiocb != NULL);
148 r->req.aiocb = NULL;
149 scsi_command_complete_noio(r, ret);
150 }
151
152 static int execute_command(BlockBackend *blk,
153 SCSIGenericReq *r, int direction,
154 BlockCompletionFunc *complete)
155 {
156 r->io_header.interface_id = 'S';
157 r->io_header.dxfer_direction = direction;
158 r->io_header.dxferp = r->buf;
159 r->io_header.dxfer_len = r->buflen;
160 r->io_header.cmdp = r->req.cmd.buf;
161 r->io_header.cmd_len = r->req.cmd.len;
162 r->io_header.mx_sb_len = sizeof(r->req.sense);
163 r->io_header.sbp = r->req.sense;
164 r->io_header.timeout = MAX_UINT;
165 r->io_header.usr_ptr = r;
166 r->io_header.flags |= SG_FLAG_DIRECT_IO;
167
168 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
169 if (r->req.aiocb == NULL) {
170 return -EIO;
171 }
172
173 return 0;
174 }
175
176 static void scsi_read_complete(void * opaque, int ret)
177 {
178 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
179 SCSIDevice *s = r->req.dev;
180 int len;
181
182 assert(r->req.aiocb != NULL);
183 r->req.aiocb = NULL;
184
185 if (ret || r->req.io_canceled) {
186 scsi_command_complete_noio(r, ret);
187 return;
188 }
189
190 len = r->io_header.dxfer_len - r->io_header.resid;
191 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
192
193 r->len = -1;
194 if (len == 0) {
195 scsi_command_complete_noio(r, 0);
196 return;
197 }
198
199 /* Snoop READ CAPACITY output to set the blocksize. */
200 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
201 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
202 s->blocksize = ldl_be_p(&r->buf[4]);
203 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
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]);
207 s->max_lba = ldq_be_p(&r->buf[0]);
208 }
209 blk_set_guest_block_size(s->conf.blk, s->blocksize);
210
211 /* Patch MODE SENSE device specific parameters if the BDS is opened
212 * readonly.
213 */
214 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) &&
215 blk_is_read_only(s->conf.blk) &&
216 (r->req.cmd.buf[0] == MODE_SENSE ||
217 r->req.cmd.buf[0] == MODE_SENSE_10) &&
218 (r->req.cmd.buf[1] & 0x8) == 0) {
219 if (r->req.cmd.buf[0] == MODE_SENSE) {
220 r->buf[2] |= 0x80;
221 } else {
222 r->buf[3] |= 0x80;
223 }
224 }
225 if (s->type == TYPE_DISK &&
226 r->req.cmd.buf[0] == INQUIRY &&
227 r->req.cmd.buf[2] == 0xb0) {
228 uint32_t max_xfer_len = blk_get_max_transfer_length(s->conf.blk);
229 if (max_xfer_len) {
230 stl_be_p(&r->buf[8], max_xfer_len);
231 /* Also take care of the opt xfer len. */
232 if (ldl_be_p(&r->buf[12]) > max_xfer_len) {
233 stl_be_p(&r->buf[12], max_xfer_len);
234 }
235 }
236 }
237 scsi_req_data(&r->req, len);
238 scsi_req_unref(&r->req);
239 }
240
241 /* Read more data from scsi device into buffer. */
242 static void scsi_read_data(SCSIRequest *req)
243 {
244 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
245 SCSIDevice *s = r->req.dev;
246 int ret;
247
248 DPRINTF("scsi_read_data 0x%x\n", req->tag);
249
250 /* The request is used as the AIO opaque value, so add a ref. */
251 scsi_req_ref(&r->req);
252 if (r->len == -1) {
253 scsi_command_complete_noio(r, 0);
254 return;
255 }
256
257 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
258 scsi_read_complete);
259 if (ret < 0) {
260 scsi_command_complete_noio(r, ret);
261 }
262 }
263
264 static void scsi_write_complete(void * opaque, int ret)
265 {
266 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
267 SCSIDevice *s = r->req.dev;
268
269 DPRINTF("scsi_write_complete() ret = %d\n", ret);
270
271 assert(r->req.aiocb != NULL);
272 r->req.aiocb = NULL;
273
274 if (ret || r->req.io_canceled) {
275 scsi_command_complete_noio(r, ret);
276 return;
277 }
278
279 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
280 s->type == TYPE_TAPE) {
281 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
282 DPRINTF("block size %d\n", s->blocksize);
283 }
284
285 scsi_command_complete_noio(r, ret);
286 }
287
288 /* Write data to a scsi device. Returns nonzero on failure.
289 The transfer may complete asynchronously. */
290 static void scsi_write_data(SCSIRequest *req)
291 {
292 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
293 SCSIDevice *s = r->req.dev;
294 int ret;
295
296 DPRINTF("scsi_write_data 0x%x\n", req->tag);
297 if (r->len == 0) {
298 r->len = r->buflen;
299 scsi_req_data(&r->req, r->len);
300 return;
301 }
302
303 /* The request is used as the AIO opaque value, so add a ref. */
304 scsi_req_ref(&r->req);
305 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
306 if (ret < 0) {
307 scsi_command_complete_noio(r, ret);
308 }
309 }
310
311 /* Return a pointer to the data buffer. */
312 static uint8_t *scsi_get_buf(SCSIRequest *req)
313 {
314 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
315
316 return r->buf;
317 }
318
319 /* Execute a scsi command. Returns the length of the data expected by the
320 command. This will be Positive for data transfers from the device
321 (eg. disk reads), negative for transfers to the device (eg. disk writes),
322 and zero if the command does not transfer any data. */
323
324 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
325 {
326 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
327 SCSIDevice *s = r->req.dev;
328 int ret;
329
330 #ifdef DEBUG_SCSI
331 {
332 int i;
333 for (i = 1; i < r->req.cmd.len; i++) {
334 printf(" 0x%02x", cmd[i]);
335 }
336 printf("\n");
337 }
338 #endif
339
340 if (r->req.cmd.xfer == 0) {
341 g_free(r->buf);
342 r->buflen = 0;
343 r->buf = NULL;
344 /* The request is used as the AIO opaque value, so add a ref. */
345 scsi_req_ref(&r->req);
346 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
347 scsi_command_complete);
348 if (ret < 0) {
349 scsi_command_complete_noio(r, ret);
350 return 0;
351 }
352 return 0;
353 }
354
355 if (r->buflen != r->req.cmd.xfer) {
356 g_free(r->buf);
357 r->buf = g_malloc(r->req.cmd.xfer);
358 r->buflen = r->req.cmd.xfer;
359 }
360
361 memset(r->buf, 0, r->buflen);
362 r->len = r->req.cmd.xfer;
363 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
364 r->len = 0;
365 return -r->req.cmd.xfer;
366 } else {
367 return r->req.cmd.xfer;
368 }
369 }
370
371 static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
372 {
373 int i;
374
375 if ((p[1] & 0xF) == 3) {
376 /* NAA designator type */
377 if (p[3] != 8) {
378 return -EINVAL;
379 }
380 *p_wwn = ldq_be_p(p + 4);
381 return 0;
382 }
383
384 if ((p[1] & 0xF) == 8) {
385 /* SCSI name string designator type */
386 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
387 return -EINVAL;
388 }
389 if (p[3] > 20 && p[24] != ',') {
390 return -EINVAL;
391 }
392 *p_wwn = 0;
393 for (i = 8; i < 24; i++) {
394 char c = toupper(p[i]);
395 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
396 *p_wwn = (*p_wwn << 4) | c;
397 }
398 return 0;
399 }
400
401 return -EINVAL;
402 }
403
404 void scsi_generic_read_device_identification(SCSIDevice *s)
405 {
406 uint8_t cmd[6];
407 uint8_t buf[250];
408 uint8_t sensebuf[8];
409 sg_io_hdr_t io_header;
410 int ret;
411 int i, len;
412
413 memset(cmd, 0, sizeof(cmd));
414 memset(buf, 0, sizeof(buf));
415 cmd[0] = INQUIRY;
416 cmd[1] = 1;
417 cmd[2] = 0x83;
418 cmd[4] = sizeof(buf);
419
420 memset(&io_header, 0, sizeof(io_header));
421 io_header.interface_id = 'S';
422 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
423 io_header.dxfer_len = sizeof(buf);
424 io_header.dxferp = buf;
425 io_header.cmdp = cmd;
426 io_header.cmd_len = sizeof(cmd);
427 io_header.mx_sb_len = sizeof(sensebuf);
428 io_header.sbp = sensebuf;
429 io_header.timeout = 6000; /* XXX */
430
431 ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
432 if (ret < 0 || io_header.driver_status || io_header.host_status) {
433 return;
434 }
435
436 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
437 for (i = 0; i + 3 <= len; ) {
438 const uint8_t *p = &buf[i + 4];
439 uint64_t wwn;
440
441 if (i + (p[3] + 4) > len) {
442 break;
443 }
444
445 if ((p[1] & 0x10) == 0) {
446 /* Associated with the logical unit */
447 if (read_naa_id(p, &wwn) == 0) {
448 s->wwn = wwn;
449 }
450 } else if ((p[1] & 0x10) == 0x10) {
451 /* Associated with the target port */
452 if (read_naa_id(p, &wwn) == 0) {
453 s->port_wwn = wwn;
454 }
455 }
456
457 i += p[3] + 4;
458 }
459 }
460
461 static int get_stream_blocksize(BlockBackend *blk)
462 {
463 uint8_t cmd[6];
464 uint8_t buf[12];
465 uint8_t sensebuf[8];
466 sg_io_hdr_t io_header;
467 int ret;
468
469 memset(cmd, 0, sizeof(cmd));
470 memset(buf, 0, sizeof(buf));
471 cmd[0] = MODE_SENSE;
472 cmd[4] = sizeof(buf);
473
474 memset(&io_header, 0, sizeof(io_header));
475 io_header.interface_id = 'S';
476 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
477 io_header.dxfer_len = sizeof(buf);
478 io_header.dxferp = buf;
479 io_header.cmdp = cmd;
480 io_header.cmd_len = sizeof(cmd);
481 io_header.mx_sb_len = sizeof(sensebuf);
482 io_header.sbp = sensebuf;
483 io_header.timeout = 6000; /* XXX */
484
485 ret = blk_ioctl(blk, SG_IO, &io_header);
486 if (ret < 0 || io_header.driver_status || io_header.host_status) {
487 return -1;
488 }
489 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
490 }
491
492 static void scsi_generic_reset(DeviceState *dev)
493 {
494 SCSIDevice *s = SCSI_DEVICE(dev);
495
496 scsi_device_purge_requests(s, SENSE_CODE(RESET));
497 }
498
499 static void scsi_generic_realize(SCSIDevice *s, Error **errp)
500 {
501 int rc;
502 int sg_version;
503 struct sg_scsi_id scsiid;
504
505 if (!s->conf.blk) {
506 error_setg(errp, "drive property not set");
507 return;
508 }
509
510 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
511 error_setg(errp, "Device doesn't support drive option werror");
512 return;
513 }
514 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
515 error_setg(errp, "Device doesn't support drive option rerror");
516 return;
517 }
518
519 /* check we are using a driver managing SG_IO (version 3 and after */
520 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
521 if (rc < 0) {
522 error_setg(errp, "cannot get SG_IO version number: %s. "
523 "Is this a SCSI device?",
524 strerror(-rc));
525 return;
526 }
527 if (sg_version < 30000) {
528 error_setg(errp, "scsi generic interface too old");
529 return;
530 }
531
532 /* get LUN of the /dev/sg? */
533 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
534 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
535 return;
536 }
537
538 /* define device state */
539 s->type = scsiid.scsi_type;
540 DPRINTF("device type %d\n", s->type);
541
542 switch (s->type) {
543 case TYPE_TAPE:
544 s->blocksize = get_stream_blocksize(s->conf.blk);
545 if (s->blocksize == -1) {
546 s->blocksize = 0;
547 }
548 break;
549
550 /* Make a guess for block devices, we'll fix it when the guest sends.
551 * READ CAPACITY. If they don't, they likely would assume these sizes
552 * anyway. (TODO: they could also send MODE SENSE).
553 */
554 case TYPE_ROM:
555 case TYPE_WORM:
556 s->blocksize = 2048;
557 break;
558 default:
559 s->blocksize = 512;
560 break;
561 }
562
563 DPRINTF("block size %d\n", s->blocksize);
564
565 scsi_generic_read_device_identification(s);
566 }
567
568 const SCSIReqOps scsi_generic_req_ops = {
569 .size = sizeof(SCSIGenericReq),
570 .free_req = scsi_free_request,
571 .send_command = scsi_send_command,
572 .read_data = scsi_read_data,
573 .write_data = scsi_write_data,
574 .get_buf = scsi_get_buf,
575 .load_request = scsi_generic_load_request,
576 .save_request = scsi_generic_save_request,
577 };
578
579 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
580 uint8_t *buf, void *hba_private)
581 {
582 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
583 }
584
585 static Property scsi_generic_properties[] = {
586 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
587 DEFINE_PROP_END_OF_LIST(),
588 };
589
590 static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
591 uint8_t *buf, void *hba_private)
592 {
593 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
594 }
595
596 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
597 {
598 DeviceClass *dc = DEVICE_CLASS(klass);
599 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
600
601 sc->realize = scsi_generic_realize;
602 sc->alloc_req = scsi_new_request;
603 sc->parse_cdb = scsi_generic_parse_cdb;
604 dc->fw_name = "disk";
605 dc->desc = "pass through generic scsi device (/dev/sg*)";
606 dc->reset = scsi_generic_reset;
607 dc->props = scsi_generic_properties;
608 dc->vmsd = &vmstate_scsi_device;
609 }
610
611 static const TypeInfo scsi_generic_info = {
612 .name = "scsi-generic",
613 .parent = TYPE_SCSI_DEVICE,
614 .instance_size = sizeof(SCSIDevice),
615 .class_init = scsi_generic_class_initfn,
616 };
617
618 static void scsi_generic_register_types(void)
619 {
620 type_register_static(&scsi_generic_info);
621 }
622
623 type_init(scsi_generic_register_types)
624
625 #endif /* __linux__ */