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 licenced under the LGPL.
14 #include "qemu-common.h"
23 #define DPRINTF(fmt, ...) \
24 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26 #define DPRINTF(fmt, ...) do {} while(0)
29 #define BADF(fmt, ...) \
30 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
33 #include <sys/types.h>
37 #include "scsi-defs.h"
39 #define SCSI_SENSE_BUF_SIZE 96
41 #define SG_ERR_DRIVER_TIMEOUT 0x06
42 #define SG_ERR_DRIVER_SENSE 0x08
45 #define MAX_UINT ((unsigned int)-1)
48 typedef struct SCSIGenericState SCSIGenericState
;
50 typedef struct SCSIGenericReq
{
55 sg_io_hdr_t io_header
;
58 struct SCSIGenericState
64 uint8_t sensebuf
[SCSI_SENSE_BUF_SIZE
];
68 static SCSIGenericReq
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
)
72 req
= scsi_req_alloc(sizeof(SCSIGenericReq
), d
, tag
, lun
);
73 return DO_UPCAST(SCSIGenericReq
, req
, req
);
76 static void scsi_remove_request(SCSIGenericReq
*r
)
79 scsi_req_free(&r
->req
);
82 static SCSIGenericReq
*scsi_find_request(SCSIGenericState
*s
, uint32_t tag
)
84 return DO_UPCAST(SCSIGenericReq
, req
, scsi_req_find(&s
->qdev
, tag
));
87 /* Helper function for command completion. */
88 static void scsi_command_complete(void *opaque
, int ret
)
90 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
91 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
93 s
->driver_status
= r
->io_header
.driver_status
;
94 if (s
->driver_status
& SG_ERR_DRIVER_SENSE
)
95 s
->senselen
= r
->io_header
.sb_len_wr
;
98 r
->req
.status
= BUSY
<< 1;
100 if (s
->driver_status
& SG_ERR_DRIVER_TIMEOUT
) {
101 r
->req
.status
= BUSY
<< 1;
102 BADF("Driver Timeout\n");
103 } else if (r
->io_header
.status
)
104 r
->req
.status
= r
->io_header
.status
;
105 else if (s
->driver_status
& SG_ERR_DRIVER_SENSE
)
106 r
->req
.status
= CHECK_CONDITION
<< 1;
108 r
->req
.status
= GOOD
<< 1;
110 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
111 r
, r
->req
.tag
, r
->req
.status
);
113 scsi_req_complete(&r
->req
);
114 scsi_remove_request(r
);
117 /* Cancel a pending data transfer. */
118 static void scsi_cancel_io(SCSIDevice
*d
, uint32_t tag
)
120 DPRINTF("scsi_cancel_io 0x%x\n", tag
);
121 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
123 DPRINTF("Cancel tag=0x%x\n", tag
);
124 r
= scsi_find_request(s
, tag
);
127 bdrv_aio_cancel(r
->req
.aiocb
);
129 scsi_remove_request(r
);
133 static int execute_command(BlockDriverState
*bdrv
,
134 SCSIGenericReq
*r
, int direction
,
135 BlockDriverCompletionFunc
*complete
)
137 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
139 r
->io_header
.interface_id
= 'S';
140 r
->io_header
.dxfer_direction
= direction
;
141 r
->io_header
.dxferp
= r
->buf
;
142 r
->io_header
.dxfer_len
= r
->buflen
;
143 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
144 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
145 r
->io_header
.mx_sb_len
= sizeof(s
->sensebuf
);
146 r
->io_header
.sbp
= s
->sensebuf
;
147 r
->io_header
.timeout
= MAX_UINT
;
148 r
->io_header
.usr_ptr
= r
;
149 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
151 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
152 if (r
->req
.aiocb
== NULL
) {
153 BADF("execute_command: read failed !\n");
160 static void scsi_read_complete(void * opaque
, int ret
)
162 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
166 DPRINTF("IO error\n");
167 scsi_command_complete(r
, ret
);
170 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
171 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
174 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, len
);
176 scsi_command_complete(r
, 0);
179 /* Read more data from scsi device into buffer. */
180 static void scsi_read_data(SCSIDevice
*d
, uint32_t tag
)
182 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
186 DPRINTF("scsi_read_data 0x%x\n", tag
);
187 r
= scsi_find_request(s
, tag
);
189 BADF("Bad read tag 0x%x\n", tag
);
190 /* ??? This is the wrong error. */
191 scsi_command_complete(r
, -EINVAL
);
196 scsi_command_complete(r
, 0);
200 if (r
->req
.cmd
.buf
[0] == REQUEST_SENSE
&& s
->driver_status
& SG_ERR_DRIVER_SENSE
)
202 s
->senselen
= MIN(r
->len
, s
->senselen
);
203 memcpy(r
->buf
, s
->sensebuf
, s
->senselen
);
204 r
->io_header
.driver_status
= 0;
205 r
->io_header
.status
= 0;
206 r
->io_header
.dxfer_len
= s
->senselen
;
208 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, s
->senselen
);
209 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
210 r
->buf
[0], r
->buf
[1], r
->buf
[2], r
->buf
[3],
211 r
->buf
[4], r
->buf
[5], r
->buf
[6], r
->buf
[7]);
212 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, s
->senselen
);
216 ret
= execute_command(s
->bs
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
218 scsi_command_complete(r
, -EINVAL
);
223 static void scsi_write_complete(void * opaque
, int ret
)
225 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
226 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
228 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
230 DPRINTF("IO error\n");
231 scsi_command_complete(r
, ret
);
235 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
236 s
->qdev
.type
== TYPE_TAPE
) {
237 s
->qdev
.blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
238 DPRINTF("block size %d\n", s
->blocksize
);
241 scsi_command_complete(r
, ret
);
244 /* Write data to a scsi device. Returns nonzero on failure.
245 The transfer may complete asynchronously. */
246 static int scsi_write_data(SCSIDevice
*d
, uint32_t tag
)
248 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
252 DPRINTF("scsi_write_data 0x%x\n", tag
);
253 r
= scsi_find_request(s
, tag
);
255 BADF("Bad write tag 0x%x\n", tag
);
256 /* ??? This is the wrong error. */
257 scsi_command_complete(r
, -EINVAL
);
263 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, r
->len
);
267 ret
= execute_command(s
->bs
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
269 scsi_command_complete(r
, -EINVAL
);
276 /* Return a pointer to the data buffer. */
277 static uint8_t *scsi_get_buf(SCSIDevice
*d
, uint32_t tag
)
279 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
281 r
= scsi_find_request(s
, tag
);
283 BADF("Bad buffer tag 0x%x\n", tag
);
289 static void scsi_req_fixup(SCSIRequest
*req
)
291 switch(req
->cmd
.buf
[0]) {
293 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
296 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
300 if (req
->dev
->type
== TYPE_TAPE
) {
301 /* force IMMED, otherwise qemu waits end of command */
302 req
->cmd
.buf
[1] = 0x01;
308 /* Execute a scsi command. Returns the length of the data expected by the
309 command. This will be Positive for data transfers from the device
310 (eg. disk reads), negative for transfers to the device (eg. disk writes),
311 and zero if the command does not transfer any data. */
313 static int32_t scsi_send_command(SCSIDevice
*d
, uint32_t tag
,
314 uint8_t *cmd
, int lun
)
316 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
321 if (cmd
[0] != REQUEST_SENSE
&&
322 (lun
!= s
->lun
|| (cmd
[1] >> 5) != s
->lun
)) {
323 DPRINTF("Unimplemented LUN %d\n", lun
? lun
: cmd
[1] >> 5);
325 s
->sensebuf
[0] = 0x70;
326 s
->sensebuf
[1] = 0x00;
327 s
->sensebuf
[2] = ILLEGAL_REQUEST
;
328 s
->sensebuf
[3] = 0x00;
329 s
->sensebuf
[4] = 0x00;
330 s
->sensebuf
[5] = 0x00;
331 s
->sensebuf
[6] = 0x00;
333 s
->driver_status
= SG_ERR_DRIVER_SENSE
;
334 bus
= scsi_bus_from_device(d
);
335 bus
->complete(bus
, SCSI_REASON_DONE
, tag
, CHECK_CONDITION
<< 1);
339 r
= scsi_find_request(s
, tag
);
341 BADF("Tag 0x%x already in use %p\n", tag
, r
);
342 scsi_cancel_io(d
, tag
);
344 r
= scsi_new_request(d
, tag
, lun
);
346 if (-1 == scsi_req_parse(&r
->req
, cmd
)) {
347 BADF("Unsupported command length, command %x\n", cmd
[0]);
348 scsi_remove_request(r
);
351 scsi_req_fixup(&r
->req
);
353 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun
, tag
,
354 cmd
[0], r
->req
.cmd
.xfer
);
356 if (r
->req
.cmd
.xfer
== 0) {
361 ret
= execute_command(s
->bs
, r
, SG_DXFER_NONE
, scsi_command_complete
);
363 scsi_command_complete(r
, -EINVAL
);
369 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
372 r
->buf
= qemu_malloc(r
->req
.cmd
.xfer
);
373 r
->buflen
= r
->req
.cmd
.xfer
;
376 memset(r
->buf
, 0, r
->buflen
);
377 r
->len
= r
->req
.cmd
.xfer
;
378 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
380 return -r
->req
.cmd
.xfer
;
383 return r
->req
.cmd
.xfer
;
386 static int get_blocksize(BlockDriverState
*bdrv
)
391 sg_io_hdr_t io_header
;
394 memset(cmd
, 0, sizeof(cmd
));
395 memset(buf
, 0, sizeof(buf
));
396 cmd
[0] = READ_CAPACITY
;
398 memset(&io_header
, 0, sizeof(io_header
));
399 io_header
.interface_id
= 'S';
400 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
401 io_header
.dxfer_len
= sizeof(buf
);
402 io_header
.dxferp
= buf
;
403 io_header
.cmdp
= cmd
;
404 io_header
.cmd_len
= sizeof(cmd
);
405 io_header
.mx_sb_len
= sizeof(sensebuf
);
406 io_header
.sbp
= sensebuf
;
407 io_header
.timeout
= 6000; /* XXX */
409 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
413 return (buf
[4] << 24) | (buf
[5] << 16) | (buf
[6] << 8) | buf
[7];
416 static int get_stream_blocksize(BlockDriverState
*bdrv
)
421 sg_io_hdr_t io_header
;
424 memset(cmd
, 0, sizeof(cmd
));
425 memset(buf
, 0, sizeof(buf
));
427 cmd
[4] = sizeof(buf
);
429 memset(&io_header
, 0, sizeof(io_header
));
430 io_header
.interface_id
= 'S';
431 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
432 io_header
.dxfer_len
= sizeof(buf
);
433 io_header
.dxferp
= buf
;
434 io_header
.cmdp
= cmd
;
435 io_header
.cmd_len
= sizeof(cmd
);
436 io_header
.mx_sb_len
= sizeof(sensebuf
);
437 io_header
.sbp
= sensebuf
;
438 io_header
.timeout
= 6000; /* XXX */
440 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
444 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
447 static void scsi_destroy(SCSIDevice
*d
)
449 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
452 while (!QTAILQ_EMPTY(&s
->qdev
.requests
)) {
453 r
= DO_UPCAST(SCSIGenericReq
, req
, QTAILQ_FIRST(&s
->qdev
.requests
));
454 scsi_remove_request(r
);
456 drive_uninit(s
->qdev
.conf
.dinfo
);
459 static int scsi_generic_initfn(SCSIDevice
*dev
)
461 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, dev
);
463 struct sg_scsi_id scsiid
;
465 if (!s
->qdev
.conf
.dinfo
|| !s
->qdev
.conf
.dinfo
->bdrv
) {
466 qemu_error("scsi-generic: drive property not set\n");
469 s
->bs
= s
->qdev
.conf
.dinfo
->bdrv
;
471 /* check we are really using a /dev/sg* file */
472 if (!bdrv_is_sg(s
->bs
)) {
473 qemu_error("scsi-generic: not /dev/sg*\n");
477 /* check we are using a driver managing SG_IO (version 3 and after */
478 if (bdrv_ioctl(s
->bs
, SG_GET_VERSION_NUM
, &sg_version
) < 0 ||
479 sg_version
< 30000) {
480 qemu_error("scsi-generic: scsi generic interface too old\n");
484 /* get LUN of the /dev/sg? */
485 if (bdrv_ioctl(s
->bs
, SG_GET_SCSI_ID
, &scsiid
)) {
486 qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
490 /* define device state */
492 DPRINTF("LUN %d\n", s
->lun
);
493 s
->qdev
.type
= scsiid
.scsi_type
;
494 DPRINTF("device type %d\n", s
->qdev
.type
);
495 if (s
->qdev
.type
== TYPE_TAPE
) {
496 s
->qdev
.blocksize
= get_stream_blocksize(s
->bs
);
497 if (s
->qdev
.blocksize
== -1)
498 s
->qdev
.blocksize
= 0;
500 s
->qdev
.blocksize
= get_blocksize(s
->bs
);
501 /* removable media returns 0 if not present */
502 if (s
->qdev
.blocksize
<= 0) {
503 if (s
->qdev
.type
== TYPE_ROM
|| s
->qdev
.type
== TYPE_WORM
)
504 s
->qdev
.blocksize
= 2048;
506 s
->qdev
.blocksize
= 512;
509 DPRINTF("block size %d\n", s
->qdev
.blocksize
);
510 s
->driver_status
= 0;
511 memset(s
->sensebuf
, 0, sizeof(s
->sensebuf
));
515 static SCSIDeviceInfo scsi_generic_info
= {
516 .qdev
.name
= "scsi-generic",
517 .qdev
.desc
= "pass through generic scsi device (/dev/sg*)",
518 .qdev
.size
= sizeof(SCSIGenericState
),
519 .init
= scsi_generic_initfn
,
520 .destroy
= scsi_destroy
,
521 .send_command
= scsi_send_command
,
522 .read_data
= scsi_read_data
,
523 .write_data
= scsi_write_data
,
524 .cancel_io
= scsi_cancel_io
,
525 .get_buf
= scsi_get_buf
,
526 .qdev
.props
= (Property
[]) {
527 DEFINE_BLOCK_PROPERTIES(SCSIGenericState
, qdev
.conf
),
528 DEFINE_PROP_END_OF_LIST(),
532 static void scsi_generic_register_devices(void)
534 scsi_qdev_register(&scsi_generic_info
);
536 device_init(scsi_generic_register_devices
)
538 #endif /* __linux__ */