Merge branch 'master' of git://git.qemu.org/qemu
[qemu.git] / hw / scsi-generic.c
blobe62044f3955d9242d9baa6faeced5c0711342a91
1 /*
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"
16 #include "scsi.h"
17 #include "blockdev.h"
19 #ifdef __linux__
21 //#define DEBUG_SCSI
23 #ifdef DEBUG_SCSI
24 #define DPRINTF(fmt, ...) \
25 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26 #else
27 #define DPRINTF(fmt, ...) do {} while(0)
28 #endif
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <scsi/sg.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
50 #ifndef MAX_UINT
51 #define MAX_UINT ((unsigned int)-1)
52 #endif
54 typedef struct SCSIGenericReq {
55 SCSIRequest req;
56 uint8_t *buf;
57 int buflen;
58 int len;
59 sg_io_hdr_t io_header;
60 } SCSIGenericReq;
62 static void scsi_free_request(SCSIRequest *req)
64 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
66 g_free(r->buf);
69 /* Helper function for command completion. */
70 static void scsi_command_complete(void *opaque, int ret)
72 int status;
73 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
75 r->req.aiocb = NULL;
76 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
77 r->req.sense_len = r->io_header.sb_len_wr;
80 if (ret != 0) {
81 switch (ret) {
82 case -EDOM:
83 status = TASK_SET_FULL;
84 break;
85 case -ENOMEM:
86 status = CHECK_CONDITION;
87 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
88 break;
89 default:
90 status = CHECK_CONDITION;
91 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
92 break;
94 } else {
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)) {
99 status = BUSY;
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;
108 } else {
109 status = GOOD;
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);
116 if (!r->req.io_canceled) {
117 scsi_req_unref(&r->req);
121 /* Cancel a pending data transfer. */
122 static void scsi_cancel_io(SCSIRequest *req)
124 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
126 DPRINTF("Cancel tag=0x%x\n", req->tag);
127 if (r->req.aiocb) {
128 bdrv_aio_cancel(r->req.aiocb);
130 /* This reference was left in by scsi_*_data. We take ownership of
131 * it independent of whether bdrv_aio_cancel completes the request
132 * or not. */
133 scsi_req_unref(&r->req);
135 r->req.aiocb = NULL;
138 static int execute_command(BlockDriverState *bdrv,
139 SCSIGenericReq *r, int direction,
140 BlockDriverCompletionFunc *complete)
142 r->io_header.interface_id = 'S';
143 r->io_header.dxfer_direction = direction;
144 r->io_header.dxferp = r->buf;
145 r->io_header.dxfer_len = r->buflen;
146 r->io_header.cmdp = r->req.cmd.buf;
147 r->io_header.cmd_len = r->req.cmd.len;
148 r->io_header.mx_sb_len = sizeof(r->req.sense);
149 r->io_header.sbp = r->req.sense;
150 r->io_header.timeout = MAX_UINT;
151 r->io_header.usr_ptr = r;
152 r->io_header.flags |= SG_FLAG_DIRECT_IO;
154 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
155 if (r->req.aiocb == NULL) {
156 BADF("execute_command: read failed !\n");
157 return -ENOMEM;
160 return 0;
163 static void scsi_read_complete(void * opaque, int ret)
165 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
166 SCSIDevice *s = r->req.dev;
167 int len;
169 r->req.aiocb = NULL;
170 if (ret) {
171 DPRINTF("IO error ret %d\n", ret);
172 scsi_command_complete(r, ret);
173 return;
175 len = r->io_header.dxfer_len - r->io_header.resid;
176 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
178 r->len = -1;
179 if (len == 0) {
180 scsi_command_complete(r, 0);
181 } else {
182 /* Snoop READ CAPACITY output to set the blocksize. */
183 if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
184 s->blocksize = ldl_be_p(&r->buf[4]);
185 s->max_lba = ldl_be_p(&r->buf[0]);
186 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
187 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
188 s->blocksize = ldl_be_p(&r->buf[8]);
189 s->max_lba = ldq_be_p(&r->buf[0]);
191 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
193 scsi_req_data(&r->req, len);
194 if (!r->req.io_canceled) {
195 scsi_req_unref(&r->req);
200 /* Read more data from scsi device into buffer. */
201 static void scsi_read_data(SCSIRequest *req)
203 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
204 SCSIDevice *s = r->req.dev;
205 int ret;
207 DPRINTF("scsi_read_data 0x%x\n", req->tag);
209 /* The request is used as the AIO opaque value, so add a ref. */
210 scsi_req_ref(&r->req);
211 if (r->len == -1) {
212 scsi_command_complete(r, 0);
213 return;
216 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
217 if (ret < 0) {
218 scsi_command_complete(r, ret);
222 static void scsi_write_complete(void * opaque, int ret)
224 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
225 SCSIDevice *s = r->req.dev;
227 DPRINTF("scsi_write_complete() ret = %d\n", ret);
228 r->req.aiocb = NULL;
229 if (ret) {
230 DPRINTF("IO error\n");
231 scsi_command_complete(r, ret);
232 return;
235 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
236 s->type == TYPE_TAPE) {
237 s->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 void scsi_write_data(SCSIRequest *req)
248 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
249 SCSIDevice *s = r->req.dev;
250 int ret;
252 DPRINTF("scsi_write_data 0x%x\n", req->tag);
253 if (r->len == 0) {
254 r->len = r->buflen;
255 scsi_req_data(&r->req, r->len);
256 return;
259 /* The request is used as the AIO opaque value, so add a ref. */
260 scsi_req_ref(&r->req);
261 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
262 if (ret < 0) {
263 scsi_command_complete(r, ret);
267 /* Return a pointer to the data buffer. */
268 static uint8_t *scsi_get_buf(SCSIRequest *req)
270 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
272 return r->buf;
275 /* Execute a scsi command. Returns the length of the data expected by the
276 command. This will be Positive for data transfers from the device
277 (eg. disk reads), negative for transfers to the device (eg. disk writes),
278 and zero if the command does not transfer any data. */
280 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
282 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
283 SCSIDevice *s = r->req.dev;
284 int ret;
286 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
287 r->req.cmd.xfer, cmd[0]);
289 #ifdef DEBUG_SCSI
291 int i;
292 for (i = 1; i < r->req.cmd.len; i++) {
293 printf(" 0x%02x", cmd[i]);
295 printf("\n");
297 #endif
299 if (r->req.cmd.xfer == 0) {
300 if (r->buf != NULL)
301 g_free(r->buf);
302 r->buflen = 0;
303 r->buf = NULL;
304 /* The request is used as the AIO opaque value, so add a ref. */
305 scsi_req_ref(&r->req);
306 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
307 if (ret < 0) {
308 scsi_command_complete(r, ret);
309 return 0;
311 return 0;
314 if (r->buflen != r->req.cmd.xfer) {
315 if (r->buf != NULL)
316 g_free(r->buf);
317 r->buf = g_malloc(r->req.cmd.xfer);
318 r->buflen = r->req.cmd.xfer;
321 memset(r->buf, 0, r->buflen);
322 r->len = r->req.cmd.xfer;
323 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
324 r->len = 0;
325 return -r->req.cmd.xfer;
326 } else {
327 return r->req.cmd.xfer;
331 static int get_stream_blocksize(BlockDriverState *bdrv)
333 uint8_t cmd[6];
334 uint8_t buf[12];
335 uint8_t sensebuf[8];
336 sg_io_hdr_t io_header;
337 int ret;
339 memset(cmd, 0, sizeof(cmd));
340 memset(buf, 0, sizeof(buf));
341 cmd[0] = MODE_SENSE;
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) {
357 return -1;
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)
377 int sg_version;
378 struct sg_scsi_id scsiid;
380 if (!s->conf.bs) {
381 error_report("scsi-generic: drive property not set");
382 return -1;
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*");
388 return -1;
391 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
392 error_report("Device doesn't support drive option werror");
393 return -1;
395 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
396 error_report("Device doesn't support drive option rerror");
397 return -1;
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");
404 return -1;
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");
410 return -1;
413 /* define device state */
414 s->type = scsiid.scsi_type;
415 DPRINTF("device type %d\n", s->type);
416 if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
417 add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
420 switch (s->type) {
421 case TYPE_TAPE:
422 s->blocksize = get_stream_blocksize(s->conf.bs);
423 if (s->blocksize == -1) {
424 s->blocksize = 0;
426 break;
428 /* Make a guess for block devices, we'll fix it when the guest sends.
429 * READ CAPACITY. If they don't, they likely would assume these sizes
430 * anyway. (TODO: they could also send MODE SENSE).
432 case TYPE_ROM:
433 case TYPE_WORM:
434 s->blocksize = 2048;
435 break;
436 default:
437 s->blocksize = 512;
438 break;
441 DPRINTF("block size %d\n", s->blocksize);
442 return 0;
445 const SCSIReqOps scsi_generic_req_ops = {
446 .size = sizeof(SCSIGenericReq),
447 .free_req = scsi_free_request,
448 .send_command = scsi_send_command,
449 .read_data = scsi_read_data,
450 .write_data = scsi_write_data,
451 .cancel_io = scsi_cancel_io,
452 .get_buf = scsi_get_buf,
455 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
456 uint8_t *buf, void *hba_private)
458 SCSIRequest *req;
460 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
461 return req;
464 static SCSIDeviceInfo scsi_generic_info = {
465 .qdev.name = "scsi-generic",
466 .qdev.fw_name = "disk",
467 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
468 .qdev.size = sizeof(SCSIDevice),
469 .qdev.reset = scsi_generic_reset,
470 .init = scsi_generic_initfn,
471 .destroy = scsi_destroy,
472 .alloc_req = scsi_new_request,
473 .qdev.props = (Property[]) {
474 DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
475 DEFINE_PROP_END_OF_LIST(),
479 static void scsi_generic_register_devices(void)
481 scsi_qdev_register(&scsi_generic_info);
483 device_init(scsi_generic_register_devices)
485 #endif /* __linux__ */