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"
16 #include "scsi-disk.h"
20 SCSIDevice
*scsi_generic_init(BlockDriverState
*bdrv
, int tcq
,
21 scsi_completionfn completion
, void *opaque
)
31 #define DPRINTF(fmt, args...) \
32 do { printf("scsi-generic: " fmt , ##args); } while (0)
34 #define DPRINTF(fmt, args...) do {} while(0)
37 #define BADF(fmt, args...) \
38 do { fprintf(stderr, "scsi-generic: " fmt , ##args); } while (0)
41 #include <sys/types.h>
45 #include <scsi/scsi.h>
47 #define LOAD_UNLOAD 0xa6
48 #define SET_CD_SPEED 0xbb
51 #define SCSI_CMD_BUF_SIZE 16
52 #define SCSI_SENSE_BUF_SIZE 32
54 #define SG_ERR_DRIVER_TIMEOUT 0x06
55 #define SG_ERR_DRIVER_SENSE 0x08
58 #define MAX_UINT ((unsigned int)-1)
61 typedef struct SCSIRequest
{
62 BlockDriverAIOCB
*aiocb
;
63 struct SCSIRequest
*next
;
66 uint8_t cmd
[SCSI_CMD_BUF_SIZE
];
71 sg_io_hdr_t io_header
;
74 struct SCSIDeviceState
76 SCSIRequest
*requests
;
77 BlockDriverState
*bdrv
;
80 scsi_completionfn completion
;
83 uint8_t sensebuf
[SCSI_SENSE_BUF_SIZE
];
86 /* Global pool of SCSIRequest structures. */
87 static SCSIRequest
*free_requests
= NULL
;
89 static SCSIRequest
*scsi_new_request(SCSIDeviceState
*s
, uint32_t tag
)
95 free_requests
= r
->next
;
97 r
= qemu_malloc(sizeof(SCSIRequest
));
103 memset(r
->cmd
, 0, sizeof(r
->cmd
));
104 memset(&r
->io_header
, 0, sizeof(r
->io_header
));
111 r
->next
= s
->requests
;
116 static void scsi_remove_request(SCSIRequest
*r
)
119 SCSIDeviceState
*s
= r
->dev
;
121 if (s
->requests
== r
) {
122 s
->requests
= r
->next
;
125 while (last
&& last
->next
!= r
)
128 last
->next
= r
->next
;
130 BADF("Orphaned request\n");
133 r
->next
= free_requests
;
137 static SCSIRequest
*scsi_find_request(SCSIDeviceState
*s
, uint32_t tag
)
142 while (r
&& r
->tag
!= tag
)
148 /* Helper function for command completion. */
149 static void scsi_command_complete(void *opaque
, int ret
)
151 SCSIRequest
*r
= (SCSIRequest
*)opaque
;
152 SCSIDeviceState
*s
= r
->dev
;
156 s
->driver_status
= r
->io_header
.driver_status
;
158 sense
= HARDWARE_ERROR
;
160 if (s
->driver_status
& SG_ERR_DRIVER_TIMEOUT
) {
161 sense
= HARDWARE_ERROR
;
162 BADF("Driver Timeout\n");
163 } else if ((s
->driver_status
& SG_ERR_DRIVER_SENSE
) == 0)
166 sense
= s
->sensebuf
[2] & 0x0f;
169 DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r
, r
->tag
, sense
);
171 scsi_remove_request(r
);
172 s
->completion(s
->opaque
, SCSI_REASON_DONE
, tag
, sense
);
175 /* Cancel a pending data transfer. */
176 static void scsi_cancel_io(SCSIDevice
*d
, uint32_t tag
)
178 DPRINTF("scsi_cancel_io 0x%x\n", tag
);
179 SCSIDeviceState
*s
= d
->state
;
181 DPRINTF("Cancel tag=0x%x\n", tag
);
182 r
= scsi_find_request(s
, tag
);
185 bdrv_aio_cancel(r
->aiocb
);
187 scsi_remove_request(r
);
191 static int execute_command(BlockDriverState
*bdrv
,
192 SCSIRequest
*r
, int direction
,
193 BlockDriverCompletionFunc
*complete
)
196 r
->io_header
.interface_id
= 'S';
197 r
->io_header
.dxfer_direction
= direction
;
198 r
->io_header
.dxferp
= r
->buf
;
199 r
->io_header
.dxfer_len
= r
->buflen
;
200 r
->io_header
.cmdp
= r
->cmd
;
201 r
->io_header
.cmd_len
= r
->cmdlen
;
202 r
->io_header
.mx_sb_len
= sizeof(r
->dev
->sensebuf
);
203 r
->io_header
.sbp
= r
->dev
->sensebuf
;
204 r
->io_header
.timeout
= MAX_UINT
;
205 r
->io_header
.usr_ptr
= r
;
206 r
->io_header
.flags
|= SG_FLAG_DIRECT_IO
;
208 if (bdrv_pwrite(bdrv
, -1, &r
->io_header
, sizeof(r
->io_header
)) == -1) {
209 BADF("execute_command: write failed ! (%d)\n", errno
);
212 if (complete
== NULL
) {
215 while ((ret
= bdrv_pread(bdrv
, -1, &r
->io_header
,
216 sizeof(r
->io_header
))) == -1 &&
219 BADF("execute_command: read failed !\n");
225 r
->aiocb
= bdrv_aio_read(bdrv
, 0, (uint8_t*)&r
->io_header
,
226 -(int64_t)sizeof(r
->io_header
), complete
, r
);
227 if (r
->aiocb
== NULL
) {
228 BADF("execute_command: read failed !\n");
235 static void scsi_read_complete(void * opaque
, int ret
)
237 SCSIRequest
*r
= (SCSIRequest
*)opaque
;
238 SCSIDeviceState
*s
= r
->dev
;
242 DPRINTF("IO error\n");
243 scsi_command_complete(r
, ret
);
246 len
= r
->io_header
.dxfer_len
- r
->io_header
.resid
;
247 DPRINTF("Data ready tag=0x%x len=%d\n", r
->tag
, len
);
250 s
->completion(s
->opaque
, SCSI_REASON_DATA
, r
->tag
, len
);
253 /* Read more data from scsi device into buffer. */
254 static void scsi_read_data(SCSIDevice
*d
, uint32_t tag
)
256 SCSIDeviceState
*s
= d
->state
;
260 DPRINTF("scsi_read_data 0x%x\n", tag
);
261 r
= scsi_find_request(s
, tag
);
263 BADF("Bad read tag 0x%x\n", tag
);
264 /* ??? This is the wrong error. */
265 scsi_command_complete(r
, -EINVAL
);
270 scsi_command_complete(r
, 0);
274 if (r
->cmd
[0] == REQUEST_SENSE
&& s
->driver_status
& SG_ERR_DRIVER_SENSE
)
276 memcpy(r
->buf
, s
->sensebuf
, 16);
277 r
->io_header
.driver_status
= 0;
279 s
->completion(s
->opaque
, SCSI_REASON_DATA
, r
->tag
, 16);
283 ret
= execute_command(s
->bdrv
, r
, SG_DXFER_FROM_DEV
, scsi_read_complete
);
285 scsi_command_complete(r
, -EINVAL
);
290 static void scsi_write_complete(void * opaque
, int ret
)
292 SCSIRequest
*r
= (SCSIRequest
*)opaque
;
294 DPRINTF("scsi_write_complete() ret = %d\n", ret
);
296 DPRINTF("IO error\n");
297 scsi_command_complete(r
, ret
);
301 scsi_command_complete(r
, ret
);
304 /* Write data to a scsi device. Returns nonzero on failure.
305 The transfer may complete asynchronously. */
306 static int scsi_write_data(SCSIDevice
*d
, uint32_t tag
)
308 SCSIDeviceState
*s
= d
->state
;
312 DPRINTF("scsi_write_data 0x%x\n", tag
);
313 r
= scsi_find_request(s
, tag
);
315 BADF("Bad write tag 0x%x\n", tag
);
316 /* ??? This is the wrong error. */
317 scsi_command_complete(r
, -EINVAL
);
323 s
->completion(s
->opaque
, SCSI_REASON_DATA
, r
->tag
, r
->len
);
327 ret
= execute_command(s
->bdrv
, r
, SG_DXFER_TO_DEV
, scsi_write_complete
);
329 scsi_command_complete(r
, -EINVAL
);
336 /* Return a pointer to the data buffer. */
337 static uint8_t *scsi_get_buf(SCSIDevice
*d
, uint32_t tag
)
339 SCSIDeviceState
*s
= d
->state
;
341 r
= scsi_find_request(s
, tag
);
343 BADF("Bad buffer tag 0x%x\n", tag
);
349 static int scsi_length(uint8_t *cmd
, int blocksize
, int *cmdlen
, uint32_t *len
)
351 switch (cmd
[0] >> 5) {
358 *len
= cmd
[8] | (cmd
[7] << 8);
362 *len
= cmd
[13] | (cmd
[12] << 8) | (cmd
[11] << 16) | (cmd
[10] << 24);
366 *len
= cmd
[9] | (cmd
[8] << 8) | (cmd
[7] << 16) | (cmd
[6] << 24);
374 case TEST_UNIT_READY
:
378 case WRITE_FILEMARKS
:
381 case ALLOW_MEDIUM_REMOVAL
:
384 case SYNCHRONIZE_CACHE
:
385 case LOCK_UNLOCK_CACHE
:
402 case READ_BLOCK_LIMITS
:
408 case SEND_VOLUME_TAG
:
415 cmd
[1] &= ~0x08; /* disable FUA */
419 case WRITE_VERIFY_12
:
423 cmd
[1] &= ~0x08; /* disable FUA */
426 case RECOVER_BUFFERED_DATA
:
434 static int is_write(int command
)
440 case CHANGE_DEFINITION
:
444 case SEND_DIAGNOSTIC
:
447 case REASSIGN_BLOCKS
:
459 case SEARCH_EQUAL_12
:
462 case WRITE_VERIFY_12
:
465 case SEND_VOLUME_TAG
:
472 /* Execute a scsi command. Returns the length of the data expected by the
473 command. This will be Positive for data transfers from the device
474 (eg. disk reads), negative for transfers to the device (eg. disk writes),
475 and zero if the command does not transfer any data. */
477 static int32_t scsi_send_command(SCSIDevice
*d
, uint32_t tag
,
478 uint8_t *cmd
, int lun
)
480 SCSIDeviceState
*s
= d
->state
;
486 /* ??? Tags are not unique for different luns. We only implement a
487 single lun, so this should not matter. */
489 if (lun
!= s
->lun
|| (cmd
[1] >> 5) != s
->lun
) {
490 DPRINTF("Unimplemented LUN %d\n", lun
? lun
: cmd
[1] >> 5);
491 s
->completion(s
->opaque
, SCSI_REASON_DONE
, tag
, ILLEGAL_REQUEST
);
495 if (scsi_length(cmd
, s
->blocksize
, &cmdlen
, &len
) == -1) {
496 BADF("Unsupported command length, command %x\n", cmd
[0]);
500 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun
, tag
,
503 r
= scsi_find_request(s
, tag
);
505 BADF("Tag 0x%x already in use %p\n", tag
, r
);
506 scsi_cancel_io(d
, tag
);
508 r
= scsi_new_request(s
, tag
);
510 memcpy(r
->cmd
, cmd
, cmdlen
);
518 ret
= execute_command(s
->bdrv
, r
, SG_DXFER_NONE
, scsi_command_complete
);
520 scsi_command_complete(r
, -EINVAL
);
526 if (r
->buflen
!= len
) {
529 r
->buf
= qemu_malloc(len
);
533 memset(r
->buf
, 0, r
->buflen
);
535 if (is_write(cmd
[0])) {
543 static int get_blocksize(BlockDriverState
*bdrv
)
548 sg_io_hdr_t io_header
;
551 memset(cmd
, sizeof(cmd
), 0);
552 memset(buf
, sizeof(buf
), 0);
553 cmd
[0] = READ_CAPACITY
;
555 memset(&io_header
, 0, sizeof(io_header
));
556 io_header
.interface_id
= 'S';
557 io_header
.dxfer_direction
= SG_DXFER_FROM_DEV
;
558 io_header
.dxfer_len
= sizeof(buf
);
559 io_header
.dxferp
= buf
;
560 io_header
.cmdp
= cmd
;
561 io_header
.cmd_len
= sizeof(cmd
);
562 io_header
.mx_sb_len
= sizeof(sensebuf
);
563 io_header
.sbp
= sensebuf
;
564 io_header
.timeout
= 6000; /* XXX */
566 ret
= bdrv_pwrite(bdrv
, -1, &io_header
, sizeof(io_header
));
570 while ((ret
= bdrv_pread(bdrv
, -1, &io_header
, sizeof(io_header
))) == -1 &&
576 return (buf
[4] << 24) | (buf
[5] << 16) | (buf
[6] << 8) | buf
[7];
579 static void scsi_destroy(SCSIDevice
*d
)
583 r
= d
->state
->requests
;
601 SCSIDevice
*scsi_generic_init(BlockDriverState
*bdrv
, int tcq
,
602 scsi_completionfn completion
, void *opaque
)
607 struct sg_scsi_id scsiid
;
609 /* check we are really using a /dev/sg* file */
611 if (!bdrv_is_sg(bdrv
))
614 /* check we are using a driver managing SG_IO (version 3 and after */
616 if (bdrv_ioctl(bdrv
, SG_GET_VERSION_NUM
, &sg_version
) < 0 ||
620 /* get LUN of the /dev/sg? */
622 if (bdrv_ioctl(bdrv
, SG_GET_SCSI_ID
, &scsiid
))
625 /* define device state */
627 s
= (SCSIDeviceState
*)qemu_mallocz(sizeof(SCSIDeviceState
));
630 s
->completion
= completion
;
633 s
->blocksize
= get_blocksize(s
->bdrv
);
634 s
->driver_status
= 0;
635 memset(s
->sensebuf
, 0, sizeof(s
->sensebuf
));
636 /* removable media returns 0 if not present */
637 if (s
->blocksize
<= 0)
640 /* define function to manage device */
642 d
= (SCSIDevice
*)qemu_mallocz(sizeof(SCSIDevice
));
644 d
->destroy
= scsi_destroy
;
645 d
->send_command
= scsi_send_command
;
646 d
->read_data
= scsi_read_data
;
647 d
->write_data
= scsi_write_data
;
648 d
->cancel_io
= scsi_cancel_io
;
649 d
->get_buf
= scsi_get_buf
;
653 #endif /* __linux__ */