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"
30 #include "scsi/constants.h"
33 #define MAX_UINT ((unsigned int)-1)
36 typedef struct SCSIGenericReq
{
41 sg_io_hdr_t io_header
;
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
) {
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
) {
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
);
73 /* Helper function for command completion. */
74 static void scsi_command_complete_noio(SCSIGenericReq
*r
, int ret
)
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
);
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
);
94 } else if (io_hdr
->driver_status
& SG_ERR_DRIVER_TIMEOUT
) {
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
);
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
);
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
) {
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
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];
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];
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
)
225 SCSIBlockLimits bl
= {
226 .max_io_sectors
= blk_get_max_transfer(s
->conf
.blk
) / s
->blocksize
229 memset(r
->buf
, 0, r
->buflen
);
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;
252 static void scsi_read_complete(void * opaque
, int ret
)
254 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
255 SCSIDevice
*s
= r
->req
.dev
;
258 assert(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
);
268 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
269 trace_scsi_generic_read_complete(r
->req
.tag
, len
);
273 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_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.
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
||
303 scsi_command_complete_noio(r
, 0);
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
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
) {
334 if (r
->req
.cmd
.buf
[0] == INQUIRY
) {
335 scsi_handle_inquiry_reply(r
, s
);
339 scsi_req_data(&r
->req
, len
);
340 scsi_req_unref(&r
->req
);
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
;
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
);
358 scsi_command_complete_noio(r
, 0);
362 ret
= execute_command(s
->conf
.blk
, r
, SG_DXFER_FROM_DEV
,
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
);
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
);
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
);
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
;
406 trace_scsi_generic_write_data(req
->tag
);
409 scsi_req_data(&r
->req
, r
->len
);
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
);
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
);
429 static void scsi_generic_command_dump(uint8_t *cmd
, int len
)
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
);
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
;
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) {
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
);
468 scsi_command_complete_noio(r
, ret
);
474 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
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
) {
484 return -r
->req
.cmd
.xfer
;
486 return r
->req
.cmd
.xfer
;
490 static int read_naa_id(const uint8_t *p
, uint64_t *p_wwn
)
494 if ((p
[1] & 0xF) == 3) {
495 /* NAA designator type */
499 *p_wwn
= ldq_be_p(p
+ 4);
503 if ((p
[1] & 0xF) == 8) {
504 /* SCSI name string designator type */
505 if (p
[3] < 20 || memcmp(&p
[4], "naa.", 4)) {
508 if (p
[3] > 20 && p
[24] != ',') {
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
;
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
;
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
);
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
)
565 memset(cmd
, 0, sizeof(cmd
));
566 memset(buf
, 0, sizeof(buf
));
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
);
576 * Do not assume anything if we can't retrieve the
577 * INQUIRY response to assert the VPD Block Limits
580 s
->needs_vpd_bl_emulation
= false;
585 for (i
= 4; i
< MIN(sizeof(buf
), page_len
+ 4); i
++) {
586 if (buf
[i
] == 0xb0) {
587 s
->needs_vpd_bl_emulation
= false;
591 s
->needs_vpd_bl_emulation
= true;
594 static void scsi_generic_read_device_identification(SCSIDevice
*s
)
601 memset(cmd
, 0, sizeof(cmd
));
602 memset(buf
, 0, sizeof(buf
));
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
);
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];
619 if (i
+ (p
[3] + 4) > len
) {
623 if ((p
[1] & 0x10) == 0) {
624 /* Associated with the logical unit */
625 if (read_naa_id(p
, &wwn
) == 0) {
628 } else if ((p
[1] & 0x10) == 0x10) {
629 /* Associated with the target port */
630 if (read_naa_id(p
, &wwn
) == 0) {
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
);
645 s
->needs_vpd_bl_emulation
= false;
649 static int get_stream_blocksize(BlockBackend
*blk
)
655 memset(cmd
, 0, sizeof(cmd
));
656 memset(buf
, 0, sizeof(buf
));
658 cmd
[4] = sizeof(buf
);
660 ret
= scsi_SG_IO_FROM_DEV(blk
, cmd
, sizeof(cmd
), buf
, sizeof(buf
), 6);
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
)
680 struct sg_scsi_id scsiid
;
683 error_setg(errp
, "drive property not set");
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");
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");
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
);
700 error_setg_errno(errp
, -rc
, "cannot get SG_IO version number");
702 error_append_hint(errp
, "Is this a SCSI device?\n");
706 if (sg_version
< 30000) {
707 error_setg(errp
, "scsi generic interface too old");
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");
716 if (!blkconf_apply_backend_options(&s
->conf
,
717 !blk_supports_write_perm(s
->conf
.blk
),
722 /* define device state */
723 s
->type
= scsiid
.scsi_type
;
724 trace_scsi_generic_realize_type(s
->type
);
728 s
->blocksize
= get_stream_blocksize(s
->conf
.blk
);
729 if (s
->blocksize
== -1) {
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).
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
,
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__ */