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/ctype.h"
17#include "qemu/error-report.h"
18#include "qemu/module.h"
19#include "hw/scsi/scsi.h"
20#include "migration/qemu-file-types.h"
21#include "hw/qdev-properties.h"
22#include "hw/qdev-properties-system.h"
23#include "hw/scsi/emulation.h"
24#include "sysemu/block-backend.h"
25#include "trace.h"
26
27#ifdef __linux__
28
29#include <scsi/sg.h>
30#include "scsi/constants.h"
31
32#ifndef MAX_UINT
33#define MAX_UINT ((unsigned int)-1)
34#endif
35
36typedef struct SCSIGenericReq {
37 SCSIRequest req;
38 uint8_t *buf;
39 int buflen;
40 int len;
41 sg_io_hdr_t io_header;
42} SCSIGenericReq;
43
44static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
45{
46 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
47
48 qemu_put_sbe32s(f, &r->buflen);
49 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
50 assert(!r->req.sg);
51 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
52 }
53}
54
55static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
56{
57 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
58
59 qemu_get_sbe32s(f, &r->buflen);
60 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
61 assert(!r->req.sg);
62 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
63 }
64}
65
66static void scsi_free_request(SCSIRequest *req)
67{
68 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
69
70 g_free(r->buf);
71}
72
73
74static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
75{
76 int status;
77 SCSISense sense;
78 sg_io_hdr_t *io_hdr = &r->io_header;
79
80 assert(r->req.aiocb == NULL);
81
82 if (r->req.io_canceled) {
83 scsi_req_cancel_complete(&r->req);
84 goto done;
85 }
86 if (ret < 0) {
87 status = scsi_sense_from_errno(-ret, &sense);
88 if (status == CHECK_CONDITION) {
89 scsi_req_build_sense(&r->req, sense);
90 }
91 } else if (io_hdr->host_status != SCSI_HOST_OK) {
92 scsi_req_complete_failed(&r->req, io_hdr->host_status);
93 goto done;
94 } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
95 status = BUSY;
96 } else {
97 status = io_hdr->status;
98 if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
99 r->req.sense_len = io_hdr->sb_len_wr;
100 }
101 }
102 trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
103
104 scsi_req_complete(&r->req, status);
105done:
106 scsi_req_unref(&r->req);
107}
108
109static void scsi_command_complete(void *opaque, int ret)
110{
111 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
112 SCSIDevice *s = r->req.dev;
113
114 aio_context_acquire(blk_get_aio_context(s->conf.blk));
115
116 assert(r->req.aiocb != NULL);
117 r->req.aiocb = NULL;
118
119 scsi_command_complete_noio(r, ret);
120 aio_context_release(blk_get_aio_context(s->conf.blk));
121}
122
123static int execute_command(BlockBackend *blk,
124 SCSIGenericReq *r, int direction,
125 BlockCompletionFunc *complete)
126{
127 SCSIDevice *s = r->req.dev;
128
129 r->io_header.interface_id = 'S';
130 r->io_header.dxfer_direction = direction;
131 r->io_header.dxferp = r->buf;
132 r->io_header.dxfer_len = r->buflen;
133 r->io_header.cmdp = r->req.cmd.buf;
134 r->io_header.cmd_len = r->req.cmd.len;
135 r->io_header.mx_sb_len = sizeof(r->req.sense);
136 r->io_header.sbp = r->req.sense;
137 r->io_header.timeout = s->io_timeout * 1000;
138 r->io_header.usr_ptr = r;
139 r->io_header.flags |= SG_FLAG_DIRECT_IO;
140
141 trace_scsi_generic_aio_sgio_command(r->req.tag, r->req.cmd.buf[0],
142 r->io_header.timeout);
143 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
144 if (r->req.aiocb == NULL) {
145 return -EIO;
146 }
147
148 return 0;
149}
150
151static uint64_t calculate_max_transfer(SCSIDevice *s)
152{
153 uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
154 uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
155
156 assert(max_transfer);
157 max_transfer = MIN_NON_ZERO(max_transfer,
158 max_iov * qemu_real_host_page_size());
159
160 return max_transfer / s->blocksize;
161}
162
163static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
164{
165 uint8_t page, page_idx;
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
185 s->scsi_version = r->buf[2] & 0x07;
186 if (s->scsi_version > 2) {
187 s->scsi_version = r->buf[2];
188 }
189 }
190
191 if ((s->type == TYPE_DISK || s->type == TYPE_ZBC) &&
192 (r->req.cmd.buf[1] & 0x01)) {
193 page = r->req.cmd.buf[2];
194 if (page == 0xb0 && r->buflen >= 8) {
195 uint8_t buf[16] = {};
196 uint8_t buf_used = MIN(r->buflen, 16);
197 uint64_t max_transfer = calculate_max_transfer(s);
198
199 memcpy(buf, r->buf, buf_used);
200 stl_be_p(&buf[8], max_transfer);
201 stl_be_p(&buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&buf[12])));
202 memcpy(r->buf + 8, buf + 8, buf_used - 8);
203
204 } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
205
206
207
208
209
210
211
212
213
214
215
216
217
218 page_idx = lduw_be_p(r->buf + 2) + 4;
219 page_idx = MIN(page_idx, r->buflen);
220 while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
221 if (page_idx < r->buflen) {
222 r->buf[page_idx] = r->buf[page_idx - 1];
223 }
224 page_idx--;
225 }
226 if (page_idx < r->buflen) {
227 r->buf[page_idx] = 0xb0;
228 }
229 stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
230
231 if (len < r->buflen) {
232 len++;
233 }
234 }
235 }
236 return len;
237}
238
239static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
240{
241 int len;
242 uint8_t buf[64];
243
244 SCSIBlockLimits bl = {
245 .max_io_sectors = calculate_max_transfer(s),
246 };
247
248 memset(r->buf, 0, r->buflen);
249 stb_p(buf, s->type);
250 stb_p(buf + 1, 0xb0);
251 len = scsi_emulate_block_limits(buf + 4, &bl);
252 assert(len <= sizeof(buf) - 4);
253 stw_be_p(buf + 2, len);
254
255 memcpy(r->buf, buf, MIN(r->buflen, len + 4));
256
257 r->io_header.sb_len_wr = 0;
258
259
260
261
262
263
264
265 r->io_header.driver_status = 0;
266 r->io_header.status = 0;
267
268 return r->buflen;
269}
270
271static void scsi_read_complete(void * opaque, int ret)
272{
273 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
274 SCSIDevice *s = r->req.dev;
275 int len;
276
277 aio_context_acquire(blk_get_aio_context(s->conf.blk));
278
279 assert(r->req.aiocb != NULL);
280 r->req.aiocb = NULL;
281
282 if (ret || r->req.io_canceled) {
283 scsi_command_complete_noio(r, ret);
284 goto done;
285 }
286
287 len = r->io_header.dxfer_len - r->io_header.resid;
288 trace_scsi_generic_read_complete(r->req.tag, len);
289
290 r->len = -1;
291
292 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
293 SCSISense sense =
294 scsi_parse_sense_buf(r->req.sense, r->io_header.sb_len_wr);
295
296
297
298
299
300
301 if (sense.key == ILLEGAL_REQUEST &&
302 s->needs_vpd_bl_emulation &&
303 r->req.cmd.buf[0] == INQUIRY &&
304 (r->req.cmd.buf[1] & 0x01) &&
305 r->req.cmd.buf[2] == 0xb0) {
306 len = scsi_generic_emulate_block_limits(r, s);
307
308
309
310
311
312 }
313 if (sense.key) {
314 goto req_complete;
315 }
316 }
317
318 if (r->io_header.host_status != SCSI_HOST_OK ||
319 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) ||
320 r->io_header.status != GOOD ||
321 len == 0) {
322 scsi_command_complete_noio(r, 0);
323 goto done;
324 }
325
326
327 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
328 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
329 s->blocksize = ldl_be_p(&r->buf[4]);
330 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
331 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
332 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
333 s->blocksize = ldl_be_p(&r->buf[8]);
334 s->max_lba = ldq_be_p(&r->buf[0]);
335 }
336
337
338
339
340
341 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE || s->type == TYPE_ZBC) &&
342 !blk_is_writable(s->conf.blk) &&
343 (r->req.cmd.buf[0] == MODE_SENSE ||
344 r->req.cmd.buf[0] == MODE_SENSE_10) &&
345 (r->req.cmd.buf[1] & 0x8) == 0) {
346 if (r->req.cmd.buf[0] == MODE_SENSE) {
347 r->buf[2] |= 0x80;
348 } else {
349 r->buf[3] |= 0x80;
350 }
351 }
352 if (r->req.cmd.buf[0] == INQUIRY) {
353 len = scsi_handle_inquiry_reply(r, s, len);
354 }
355
356req_complete:
357 scsi_req_data(&r->req, len);
358 scsi_req_unref(&r->req);
359
360done:
361 aio_context_release(blk_get_aio_context(s->conf.blk));
362}
363
364
365static void scsi_read_data(SCSIRequest *req)
366{
367 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
368 SCSIDevice *s = r->req.dev;
369 int ret;
370
371 trace_scsi_generic_read_data(req->tag);
372
373
374 scsi_req_ref(&r->req);
375 if (r->len == -1) {
376 scsi_command_complete_noio(r, 0);
377 return;
378 }
379
380 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
381 scsi_read_complete);
382 if (ret < 0) {
383 scsi_command_complete_noio(r, ret);
384 }
385}
386
387static void scsi_write_complete(void * opaque, int ret)
388{
389 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
390 SCSIDevice *s = r->req.dev;
391
392 trace_scsi_generic_write_complete(ret);
393
394 aio_context_acquire(blk_get_aio_context(s->conf.blk));
395
396 assert(r->req.aiocb != NULL);
397 r->req.aiocb = NULL;
398
399 if (ret || r->req.io_canceled) {
400 scsi_command_complete_noio(r, ret);
401 goto done;
402 }
403
404 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
405 s->type == TYPE_TAPE) {
406 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
407 trace_scsi_generic_write_complete_blocksize(s->blocksize);
408 }
409
410 scsi_command_complete_noio(r, ret);
411
412done:
413 aio_context_release(blk_get_aio_context(s->conf.blk));
414}
415
416
417
418static void scsi_write_data(SCSIRequest *req)
419{
420 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
421 SCSIDevice *s = r->req.dev;
422 int ret;
423
424 trace_scsi_generic_write_data(req->tag);
425 if (r->len == 0) {
426 r->len = r->buflen;
427 scsi_req_data(&r->req, r->len);
428 return;
429 }
430
431
432 scsi_req_ref(&r->req);
433 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
434 if (ret < 0) {
435 scsi_command_complete_noio(r, ret);
436 }
437}
438
439
440static uint8_t *scsi_get_buf(SCSIRequest *req)
441{
442 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
443
444 return r->buf;
445}
446
447static void scsi_generic_command_dump(uint8_t *cmd, int len)
448{
449 int i;
450 char *line_buffer, *p;
451
452 line_buffer = g_malloc(len * 5 + 1);
453
454 for (i = 0, p = line_buffer; i < len; i++) {
455 p += sprintf(p, " 0x%02x", cmd[i]);
456 }
457 trace_scsi_generic_send_command(line_buffer);
458
459 g_free(line_buffer);
460}
461
462
463
464
465
466
467static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
468{
469 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
470 SCSIDevice *s = r->req.dev;
471 int ret;
472
473 if (trace_event_get_state_backends(TRACE_SCSI_GENERIC_SEND_COMMAND)) {
474 scsi_generic_command_dump(cmd, r->req.cmd.len);
475 }
476
477 if (r->req.cmd.xfer == 0) {
478 g_free(r->buf);
479 r->buflen = 0;
480 r->buf = NULL;
481
482 scsi_req_ref(&r->req);
483 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
484 scsi_command_complete);
485 if (ret < 0) {
486 scsi_command_complete_noio(r, ret);
487 return 0;
488 }
489 return 0;
490 }
491
492 if (r->buflen != r->req.cmd.xfer) {
493 g_free(r->buf);
494 r->buf = g_malloc(r->req.cmd.xfer);
495 r->buflen = r->req.cmd.xfer;
496 }
497
498 memset(r->buf, 0, r->buflen);
499 r->len = r->req.cmd.xfer;
500 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
501 r->len = 0;
502 return -r->req.cmd.xfer;
503 } else {
504 return r->req.cmd.xfer;
505 }
506}
507
508static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
509{
510 int i;
511
512 if ((p[1] & 0xF) == 3) {
513
514 if (p[3] != 8) {
515 return -EINVAL;
516 }
517 *p_wwn = ldq_be_p(p + 4);
518 return 0;
519 }
520
521 if ((p[1] & 0xF) == 8) {
522
523 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
524 return -EINVAL;
525 }
526 if (p[3] > 20 && p[24] != ',') {
527 return -EINVAL;
528 }
529 *p_wwn = 0;
530 for (i = 8; i < 24; i++) {
531 char c = qemu_toupper(p[i]);
532 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
533 *p_wwn = (*p_wwn << 4) | c;
534 }
535 return 0;
536 }
537
538 return -EINVAL;
539}
540
541int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
542 uint8_t *buf, uint8_t buf_size, uint32_t timeout)
543{
544 sg_io_hdr_t io_header;
545 uint8_t sensebuf[8];
546 int ret;
547
548 memset(&io_header, 0, sizeof(io_header));
549 io_header.interface_id = 'S';
550 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
551 io_header.dxfer_len = buf_size;
552 io_header.dxferp = buf;
553 io_header.cmdp = cmd;
554 io_header.cmd_len = cmd_size;
555 io_header.mx_sb_len = sizeof(sensebuf);
556 io_header.sbp = sensebuf;
557 io_header.timeout = timeout * 1000;
558
559 trace_scsi_generic_ioctl_sgio_command(cmd[0], io_header.timeout);
560 ret = blk_ioctl(blk, SG_IO, &io_header);
561 if (ret < 0 || io_header.status ||
562 io_header.driver_status || io_header.host_status) {
563 trace_scsi_generic_ioctl_sgio_done(cmd[0], ret, io_header.status,
564 io_header.host_status);
565 return -1;
566 }
567 return 0;
568}
569
570
571
572
573
574
575
576static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
577{
578 uint8_t cmd[6];
579 uint8_t buf[250];
580 uint8_t page_len;
581 int ret, i;
582
583 memset(cmd, 0, sizeof(cmd));
584 memset(buf, 0, sizeof(buf));
585 cmd[0] = INQUIRY;
586 cmd[1] = 1;
587 cmd[2] = 0x00;
588 cmd[4] = sizeof(buf);
589
590 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
591 buf, sizeof(buf), s->io_timeout);
592 if (ret < 0) {
593
594
595
596
597
598 s->needs_vpd_bl_emulation = false;
599 return;
600 }
601
602 page_len = buf[3];
603 for (i = 4; i < MIN(sizeof(buf), page_len + 4); i++) {
604 if (buf[i] == 0xb0) {
605 s->needs_vpd_bl_emulation = false;
606 return;
607 }
608 }
609 s->needs_vpd_bl_emulation = true;
610}
611
612static void scsi_generic_read_device_identification(SCSIDevice *s)
613{
614 uint8_t cmd[6];
615 uint8_t buf[250];
616 int ret;
617 int i, len;
618
619 memset(cmd, 0, sizeof(cmd));
620 memset(buf, 0, sizeof(buf));
621 cmd[0] = INQUIRY;
622 cmd[1] = 1;
623 cmd[2] = 0x83;
624 cmd[4] = sizeof(buf);
625
626 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
627 buf, sizeof(buf), s->io_timeout);
628 if (ret < 0) {
629 return;
630 }
631
632 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
633 for (i = 0; i + 3 <= len; ) {
634 const uint8_t *p = &buf[i + 4];
635 uint64_t wwn;
636
637 if (i + (p[3] + 4) > len) {
638 break;
639 }
640
641 if ((p[1] & 0x10) == 0) {
642
643 if (read_naa_id(p, &wwn) == 0) {
644 s->wwn = wwn;
645 }
646 } else if ((p[1] & 0x10) == 0x10) {
647
648 if (read_naa_id(p, &wwn) == 0) {
649 s->port_wwn = wwn;
650 }
651 }
652
653 i += p[3] + 4;
654 }
655}
656
657void scsi_generic_read_device_inquiry(SCSIDevice *s)
658{
659 scsi_generic_read_device_identification(s);
660 if (s->type == TYPE_DISK || s->type == TYPE_ZBC) {
661 scsi_generic_set_vpd_bl_emulation(s);
662 } else {
663 s->needs_vpd_bl_emulation = false;
664 }
665}
666
667static int get_stream_blocksize(BlockBackend *blk)
668{
669 uint8_t cmd[6];
670 uint8_t buf[12];
671 int ret;
672
673 memset(cmd, 0, sizeof(cmd));
674 memset(buf, 0, sizeof(buf));
675 cmd[0] = MODE_SENSE;
676 cmd[4] = sizeof(buf);
677
678 ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6);
679 if (ret < 0) {
680 return -1;
681 }
682
683 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
684}
685
686static void scsi_generic_reset(DeviceState *dev)
687{
688 SCSIDevice *s = SCSI_DEVICE(dev);
689
690 s->scsi_version = s->default_scsi_version;
691 scsi_device_purge_requests(s, SENSE_CODE(RESET));
692}
693
694static void scsi_generic_realize(SCSIDevice *s, Error **errp)
695{
696 int rc;
697 int sg_version;
698 struct sg_scsi_id scsiid;
699
700 if (!s->conf.blk) {
701 error_setg(errp, "drive property not set");
702 return;
703 }
704
705 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC &&
706 blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) {
707 error_setg(errp, "Device doesn't support drive option werror");
708 return;
709 }
710 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
711 error_setg(errp, "Device doesn't support drive option rerror");
712 return;
713 }
714
715
716 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
717 if (rc < 0) {
718 error_setg_errno(errp, -rc, "cannot get SG_IO version number");
719 if (rc != -EPERM) {
720 error_append_hint(errp, "Is this a SCSI device?\n");
721 }
722 return;
723 }
724 if (sg_version < 30000) {
725 error_setg(errp, "scsi generic interface too old");
726 return;
727 }
728
729
730 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
731 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
732 return;
733 }
734 if (!blkconf_apply_backend_options(&s->conf,
735 !blk_supports_write_perm(s->conf.blk),
736 true, errp)) {
737 return;
738 }
739
740
741 s->type = scsiid.scsi_type;
742 trace_scsi_generic_realize_type(s->type);
743
744 switch (s->type) {
745 case TYPE_TAPE:
746 s->blocksize = get_stream_blocksize(s->conf.blk);
747 if (s->blocksize == -1) {
748 s->blocksize = 0;
749 }
750 break;
751
752
753
754
755
756 case TYPE_ROM:
757 case TYPE_WORM:
758 s->blocksize = 2048;
759 break;
760 default:
761 s->blocksize = 512;
762 break;
763 }
764
765 trace_scsi_generic_realize_blocksize(s->blocksize);
766
767
768 s->default_scsi_version = -1;
769 s->io_timeout = DEFAULT_IO_TIMEOUT;
770 scsi_generic_read_device_inquiry(s);
771}
772
773const SCSIReqOps scsi_generic_req_ops = {
774 .size = sizeof(SCSIGenericReq),
775 .free_req = scsi_free_request,
776 .send_command = scsi_send_command,
777 .read_data = scsi_read_data,
778 .write_data = scsi_write_data,
779 .get_buf = scsi_get_buf,
780 .load_request = scsi_generic_load_request,
781 .save_request = scsi_generic_save_request,
782};
783
784static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
785 uint8_t *buf, void *hba_private)
786{
787 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
788}
789
790static Property scsi_generic_properties[] = {
791 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
792 DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
793 DEFINE_PROP_UINT32("io_timeout", SCSIDevice, io_timeout,
794 DEFAULT_IO_TIMEOUT),
795 DEFINE_PROP_END_OF_LIST(),
796};
797
798static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
799 uint8_t *buf, size_t buf_len,
800 void *hba_private)
801{
802 return scsi_bus_parse_cdb(dev, cmd, buf, buf_len, hba_private);
803}
804
805static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
806{
807 DeviceClass *dc = DEVICE_CLASS(klass);
808 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
809
810 sc->realize = scsi_generic_realize;
811 sc->alloc_req = scsi_new_request;
812 sc->parse_cdb = scsi_generic_parse_cdb;
813 dc->fw_name = "disk";
814 dc->desc = "pass through generic scsi device (/dev/sg*)";
815 dc->reset = scsi_generic_reset;
816 device_class_set_props(dc, scsi_generic_properties);
817 dc->vmsd = &vmstate_scsi_device;
818}
819
820static const TypeInfo scsi_generic_info = {
821 .name = "scsi-generic",
822 .parent = TYPE_SCSI_DEVICE,
823 .instance_size = sizeof(SCSIDevice),
824 .class_init = scsi_generic_class_initfn,
825};
826
827static void scsi_generic_register_types(void)
828{
829 type_register_static(&scsi_generic_info);
830}
831
832type_init(scsi_generic_register_types)
833
834#endif
835