scsi: introduce scsi_req_continue
[qemu/aliguori.git] / hw / scsi-generic.c
blob90f2a4af1b0886f8deb0bedc8c584adc78d2949a
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 licenced 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 #ifndef MAX_UINT
46 #define MAX_UINT ((unsigned int)-1)
47 #endif
49 typedef struct SCSIGenericState SCSIGenericState;
51 typedef struct SCSIGenericReq {
52 SCSIRequest req;
53 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
57 } SCSIGenericReq;
59 struct SCSIGenericState
61 SCSIDevice qdev;
62 BlockDriverState *bs;
63 int lun;
64 int driver_status;
65 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
66 uint8_t senselen;
69 static void scsi_set_sense(SCSIGenericState *s, SCSISense sense)
71 s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0);
72 s->driver_status = SG_ERR_DRIVER_SENSE;
75 static void scsi_clear_sense(SCSIGenericState *s)
77 memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE);
78 s->senselen = 0;
79 s->driver_status = 0;
82 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
84 SCSIRequest *req;
86 req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
87 return req;
90 static void scsi_free_request(SCSIRequest *req)
92 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
94 qemu_free(r->buf);
97 /* Helper function for command completion. */
98 static void scsi_command_complete(void *opaque, int ret)
100 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
101 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
103 r->req.aiocb = NULL;
104 s->driver_status = r->io_header.driver_status;
105 if (s->driver_status & SG_ERR_DRIVER_SENSE)
106 s->senselen = r->io_header.sb_len_wr;
108 if (ret != 0) {
109 switch (ret) {
110 case -EINVAL:
111 r->req.status = CHECK_CONDITION;
112 scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
113 break;
114 case -ENOMEM:
115 r->req.status = CHECK_CONDITION;
116 scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
117 break;
118 default:
119 r->req.status = CHECK_CONDITION;
120 scsi_set_sense(s, SENSE_CODE(IO_ERROR));
121 break;
123 } else {
124 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
125 r->req.status = BUSY;
126 BADF("Driver Timeout\n");
127 } else if (r->io_header.status)
128 r->req.status = r->io_header.status;
129 else if (s->driver_status & SG_ERR_DRIVER_SENSE)
130 r->req.status = CHECK_CONDITION;
131 else
132 r->req.status = GOOD;
134 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135 r, r->req.tag, r->req.status);
137 scsi_req_complete(&r->req);
140 /* Cancel a pending data transfer. */
141 static void scsi_cancel_io(SCSIRequest *req)
143 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
145 DPRINTF("Cancel tag=0x%x\n", req->tag);
146 if (r->req.aiocb) {
147 bdrv_aio_cancel(r->req.aiocb);
149 r->req.aiocb = NULL;
152 static int execute_command(BlockDriverState *bdrv,
153 SCSIGenericReq *r, int direction,
154 BlockDriverCompletionFunc *complete)
156 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
158 r->io_header.interface_id = 'S';
159 r->io_header.dxfer_direction = direction;
160 r->io_header.dxferp = r->buf;
161 r->io_header.dxfer_len = r->buflen;
162 r->io_header.cmdp = r->req.cmd.buf;
163 r->io_header.cmd_len = r->req.cmd.len;
164 r->io_header.mx_sb_len = sizeof(s->sensebuf);
165 r->io_header.sbp = s->sensebuf;
166 r->io_header.timeout = MAX_UINT;
167 r->io_header.usr_ptr = r;
168 r->io_header.flags |= SG_FLAG_DIRECT_IO;
170 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
171 if (r->req.aiocb == NULL) {
172 BADF("execute_command: read failed !\n");
173 return -ENOMEM;
176 return 0;
179 static void scsi_read_complete(void * opaque, int ret)
181 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
182 int len;
184 r->req.aiocb = NULL;
185 if (ret) {
186 DPRINTF("IO error ret %d\n", ret);
187 scsi_command_complete(r, ret);
188 return;
190 len = r->io_header.dxfer_len - r->io_header.resid;
191 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
193 r->len = -1;
194 if (len == 0) {
195 scsi_command_complete(r, 0);
196 } else {
197 scsi_req_data(&r->req, len);
201 /* Read more data from scsi device into buffer. */
202 static void scsi_read_data(SCSIRequest *req)
204 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
205 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
206 int ret;
208 DPRINTF("scsi_read_data 0x%x\n", req->tag);
209 if (r->len == -1) {
210 scsi_command_complete(r, 0);
211 return;
214 if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
216 s->senselen = MIN(r->len, s->senselen);
217 memcpy(r->buf, s->sensebuf, s->senselen);
218 r->io_header.driver_status = 0;
219 r->io_header.status = 0;
220 r->io_header.dxfer_len = s->senselen;
221 r->len = -1;
222 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
223 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
224 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
225 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
226 scsi_req_data(&r->req, s->senselen);
227 /* Clear sensebuf after REQUEST_SENSE */
228 scsi_clear_sense(s);
229 return;
232 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
233 if (ret < 0) {
234 scsi_command_complete(r, ret);
235 return;
239 static void scsi_write_complete(void * opaque, int ret)
241 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
242 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
244 DPRINTF("scsi_write_complete() ret = %d\n", ret);
245 r->req.aiocb = NULL;
246 if (ret) {
247 DPRINTF("IO error\n");
248 scsi_command_complete(r, ret);
249 return;
252 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
253 s->qdev.type == TYPE_TAPE) {
254 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
255 DPRINTF("block size %d\n", s->qdev.blocksize);
258 scsi_command_complete(r, ret);
261 /* Write data to a scsi device. Returns nonzero on failure.
262 The transfer may complete asynchronously. */
263 static int scsi_write_data(SCSIRequest *req)
265 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
266 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267 int ret;
269 DPRINTF("scsi_write_data 0x%x\n", req->tag);
270 if (r->len == 0) {
271 r->len = r->buflen;
272 scsi_req_data(&r->req, r->len);
273 return 0;
276 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
277 if (ret < 0) {
278 scsi_command_complete(r, ret);
279 return 1;
282 return 0;
285 /* Return a pointer to the data buffer. */
286 static uint8_t *scsi_get_buf(SCSIRequest *req)
288 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
290 return r->buf;
293 static void scsi_req_fixup(SCSIRequest *req)
295 switch(req->cmd.buf[0]) {
296 case WRITE_10:
297 req->cmd.buf[1] &= ~0x08; /* disable FUA */
298 break;
299 case READ_10:
300 req->cmd.buf[1] &= ~0x08; /* disable FUA */
301 break;
302 case REWIND:
303 case START_STOP:
304 if (req->dev->type == TYPE_TAPE) {
305 /* force IMMED, otherwise qemu waits end of command */
306 req->cmd.buf[1] = 0x01;
308 break;
312 /* Execute a scsi command. Returns the length of the data expected by the
313 command. This will be Positive for data transfers from the device
314 (eg. disk reads), negative for transfers to the device (eg. disk writes),
315 and zero if the command does not transfer any data. */
317 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
319 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
320 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
321 int ret;
323 if (cmd[0] != REQUEST_SENSE &&
324 (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
325 DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
326 scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
327 r->req.status = CHECK_CONDITION;
328 scsi_req_complete(&r->req);
329 return 0;
332 if (-1 == scsi_req_parse(&r->req, cmd)) {
333 BADF("Unsupported command length, command %x\n", cmd[0]);
334 scsi_command_complete(r, -EINVAL);
335 return 0;
337 scsi_req_fixup(&r->req);
339 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
340 r->req.cmd.xfer, cmd[0]);
342 #ifdef DEBUG_SCSI
344 int i;
345 for (i = 1; i < r->req.cmd.len; i++) {
346 printf(" 0x%02x", cmd[i]);
348 printf("\n");
350 #endif
352 if (r->req.cmd.xfer == 0) {
353 if (r->buf != NULL)
354 qemu_free(r->buf);
355 r->buflen = 0;
356 r->buf = NULL;
357 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
358 if (ret < 0) {
359 scsi_command_complete(r, ret);
360 return 0;
362 return 0;
365 if (r->buflen != r->req.cmd.xfer) {
366 if (r->buf != NULL)
367 qemu_free(r->buf);
368 r->buf = qemu_malloc(r->req.cmd.xfer);
369 r->buflen = r->req.cmd.xfer;
372 memset(r->buf, 0, r->buflen);
373 r->len = r->req.cmd.xfer;
374 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
375 r->len = 0;
376 return -r->req.cmd.xfer;
377 } else {
378 return r->req.cmd.xfer;
382 static int get_blocksize(BlockDriverState *bdrv)
384 uint8_t cmd[10];
385 uint8_t buf[8];
386 uint8_t sensebuf[8];
387 sg_io_hdr_t io_header;
388 int ret;
390 memset(cmd, 0, sizeof(cmd));
391 memset(buf, 0, sizeof(buf));
392 cmd[0] = READ_CAPACITY;
394 memset(&io_header, 0, sizeof(io_header));
395 io_header.interface_id = 'S';
396 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
397 io_header.dxfer_len = sizeof(buf);
398 io_header.dxferp = buf;
399 io_header.cmdp = cmd;
400 io_header.cmd_len = sizeof(cmd);
401 io_header.mx_sb_len = sizeof(sensebuf);
402 io_header.sbp = sensebuf;
403 io_header.timeout = 6000; /* XXX */
405 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
406 if (ret < 0)
407 return -1;
409 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
412 static int get_stream_blocksize(BlockDriverState *bdrv)
414 uint8_t cmd[6];
415 uint8_t buf[12];
416 uint8_t sensebuf[8];
417 sg_io_hdr_t io_header;
418 int ret;
420 memset(cmd, 0, sizeof(cmd));
421 memset(buf, 0, sizeof(buf));
422 cmd[0] = MODE_SENSE;
423 cmd[4] = sizeof(buf);
425 memset(&io_header, 0, sizeof(io_header));
426 io_header.interface_id = 'S';
427 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
428 io_header.dxfer_len = sizeof(buf);
429 io_header.dxferp = buf;
430 io_header.cmdp = cmd;
431 io_header.cmd_len = sizeof(cmd);
432 io_header.mx_sb_len = sizeof(sensebuf);
433 io_header.sbp = sensebuf;
434 io_header.timeout = 6000; /* XXX */
436 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
437 if (ret < 0)
438 return -1;
440 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
443 static void scsi_generic_reset(DeviceState *dev)
445 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
447 scsi_device_purge_requests(&s->qdev);
450 static void scsi_destroy(SCSIDevice *d)
452 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
454 scsi_device_purge_requests(&s->qdev);
455 blockdev_mark_auto_del(s->qdev.conf.bs);
458 static int scsi_generic_initfn(SCSIDevice *dev)
460 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
461 int sg_version;
462 struct sg_scsi_id scsiid;
464 if (!s->qdev.conf.bs) {
465 error_report("scsi-generic: drive property not set");
466 return -1;
468 s->bs = s->qdev.conf.bs;
470 /* check we are really using a /dev/sg* file */
471 if (!bdrv_is_sg(s->bs)) {
472 error_report("scsi-generic: not /dev/sg*");
473 return -1;
476 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
477 error_report("Device doesn't support drive option werror");
478 return -1;
480 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
481 error_report("Device doesn't support drive option rerror");
482 return -1;
485 /* check we are using a driver managing SG_IO (version 3 and after */
486 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
487 sg_version < 30000) {
488 error_report("scsi-generic: scsi generic interface too old");
489 return -1;
492 /* get LUN of the /dev/sg? */
493 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
494 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
495 return -1;
498 /* define device state */
499 s->lun = scsiid.lun;
500 DPRINTF("LUN %d\n", s->lun);
501 s->qdev.type = scsiid.scsi_type;
502 DPRINTF("device type %d\n", s->qdev.type);
503 if (s->qdev.type == TYPE_TAPE) {
504 s->qdev.blocksize = get_stream_blocksize(s->bs);
505 if (s->qdev.blocksize == -1)
506 s->qdev.blocksize = 0;
507 } else {
508 s->qdev.blocksize = get_blocksize(s->bs);
509 /* removable media returns 0 if not present */
510 if (s->qdev.blocksize <= 0) {
511 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
512 s->qdev.blocksize = 2048;
513 else
514 s->qdev.blocksize = 512;
517 DPRINTF("block size %d\n", s->qdev.blocksize);
518 s->driver_status = 0;
519 memset(s->sensebuf, 0, sizeof(s->sensebuf));
520 bdrv_set_removable(s->bs, 0);
521 return 0;
524 static SCSIDeviceInfo scsi_generic_info = {
525 .qdev.name = "scsi-generic",
526 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
527 .qdev.size = sizeof(SCSIGenericState),
528 .qdev.reset = scsi_generic_reset,
529 .init = scsi_generic_initfn,
530 .destroy = scsi_destroy,
531 .alloc_req = scsi_new_request,
532 .free_req = scsi_free_request,
533 .send_command = scsi_send_command,
534 .read_data = scsi_read_data,
535 .write_data = scsi_write_data,
536 .cancel_io = scsi_cancel_io,
537 .get_buf = scsi_get_buf,
538 .qdev.props = (Property[]) {
539 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
540 DEFINE_PROP_END_OF_LIST(),
544 static void scsi_generic_register_devices(void)
546 scsi_qdev_register(&scsi_generic_info);
548 device_init(scsi_generic_register_devices)
550 #endif /* __linux__ */