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"
16 #include "hw/scsi/scsi.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 "block/scsi.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
);
177 if (r
->req
.aiocb
== NULL
) {
184 static void scsi_read_complete(void * opaque
, int ret
)
186 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
187 SCSIDevice
*s
= r
->req
.dev
;
192 DPRINTF("IO error ret %d\n", ret
);
193 scsi_command_complete(r
, ret
);
196 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
197 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
201 scsi_command_complete(r
, 0);
203 /* Snoop READ CAPACITY output to set the blocksize. */
204 if (r
->req
.cmd
.buf
[0] == READ_CAPACITY_10
&&
205 (ldl_be_p(&r
->buf
[0]) != 0xffffffffU
|| s
->max_lba
== 0)) {
206 s
->blocksize
= ldl_be_p(&r
->buf
[4]);
207 s
->max_lba
= ldl_be_p(&r
->buf
[0]) & 0xffffffffULL
;
208 } else if (r
->req
.cmd
.buf
[0] == SERVICE_ACTION_IN_16
&&
209 (r
->req
.cmd
.buf
[1] & 31) == SAI_READ_CAPACITY_16
) {
210 s
->blocksize
= ldl_be_p(&r
->buf
[8]);
211 s
->max_lba
= ldq_be_p(&r
->buf
[0]);
213 bdrv_set_buffer_alignment(s
->conf
.bs
, s
->blocksize
);
215 scsi_req_data(&r
->req
, len
);
216 if (!r
->req
.io_canceled
) {
217 scsi_req_unref(&r
->req
);
222 /* Read more data from scsi device into buffer. */
223 static void scsi_read_data(SCSIRequest
*req
)
225 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
226 SCSIDevice
*s
= r
->req
.dev
;
229 DPRINTF("scsi_read_data 0x%x\n", req
->tag
);
231 /* The request is used as the AIO opaque value, so add a ref. */
232 scsi_req_ref(&r
->req
);
234 scsi_command_complete(r
, 0);
238 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
240 scsi_command_complete(r
, ret
);
244 static void scsi_write_complete(void * opaque
, int ret
)
246 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
247 SCSIDevice
*s
= r
->req
.dev
;
249 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
252 DPRINTF("IO error\n");
253 scsi_command_complete(r
, ret
);
257 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
258 s
->type
== TYPE_TAPE
) {
259 s
->blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
260 DPRINTF("block size %d\n", s
->blocksize
);
263 scsi_command_complete(r
, ret
);
266 /* Write data to a scsi device. Returns nonzero on failure.
267 The transfer may complete asynchronously. */
268 static void scsi_write_data(SCSIRequest
*req
)
270 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
271 SCSIDevice
*s
= r
->req
.dev
;
274 DPRINTF("scsi_write_data 0x%x\n", req
->tag
);
277 scsi_req_data(&r
->req
, r
->len
);
281 /* The request is used as the AIO opaque value, so add a ref. */
282 scsi_req_ref(&r
->req
);
283 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
285 scsi_command_complete(r
, ret
);
289 /* Return a pointer to the data buffer. */
290 static uint8_t *scsi_get_buf(SCSIRequest
*req
)
292 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
297 /* Execute a scsi command. Returns the length of the data expected by the
298 command. This will be Positive for data transfers from the device
299 (eg. disk reads), negative for transfers to the device (eg. disk writes),
300 and zero if the command does not transfer any data. */
302 static int32_t scsi_send_command(SCSIRequest
*req
, uint8_t *cmd
)
304 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
305 SCSIDevice
*s
= r
->req
.dev
;
308 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun
, tag
,
309 r
->req
.cmd
.xfer
, cmd
[0]);
314 for (i
= 1; i
< r
->req
.cmd
.len
; i
++) {
315 printf(" 0x%02x", cmd
[i
]);
321 if (r
->req
.cmd
.xfer
== 0) {
326 /* The request is used as the AIO opaque value, so add a ref. */
327 scsi_req_ref(&r
->req
);
328 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
330 scsi_command_complete(r
, ret
);
336 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
339 r
->buf
= g_malloc(r
->req
.cmd
.xfer
);
340 r
->buflen
= r
->req
.cmd
.xfer
;
343 memset(r
->buf
, 0, r
->buflen
);
344 r
->len
= r
->req
.cmd
.xfer
;
345 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
347 return -r
->req
.cmd
.xfer
;
349 return r
->req
.cmd
.xfer
;
353 static int get_stream_blocksize(BlockDriverState
*bdrv
)
358 sg_io_hdr_t io_header
;
361 memset(cmd
, 0, sizeof(cmd
));
362 memset(buf
, 0, sizeof(buf
));
364 cmd
[4] = sizeof(buf
);
366 memset(&io_header
, 0, sizeof(io_header
));
367 io_header
.interface_id
= 'S';
368 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
369 io_header
.dxfer_len
= sizeof(buf
);
370 io_header
.dxferp
= buf
;
371 io_header
.cmdp
= cmd
;
372 io_header
.cmd_len
= sizeof(cmd
);
373 io_header
.mx_sb_len
= sizeof(sensebuf
);
374 io_header
.sbp
= sensebuf
;
375 io_header
.timeout
= 6000; /* XXX */
377 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
378 if (ret
< 0 || io_header
.driver_status
|| io_header
.host_status
) {
381 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
384 static void scsi_generic_reset(DeviceState
*dev
)
386 SCSIDevice
*s
= SCSI_DEVICE(dev
);
388 scsi_device_purge_requests(s
, SENSE_CODE(RESET
));
391 static void scsi_destroy(SCSIDevice
*s
)
393 scsi_device_purge_requests(s
, SENSE_CODE(NO_SENSE
));
394 blockdev_mark_auto_del(s
->conf
.bs
);
397 static int scsi_generic_initfn(SCSIDevice
*s
)
400 struct sg_scsi_id scsiid
;
403 error_report("drive property not set");
407 if (bdrv_get_on_error(s
->conf
.bs
, 0) != BLOCKDEV_ON_ERROR_ENOSPC
) {
408 error_report("Device doesn't support drive option werror");
411 if (bdrv_get_on_error(s
->conf
.bs
, 1) != BLOCKDEV_ON_ERROR_REPORT
) {
412 error_report("Device doesn't support drive option rerror");
416 /* check we are using a driver managing SG_IO (version 3 and after */
417 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_VERSION_NUM
, &sg_version
) < 0) {
418 error_report("scsi generic interface not supported");
421 if (sg_version
< 30000) {
422 error_report("scsi generic interface too old");
426 /* get LUN of the /dev/sg? */
427 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_SCSI_ID
, &scsiid
)) {
428 error_report("SG_GET_SCSI_ID ioctl failed");
432 /* define device state */
433 s
->type
= scsiid
.scsi_type
;
434 DPRINTF("device type %d\n", s
->type
);
435 if (s
->type
== TYPE_DISK
|| s
->type
== TYPE_ROM
) {
436 add_boot_device_path(s
->conf
.bootindex
, &s
->qdev
, NULL
);
441 s
->blocksize
= get_stream_blocksize(s
->conf
.bs
);
442 if (s
->blocksize
== -1) {
447 /* Make a guess for block devices, we'll fix it when the guest sends.
448 * READ CAPACITY. If they don't, they likely would assume these sizes
449 * anyway. (TODO: they could also send MODE SENSE).
460 DPRINTF("block size %d\n", s
->blocksize
);
464 const SCSIReqOps scsi_generic_req_ops
= {
465 .size
= sizeof(SCSIGenericReq
),
466 .free_req
= scsi_free_request
,
467 .send_command
= scsi_send_command
,
468 .read_data
= scsi_read_data
,
469 .write_data
= scsi_write_data
,
470 .cancel_io
= scsi_cancel_io
,
471 .get_buf
= scsi_get_buf
,
472 .load_request
= scsi_generic_load_request
,
473 .save_request
= scsi_generic_save_request
,
476 static SCSIRequest
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
,
477 uint8_t *buf
, void *hba_private
)
481 req
= scsi_req_alloc(&scsi_generic_req_ops
, d
, tag
, lun
, hba_private
);
485 static Property scsi_generic_properties
[] = {
486 DEFINE_PROP_DRIVE("drive", SCSIDevice
, conf
.bs
),
487 DEFINE_PROP_INT32("bootindex", SCSIDevice
, conf
.bootindex
, -1),
488 DEFINE_PROP_END_OF_LIST(),
491 static void scsi_generic_class_initfn(ObjectClass
*klass
, void *data
)
493 DeviceClass
*dc
= DEVICE_CLASS(klass
);
494 SCSIDeviceClass
*sc
= SCSI_DEVICE_CLASS(klass
);
496 sc
->init
= scsi_generic_initfn
;
497 sc
->destroy
= scsi_destroy
;
498 sc
->alloc_req
= scsi_new_request
;
499 dc
->fw_name
= "disk";
500 dc
->desc
= "pass through generic scsi device (/dev/sg*)";
501 dc
->reset
= scsi_generic_reset
;
502 dc
->props
= scsi_generic_properties
;
503 dc
->vmsd
= &vmstate_scsi_device
;
506 static const TypeInfo scsi_generic_info
= {
507 .name
= "scsi-generic",
508 .parent
= TYPE_SCSI_DEVICE
,
509 .instance_size
= sizeof(SCSIDevice
),
510 .class_init
= scsi_generic_class_initfn
,
513 static void scsi_generic_register_types(void)
515 type_register_static(&scsi_generic_info
);
518 type_init(scsi_generic_register_types
)
520 #endif /* __linux__ */