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-common.h"
15 #include "qemu/error-report.h"
17 #include "sysemu/blockdev.h"
24 #define DPRINTF(fmt, ...) \
25 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
27 #define DPRINTF(fmt, ...) do {} while(0)
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
34 #include <sys/types.h>
38 #include "scsi-defs.h"
40 #define SCSI_SENSE_BUF_SIZE 96
42 #define SG_ERR_DRIVER_TIMEOUT 0x06
43 #define SG_ERR_DRIVER_SENSE 0x08
45 #define SG_ERR_DID_OK 0x00
46 #define SG_ERR_DID_NO_CONNECT 0x01
47 #define SG_ERR_DID_BUS_BUSY 0x02
48 #define SG_ERR_DID_TIME_OUT 0x03
51 #define MAX_UINT ((unsigned int)-1)
54 typedef struct SCSIGenericReq
{
59 sg_io_hdr_t io_header
;
62 static void scsi_generic_save_request(QEMUFile
*f
, SCSIRequest
*req
)
64 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
66 qemu_put_sbe32s(f
, &r
->buflen
);
67 if (r
->buflen
&& r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
69 qemu_put_buffer(f
, r
->buf
, r
->req
.cmd
.xfer
);
73 static void scsi_generic_load_request(QEMUFile
*f
, SCSIRequest
*req
)
75 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
77 qemu_get_sbe32s(f
, &r
->buflen
);
78 if (r
->buflen
&& r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
80 qemu_get_buffer(f
, r
->buf
, r
->req
.cmd
.xfer
);
84 static void scsi_free_request(SCSIRequest
*req
)
86 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
91 /* Helper function for command completion. */
92 static void scsi_command_complete(void *opaque
, int ret
)
95 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
98 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
99 r
->req
.sense_len
= r
->io_header
.sb_len_wr
;
105 status
= TASK_SET_FULL
;
108 status
= CHECK_CONDITION
;
109 scsi_req_build_sense(&r
->req
, SENSE_CODE(TARGET_FAILURE
));
112 status
= CHECK_CONDITION
;
113 scsi_req_build_sense(&r
->req
, SENSE_CODE(IO_ERROR
));
117 if (r
->io_header
.host_status
== SG_ERR_DID_NO_CONNECT
||
118 r
->io_header
.host_status
== SG_ERR_DID_BUS_BUSY
||
119 r
->io_header
.host_status
== SG_ERR_DID_TIME_OUT
||
120 (r
->io_header
.driver_status
& SG_ERR_DRIVER_TIMEOUT
)) {
122 BADF("Driver Timeout\n");
123 } else if (r
->io_header
.host_status
) {
124 status
= CHECK_CONDITION
;
125 scsi_req_build_sense(&r
->req
, SENSE_CODE(I_T_NEXUS_LOSS
));
126 } else if (r
->io_header
.status
) {
127 status
= r
->io_header
.status
;
128 } else if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
129 status
= CHECK_CONDITION
;
134 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135 r
, r
->req
.tag
, status
);
137 scsi_req_complete(&r
->req
, status
);
138 if (!r
->req
.io_canceled
) {
139 scsi_req_unref(&r
->req
);
143 /* Cancel a pending data transfer. */
144 static void scsi_cancel_io(SCSIRequest
*req
)
146 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
148 DPRINTF("Cancel tag=0x%x\n", req
->tag
);
150 bdrv_aio_cancel(r
->req
.aiocb
);
152 /* This reference was left in by scsi_*_data. We take ownership of
153 * it independent of whether bdrv_aio_cancel completes the request
155 scsi_req_unref(&r
->req
);
160 static int execute_command(BlockDriverState
*bdrv
,
161 SCSIGenericReq
*r
, int direction
,
162 BlockDriverCompletionFunc
*complete
)
164 r
->io_header
.interface_id
= 'S';
165 r
->io_header
.dxfer_direction
= direction
;
166 r
->io_header
.dxferp
= r
->buf
;
167 r
->io_header
.dxfer_len
= r
->buflen
;
168 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
169 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
170 r
->io_header
.mx_sb_len
= sizeof(r
->req
.sense
);
171 r
->io_header
.sbp
= r
->req
.sense
;
172 r
->io_header
.timeout
= MAX_UINT
;
173 r
->io_header
.usr_ptr
= r
;
174 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
176 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
181 static void scsi_read_complete(void * opaque
, int ret
)
183 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
184 SCSIDevice
*s
= r
->req
.dev
;
189 DPRINTF("IO error ret %d\n", ret
);
190 scsi_command_complete(r
, ret
);
193 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
194 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
198 scsi_command_complete(r
, 0);
200 /* Snoop READ CAPACITY output to set the blocksize. */
201 if (r
->req
.cmd
.buf
[0] == READ_CAPACITY_10
) {
202 s
->blocksize
= ldl_be_p(&r
->buf
[4]);
203 s
->max_lba
= ldl_be_p(&r
->buf
[0]);
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]);
209 bdrv_set_buffer_alignment(s
->conf
.bs
, s
->blocksize
);
211 scsi_req_data(&r
->req
, len
);
212 if (!r
->req
.io_canceled
) {
213 scsi_req_unref(&r
->req
);
218 /* Read more data from scsi device into buffer. */
219 static void scsi_read_data(SCSIRequest
*req
)
221 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
222 SCSIDevice
*s
= r
->req
.dev
;
225 DPRINTF("scsi_read_data 0x%x\n", req
->tag
);
227 /* The request is used as the AIO opaque value, so add a ref. */
228 scsi_req_ref(&r
->req
);
230 scsi_command_complete(r
, 0);
234 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
236 scsi_command_complete(r
, ret
);
240 static void scsi_write_complete(void * opaque
, int ret
)
242 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
243 SCSIDevice
*s
= r
->req
.dev
;
245 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
248 DPRINTF("IO error\n");
249 scsi_command_complete(r
, ret
);
253 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
254 s
->type
== TYPE_TAPE
) {
255 s
->blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
256 DPRINTF("block size %d\n", s
->blocksize
);
259 scsi_command_complete(r
, ret
);
262 /* Write data to a scsi device. Returns nonzero on failure.
263 The transfer may complete asynchronously. */
264 static void scsi_write_data(SCSIRequest
*req
)
266 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
267 SCSIDevice
*s
= r
->req
.dev
;
270 DPRINTF("scsi_write_data 0x%x\n", req
->tag
);
273 scsi_req_data(&r
->req
, r
->len
);
277 /* The request is used as the AIO opaque value, so add a ref. */
278 scsi_req_ref(&r
->req
);
279 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
281 scsi_command_complete(r
, ret
);
285 /* Return a pointer to the data buffer. */
286 static uint8_t *scsi_get_buf(SCSIRequest
*req
)
288 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
293 /* Execute a scsi command. Returns the length of the data expected by the
294 command. This will be Positive for data transfers from the device
295 (eg. disk reads), negative for transfers to the device (eg. disk writes),
296 and zero if the command does not transfer any data. */
298 static int32_t scsi_send_command(SCSIRequest
*req
, uint8_t *cmd
)
300 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
301 SCSIDevice
*s
= r
->req
.dev
;
304 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun
, tag
,
305 r
->req
.cmd
.xfer
, cmd
[0]);
310 for (i
= 1; i
< r
->req
.cmd
.len
; i
++) {
311 printf(" 0x%02x", cmd
[i
]);
317 if (r
->req
.cmd
.xfer
== 0) {
322 /* The request is used as the AIO opaque value, so add a ref. */
323 scsi_req_ref(&r
->req
);
324 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
326 scsi_command_complete(r
, ret
);
332 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
335 r
->buf
= g_malloc(r
->req
.cmd
.xfer
);
336 r
->buflen
= r
->req
.cmd
.xfer
;
339 memset(r
->buf
, 0, r
->buflen
);
340 r
->len
= r
->req
.cmd
.xfer
;
341 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
343 return -r
->req
.cmd
.xfer
;
345 return r
->req
.cmd
.xfer
;
349 static int get_stream_blocksize(BlockDriverState
*bdrv
)
354 sg_io_hdr_t io_header
;
357 memset(cmd
, 0, sizeof(cmd
));
358 memset(buf
, 0, sizeof(buf
));
360 cmd
[4] = sizeof(buf
);
362 memset(&io_header
, 0, sizeof(io_header
));
363 io_header
.interface_id
= 'S';
364 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
365 io_header
.dxfer_len
= sizeof(buf
);
366 io_header
.dxferp
= buf
;
367 io_header
.cmdp
= cmd
;
368 io_header
.cmd_len
= sizeof(cmd
);
369 io_header
.mx_sb_len
= sizeof(sensebuf
);
370 io_header
.sbp
= sensebuf
;
371 io_header
.timeout
= 6000; /* XXX */
373 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
374 if (ret
< 0 || io_header
.driver_status
|| io_header
.host_status
) {
377 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
380 static void scsi_generic_reset(DeviceState
*dev
)
382 SCSIDevice
*s
= SCSI_DEVICE(dev
);
384 scsi_device_purge_requests(s
, SENSE_CODE(RESET
));
387 static void scsi_destroy(SCSIDevice
*s
)
389 scsi_device_purge_requests(s
, SENSE_CODE(NO_SENSE
));
390 blockdev_mark_auto_del(s
->conf
.bs
);
393 static int scsi_generic_initfn(SCSIDevice
*s
)
396 struct sg_scsi_id scsiid
;
399 error_report("drive property not set");
403 if (bdrv_get_on_error(s
->conf
.bs
, 0) != BLOCKDEV_ON_ERROR_ENOSPC
) {
404 error_report("Device doesn't support drive option werror");
407 if (bdrv_get_on_error(s
->conf
.bs
, 1) != BLOCKDEV_ON_ERROR_REPORT
) {
408 error_report("Device doesn't support drive option rerror");
412 /* check we are using a driver managing SG_IO (version 3 and after */
413 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_VERSION_NUM
, &sg_version
) < 0) {
414 error_report("scsi generic interface not supported");
417 if (sg_version
< 30000) {
418 error_report("scsi generic interface too old");
422 /* get LUN of the /dev/sg? */
423 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_SCSI_ID
, &scsiid
)) {
424 error_report("SG_GET_SCSI_ID ioctl failed");
428 /* define device state */
429 s
->type
= scsiid
.scsi_type
;
430 DPRINTF("device type %d\n", s
->type
);
431 if (s
->type
== TYPE_DISK
|| s
->type
== TYPE_ROM
) {
432 add_boot_device_path(s
->conf
.bootindex
, &s
->qdev
, NULL
);
437 s
->blocksize
= get_stream_blocksize(s
->conf
.bs
);
438 if (s
->blocksize
== -1) {
443 /* Make a guess for block devices, we'll fix it when the guest sends.
444 * READ CAPACITY. If they don't, they likely would assume these sizes
445 * anyway. (TODO: they could also send MODE SENSE).
456 DPRINTF("block size %d\n", s
->blocksize
);
460 const SCSIReqOps scsi_generic_req_ops
= {
461 .size
= sizeof(SCSIGenericReq
),
462 .free_req
= scsi_free_request
,
463 .send_command
= scsi_send_command
,
464 .read_data
= scsi_read_data
,
465 .write_data
= scsi_write_data
,
466 .cancel_io
= scsi_cancel_io
,
467 .get_buf
= scsi_get_buf
,
468 .load_request
= scsi_generic_load_request
,
469 .save_request
= scsi_generic_save_request
,
472 static SCSIRequest
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
,
473 uint8_t *buf
, void *hba_private
)
477 req
= scsi_req_alloc(&scsi_generic_req_ops
, d
, tag
, lun
, hba_private
);
481 static Property scsi_generic_properties
[] = {
482 DEFINE_PROP_DRIVE("drive", SCSIDevice
, conf
.bs
),
483 DEFINE_PROP_INT32("bootindex", SCSIDevice
, conf
.bootindex
, -1),
484 DEFINE_PROP_END_OF_LIST(),
487 static void scsi_generic_class_initfn(ObjectClass
*klass
, void *data
)
489 DeviceClass
*dc
= DEVICE_CLASS(klass
);
490 SCSIDeviceClass
*sc
= SCSI_DEVICE_CLASS(klass
);
492 sc
->init
= scsi_generic_initfn
;
493 sc
->destroy
= scsi_destroy
;
494 sc
->alloc_req
= scsi_new_request
;
495 dc
->fw_name
= "disk";
496 dc
->desc
= "pass through generic scsi device (/dev/sg*)";
497 dc
->reset
= scsi_generic_reset
;
498 dc
->props
= scsi_generic_properties
;
499 dc
->vmsd
= &vmstate_scsi_device
;
502 static const TypeInfo scsi_generic_info
= {
503 .name
= "scsi-generic",
504 .parent
= TYPE_SCSI_DEVICE
,
505 .instance_size
= sizeof(SCSIDevice
),
506 .class_init
= scsi_generic_class_initfn
,
509 static void scsi_generic_register_types(void)
511 type_register_static(&scsi_generic_info
);
514 type_init(scsi_generic_register_types
)
516 #endif /* __linux__ */