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
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_free_request(SCSIRequest
*req
)
64 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
69 /* Helper function for command completion. */
70 static void scsi_command_complete(void *opaque
, int ret
)
73 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
76 if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
77 r
->req
.sense_len
= r
->io_header
.sb_len_wr
;
83 status
= TASK_SET_FULL
;
86 status
= CHECK_CONDITION
;
87 scsi_req_build_sense(&r
->req
, SENSE_CODE(TARGET_FAILURE
));
90 status
= CHECK_CONDITION
;
91 scsi_req_build_sense(&r
->req
, SENSE_CODE(IO_ERROR
));
95 if (r
->io_header
.host_status
== SG_ERR_DID_NO_CONNECT
||
96 r
->io_header
.host_status
== SG_ERR_DID_BUS_BUSY
||
97 r
->io_header
.host_status
== SG_ERR_DID_TIME_OUT
||
98 (r
->io_header
.driver_status
& SG_ERR_DRIVER_TIMEOUT
)) {
100 BADF("Driver Timeout\n");
101 } else if (r
->io_header
.host_status
) {
102 status
= CHECK_CONDITION
;
103 scsi_req_build_sense(&r
->req
, SENSE_CODE(I_T_NEXUS_LOSS
));
104 } else if (r
->io_header
.status
) {
105 status
= r
->io_header
.status
;
106 } else if (r
->io_header
.driver_status
& SG_ERR_DRIVER_SENSE
) {
107 status
= CHECK_CONDITION
;
112 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113 r
, r
->req
.tag
, status
);
115 scsi_req_complete(&r
->req
, status
);
118 /* Cancel a pending data transfer. */
119 static void scsi_cancel_io(SCSIRequest
*req
)
121 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
123 DPRINTF("Cancel tag=0x%x\n", req
->tag
);
125 bdrv_aio_cancel(r
->req
.aiocb
);
130 static int execute_command(BlockDriverState
*bdrv
,
131 SCSIGenericReq
*r
, int direction
,
132 BlockDriverCompletionFunc
*complete
)
134 r
->io_header
.interface_id
= 'S';
135 r
->io_header
.dxfer_direction
= direction
;
136 r
->io_header
.dxferp
= r
->buf
;
137 r
->io_header
.dxfer_len
= r
->buflen
;
138 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
139 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
140 r
->io_header
.mx_sb_len
= sizeof(r
->req
.sense
);
141 r
->io_header
.sbp
= r
->req
.sense
;
142 r
->io_header
.timeout
= MAX_UINT
;
143 r
->io_header
.usr_ptr
= r
;
144 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
146 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
147 if (r
->req
.aiocb
== NULL
) {
148 BADF("execute_command: read failed !\n");
155 static void scsi_read_complete(void * opaque
, int ret
)
157 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
162 DPRINTF("IO error ret %d\n", ret
);
163 scsi_command_complete(r
, ret
);
166 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
167 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
171 scsi_command_complete(r
, 0);
173 scsi_req_data(&r
->req
, len
);
177 /* Read more data from scsi device into buffer. */
178 static void scsi_read_data(SCSIRequest
*req
)
180 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
181 SCSIDevice
*s
= r
->req
.dev
;
184 DPRINTF("scsi_read_data 0x%x\n", req
->tag
);
186 scsi_command_complete(r
, 0);
190 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
192 scsi_command_complete(r
, ret
);
196 static void scsi_write_complete(void * opaque
, int ret
)
198 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
199 SCSIDevice
*s
= r
->req
.dev
;
201 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
204 DPRINTF("IO error\n");
205 scsi_command_complete(r
, ret
);
209 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
210 s
->type
== TYPE_TAPE
) {
211 s
->blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
212 DPRINTF("block size %d\n", s
->blocksize
);
215 scsi_command_complete(r
, ret
);
218 /* Write data to a scsi device. Returns nonzero on failure.
219 The transfer may complete asynchronously. */
220 static void scsi_write_data(SCSIRequest
*req
)
222 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
223 SCSIDevice
*s
= r
->req
.dev
;
226 DPRINTF("scsi_write_data 0x%x\n", req
->tag
);
229 scsi_req_data(&r
->req
, r
->len
);
233 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
235 scsi_command_complete(r
, ret
);
239 /* Return a pointer to the data buffer. */
240 static uint8_t *scsi_get_buf(SCSIRequest
*req
)
242 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
247 /* Execute a scsi command. Returns the length of the data expected by the
248 command. This will be Positive for data transfers from the device
249 (eg. disk reads), negative for transfers to the device (eg. disk writes),
250 and zero if the command does not transfer any data. */
252 static int32_t scsi_send_command(SCSIRequest
*req
, uint8_t *cmd
)
254 SCSIGenericReq
*r
= DO_UPCAST(SCSIGenericReq
, req
, req
);
255 SCSIDevice
*s
= r
->req
.dev
;
258 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun
, tag
,
259 r
->req
.cmd
.xfer
, cmd
[0]);
264 for (i
= 1; i
< r
->req
.cmd
.len
; i
++) {
265 printf(" 0x%02x", cmd
[i
]);
271 if (r
->req
.cmd
.xfer
== 0) {
276 ret
= execute_command(s
->conf
.bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
278 scsi_command_complete(r
, ret
);
284 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
287 r
->buf
= g_malloc(r
->req
.cmd
.xfer
);
288 r
->buflen
= r
->req
.cmd
.xfer
;
291 memset(r
->buf
, 0, r
->buflen
);
292 r
->len
= r
->req
.cmd
.xfer
;
293 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
295 return -r
->req
.cmd
.xfer
;
297 return r
->req
.cmd
.xfer
;
301 static int get_blocksize(BlockDriverState
*bdrv
)
306 sg_io_hdr_t io_header
;
309 memset(cmd
, 0, sizeof(cmd
));
310 memset(buf
, 0, sizeof(buf
));
311 cmd
[0] = READ_CAPACITY_10
;
313 memset(&io_header
, 0, sizeof(io_header
));
314 io_header
.interface_id
= 'S';
315 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
316 io_header
.dxfer_len
= sizeof(buf
);
317 io_header
.dxferp
= buf
;
318 io_header
.cmdp
= cmd
;
319 io_header
.cmd_len
= sizeof(cmd
);
320 io_header
.mx_sb_len
= sizeof(sensebuf
);
321 io_header
.sbp
= sensebuf
;
322 io_header
.timeout
= 6000; /* XXX */
324 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
325 if (ret
< 0 || io_header
.driver_status
|| io_header
.host_status
) {
328 return (buf
[4] << 24) | (buf
[5] << 16) | (buf
[6] << 8) | buf
[7];
331 static int get_stream_blocksize(BlockDriverState
*bdrv
)
336 sg_io_hdr_t io_header
;
339 memset(cmd
, 0, sizeof(cmd
));
340 memset(buf
, 0, sizeof(buf
));
342 cmd
[4] = sizeof(buf
);
344 memset(&io_header
, 0, sizeof(io_header
));
345 io_header
.interface_id
= 'S';
346 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
347 io_header
.dxfer_len
= sizeof(buf
);
348 io_header
.dxferp
= buf
;
349 io_header
.cmdp
= cmd
;
350 io_header
.cmd_len
= sizeof(cmd
);
351 io_header
.mx_sb_len
= sizeof(sensebuf
);
352 io_header
.sbp
= sensebuf
;
353 io_header
.timeout
= 6000; /* XXX */
355 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
356 if (ret
< 0 || io_header
.driver_status
|| io_header
.host_status
) {
359 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
362 static void scsi_generic_reset(DeviceState
*dev
)
364 SCSIDevice
*s
= DO_UPCAST(SCSIDevice
, qdev
, dev
);
366 scsi_device_purge_requests(s
, SENSE_CODE(RESET
));
369 static void scsi_destroy(SCSIDevice
*s
)
371 scsi_device_purge_requests(s
, SENSE_CODE(NO_SENSE
));
372 blockdev_mark_auto_del(s
->conf
.bs
);
375 static int scsi_generic_initfn(SCSIDevice
*s
)
378 struct sg_scsi_id scsiid
;
381 error_report("scsi-generic: drive property not set");
385 /* check we are really using a /dev/sg* file */
386 if (!bdrv_is_sg(s
->conf
.bs
)) {
387 error_report("scsi-generic: not /dev/sg*");
391 if (bdrv_get_on_error(s
->conf
.bs
, 0) != BLOCK_ERR_STOP_ENOSPC
) {
392 error_report("Device doesn't support drive option werror");
395 if (bdrv_get_on_error(s
->conf
.bs
, 1) != BLOCK_ERR_REPORT
) {
396 error_report("Device doesn't support drive option rerror");
400 /* check we are using a driver managing SG_IO (version 3 and after */
401 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_VERSION_NUM
, &sg_version
) < 0 ||
402 sg_version
< 30000) {
403 error_report("scsi-generic: scsi generic interface too old");
407 /* get LUN of the /dev/sg? */
408 if (bdrv_ioctl(s
->conf
.bs
, SG_GET_SCSI_ID
, &scsiid
)) {
409 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
413 /* define device state */
414 s
->type
= scsiid
.scsi_type
;
415 DPRINTF("device type %d\n", s
->type
);
416 if (s
->type
== TYPE_TAPE
) {
417 s
->blocksize
= get_stream_blocksize(s
->conf
.bs
);
418 if (s
->blocksize
== -1) {
422 s
->blocksize
= get_blocksize(s
->conf
.bs
);
423 /* removable media returns 0 if not present */
424 if (s
->blocksize
<= 0) {
425 if (s
->type
== TYPE_ROM
|| s
->type
== TYPE_WORM
) {
433 DPRINTF("block size %d\n", s
->blocksize
);
437 static SCSIReqOps scsi_generic_req_ops
= {
438 .size
= sizeof(SCSIGenericReq
),
439 .free_req
= scsi_free_request
,
440 .send_command
= scsi_send_command
,
441 .read_data
= scsi_read_data
,
442 .write_data
= scsi_write_data
,
443 .cancel_io
= scsi_cancel_io
,
444 .get_buf
= scsi_get_buf
,
447 static SCSIRequest
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
,
452 req
= scsi_req_alloc(&scsi_generic_req_ops
, d
, tag
, lun
, hba_private
);
456 static SCSIDeviceInfo scsi_generic_info
= {
457 .qdev
.name
= "scsi-generic",
458 .qdev
.desc
= "pass through generic scsi device (/dev/sg*)",
459 .qdev
.size
= sizeof(SCSIDevice
),
460 .qdev
.reset
= scsi_generic_reset
,
461 .init
= scsi_generic_initfn
,
462 .destroy
= scsi_destroy
,
463 .alloc_req
= scsi_new_request
,
464 .qdev
.props
= (Property
[]) {
465 DEFINE_BLOCK_PROPERTIES(SCSIDevice
, conf
),
466 DEFINE_PROP_END_OF_LIST(),
470 static void scsi_generic_register_devices(void)
472 scsi_qdev_register(&scsi_generic_info
);
474 device_init(scsi_generic_register_devices
)
476 #endif /* __linux__ */