scsi: make io_timeout configurable
[qemu/ar7.git] / hw / scsi / scsi-generic.c
blob3dd3ccd0977b8171bf42d4895aaabc988f65817f
1 /*
2 * Generic SCSI Device support
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
10 * This code is licensed under the LGPL.
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"
27 #ifdef __linux__
29 #include <scsi/sg.h>
30 #include "scsi/constants.h"
32 #ifndef MAX_UINT
33 #define MAX_UINT ((unsigned int)-1)
34 #endif
36 typedef struct SCSIGenericReq {
37 SCSIRequest req;
38 uint8_t *buf;
39 int buflen;
40 int len;
41 sg_io_hdr_t io_header;
42 } SCSIGenericReq;
44 static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
46 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
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);
55 static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
57 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
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);
66 static void scsi_free_request(SCSIRequest *req)
68 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
70 g_free(r->buf);
73 /* Helper function for command completion. */
74 static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
76 int status;
77 SCSISense sense;
79 assert(r->req.aiocb == NULL);
81 if (r->req.io_canceled) {
82 scsi_req_cancel_complete(&r->req);
83 goto done;
85 status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
86 if (status == CHECK_CONDITION) {
87 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
88 r->req.sense_len = r->io_header.sb_len_wr;
89 } else {
90 scsi_req_build_sense(&r->req, sense);
94 trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
96 scsi_req_complete(&r->req, status);
97 done:
98 scsi_req_unref(&r->req);
101 static void scsi_command_complete(void *opaque, int ret)
103 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
104 SCSIDevice *s = r->req.dev;
106 assert(r->req.aiocb != NULL);
107 r->req.aiocb = NULL;
109 aio_context_acquire(blk_get_aio_context(s->conf.blk));
110 scsi_command_complete_noio(r, ret);
111 aio_context_release(blk_get_aio_context(s->conf.blk));
114 static int execute_command(BlockBackend *blk,
115 SCSIGenericReq *r, int direction,
116 BlockCompletionFunc *complete)
118 SCSIDevice *s = r->req.dev;
120 r->io_header.interface_id = 'S';
121 r->io_header.dxfer_direction = direction;
122 r->io_header.dxferp = r->buf;
123 r->io_header.dxfer_len = r->buflen;
124 r->io_header.cmdp = r->req.cmd.buf;
125 r->io_header.cmd_len = r->req.cmd.len;
126 r->io_header.mx_sb_len = sizeof(r->req.sense);
127 r->io_header.sbp = r->req.sense;
128 r->io_header.timeout = s->io_timeout * 1000;
129 r->io_header.usr_ptr = r;
130 r->io_header.flags |= SG_FLAG_DIRECT_IO;
132 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
133 if (r->req.aiocb == NULL) {
134 return -EIO;
137 return 0;
140 static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
142 uint8_t page, page_idx;
145 * EVPD set to zero returns the standard INQUIRY data.
147 * Check if scsi_version is unset (-1) to avoid re-defining it
148 * each time an INQUIRY with standard data is received.
149 * scsi_version is initialized with -1 in scsi_generic_reset
150 * and scsi_disk_reset, making sure that we'll set the
151 * scsi_version after a reset. If the version field of the
152 * INQUIRY response somehow changes after a guest reboot,
153 * we'll be able to keep track of it.
155 * On SCSI-2 and older, first 3 bits of byte 2 is the
156 * ANSI-approved version, while on later versions the
157 * whole byte 2 contains the version. Check if we're dealing
158 * with a newer version and, in that case, assign the
159 * whole byte.
161 if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
162 s->scsi_version = r->buf[2] & 0x07;
163 if (s->scsi_version > 2) {
164 s->scsi_version = r->buf[2];
168 if ((s->type == TYPE_DISK || s->type == TYPE_ZBC) &&
169 (r->req.cmd.buf[1] & 0x01)) {
170 page = r->req.cmd.buf[2];
171 if (page == 0xb0) {
172 uint32_t max_transfer =
173 blk_get_max_transfer(s->conf.blk) / s->blocksize;
175 assert(max_transfer);
176 stl_be_p(&r->buf[8], max_transfer);
177 /* Also take care of the opt xfer len. */
178 stl_be_p(&r->buf[12],
179 MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
180 } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
182 * Now we're capable of supplying the VPD Block Limits
183 * response if the hardware can't. Add it in the INQUIRY
184 * Supported VPD pages response in case we are using the
185 * emulation for this device.
187 * This way, the guest kernel will be aware of the support
188 * and will use it to proper setup the SCSI device.
190 * VPD page numbers must be sorted, so insert 0xb0 at the
191 * right place with an in-place insert. When the while loop
192 * begins the device response is at r[0] to r[page_idx - 1].
194 page_idx = lduw_be_p(r->buf + 2) + 4;
195 page_idx = MIN(page_idx, r->buflen);
196 while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
197 if (page_idx < r->buflen) {
198 r->buf[page_idx] = r->buf[page_idx - 1];
200 page_idx--;
202 if (page_idx < r->buflen) {
203 r->buf[page_idx] = 0xb0;
205 stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
210 static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
212 int len;
213 uint8_t buf[64];
215 SCSIBlockLimits bl = {
216 .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize
219 memset(r->buf, 0, r->buflen);
220 stb_p(buf, s->type);
221 stb_p(buf + 1, 0xb0);
222 len = scsi_emulate_block_limits(buf + 4, &bl);
223 assert(len <= sizeof(buf) - 4);
224 stw_be_p(buf + 2, len);
226 memcpy(r->buf, buf, MIN(r->buflen, len + 4));
228 r->io_header.sb_len_wr = 0;
231 * We have valid contents in the reply buffer but the
232 * io_header can report a sense error coming from
233 * the hardware in scsi_command_complete_noio. Clean
234 * up the io_header to avoid reporting it.
236 r->io_header.driver_status = 0;
237 r->io_header.status = 0;
239 return r->buflen;
242 static void scsi_read_complete(void * opaque, int ret)
244 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
245 SCSIDevice *s = r->req.dev;
246 int len;
248 assert(r->req.aiocb != NULL);
249 r->req.aiocb = NULL;
251 aio_context_acquire(blk_get_aio_context(s->conf.blk));
253 if (ret || r->req.io_canceled) {
254 scsi_command_complete_noio(r, ret);
255 goto done;
258 len = r->io_header.dxfer_len - r->io_header.resid;
259 trace_scsi_generic_read_complete(r->req.tag, len);
261 r->len = -1;
263 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
264 SCSISense sense =
265 scsi_parse_sense_buf(r->req.sense, r->io_header.sb_len_wr);
268 * Check if this is a VPD Block Limits request that
269 * resulted in sense error but would need emulation.
270 * In this case, emulate a valid VPD response.
272 if (sense.key == ILLEGAL_REQUEST &&
273 s->needs_vpd_bl_emulation &&
274 r->req.cmd.buf[0] == INQUIRY &&
275 (r->req.cmd.buf[1] & 0x01) &&
276 r->req.cmd.buf[2] == 0xb0) {
277 len = scsi_generic_emulate_block_limits(r, s);
279 * It's okay to jup to req_complete: no need to
280 * let scsi_handle_inquiry_reply handle an
281 * INQUIRY VPD BL request we created manually.
284 if (sense.key) {
285 goto req_complete;
289 if (len == 0) {
290 scsi_command_complete_noio(r, 0);
291 goto done;
294 /* Snoop READ CAPACITY output to set the blocksize. */
295 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
296 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
297 s->blocksize = ldl_be_p(&r->buf[4]);
298 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
299 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
300 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
301 s->blocksize = ldl_be_p(&r->buf[8]);
302 s->max_lba = ldq_be_p(&r->buf[0]);
304 blk_set_guest_block_size(s->conf.blk, s->blocksize);
307 * Patch MODE SENSE device specific parameters if the BDS is opened
308 * readonly.
310 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE || s->type == TYPE_ZBC) &&
311 !blk_is_writable(s->conf.blk) &&
312 (r->req.cmd.buf[0] == MODE_SENSE ||
313 r->req.cmd.buf[0] == MODE_SENSE_10) &&
314 (r->req.cmd.buf[1] & 0x8) == 0) {
315 if (r->req.cmd.buf[0] == MODE_SENSE) {
316 r->buf[2] |= 0x80;
317 } else {
318 r->buf[3] |= 0x80;
321 if (r->req.cmd.buf[0] == INQUIRY) {
322 scsi_handle_inquiry_reply(r, s);
325 req_complete:
326 scsi_req_data(&r->req, len);
327 scsi_req_unref(&r->req);
329 done:
330 aio_context_release(blk_get_aio_context(s->conf.blk));
333 /* Read more data from scsi device into buffer. */
334 static void scsi_read_data(SCSIRequest *req)
336 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
337 SCSIDevice *s = r->req.dev;
338 int ret;
340 trace_scsi_generic_read_data(req->tag);
342 /* The request is used as the AIO opaque value, so add a ref. */
343 scsi_req_ref(&r->req);
344 if (r->len == -1) {
345 scsi_command_complete_noio(r, 0);
346 return;
349 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
350 scsi_read_complete);
351 if (ret < 0) {
352 scsi_command_complete_noio(r, ret);
356 static void scsi_write_complete(void * opaque, int ret)
358 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
359 SCSIDevice *s = r->req.dev;
361 trace_scsi_generic_write_complete(ret);
363 assert(r->req.aiocb != NULL);
364 r->req.aiocb = NULL;
366 aio_context_acquire(blk_get_aio_context(s->conf.blk));
368 if (ret || r->req.io_canceled) {
369 scsi_command_complete_noio(r, ret);
370 goto done;
373 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
374 s->type == TYPE_TAPE) {
375 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
376 trace_scsi_generic_write_complete_blocksize(s->blocksize);
379 scsi_command_complete_noio(r, ret);
381 done:
382 aio_context_release(blk_get_aio_context(s->conf.blk));
385 /* Write data to a scsi device. Returns nonzero on failure.
386 The transfer may complete asynchronously. */
387 static void scsi_write_data(SCSIRequest *req)
389 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
390 SCSIDevice *s = r->req.dev;
391 int ret;
393 trace_scsi_generic_write_data(req->tag);
394 if (r->len == 0) {
395 r->len = r->buflen;
396 scsi_req_data(&r->req, r->len);
397 return;
400 /* The request is used as the AIO opaque value, so add a ref. */
401 scsi_req_ref(&r->req);
402 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
403 if (ret < 0) {
404 scsi_command_complete_noio(r, ret);
408 /* Return a pointer to the data buffer. */
409 static uint8_t *scsi_get_buf(SCSIRequest *req)
411 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
413 return r->buf;
416 static void scsi_generic_command_dump(uint8_t *cmd, int len)
418 int i;
419 char *line_buffer, *p;
421 line_buffer = g_malloc(len * 5 + 1);
423 for (i = 0, p = line_buffer; i < len; i++) {
424 p += sprintf(p, " 0x%02x", cmd[i]);
426 trace_scsi_generic_send_command(line_buffer);
428 g_free(line_buffer);
431 /* Execute a scsi command. Returns the length of the data expected by the
432 command. This will be Positive for data transfers from the device
433 (eg. disk reads), negative for transfers to the device (eg. disk writes),
434 and zero if the command does not transfer any data. */
436 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
438 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
439 SCSIDevice *s = r->req.dev;
440 int ret;
442 if (trace_event_get_state_backends(TRACE_SCSI_GENERIC_SEND_COMMAND)) {
443 scsi_generic_command_dump(cmd, r->req.cmd.len);
446 if (r->req.cmd.xfer == 0) {
447 g_free(r->buf);
448 r->buflen = 0;
449 r->buf = NULL;
450 /* The request is used as the AIO opaque value, so add a ref. */
451 scsi_req_ref(&r->req);
452 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
453 scsi_command_complete);
454 if (ret < 0) {
455 scsi_command_complete_noio(r, ret);
456 return 0;
458 return 0;
461 if (r->buflen != r->req.cmd.xfer) {
462 g_free(r->buf);
463 r->buf = g_malloc(r->req.cmd.xfer);
464 r->buflen = r->req.cmd.xfer;
467 memset(r->buf, 0, r->buflen);
468 r->len = r->req.cmd.xfer;
469 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
470 r->len = 0;
471 return -r->req.cmd.xfer;
472 } else {
473 return r->req.cmd.xfer;
477 static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
479 int i;
481 if ((p[1] & 0xF) == 3) {
482 /* NAA designator type */
483 if (p[3] != 8) {
484 return -EINVAL;
486 *p_wwn = ldq_be_p(p + 4);
487 return 0;
490 if ((p[1] & 0xF) == 8) {
491 /* SCSI name string designator type */
492 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
493 return -EINVAL;
495 if (p[3] > 20 && p[24] != ',') {
496 return -EINVAL;
498 *p_wwn = 0;
499 for (i = 8; i < 24; i++) {
500 char c = qemu_toupper(p[i]);
501 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
502 *p_wwn = (*p_wwn << 4) | c;
504 return 0;
507 return -EINVAL;
510 int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
511 uint8_t *buf, uint8_t buf_size, uint32_t timeout)
513 sg_io_hdr_t io_header;
514 uint8_t sensebuf[8];
515 int ret;
517 memset(&io_header, 0, sizeof(io_header));
518 io_header.interface_id = 'S';
519 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
520 io_header.dxfer_len = buf_size;
521 io_header.dxferp = buf;
522 io_header.cmdp = cmd;
523 io_header.cmd_len = cmd_size;
524 io_header.mx_sb_len = sizeof(sensebuf);
525 io_header.sbp = sensebuf;
526 io_header.timeout = timeout * 1000;
528 ret = blk_ioctl(blk, SG_IO, &io_header);
529 if (ret < 0 || io_header.driver_status || io_header.host_status) {
530 return -1;
532 return 0;
536 * Executes an INQUIRY request with EVPD set to retrieve the
537 * available VPD pages of the device. If the device does
538 * not support the Block Limits page (page 0xb0), set
539 * the needs_vpd_bl_emulation flag for future use.
541 static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
543 uint8_t cmd[6];
544 uint8_t buf[250];
545 uint8_t page_len;
546 int ret, i;
548 memset(cmd, 0, sizeof(cmd));
549 memset(buf, 0, sizeof(buf));
550 cmd[0] = INQUIRY;
551 cmd[1] = 1;
552 cmd[2] = 0x00;
553 cmd[4] = sizeof(buf);
555 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
556 buf, sizeof(buf), s->io_timeout);
557 if (ret < 0) {
559 * Do not assume anything if we can't retrieve the
560 * INQUIRY response to assert the VPD Block Limits
561 * support.
563 s->needs_vpd_bl_emulation = false;
564 return;
567 page_len = buf[3];
568 for (i = 4; i < MIN(sizeof(buf), page_len + 4); i++) {
569 if (buf[i] == 0xb0) {
570 s->needs_vpd_bl_emulation = false;
571 return;
574 s->needs_vpd_bl_emulation = true;
577 static void scsi_generic_read_device_identification(SCSIDevice *s)
579 uint8_t cmd[6];
580 uint8_t buf[250];
581 int ret;
582 int i, len;
584 memset(cmd, 0, sizeof(cmd));
585 memset(buf, 0, sizeof(buf));
586 cmd[0] = INQUIRY;
587 cmd[1] = 1;
588 cmd[2] = 0x83;
589 cmd[4] = sizeof(buf);
591 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
592 buf, sizeof(buf), s->io_timeout);
593 if (ret < 0) {
594 return;
597 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
598 for (i = 0; i + 3 <= len; ) {
599 const uint8_t *p = &buf[i + 4];
600 uint64_t wwn;
602 if (i + (p[3] + 4) > len) {
603 break;
606 if ((p[1] & 0x10) == 0) {
607 /* Associated with the logical unit */
608 if (read_naa_id(p, &wwn) == 0) {
609 s->wwn = wwn;
611 } else if ((p[1] & 0x10) == 0x10) {
612 /* Associated with the target port */
613 if (read_naa_id(p, &wwn) == 0) {
614 s->port_wwn = wwn;
618 i += p[3] + 4;
622 void scsi_generic_read_device_inquiry(SCSIDevice *s)
624 scsi_generic_read_device_identification(s);
625 if (s->type == TYPE_DISK || s->type == TYPE_ZBC) {
626 scsi_generic_set_vpd_bl_emulation(s);
627 } else {
628 s->needs_vpd_bl_emulation = false;
632 static int get_stream_blocksize(BlockBackend *blk)
634 uint8_t cmd[6];
635 uint8_t buf[12];
636 int ret;
638 memset(cmd, 0, sizeof(cmd));
639 memset(buf, 0, sizeof(buf));
640 cmd[0] = MODE_SENSE;
641 cmd[4] = sizeof(buf);
643 ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6);
644 if (ret < 0) {
645 return -1;
648 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
651 static void scsi_generic_reset(DeviceState *dev)
653 SCSIDevice *s = SCSI_DEVICE(dev);
655 s->scsi_version = s->default_scsi_version;
656 scsi_device_purge_requests(s, SENSE_CODE(RESET));
659 static void scsi_generic_realize(SCSIDevice *s, Error **errp)
661 int rc;
662 int sg_version;
663 struct sg_scsi_id scsiid;
665 if (!s->conf.blk) {
666 error_setg(errp, "drive property not set");
667 return;
670 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
671 error_setg(errp, "Device doesn't support drive option werror");
672 return;
674 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
675 error_setg(errp, "Device doesn't support drive option rerror");
676 return;
679 /* check we are using a driver managing SG_IO (version 3 and after */
680 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
681 if (rc < 0) {
682 error_setg_errno(errp, -rc, "cannot get SG_IO version number");
683 if (rc != -EPERM) {
684 error_append_hint(errp, "Is this a SCSI device?\n");
686 return;
688 if (sg_version < 30000) {
689 error_setg(errp, "scsi generic interface too old");
690 return;
693 /* get LUN of the /dev/sg? */
694 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
695 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
696 return;
698 if (!blkconf_apply_backend_options(&s->conf,
699 !blk_supports_write_perm(s->conf.blk),
700 true, errp)) {
701 return;
704 /* define device state */
705 s->type = scsiid.scsi_type;
706 trace_scsi_generic_realize_type(s->type);
708 switch (s->type) {
709 case TYPE_TAPE:
710 s->blocksize = get_stream_blocksize(s->conf.blk);
711 if (s->blocksize == -1) {
712 s->blocksize = 0;
714 break;
716 /* Make a guess for block devices, we'll fix it when the guest sends.
717 * READ CAPACITY. If they don't, they likely would assume these sizes
718 * anyway. (TODO: they could also send MODE SENSE).
720 case TYPE_ROM:
721 case TYPE_WORM:
722 s->blocksize = 2048;
723 break;
724 default:
725 s->blocksize = 512;
726 break;
729 trace_scsi_generic_realize_blocksize(s->blocksize);
731 /* Only used by scsi-block, but initialize it nevertheless to be clean. */
732 s->default_scsi_version = -1;
733 s->io_timeout = DEFAULT_IO_TIMEOUT;
734 scsi_generic_read_device_inquiry(s);
737 const SCSIReqOps scsi_generic_req_ops = {
738 .size = sizeof(SCSIGenericReq),
739 .free_req = scsi_free_request,
740 .send_command = scsi_send_command,
741 .read_data = scsi_read_data,
742 .write_data = scsi_write_data,
743 .get_buf = scsi_get_buf,
744 .load_request = scsi_generic_load_request,
745 .save_request = scsi_generic_save_request,
748 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
749 uint8_t *buf, void *hba_private)
751 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
754 static Property scsi_generic_properties[] = {
755 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
756 DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
757 DEFINE_PROP_UINT32("io_timeout", SCSIDevice, io_timeout,
758 DEFAULT_IO_TIMEOUT),
759 DEFINE_PROP_END_OF_LIST(),
762 static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
763 uint8_t *buf, void *hba_private)
765 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
768 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
770 DeviceClass *dc = DEVICE_CLASS(klass);
771 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
773 sc->realize = scsi_generic_realize;
774 sc->alloc_req = scsi_new_request;
775 sc->parse_cdb = scsi_generic_parse_cdb;
776 dc->fw_name = "disk";
777 dc->desc = "pass through generic scsi device (/dev/sg*)";
778 dc->reset = scsi_generic_reset;
779 device_class_set_props(dc, scsi_generic_properties);
780 dc->vmsd = &vmstate_scsi_device;
783 static const TypeInfo scsi_generic_info = {
784 .name = "scsi-generic",
785 .parent = TYPE_SCSI_DEVICE,
786 .instance_size = sizeof(SCSIDevice),
787 .class_init = scsi_generic_class_initfn,
790 static void scsi_generic_register_types(void)
792 type_register_static(&scsi_generic_info);
795 type_init(scsi_generic_register_types)
797 #endif /* __linux__ */