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 SG_ERR_DRIVER_TIMEOUT 0x06
41 #define SG_ERR_DRIVER_SENSE 0x08
43 #define SG_ERR_DID_OK 0x00
44 #define SG_ERR_DID_NO_CONNECT 0x01
45 #define SG_ERR_DID_BUS_BUSY 0x02
46 #define SG_ERR_DID_TIME_OUT 0x03
49 #define MAX_UINT ((unsigned int)-1)
52 typedef struct SCSIGenericReq
{
57 sg_io_hdr_t io_header
;
60 static void scsi_generic_save_request(QEMUFile
*f
, SCSIRequest
*req
)
62 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
64 qemu_put_sbe32s(f
, &r
->buflen
);
65 if (r
->buflen
&& r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
67 qemu_put_buffer(f
, r
->buf
, r
->req
.cmd
.xfer
);
71 static void scsi_generic_load_request(QEMUFile
*f
, SCSIRequest
*req
)
73 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
75 qemu_get_sbe32s(f
, &r
->buflen
);
76 if (r
->buflen
&& r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
78 qemu_get_buffer(f
, r
->buf
, r
->req
.cmd
.xfer
);
82 static void scsi_free_request(SCSIRequest
*req
)
84 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
89 /* Helper function for command completion. */
90 static void scsi_command_complete(void *opaque
, int ret
)
93 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
96 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
97 r
->req
.sense_len
= r
->io_header
.sb_len_wr
;
103 status
= TASK_SET_FULL
;
106 status
= CHECK_CONDITION
;
107 scsi_req_build_sense(&r
->req
, SENSE_CODE(TARGET_FAILURE
));
110 status
= CHECK_CONDITION
;
111 scsi_req_build_sense(&r
->req
, SENSE_CODE(IO_ERROR
));
115 if (r
->io_header
.host_status
== SG_ERR_DID_NO_CONNECT
||
116 r
->io_header
.host_status
== SG_ERR_DID_BUS_BUSY
||
117 r
->io_header
.host_status
== SG_ERR_DID_TIME_OUT
||
118 (r
->io_header
.driver_status
& SG_ERR_DRIVER_TIMEOUT
)) {
120 BADF("Driver Timeout\n");
121 } else if (r
->io_header
.host_status
) {
122 status
= CHECK_CONDITION
;
123 scsi_req_build_sense(&r
->req
, SENSE_CODE(I_T_NEXUS_LOSS
));
124 } else if (r
->io_header
.status
) {
125 status
= r
->io_header
.status
;
126 } else if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
127 status
= CHECK_CONDITION
;
132 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
133 r
, r
->req
.tag
, status
);
135 scsi_req_complete(&r
->req
, status
);
136 if (!r
->req
.io_canceled
) {
137 scsi_req_unref(&r
->req
);
141 /* Cancel a pending data transfer. */
142 static void scsi_cancel_io(SCSIRequest
*req
)
144 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
146 DPRINTF("Cancel tag=0x%x\n", req
->tag
);
148 bdrv_aio_cancel(r
->req
.aiocb
);
150 /* This reference was left in by scsi_*_data. We take ownership of
151 * it independent of whether bdrv_aio_cancel completes the request
153 scsi_req_unref(&r
->req
);
158 static int execute_command(BlockDriverState
*bdrv
,
159 SCSIGenericReq
*r
, int direction
,
160 BlockDriverCompletionFunc
*complete
)
162 r
->io_header
.interface_id
= 'S';
163 r
->io_header
.dxfer_direction
= direction
;
164 r
->io_header
.dxferp
= r
->buf
;
165 r
->io_header
.dxfer_len
= r
->buflen
;
166 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
167 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
168 r
->io_header
.mx_sb_len
= sizeof(r
->req
.sense
);
169 r
->io_header
.sbp
= r
->req
.sense
;
170 r
->io_header
.timeout
= MAX_UINT
;
171 r
->io_header
.usr_ptr
= r
;
172 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
174 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
175 if (r
->req
.aiocb
== NULL
) {
182 static void scsi_read_complete(void * opaque
, int ret
)
184 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
185 SCSIDevice
*s
= r
->req
.dev
;
190 DPRINTF("IO error ret %d\n", ret
);
191 scsi_command_complete(r
, ret
);
194 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
195 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
199 scsi_command_complete(r
, 0);
201 /* Snoop READ CAPACITY output to set the blocksize. */
202 if (r
->req
.cmd
.buf
[0] == READ_CAPACITY_10
&&
203 (ldl_be_p(&r
->buf
[0]) != 0xffffffffU
|| s
->max_lba
== 0)) {
204 s
->blocksize
= ldl_be_p(&r
->buf
[4]);
205 s
->max_lba
= ldl_be_p(&r
->buf
[0]) & 0xffffffffULL
;
206 } else if (r
->req
.cmd
.buf
[0] == SERVICE_ACTION_IN_16
&&
207 (r
->req
.cmd
.buf
[1] & 31) == SAI_READ_CAPACITY_16
) {
208 s
->blocksize
= ldl_be_p(&r
->buf
[8]);
209 s
->max_lba
= ldq_be_p(&r
->buf
[0]);
211 bdrv_set_guest_block_size(s
->conf
.bs
, s
->blocksize
);
213 scsi_req_data(&r
->req
, len
);
214 if (!r
->req
.io_canceled
) {
215 scsi_req_unref(&r
->req
);
220 /* Read more data from scsi device into buffer. */
221 static void scsi_read_data(SCSIRequest
*req
)
223 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
224 SCSIDevice
*s
= r
->req
.dev
;
227 DPRINTF("scsi_read_data 0x%x\n", req
->tag
);
229 /* The request is used as the AIO opaque value, so add a ref. */
230 scsi_req_ref(&r
->req
);
232 scsi_command_complete(r
, 0);
236 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
238 scsi_command_complete(r
, ret
);
242 static void scsi_write_complete(void * opaque
, int ret
)
244 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
245 SCSIDevice
*s
= r
->req
.dev
;
247 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
250 DPRINTF("IO error\n");
251 scsi_command_complete(r
, ret
);
255 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
256 s
->type
== TYPE_TAPE
) {
257 s
->blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
258 DPRINTF("block size %d\n", s
->blocksize
);
261 scsi_command_complete(r
, ret
);
264 /* Write data to a scsi device. Returns nonzero on failure.
265 The transfer may complete asynchronously. */
266 static void scsi_write_data(SCSIRequest
*req
)
268 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
269 SCSIDevice
*s
= r
->req
.dev
;
272 DPRINTF("scsi_write_data 0x%x\n", req
->tag
);
275 scsi_req_data(&r
->req
, r
->len
);
279 /* The request is used as the AIO opaque value, so add a ref. */
280 scsi_req_ref(&r
->req
);
281 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
283 scsi_command_complete(r
, ret
);
287 /* Return a pointer to the data buffer. */
288 static uint8_t *scsi_get_buf(SCSIRequest
*req
)
290 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
295 /* Execute a scsi command. Returns the length of the data expected by the
296 command. This will be Positive for data transfers from the device
297 (eg. disk reads), negative for transfers to the device (eg. disk writes),
298 and zero if the command does not transfer any data. */
300 static int32_t scsi_send_command(SCSIRequest
*req
, uint8_t *cmd
)
302 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
303 SCSIDevice
*s
= r
->req
.dev
;
306 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun
, tag
,
307 r
->req
.cmd
.xfer
, cmd
[0]);
312 for (i
= 1; i
< r
->req
.cmd
.len
; i
++) {
313 printf(" 0x%02x", cmd
[i
]);
319 if (r
->req
.cmd
.xfer
== 0) {
324 /* The request is used as the AIO opaque value, so add a ref. */
325 scsi_req_ref(&r
->req
);
326 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
328 scsi_command_complete(r
, ret
);
334 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
337 r
->buf
= g_malloc(r
->req
.cmd
.xfer
);
338 r
->buflen
= r
->req
.cmd
.xfer
;
341 memset(r
->buf
, 0, r
->buflen
);
342 r
->len
= r
->req
.cmd
.xfer
;
343 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
345 return -r
->req
.cmd
.xfer
;
347 return r
->req
.cmd
.xfer
;
351 static int get_stream_blocksize(BlockDriverState
*bdrv
)
356 sg_io_hdr_t io_header
;
359 memset(cmd
, 0, sizeof(cmd
));
360 memset(buf
, 0, sizeof(buf
));
362 cmd
[4] = sizeof(buf
);
364 memset(&io_header
, 0, sizeof(io_header
));
365 io_header
.interface_id
= 'S';
366 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
367 io_header
.dxfer_len
= sizeof(buf
);
368 io_header
.dxferp
= buf
;
369 io_header
.cmdp
= cmd
;
370 io_header
.cmd_len
= sizeof(cmd
);
371 io_header
.mx_sb_len
= sizeof(sensebuf
);
372 io_header
.sbp
= sensebuf
;
373 io_header
.timeout
= 6000; /* XXX */
375 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
376 if (ret
< 0 || io_header
.driver_status
|| io_header
.host_status
) {
379 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
382 static void scsi_generic_reset(DeviceState
*dev
)
384 SCSIDevice
*s
= SCSI_DEVICE(dev
);
386 scsi_device_purge_requests(s
, SENSE_CODE(RESET
));
389 static void scsi_destroy(SCSIDevice
*s
)
391 scsi_device_purge_requests(s
, SENSE_CODE(NO_SENSE
));
392 blockdev_mark_auto_del(s
->conf
.bs
);
395 static int scsi_generic_initfn(SCSIDevice
*s
)
399 struct sg_scsi_id scsiid
;
402 error_report("drive property not set");
406 if (bdrv_get_on_error(s
->conf
.bs
, 0) != BLOCKDEV_ON_ERROR_ENOSPC
) {
407 error_report("Device doesn't support drive option werror");
410 if (bdrv_get_on_error(s
->conf
.bs
, 1) != BLOCKDEV_ON_ERROR_REPORT
) {
411 error_report("Device doesn't support drive option rerror");
415 /* check we are using a driver managing SG_IO (version 3 and after */
416 rc
= bdrv_ioctl(s
->conf
.bs
, SG_GET_VERSION_NUM
, &sg_version
);
418 error_report("cannot get SG_IO version number: %s. "
419 "Is this a SCSI device?",
423 if (sg_version
< 30000) {
424 error_report("scsi generic interface too old");
428 /* get LUN of the /dev/sg? */
429 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_SCSI_ID
, &scsiid
)) {
430 error_report("SG_GET_SCSI_ID ioctl failed");
434 /* define device state */
435 s
->type
= scsiid
.scsi_type
;
436 DPRINTF("device type %d\n", s
->type
);
437 if (s
->type
== TYPE_DISK
|| s
->type
== TYPE_ROM
) {
438 add_boot_device_path(s
->conf
.bootindex
, &s
->qdev
, NULL
);
443 s
->blocksize
= get_stream_blocksize(s
->conf
.bs
);
444 if (s
->blocksize
== -1) {
449 /* Make a guess for block devices, we'll fix it when the guest sends.
450 * READ CAPACITY. If they don't, they likely would assume these sizes
451 * anyway. (TODO: they could also send MODE SENSE).
462 DPRINTF("block size %d\n", s
->blocksize
);
466 const SCSIReqOps scsi_generic_req_ops
= {
467 .size
= sizeof(SCSIGenericReq
),
468 .free_req
= scsi_free_request
,
469 .send_command
= scsi_send_command
,
470 .read_data
= scsi_read_data
,
471 .write_data
= scsi_write_data
,
472 .cancel_io
= scsi_cancel_io
,
473 .get_buf
= scsi_get_buf
,
474 .load_request
= scsi_generic_load_request
,
475 .save_request
= scsi_generic_save_request
,
478 static SCSIRequest
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
,
479 uint8_t *buf
, void *hba_private
)
483 req
= scsi_req_alloc(&scsi_generic_req_ops
, d
, tag
, lun
, hba_private
);
487 static Property scsi_generic_properties
[] = {
488 DEFINE_PROP_DRIVE("drive", SCSIDevice
, conf
.bs
),
489 DEFINE_PROP_INT32("bootindex", SCSIDevice
, conf
.bootindex
, -1),
490 DEFINE_PROP_END_OF_LIST(),
493 static void scsi_generic_class_initfn(ObjectClass
*klass
, void *data
)
495 DeviceClass
*dc
= DEVICE_CLASS(klass
);
496 SCSIDeviceClass
*sc
= SCSI_DEVICE_CLASS(klass
);
498 sc
->init
= scsi_generic_initfn
;
499 sc
->destroy
= scsi_destroy
;
500 sc
->alloc_req
= scsi_new_request
;
501 dc
->fw_name
= "disk";
502 dc
->desc
= "pass through generic scsi device (/dev/sg*)";
503 dc
->reset
= scsi_generic_reset
;
504 dc
->props
= scsi_generic_properties
;
505 dc
->vmsd
= &vmstate_scsi_device
;
508 static const TypeInfo scsi_generic_info
= {
509 .name
= "scsi-generic",
510 .parent
= TYPE_SCSI_DEVICE
,
511 .instance_size
= sizeof(SCSIDevice
),
512 .class_init
= scsi_generic_class_initfn
,
515 static void scsi_generic_register_types(void)
517 type_register_static(&scsi_generic_info
);
520 type_init(scsi_generic_register_types
)
522 #endif /* __linux__ */