exec/memory: Use struct Object typedef
[qemu/ar7.git] / hw / scsi / scsi-generic.c
blob98c30c5d5c3d5db9d6782e91b57fb3b355cd63fc
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;
78 sg_io_hdr_t *io_hdr = &r->io_header;
80 assert(r->req.aiocb == NULL);
82 if (r->req.io_canceled) {
83 scsi_req_cancel_complete(&r->req);
84 goto done;
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);
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;
102 trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
104 scsi_req_complete(&r->req, status);
105 done:
106 scsi_req_unref(&r->req);
109 static void scsi_command_complete(void *opaque, int ret)
111 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
112 SCSIDevice *s = r->req.dev;
114 assert(r->req.aiocb != NULL);
115 r->req.aiocb = NULL;
117 aio_context_acquire(blk_get_aio_context(s->conf.blk));
118 scsi_command_complete_noio(r, ret);
119 aio_context_release(blk_get_aio_context(s->conf.blk));
122 static int execute_command(BlockBackend *blk,
123 SCSIGenericReq *r, int direction,
124 BlockCompletionFunc *complete)
126 SCSIDevice *s = r->req.dev;
128 r->io_header.interface_id = 'S';
129 r->io_header.dxfer_direction = direction;
130 r->io_header.dxferp = r->buf;
131 r->io_header.dxfer_len = r->buflen;
132 r->io_header.cmdp = r->req.cmd.buf;
133 r->io_header.cmd_len = r->req.cmd.len;
134 r->io_header.mx_sb_len = sizeof(r->req.sense);
135 r->io_header.sbp = r->req.sense;
136 r->io_header.timeout = s->io_timeout * 1000;
137 r->io_header.usr_ptr = r;
138 r->io_header.flags |= SG_FLAG_DIRECT_IO;
140 trace_scsi_generic_aio_sgio_command(r->req.tag, r->req.cmd.buf[0],
141 r->io_header.timeout);
142 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
143 if (r->req.aiocb == NULL) {
144 return -EIO;
147 return 0;
150 static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
152 uint8_t page, page_idx;
155 * EVPD set to zero returns the standard INQUIRY data.
157 * Check if scsi_version is unset (-1) to avoid re-defining it
158 * each time an INQUIRY with standard data is received.
159 * scsi_version is initialized with -1 in scsi_generic_reset
160 * and scsi_disk_reset, making sure that we'll set the
161 * scsi_version after a reset. If the version field of the
162 * INQUIRY response somehow changes after a guest reboot,
163 * we'll be able to keep track of it.
165 * On SCSI-2 and older, first 3 bits of byte 2 is the
166 * ANSI-approved version, while on later versions the
167 * whole byte 2 contains the version. Check if we're dealing
168 * with a newer version and, in that case, assign the
169 * whole byte.
171 if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
172 s->scsi_version = r->buf[2] & 0x07;
173 if (s->scsi_version > 2) {
174 s->scsi_version = r->buf[2];
178 if ((s->type == TYPE_DISK || s->type == TYPE_ZBC) &&
179 (r->req.cmd.buf[1] & 0x01)) {
180 page = r->req.cmd.buf[2];
181 if (page == 0xb0) {
182 uint32_t max_transfer =
183 blk_get_max_transfer(s->conf.blk) / s->blocksize;
185 assert(max_transfer);
186 stl_be_p(&r->buf[8], max_transfer);
187 /* Also take care of the opt xfer len. */
188 stl_be_p(&r->buf[12],
189 MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
190 } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
192 * Now we're capable of supplying the VPD Block Limits
193 * response if the hardware can't. Add it in the INQUIRY
194 * Supported VPD pages response in case we are using the
195 * emulation for this device.
197 * This way, the guest kernel will be aware of the support
198 * and will use it to proper setup the SCSI device.
200 * VPD page numbers must be sorted, so insert 0xb0 at the
201 * right place with an in-place insert. When the while loop
202 * begins the device response is at r[0] to r[page_idx - 1].
204 page_idx = lduw_be_p(r->buf + 2) + 4;
205 page_idx = MIN(page_idx, r->buflen);
206 while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
207 if (page_idx < r->buflen) {
208 r->buf[page_idx] = r->buf[page_idx - 1];
210 page_idx--;
212 if (page_idx < r->buflen) {
213 r->buf[page_idx] = 0xb0;
215 stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
220 static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
222 int len;
223 uint8_t buf[64];
225 SCSIBlockLimits bl = {
226 .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize
229 memset(r->buf, 0, r->buflen);
230 stb_p(buf, s->type);
231 stb_p(buf + 1, 0xb0);
232 len = scsi_emulate_block_limits(buf + 4, &bl);
233 assert(len <= sizeof(buf) - 4);
234 stw_be_p(buf + 2, len);
236 memcpy(r->buf, buf, MIN(r->buflen, len + 4));
238 r->io_header.sb_len_wr = 0;
241 * We have valid contents in the reply buffer but the
242 * io_header can report a sense error coming from
243 * the hardware in scsi_command_complete_noio. Clean
244 * up the io_header to avoid reporting it.
246 r->io_header.driver_status = 0;
247 r->io_header.status = 0;
249 return r->buflen;
252 static void scsi_read_complete(void * opaque, int ret)
254 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
255 SCSIDevice *s = r->req.dev;
256 int len;
258 assert(r->req.aiocb != NULL);
259 r->req.aiocb = NULL;
261 aio_context_acquire(blk_get_aio_context(s->conf.blk));
263 if (ret || r->req.io_canceled) {
264 scsi_command_complete_noio(r, ret);
265 goto done;
268 len = r->io_header.dxfer_len - r->io_header.resid;
269 trace_scsi_generic_read_complete(r->req.tag, len);
271 r->len = -1;
273 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
274 SCSISense sense =
275 scsi_parse_sense_buf(r->req.sense, r->io_header.sb_len_wr);
278 * Check if this is a VPD Block Limits request that
279 * resulted in sense error but would need emulation.
280 * In this case, emulate a valid VPD response.
282 if (sense.key == ILLEGAL_REQUEST &&
283 s->needs_vpd_bl_emulation &&
284 r->req.cmd.buf[0] == INQUIRY &&
285 (r->req.cmd.buf[1] & 0x01) &&
286 r->req.cmd.buf[2] == 0xb0) {
287 len = scsi_generic_emulate_block_limits(r, s);
289 * It's okay to jup to req_complete: no need to
290 * let scsi_handle_inquiry_reply handle an
291 * INQUIRY VPD BL request we created manually.
294 if (sense.key) {
295 goto req_complete;
299 if (r->io_header.host_status != SCSI_HOST_OK ||
300 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) ||
301 r->io_header.status != GOOD ||
302 len == 0) {
303 scsi_command_complete_noio(r, 0);
304 goto done;
307 /* Snoop READ CAPACITY output to set the blocksize. */
308 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
309 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
310 s->blocksize = ldl_be_p(&r->buf[4]);
311 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
312 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
313 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
314 s->blocksize = ldl_be_p(&r->buf[8]);
315 s->max_lba = ldq_be_p(&r->buf[0]);
317 blk_set_guest_block_size(s->conf.blk, s->blocksize);
320 * Patch MODE SENSE device specific parameters if the BDS is opened
321 * readonly.
323 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE || s->type == TYPE_ZBC) &&
324 !blk_is_writable(s->conf.blk) &&
325 (r->req.cmd.buf[0] == MODE_SENSE ||
326 r->req.cmd.buf[0] == MODE_SENSE_10) &&
327 (r->req.cmd.buf[1] & 0x8) == 0) {
328 if (r->req.cmd.buf[0] == MODE_SENSE) {
329 r->buf[2] |= 0x80;
330 } else {
331 r->buf[3] |= 0x80;
334 if (r->req.cmd.buf[0] == INQUIRY) {
335 scsi_handle_inquiry_reply(r, s);
338 req_complete:
339 scsi_req_data(&r->req, len);
340 scsi_req_unref(&r->req);
342 done:
343 aio_context_release(blk_get_aio_context(s->conf.blk));
346 /* Read more data from scsi device into buffer. */
347 static void scsi_read_data(SCSIRequest *req)
349 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
350 SCSIDevice *s = r->req.dev;
351 int ret;
353 trace_scsi_generic_read_data(req->tag);
355 /* The request is used as the AIO opaque value, so add a ref. */
356 scsi_req_ref(&r->req);
357 if (r->len == -1) {
358 scsi_command_complete_noio(r, 0);
359 return;
362 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
363 scsi_read_complete);
364 if (ret < 0) {
365 scsi_command_complete_noio(r, ret);
369 static void scsi_write_complete(void * opaque, int ret)
371 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
372 SCSIDevice *s = r->req.dev;
374 trace_scsi_generic_write_complete(ret);
376 assert(r->req.aiocb != NULL);
377 r->req.aiocb = NULL;
379 aio_context_acquire(blk_get_aio_context(s->conf.blk));
381 if (ret || r->req.io_canceled) {
382 scsi_command_complete_noio(r, ret);
383 goto done;
386 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
387 s->type == TYPE_TAPE) {
388 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
389 trace_scsi_generic_write_complete_blocksize(s->blocksize);
392 scsi_command_complete_noio(r, ret);
394 done:
395 aio_context_release(blk_get_aio_context(s->conf.blk));
398 /* Write data to a scsi device. Returns nonzero on failure.
399 The transfer may complete asynchronously. */
400 static void scsi_write_data(SCSIRequest *req)
402 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
403 SCSIDevice *s = r->req.dev;
404 int ret;
406 trace_scsi_generic_write_data(req->tag);
407 if (r->len == 0) {
408 r->len = r->buflen;
409 scsi_req_data(&r->req, r->len);
410 return;
413 /* The request is used as the AIO opaque value, so add a ref. */
414 scsi_req_ref(&r->req);
415 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
416 if (ret < 0) {
417 scsi_command_complete_noio(r, ret);
421 /* Return a pointer to the data buffer. */
422 static uint8_t *scsi_get_buf(SCSIRequest *req)
424 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
426 return r->buf;
429 static void scsi_generic_command_dump(uint8_t *cmd, int len)
431 int i;
432 char *line_buffer, *p;
434 line_buffer = g_malloc(len * 5 + 1);
436 for (i = 0, p = line_buffer; i < len; i++) {
437 p += sprintf(p, " 0x%02x", cmd[i]);
439 trace_scsi_generic_send_command(line_buffer);
441 g_free(line_buffer);
444 /* Execute a scsi command. Returns the length of the data expected by the
445 command. This will be Positive for data transfers from the device
446 (eg. disk reads), negative for transfers to the device (eg. disk writes),
447 and zero if the command does not transfer any data. */
449 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
451 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
452 SCSIDevice *s = r->req.dev;
453 int ret;
455 if (trace_event_get_state_backends(TRACE_SCSI_GENERIC_SEND_COMMAND)) {
456 scsi_generic_command_dump(cmd, r->req.cmd.len);
459 if (r->req.cmd.xfer == 0) {
460 g_free(r->buf);
461 r->buflen = 0;
462 r->buf = NULL;
463 /* The request is used as the AIO opaque value, so add a ref. */
464 scsi_req_ref(&r->req);
465 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
466 scsi_command_complete);
467 if (ret < 0) {
468 scsi_command_complete_noio(r, ret);
469 return 0;
471 return 0;
474 if (r->buflen != r->req.cmd.xfer) {
475 g_free(r->buf);
476 r->buf = g_malloc(r->req.cmd.xfer);
477 r->buflen = r->req.cmd.xfer;
480 memset(r->buf, 0, r->buflen);
481 r->len = r->req.cmd.xfer;
482 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
483 r->len = 0;
484 return -r->req.cmd.xfer;
485 } else {
486 return r->req.cmd.xfer;
490 static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
492 int i;
494 if ((p[1] & 0xF) == 3) {
495 /* NAA designator type */
496 if (p[3] != 8) {
497 return -EINVAL;
499 *p_wwn = ldq_be_p(p + 4);
500 return 0;
503 if ((p[1] & 0xF) == 8) {
504 /* SCSI name string designator type */
505 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
506 return -EINVAL;
508 if (p[3] > 20 && p[24] != ',') {
509 return -EINVAL;
511 *p_wwn = 0;
512 for (i = 8; i < 24; i++) {
513 char c = qemu_toupper(p[i]);
514 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
515 *p_wwn = (*p_wwn << 4) | c;
517 return 0;
520 return -EINVAL;
523 int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
524 uint8_t *buf, uint8_t buf_size, uint32_t timeout)
526 sg_io_hdr_t io_header;
527 uint8_t sensebuf[8];
528 int ret;
530 memset(&io_header, 0, sizeof(io_header));
531 io_header.interface_id = 'S';
532 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
533 io_header.dxfer_len = buf_size;
534 io_header.dxferp = buf;
535 io_header.cmdp = cmd;
536 io_header.cmd_len = cmd_size;
537 io_header.mx_sb_len = sizeof(sensebuf);
538 io_header.sbp = sensebuf;
539 io_header.timeout = timeout * 1000;
541 trace_scsi_generic_ioctl_sgio_command(cmd[0], io_header.timeout);
542 ret = blk_ioctl(blk, SG_IO, &io_header);
543 if (ret < 0 || io_header.status ||
544 io_header.driver_status || io_header.host_status) {
545 trace_scsi_generic_ioctl_sgio_done(cmd[0], ret, io_header.status,
546 io_header.host_status);
547 return -1;
549 return 0;
553 * Executes an INQUIRY request with EVPD set to retrieve the
554 * available VPD pages of the device. If the device does
555 * not support the Block Limits page (page 0xb0), set
556 * the needs_vpd_bl_emulation flag for future use.
558 static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
560 uint8_t cmd[6];
561 uint8_t buf[250];
562 uint8_t page_len;
563 int ret, i;
565 memset(cmd, 0, sizeof(cmd));
566 memset(buf, 0, sizeof(buf));
567 cmd[0] = INQUIRY;
568 cmd[1] = 1;
569 cmd[2] = 0x00;
570 cmd[4] = sizeof(buf);
572 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
573 buf, sizeof(buf), s->io_timeout);
574 if (ret < 0) {
576 * Do not assume anything if we can't retrieve the
577 * INQUIRY response to assert the VPD Block Limits
578 * support.
580 s->needs_vpd_bl_emulation = false;
581 return;
584 page_len = buf[3];
585 for (i = 4; i < MIN(sizeof(buf), page_len + 4); i++) {
586 if (buf[i] == 0xb0) {
587 s->needs_vpd_bl_emulation = false;
588 return;
591 s->needs_vpd_bl_emulation = true;
594 static void scsi_generic_read_device_identification(SCSIDevice *s)
596 uint8_t cmd[6];
597 uint8_t buf[250];
598 int ret;
599 int i, len;
601 memset(cmd, 0, sizeof(cmd));
602 memset(buf, 0, sizeof(buf));
603 cmd[0] = INQUIRY;
604 cmd[1] = 1;
605 cmd[2] = 0x83;
606 cmd[4] = sizeof(buf);
608 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
609 buf, sizeof(buf), s->io_timeout);
610 if (ret < 0) {
611 return;
614 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
615 for (i = 0; i + 3 <= len; ) {
616 const uint8_t *p = &buf[i + 4];
617 uint64_t wwn;
619 if (i + (p[3] + 4) > len) {
620 break;
623 if ((p[1] & 0x10) == 0) {
624 /* Associated with the logical unit */
625 if (read_naa_id(p, &wwn) == 0) {
626 s->wwn = wwn;
628 } else if ((p[1] & 0x10) == 0x10) {
629 /* Associated with the target port */
630 if (read_naa_id(p, &wwn) == 0) {
631 s->port_wwn = wwn;
635 i += p[3] + 4;
639 void scsi_generic_read_device_inquiry(SCSIDevice *s)
641 scsi_generic_read_device_identification(s);
642 if (s->type == TYPE_DISK || s->type == TYPE_ZBC) {
643 scsi_generic_set_vpd_bl_emulation(s);
644 } else {
645 s->needs_vpd_bl_emulation = false;
649 static int get_stream_blocksize(BlockBackend *blk)
651 uint8_t cmd[6];
652 uint8_t buf[12];
653 int ret;
655 memset(cmd, 0, sizeof(cmd));
656 memset(buf, 0, sizeof(buf));
657 cmd[0] = MODE_SENSE;
658 cmd[4] = sizeof(buf);
660 ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6);
661 if (ret < 0) {
662 return -1;
665 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
668 static void scsi_generic_reset(DeviceState *dev)
670 SCSIDevice *s = SCSI_DEVICE(dev);
672 s->scsi_version = s->default_scsi_version;
673 scsi_device_purge_requests(s, SENSE_CODE(RESET));
676 static void scsi_generic_realize(SCSIDevice *s, Error **errp)
678 int rc;
679 int sg_version;
680 struct sg_scsi_id scsiid;
682 if (!s->conf.blk) {
683 error_setg(errp, "drive property not set");
684 return;
687 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC &&
688 blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) {
689 error_setg(errp, "Device doesn't support drive option werror");
690 return;
692 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
693 error_setg(errp, "Device doesn't support drive option rerror");
694 return;
697 /* check we are using a driver managing SG_IO (version 3 and after */
698 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
699 if (rc < 0) {
700 error_setg_errno(errp, -rc, "cannot get SG_IO version number");
701 if (rc != -EPERM) {
702 error_append_hint(errp, "Is this a SCSI device?\n");
704 return;
706 if (sg_version < 30000) {
707 error_setg(errp, "scsi generic interface too old");
708 return;
711 /* get LUN of the /dev/sg? */
712 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
713 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
714 return;
716 if (!blkconf_apply_backend_options(&s->conf,
717 !blk_supports_write_perm(s->conf.blk),
718 true, errp)) {
719 return;
722 /* define device state */
723 s->type = scsiid.scsi_type;
724 trace_scsi_generic_realize_type(s->type);
726 switch (s->type) {
727 case TYPE_TAPE:
728 s->blocksize = get_stream_blocksize(s->conf.blk);
729 if (s->blocksize == -1) {
730 s->blocksize = 0;
732 break;
734 /* Make a guess for block devices, we'll fix it when the guest sends.
735 * READ CAPACITY. If they don't, they likely would assume these sizes
736 * anyway. (TODO: they could also send MODE SENSE).
738 case TYPE_ROM:
739 case TYPE_WORM:
740 s->blocksize = 2048;
741 break;
742 default:
743 s->blocksize = 512;
744 break;
747 trace_scsi_generic_realize_blocksize(s->blocksize);
749 /* Only used by scsi-block, but initialize it nevertheless to be clean. */
750 s->default_scsi_version = -1;
751 s->io_timeout = DEFAULT_IO_TIMEOUT;
752 scsi_generic_read_device_inquiry(s);
755 const SCSIReqOps scsi_generic_req_ops = {
756 .size = sizeof(SCSIGenericReq),
757 .free_req = scsi_free_request,
758 .send_command = scsi_send_command,
759 .read_data = scsi_read_data,
760 .write_data = scsi_write_data,
761 .get_buf = scsi_get_buf,
762 .load_request = scsi_generic_load_request,
763 .save_request = scsi_generic_save_request,
766 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
767 uint8_t *buf, void *hba_private)
769 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
772 static Property scsi_generic_properties[] = {
773 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
774 DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
775 DEFINE_PROP_UINT32("io_timeout", SCSIDevice, io_timeout,
776 DEFAULT_IO_TIMEOUT),
777 DEFINE_PROP_END_OF_LIST(),
780 static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
781 uint8_t *buf, void *hba_private)
783 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
786 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
788 DeviceClass *dc = DEVICE_CLASS(klass);
789 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
791 sc->realize = scsi_generic_realize;
792 sc->alloc_req = scsi_new_request;
793 sc->parse_cdb = scsi_generic_parse_cdb;
794 dc->fw_name = "disk";
795 dc->desc = "pass through generic scsi device (/dev/sg*)";
796 dc->reset = scsi_generic_reset;
797 device_class_set_props(dc, scsi_generic_properties);
798 dc->vmsd = &vmstate_scsi_device;
801 static const TypeInfo scsi_generic_info = {
802 .name = "scsi-generic",
803 .parent = TYPE_SCSI_DEVICE,
804 .instance_size = sizeof(SCSIDevice),
805 .class_init = scsi_generic_class_initfn,
808 static void scsi_generic_register_types(void)
810 type_register_static(&scsi_generic_info);
813 type_init(scsi_generic_register_types)
815 #endif /* __linux__ */