1
2
3
4
5
6
7
8
9
10
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
25
26#ifdef DEBUG_SCSI
27#define DPRINTF(fmt, ...) \
28do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
29#else
30#define DPRINTF(fmt, ...) do {} while(0)
31#endif
32
33#define BADF(fmt, ...) \
34do { 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
51typedef 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
59static 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
70static 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
81static void scsi_free_request(SCSIRequest *req)
82{
83 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
84
85 g_free(r->buf);
86}
87
88
89static 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);
139done:
140 scsi_req_unref(&r->req);
141}
142
143static 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
152static 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
176static 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
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
212
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 scsi_req_data(&r->req, len);
226 scsi_req_unref(&r->req);
227}
228
229
230static void scsi_read_data(SCSIRequest *req)
231{
232 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
233 SCSIDevice *s = r->req.dev;
234 int ret;
235
236 DPRINTF("scsi_read_data 0x%x\n", req->tag);
237
238
239 scsi_req_ref(&r->req);
240 if (r->len == -1) {
241 scsi_command_complete_noio(r, 0);
242 return;
243 }
244
245 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
246 scsi_read_complete);
247 if (ret < 0) {
248 scsi_command_complete_noio(r, ret);
249 }
250}
251
252static void scsi_write_complete(void * opaque, int ret)
253{
254 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
255 SCSIDevice *s = r->req.dev;
256
257 DPRINTF("scsi_write_complete() ret = %d\n", ret);
258
259 assert(r->req.aiocb != NULL);
260 r->req.aiocb = NULL;
261
262 if (ret || r->req.io_canceled) {
263 scsi_command_complete_noio(r, ret);
264 return;
265 }
266
267 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
268 s->type == TYPE_TAPE) {
269 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
270 DPRINTF("block size %d\n", s->blocksize);
271 }
272
273 scsi_command_complete_noio(r, ret);
274}
275
276
277
278static void scsi_write_data(SCSIRequest *req)
279{
280 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
281 SCSIDevice *s = r->req.dev;
282 int ret;
283
284 DPRINTF("scsi_write_data 0x%x\n", req->tag);
285 if (r->len == 0) {
286 r->len = r->buflen;
287 scsi_req_data(&r->req, r->len);
288 return;
289 }
290
291
292 scsi_req_ref(&r->req);
293 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
294 if (ret < 0) {
295 scsi_command_complete_noio(r, ret);
296 }
297}
298
299
300static uint8_t *scsi_get_buf(SCSIRequest *req)
301{
302 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
303
304 return r->buf;
305}
306
307
308
309
310
311
312static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
313{
314 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
315 SCSIDevice *s = r->req.dev;
316 int ret;
317
318#ifdef DEBUG_SCSI
319 {
320 int i;
321 for (i = 1; i < r->req.cmd.len; i++) {
322 printf(" 0x%02x", cmd[i]);
323 }
324 printf("\n");
325 }
326#endif
327
328 if (r->req.cmd.xfer == 0) {
329 g_free(r->buf);
330 r->buflen = 0;
331 r->buf = NULL;
332
333 scsi_req_ref(&r->req);
334 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
335 scsi_command_complete);
336 if (ret < 0) {
337 scsi_command_complete_noio(r, ret);
338 return 0;
339 }
340 return 0;
341 }
342
343 if (r->buflen != r->req.cmd.xfer) {
344 g_free(r->buf);
345 r->buf = g_malloc(r->req.cmd.xfer);
346 r->buflen = r->req.cmd.xfer;
347 }
348
349 memset(r->buf, 0, r->buflen);
350 r->len = r->req.cmd.xfer;
351 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
352 r->len = 0;
353 return -r->req.cmd.xfer;
354 } else {
355 return r->req.cmd.xfer;
356 }
357}
358
359static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
360{
361 int i;
362
363 if ((p[1] & 0xF) == 3) {
364
365 if (p[3] != 8) {
366 return -EINVAL;
367 }
368 *p_wwn = ldq_be_p(p + 4);
369 return 0;
370 }
371
372 if ((p[1] & 0xF) == 8) {
373
374 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
375 return -EINVAL;
376 }
377 if (p[3] > 20 && p[24] != ',') {
378 return -EINVAL;
379 }
380 *p_wwn = 0;
381 for (i = 8; i < 24; i++) {
382 char c = toupper(p[i]);
383 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
384 *p_wwn = (*p_wwn << 4) | c;
385 }
386 return 0;
387 }
388
389 return -EINVAL;
390}
391
392void scsi_generic_read_device_identification(SCSIDevice *s)
393{
394 uint8_t cmd[6];
395 uint8_t buf[250];
396 uint8_t sensebuf[8];
397 sg_io_hdr_t io_header;
398 int ret;
399 int i, len;
400
401 memset(cmd, 0, sizeof(cmd));
402 memset(buf, 0, sizeof(buf));
403 cmd[0] = INQUIRY;
404 cmd[1] = 1;
405 cmd[2] = 0x83;
406 cmd[4] = sizeof(buf);
407
408 memset(&io_header, 0, sizeof(io_header));
409 io_header.interface_id = 'S';
410 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
411 io_header.dxfer_len = sizeof(buf);
412 io_header.dxferp = buf;
413 io_header.cmdp = cmd;
414 io_header.cmd_len = sizeof(cmd);
415 io_header.mx_sb_len = sizeof(sensebuf);
416 io_header.sbp = sensebuf;
417 io_header.timeout = 6000;
418
419 ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
420 if (ret < 0 || io_header.driver_status || io_header.host_status) {
421 return;
422 }
423
424 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
425 for (i = 0; i + 3 <= len; ) {
426 const uint8_t *p = &buf[i + 4];
427 uint64_t wwn;
428
429 if (i + (p[3] + 4) > len) {
430 break;
431 }
432
433 if ((p[1] & 0x10) == 0) {
434
435 if (read_naa_id(p, &wwn) == 0) {
436 s->wwn = wwn;
437 }
438 } else if ((p[1] & 0x10) == 0x10) {
439
440 if (read_naa_id(p, &wwn) == 0) {
441 s->port_wwn = wwn;
442 }
443 }
444
445 i += p[3] + 4;
446 }
447}
448
449static int get_stream_blocksize(BlockBackend *blk)
450{
451 uint8_t cmd[6];
452 uint8_t buf[12];
453 uint8_t sensebuf[8];
454 sg_io_hdr_t io_header;
455 int ret;
456
457 memset(cmd, 0, sizeof(cmd));
458 memset(buf, 0, sizeof(buf));
459 cmd[0] = MODE_SENSE;
460 cmd[4] = sizeof(buf);
461
462 memset(&io_header, 0, sizeof(io_header));
463 io_header.interface_id = 'S';
464 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
465 io_header.dxfer_len = sizeof(buf);
466 io_header.dxferp = buf;
467 io_header.cmdp = cmd;
468 io_header.cmd_len = sizeof(cmd);
469 io_header.mx_sb_len = sizeof(sensebuf);
470 io_header.sbp = sensebuf;
471 io_header.timeout = 6000;
472
473 ret = blk_ioctl(blk, SG_IO, &io_header);
474 if (ret < 0 || io_header.driver_status || io_header.host_status) {
475 return -1;
476 }
477 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
478}
479
480static void scsi_generic_reset(DeviceState *dev)
481{
482 SCSIDevice *s = SCSI_DEVICE(dev);
483
484 scsi_device_purge_requests(s, SENSE_CODE(RESET));
485}
486
487static void scsi_generic_realize(SCSIDevice *s, Error **errp)
488{
489 int rc;
490 int sg_version;
491 struct sg_scsi_id scsiid;
492
493 if (!s->conf.blk) {
494 error_setg(errp, "drive property not set");
495 return;
496 }
497
498 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
499 error_setg(errp, "Device doesn't support drive option werror");
500 return;
501 }
502 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
503 error_setg(errp, "Device doesn't support drive option rerror");
504 return;
505 }
506
507
508 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
509 if (rc < 0) {
510 error_setg(errp, "cannot get SG_IO version number: %s. "
511 "Is this a SCSI device?",
512 strerror(-rc));
513 return;
514 }
515 if (sg_version < 30000) {
516 error_setg(errp, "scsi generic interface too old");
517 return;
518 }
519
520
521 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
522 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
523 return;
524 }
525
526
527 s->type = scsiid.scsi_type;
528 DPRINTF("device type %d\n", s->type);
529
530 switch (s->type) {
531 case TYPE_TAPE:
532 s->blocksize = get_stream_blocksize(s->conf.blk);
533 if (s->blocksize == -1) {
534 s->blocksize = 0;
535 }
536 break;
537
538
539
540
541
542 case TYPE_ROM:
543 case TYPE_WORM:
544 s->blocksize = 2048;
545 break;
546 default:
547 s->blocksize = 512;
548 break;
549 }
550
551 DPRINTF("block size %d\n", s->blocksize);
552
553 scsi_generic_read_device_identification(s);
554}
555
556const SCSIReqOps scsi_generic_req_ops = {
557 .size = sizeof(SCSIGenericReq),
558 .free_req = scsi_free_request,
559 .send_command = scsi_send_command,
560 .read_data = scsi_read_data,
561 .write_data = scsi_write_data,
562 .get_buf = scsi_get_buf,
563 .load_request = scsi_generic_load_request,
564 .save_request = scsi_generic_save_request,
565};
566
567static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
568 uint8_t *buf, void *hba_private)
569{
570 SCSIRequest *req;
571
572 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
573 return req;
574}
575
576static Property scsi_generic_properties[] = {
577 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
578 DEFINE_PROP_END_OF_LIST(),
579};
580
581static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
582 uint8_t *buf, void *hba_private)
583{
584 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
585}
586
587static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
588{
589 DeviceClass *dc = DEVICE_CLASS(klass);
590 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
591
592 sc->realize = scsi_generic_realize;
593 sc->alloc_req = scsi_new_request;
594 sc->parse_cdb = scsi_generic_parse_cdb;
595 dc->fw_name = "disk";
596 dc->desc = "pass through generic scsi device (/dev/sg*)";
597 dc->reset = scsi_generic_reset;
598 dc->props = scsi_generic_properties;
599 dc->vmsd = &vmstate_scsi_device;
600}
601
602static const TypeInfo scsi_generic_info = {
603 .name = "scsi-generic",
604 .parent = TYPE_SCSI_DEVICE,
605 .instance_size = sizeof(SCSIDevice),
606 .class_init = scsi_generic_class_initfn,
607};
608
609static void scsi_generic_register_types(void)
610{
611 type_register_static(&scsi_generic_info);
612}
613
614type_init(scsi_generic_register_types)
615
616#endif
617