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
);
95 s
->driver_status
= r
->io_header
.driver_status
;
96 if (s
->driver_status
& SG_ERR_DRIVER_SENSE
)
97 s
->senselen
= r
->io_header
.sb_len_wr
;
102 if (s
->driver_status
& SG_ERR_DRIVER_TIMEOUT
) {
104 BADF("Driver Timeout\n");
105 } else if (r
->io_header
.status
)
106 status
= r
->io_header
.status
;
107 else if (s
->driver_status
& SG_ERR_DRIVER_SENSE
)
108 status
= CHECK_CONDITION
<< 1;
112 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113 r
, r
->req
.tag
, status
);
115 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DONE
, tag
, status
);
116 scsi_remove_request(r
);
119 /* Cancel a pending data transfer. */
120 static void scsi_cancel_io(SCSIDevice
*d
, uint32_t tag
)
122 DPRINTF("scsi_cancel_io 0x%x\n", tag
);
123 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
125 DPRINTF("Cancel tag=0x%x\n", tag
);
126 r
= scsi_find_request(s
, tag
);
129 bdrv_aio_cancel(r
->req
.aiocb
);
131 scsi_remove_request(r
);
135 static int execute_command(BlockDriverState
*bdrv
,
136 SCSIGenericReq
*r
, int direction
,
137 BlockDriverCompletionFunc
*complete
)
139 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
141 r
->io_header
.interface_id
= 'S';
142 r
->io_header
.dxfer_direction
= direction
;
143 r
->io_header
.dxferp
= r
->buf
;
144 r
->io_header
.dxfer_len
= r
->buflen
;
145 r
->io_header
.cmdp
= r
->req
.cmd
.buf
;
146 r
->io_header
.cmd_len
= r
->req
.cmd
.len
;
147 r
->io_header
.mx_sb_len
= sizeof(s
->sensebuf
);
148 r
->io_header
.sbp
= s
->sensebuf
;
149 r
->io_header
.timeout
= MAX_UINT
;
150 r
->io_header
.usr_ptr
= r
;
151 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
153 r
->req
.aiocb
= bdrv_aio_ioctl(bdrv
, SG_IO
, &r
->io_header
, complete
, r
);
154 if (r
->req
.aiocb
== NULL
) {
155 BADF("execute_command: read failed !\n");
162 static void scsi_read_complete(void * opaque
, int ret
)
164 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
168 DPRINTF("IO error\n");
169 scsi_command_complete(r
, ret
);
172 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
173 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, len
);
176 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, len
);
178 scsi_command_complete(r
, 0);
181 /* Read more data from scsi device into buffer. */
182 static void scsi_read_data(SCSIDevice
*d
, uint32_t tag
)
184 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
188 DPRINTF("scsi_read_data 0x%x\n", tag
);
189 r
= scsi_find_request(s
, tag
);
191 BADF("Bad read tag 0x%x\n", tag
);
192 /* ??? This is the wrong error. */
193 scsi_command_complete(r
, -EINVAL
);
198 scsi_command_complete(r
, 0);
202 if (r
->req
.cmd
.buf
[0] == REQUEST_SENSE
&& s
->driver_status
& SG_ERR_DRIVER_SENSE
)
204 s
->senselen
= MIN(r
->len
, s
->senselen
);
205 memcpy(r
->buf
, s
->sensebuf
, s
->senselen
);
206 r
->io_header
.driver_status
= 0;
207 r
->io_header
.status
= 0;
208 r
->io_header
.dxfer_len
= s
->senselen
;
210 DPRINTF("Data ready tag=0x%x len=%d\n", r
->req
.tag
, s
->senselen
);
211 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
212 r
->buf
[0], r
->buf
[1], r
->buf
[2], r
->buf
[3],
213 r
->buf
[4], r
->buf
[5], r
->buf
[6], r
->buf
[7]);
214 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, s
->senselen
);
218 ret
= execute_command(s
->dinfo
->bdrv
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
220 scsi_command_complete(r
, -EINVAL
);
225 static void scsi_write_complete(void * opaque
, int ret
)
227 SCSIGenericReq
*r
= (SCSIGenericReq
*)opaque
;
228 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, r
->req
.dev
);
230 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
232 DPRINTF("IO error\n");
233 scsi_command_complete(r
, ret
);
237 if (r
->req
.cmd
.buf
[0] == MODE_SELECT
&& r
->req
.cmd
.buf
[4] == 12 &&
238 s
->qdev
.type
== TYPE_TAPE
) {
239 s
->qdev
.blocksize
= (r
->buf
[9] << 16) | (r
->buf
[10] << 8) | r
->buf
[11];
240 DPRINTF("block size %d\n", s
->blocksize
);
243 scsi_command_complete(r
, ret
);
246 /* Write data to a scsi device. Returns nonzero on failure.
247 The transfer may complete asynchronously. */
248 static int scsi_write_data(SCSIDevice
*d
, uint32_t tag
)
250 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
254 DPRINTF("scsi_write_data 0x%x\n", tag
);
255 r
= scsi_find_request(s
, tag
);
257 BADF("Bad write tag 0x%x\n", tag
);
258 /* ??? This is the wrong error. */
259 scsi_command_complete(r
, -EINVAL
);
265 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, r
->len
);
269 ret
= execute_command(s
->dinfo
->bdrv
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
271 scsi_command_complete(r
, -EINVAL
);
278 /* Return a pointer to the data buffer. */
279 static uint8_t *scsi_get_buf(SCSIDevice
*d
, uint32_t tag
)
281 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
283 r
= scsi_find_request(s
, tag
);
285 BADF("Bad buffer tag 0x%x\n", tag
);
291 static void scsi_req_fixup(SCSIRequest
*req
)
293 switch(req
->cmd
.buf
[0]) {
295 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
298 req
->cmd
.buf
[1] &= ~0x08; /* disable FUA */
302 if (req
->dev
->type
== TYPE_TAPE
) {
303 /* force IMMED, otherwise qemu waits end of command */
304 req
->cmd
.buf
[1] = 0x01;
310 /* Execute a scsi command. Returns the length of the data expected by the
311 command. This will be Positive for data transfers from the device
312 (eg. disk reads), negative for transfers to the device (eg. disk writes),
313 and zero if the command does not transfer any data. */
315 static int32_t scsi_send_command(SCSIDevice
*d
, uint32_t tag
,
316 uint8_t *cmd
, int lun
)
318 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
323 if (cmd
[0] != REQUEST_SENSE
&&
324 (lun
!= s
->lun
|| (cmd
[1] >> 5) != s
->lun
)) {
325 DPRINTF("Unimplemented LUN %d\n", lun
? lun
: cmd
[1] >> 5);
327 s
->sensebuf
[0] = 0x70;
328 s
->sensebuf
[1] = 0x00;
329 s
->sensebuf
[2] = ILLEGAL_REQUEST
;
330 s
->sensebuf
[3] = 0x00;
331 s
->sensebuf
[4] = 0x00;
332 s
->sensebuf
[5] = 0x00;
333 s
->sensebuf
[6] = 0x00;
335 s
->driver_status
= SG_ERR_DRIVER_SENSE
;
336 bus
= scsi_bus_from_device(d
);
337 bus
->complete(bus
, SCSI_REASON_DONE
, tag
, CHECK_CONDITION
<< 1);
341 r
= scsi_find_request(s
, tag
);
343 BADF("Tag 0x%x already in use %p\n", tag
, r
);
344 scsi_cancel_io(d
, tag
);
346 r
= scsi_new_request(d
, tag
, lun
);
348 if (-1 == scsi_req_parse(&r
->req
, cmd
)) {
349 BADF("Unsupported command length, command %x\n", cmd
[0]);
350 scsi_remove_request(r
);
353 scsi_req_fixup(&r
->req
);
355 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun
, tag
,
356 cmd
[0], r
->req
.cmd
.xfer
);
358 if (r
->req
.cmd
.xfer
== 0) {
363 ret
= execute_command(s
->dinfo
->bdrv
, r
, SG_DXFER_NONE
, scsi_command_complete
);
365 scsi_command_complete(r
, -EINVAL
);
371 if (r
->buflen
!= r
->req
.cmd
.xfer
) {
374 r
->buf
= qemu_malloc(r
->req
.cmd
.xfer
);
375 r
->buflen
= r
->req
.cmd
.xfer
;
378 memset(r
->buf
, 0, r
->buflen
);
379 r
->len
= r
->req
.cmd
.xfer
;
380 if (r
->req
.cmd
.mode
== SCSI_XFER_TO_DEV
) {
382 return -r
->req
.cmd
.xfer
;
385 return r
->req
.cmd
.xfer
;
388 static int get_blocksize(BlockDriverState
*bdrv
)
393 sg_io_hdr_t io_header
;
396 memset(cmd
, 0, sizeof(cmd
));
397 memset(buf
, 0, sizeof(buf
));
398 cmd
[0] = READ_CAPACITY
;
400 memset(&io_header
, 0, sizeof(io_header
));
401 io_header
.interface_id
= 'S';
402 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
403 io_header
.dxfer_len
= sizeof(buf
);
404 io_header
.dxferp
= buf
;
405 io_header
.cmdp
= cmd
;
406 io_header
.cmd_len
= sizeof(cmd
);
407 io_header
.mx_sb_len
= sizeof(sensebuf
);
408 io_header
.sbp
= sensebuf
;
409 io_header
.timeout
= 6000; /* XXX */
411 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
415 return (buf
[4] << 24) | (buf
[5] << 16) | (buf
[6] << 8) | buf
[7];
418 static int get_stream_blocksize(BlockDriverState
*bdrv
)
423 sg_io_hdr_t io_header
;
426 memset(cmd
, 0, sizeof(cmd
));
427 memset(buf
, 0, sizeof(buf
));
429 cmd
[4] = sizeof(buf
);
431 memset(&io_header
, 0, sizeof(io_header
));
432 io_header
.interface_id
= 'S';
433 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
434 io_header
.dxfer_len
= sizeof(buf
);
435 io_header
.dxferp
= buf
;
436 io_header
.cmdp
= cmd
;
437 io_header
.cmd_len
= sizeof(cmd
);
438 io_header
.mx_sb_len
= sizeof(sensebuf
);
439 io_header
.sbp
= sensebuf
;
440 io_header
.timeout
= 6000; /* XXX */
442 ret
= bdrv_ioctl(bdrv
, SG_IO
, &io_header
);
446 return (buf
[9] << 16) | (buf
[10] << 8) | buf
[11];
449 static void scsi_destroy(SCSIDevice
*d
)
451 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, d
);
454 while (!QTAILQ_EMPTY(&s
->qdev
.requests
)) {
455 r
= DO_UPCAST(SCSIGenericReq
, req
, QTAILQ_FIRST(&s
->qdev
.requests
));
456 scsi_remove_request(r
);
458 drive_uninit(s
->dinfo
);
461 static int scsi_generic_initfn(SCSIDevice
*dev
)
463 SCSIGenericState
*s
= DO_UPCAST(SCSIGenericState
, qdev
, dev
);
465 struct sg_scsi_id scsiid
;
467 if (!s
->dinfo
|| !s
->dinfo
->bdrv
) {
468 qemu_error("scsi-generic: drive property not set\n");
472 /* check we are really using a /dev/sg* file */
473 if (!bdrv_is_sg(s
->dinfo
->bdrv
)) {
474 qemu_error("scsi-generic: not /dev/sg*\n");
478 /* check we are using a driver managing SG_IO (version 3 and after */
479 if (bdrv_ioctl(s
->dinfo
->bdrv
, SG_GET_VERSION_NUM
, &sg_version
) < 0 ||
480 sg_version
< 30000) {
481 qemu_error("scsi-generic: scsi generic interface too old\n");
485 /* get LUN of the /dev/sg? */
486 if (bdrv_ioctl(s
->dinfo
->bdrv
, SG_GET_SCSI_ID
, &scsiid
)) {
487 qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
491 /* define device state */
493 DPRINTF("LUN %d\n", s
->lun
);
494 s
->qdev
.type
= scsiid
.scsi_type
;
495 DPRINTF("device type %d\n", s
->qdev
.type
);
496 if (s
->qdev
.type
== TYPE_TAPE
) {
497 s
->qdev
.blocksize
= get_stream_blocksize(s
->dinfo
->bdrv
);
498 if (s
->qdev
.blocksize
== -1)
499 s
->qdev
.blocksize
= 0;
501 s
->qdev
.blocksize
= get_blocksize(s
->dinfo
->bdrv
);
502 /* removable media returns 0 if not present */
503 if (s
->qdev
.blocksize
<= 0) {
504 if (s
->qdev
.type
== TYPE_ROM
|| s
->qdev
.type
== TYPE_WORM
)
505 s
->qdev
.blocksize
= 2048;
507 s
->qdev
.blocksize
= 512;
510 DPRINTF("block size %d\n", s
->qdev
.blocksize
);
511 s
->driver_status
= 0;
512 memset(s
->sensebuf
, 0, sizeof(s
->sensebuf
));
516 static SCSIDeviceInfo scsi_generic_info
= {
517 .qdev
.name
= "scsi-generic",
518 .qdev
.desc
= "pass through generic scsi device (/dev/sg*)",
519 .qdev
.size
= sizeof(SCSIGenericState
),
520 .init
= scsi_generic_initfn
,
521 .destroy
= scsi_destroy
,
522 .send_command
= scsi_send_command
,
523 .read_data
= scsi_read_data
,
524 .write_data
= scsi_write_data
,
525 .cancel_io
= scsi_cancel_io
,
526 .get_buf
= scsi_get_buf
,
527 .qdev
.props
= (Property
[]) {
528 DEFINE_PROP_DRIVE("drive", SCSIGenericState
, dinfo
),
529 DEFINE_PROP_END_OF_LIST(),
533 static void scsi_generic_register_devices(void)
535 scsi_qdev_register(&scsi_generic_info
);
537 device_init(scsi_generic_register_devices
)
539 #endif /* __linux__ */