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.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
46 #define MAX_UINT ((unsigned int)-1)
49 typedef struct SCSIGenericState SCSIGenericState
;
51 typedef struct SCSIGenericReq
{
56 sg_io_hdr_t io_header
;
59 struct SCSIGenericState
65 static void scsi_free_request(SCSIRequest
*req
)
67 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
72 /* Helper function for command completion. */
73 static void scsi_command_complete(void *opaque
, int ret
)
76 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
79 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
)
80 r
->req
.sense_len
= r
->io_header
.sb_len_wr
;
85 status
= TASK_SET_FULL
;
88 status
= CHECK_CONDITION
;
89 scsi_req_build_sense(&r
->req
, SENSE_CODE(TARGET_FAILURE
));
92 status
= CHECK_CONDITION
;
93 scsi_req_build_sense(&r
->req
, SENSE_CODE(IO_ERROR
));
97 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_TIMEOUT
) {
99 BADF("Driver Timeout\n");
100 } else if (r
->io_header
.status
) {
101 status
= r
->io_header
.status
;
102 } else if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
103 status
= CHECK_CONDITION
;
108 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
109 r
, r
->req
.tag
, status
);
111 scsi_req_complete(&r
->req
, status
);
114 /* Cancel a pending data transfer. */
115 static void scsi_cancel_io(SCSIRequest
*req
)
117 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
119 DPRINTF("Cancel tag=0x%x\n", req
->tag
);
121 bdrv_aio_cancel(r
->req
.aiocb
);
126 static int execute_command(BlockDriverState
*bdrv
,
127 SCSIGenericReq
*r
, int direction
,
128 BlockDriverCompletionFunc
*complete
)
130 r
->io_header
.interface_id
= 'S';
131 r
->io_header
.dxfer_direction
= direction
;
132 r
->io_header
.dxferp
= r
->buf
;
133 r
->io_header
.dxfer_len
= r
->buflen
;
134 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
135 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
136 r
->io_header
.mx_sb_len
= sizeof(r
->req
.sense
);
137 r
->io_header
.sbp
= r
->req
.sense
;
138 r
->io_header
.timeout
= MAX_UINT
;
139 r
->io_header
.usr_ptr
= r
;
140 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
142 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
143 if (r
->req
.aiocb
== NULL
) {
144 BADF("execute_command: read failed !\n");
151 static void scsi_read_complete(void * opaque
, int ret
)
153 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
158 DPRINTF("IO error ret %d\n", ret
);
159 scsi_command_complete(r
, ret
);
162 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
163 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
167 scsi_command_complete(r
, 0);
169 scsi_req_data(&r
->req
, len
);
173 /* Read more data from scsi device into buffer. */
174 static void scsi_read_data(SCSIRequest
*req
)
176 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
177 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
180 DPRINTF("scsi_read_data 0x%x\n", req
->tag
);
182 scsi_command_complete(r
, 0);
186 ret
= execute_command(s
->bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
188 scsi_command_complete(r
, ret
);
193 static void scsi_write_complete(void * opaque
, int ret
)
195 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
196 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
198 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
201 DPRINTF("IO error\n");
202 scsi_command_complete(r
, ret
);
206 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
207 s
->qdev
.type
== TYPE_TAPE
) {
208 s
->qdev
.blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
209 DPRINTF("block size %d\n", s
->qdev
.blocksize
);
212 scsi_command_complete(r
, ret
);
215 /* Write data to a scsi device. Returns nonzero on failure.
216 The transfer may complete asynchronously. */
217 static void scsi_write_data(SCSIRequest
*req
)
219 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, req
->dev
);
220 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
223 DPRINTF("scsi_write_data 0x%x\n", req
->tag
);
226 scsi_req_data(&r
->req
, r
->len
);
230 ret
= execute_command(s
->bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
232 scsi_command_complete(r
, ret
);
236 /* Return a pointer to the data buffer. */
237 static uint8_t *scsi_get_buf(SCSIRequest
*req
)
239 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
244 static void scsi_req_fixup(SCSIRequest
*req
)
246 switch(req
->cmd
.buf
[0]) {
248 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
251 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
255 if (req
->dev
->type
== TYPE_TAPE
) {
256 /* force IMMED, otherwise qemu waits end of command */
257 req
->cmd
.buf
[1] = 0x01;
263 /* Execute a scsi command. Returns the length of the data expected by the
264 command. This will be Positive for data transfers from the device
265 (eg. disk reads), negative for transfers to the device (eg. disk writes),
266 and zero if the command does not transfer any data. */
268 static int32_t scsi_send_command(SCSIRequest
*req
, uint8_t *cmd
)
270 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, req
->dev
);
271 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
274 scsi_req_fixup(&r
->req
);
276 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun
, tag
,
277 r
->req
.cmd
.xfer
, cmd
[0]);
282 for (i
= 1; i
< r
->req
.cmd
.len
; i
++) {
283 printf(" 0x%02x", cmd
[i
]);
289 if (r
->req
.cmd
.xfer
== 0) {
294 ret
= execute_command(s
->bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
296 scsi_command_complete(r
, ret
);
302 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
305 r
->buf
= g_malloc(r
->req
.cmd
.xfer
);
306 r
->buflen
= r
->req
.cmd
.xfer
;
309 memset(r
->buf
, 0, r
->buflen
);
310 r
->len
= r
->req
.cmd
.xfer
;
311 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
313 return -r
->req
.cmd
.xfer
;
315 return r
->req
.cmd
.xfer
;
319 static int get_blocksize(BlockDriverState
*bdrv
)
324 sg_io_hdr_t io_header
;
327 memset(cmd
, 0, sizeof(cmd
));
328 memset(buf
, 0, sizeof(buf
));
329 cmd
[0] = READ_CAPACITY_10
;
331 memset(&io_header
, 0, sizeof(io_header
));
332 io_header
.interface_id
= 'S';
333 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
334 io_header
.dxfer_len
= sizeof(buf
);
335 io_header
.dxferp
= buf
;
336 io_header
.cmdp
= cmd
;
337 io_header
.cmd_len
= sizeof(cmd
);
338 io_header
.mx_sb_len
= sizeof(sensebuf
);
339 io_header
.sbp
= sensebuf
;
340 io_header
.timeout
= 6000; /* XXX */
342 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
346 return (buf
[4] << 24) | (buf
[5] << 16) | (buf
[6] << 8) | buf
[7];
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
);
377 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
380 static void scsi_generic_reset(DeviceState
*dev
)
382 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
.qdev
, dev
);
384 scsi_device_purge_requests(&s
->qdev
, SENSE_CODE(RESET
));
387 static void scsi_destroy(SCSIDevice
*d
)
389 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
391 scsi_device_purge_requests(&s
->qdev
, SENSE_CODE(NO_SENSE
));
392 blockdev_mark_auto_del(s
->qdev
.conf
.bs
);
395 static int scsi_generic_initfn(SCSIDevice
*dev
)
397 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, dev
);
399 struct sg_scsi_id scsiid
;
401 if (!s
->qdev
.conf
.bs
) {
402 error_report("scsi-generic: drive property not set");
405 s
->bs
= s
->qdev
.conf
.bs
;
407 /* check we are really using a /dev/sg* file */
408 if (!bdrv_is_sg(s
->bs
)) {
409 error_report("scsi-generic: not /dev/sg*");
413 if (bdrv_get_on_error(s
->bs
, 0) != BLOCK_ERR_STOP_ENOSPC
) {
414 error_report("Device doesn't support drive option werror");
417 if (bdrv_get_on_error(s
->bs
, 1) != BLOCK_ERR_REPORT
) {
418 error_report("Device doesn't support drive option rerror");
422 /* check we are using a driver managing SG_IO (version 3 and after */
423 if (bdrv_ioctl(s
->bs
, SG_GET_VERSION_NUM
, &sg_version
) < 0 ||
424 sg_version
< 30000) {
425 error_report("scsi-generic: scsi generic interface too old");
429 /* get LUN of the /dev/sg? */
430 if (bdrv_ioctl(s
->bs
, SG_GET_SCSI_ID
, &scsiid
)) {
431 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
435 /* define device state */
436 s
->qdev
.type
= scsiid
.scsi_type
;
437 DPRINTF("device type %d\n", s
->qdev
.type
);
438 if (s
->qdev
.type
== TYPE_TAPE
) {
439 s
->qdev
.blocksize
= get_stream_blocksize(s
->bs
);
440 if (s
->qdev
.blocksize
== -1)
441 s
->qdev
.blocksize
= 0;
443 s
->qdev
.blocksize
= get_blocksize(s
->bs
);
444 /* removable media returns 0 if not present */
445 if (s
->qdev
.blocksize
<= 0) {
446 if (s
->qdev
.type
== TYPE_ROM
|| s
->qdev
.type
== TYPE_WORM
)
447 s
->qdev
.blocksize
= 2048;
449 s
->qdev
.blocksize
= 512;
452 DPRINTF("block size %d\n", s
->qdev
.blocksize
);
456 static SCSIReqOps scsi_generic_req_ops
= {
457 .size
= sizeof(SCSIGenericReq
),
458 .free_req
= scsi_free_request
,
459 .send_command
= scsi_send_command
,
460 .read_data
= scsi_read_data
,
461 .write_data
= scsi_write_data
,
462 .cancel_io
= scsi_cancel_io
,
463 .get_buf
= scsi_get_buf
,
466 static SCSIRequest
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
,
471 req
= scsi_req_alloc(&scsi_generic_req_ops
, d
, tag
, lun
, hba_private
);
475 static SCSIDeviceInfo scsi_generic_info
= {
476 .qdev
.name
= "scsi-generic",
477 .qdev
.desc
= "pass through generic scsi device (/dev/sg*)",
478 .qdev
.size
= sizeof(SCSIGenericState
),
479 .qdev
.reset
= scsi_generic_reset
,
480 .init
= scsi_generic_initfn
,
481 .destroy
= scsi_destroy
,
482 .alloc_req
= scsi_new_request
,
483 .qdev
.props
= (Property
[]) {
484 DEFINE_BLOCK_PROPERTIES(SCSIGenericState
, qdev
.conf
),
485 DEFINE_PROP_END_OF_LIST(),
489 static void scsi_generic_register_devices(void)
491 scsi_qdev_register(&scsi_generic_info
);
493 device_init(scsi_generic_register_devices
)
495 #endif /* __linux__ */