scsi: move request-related callbacks from SCSIDeviceInfo to SCSIReqOps
[qemu/mdroth.git] / hw / scsi-generic.c
blobc2bd3999569ca503ec0fb62588aa1e1b7c784b5c
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 #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;
66 static void scsi_free_request(SCSIRequest *req)
68 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
70 qemu_free(r->buf);
73 /* Helper function for command completion. */
74 static void scsi_command_complete(void *opaque, int ret)
76 int status;
77 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
79 r->req.aiocb = NULL;
80 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE)
81 r->req.sense_len = r->io_header.sb_len_wr;
83 if (ret != 0) {
84 switch (ret) {
85 case -EDOM:
86 status = TASK_SET_FULL;
87 break;
88 case -EINVAL:
89 status = CHECK_CONDITION;
90 scsi_req_build_sense(&r->req, SENSE_CODE(INVALID_FIELD));
91 break;
92 case -ENOMEM:
93 status = CHECK_CONDITION;
94 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
95 break;
96 default:
97 status = CHECK_CONDITION;
98 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
99 break;
101 } else {
102 if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) {
103 status = BUSY;
104 BADF("Driver Timeout\n");
105 } else if (r->io_header.status) {
106 status = r->io_header.status;
107 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
108 status = CHECK_CONDITION;
109 } else {
110 status = GOOD;
113 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
114 r, r->req.tag, status);
116 scsi_req_complete(&r->req, status);
119 /* Cancel a pending data transfer. */
120 static void scsi_cancel_io(SCSIRequest *req)
122 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
124 DPRINTF("Cancel tag=0x%x\n", req->tag);
125 if (r->req.aiocb) {
126 bdrv_aio_cancel(r->req.aiocb);
128 r->req.aiocb = NULL;
131 static int execute_command(BlockDriverState *bdrv,
132 SCSIGenericReq *r, int direction,
133 BlockDriverCompletionFunc *complete)
135 r->io_header.interface_id = 'S';
136 r->io_header.dxfer_direction = direction;
137 r->io_header.dxferp = r->buf;
138 r->io_header.dxfer_len = r->buflen;
139 r->io_header.cmdp = r->req.cmd.buf;
140 r->io_header.cmd_len = r->req.cmd.len;
141 r->io_header.mx_sb_len = sizeof(r->req.sense);
142 r->io_header.sbp = r->req.sense;
143 r->io_header.timeout = MAX_UINT;
144 r->io_header.usr_ptr = r;
145 r->io_header.flags |= SG_FLAG_DIRECT_IO;
147 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
148 if (r->req.aiocb == NULL) {
149 BADF("execute_command: read failed !\n");
150 return -ENOMEM;
153 return 0;
156 static void scsi_read_complete(void * opaque, int ret)
158 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
159 int len;
161 r->req.aiocb = NULL;
162 if (ret) {
163 DPRINTF("IO error ret %d\n", ret);
164 scsi_command_complete(r, ret);
165 return;
167 len = r->io_header.dxfer_len - r->io_header.resid;
168 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
170 r->len = -1;
171 if (len == 0) {
172 scsi_command_complete(r, 0);
173 } else {
174 scsi_req_data(&r->req, len);
178 /* Read more data from scsi device into buffer. */
179 static void scsi_read_data(SCSIRequest *req)
181 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
182 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
183 int ret;
185 DPRINTF("scsi_read_data 0x%x\n", req->tag);
186 if (r->len == -1) {
187 scsi_command_complete(r, 0);
188 return;
191 if (r->req.cmd.buf[0] == REQUEST_SENSE) {
192 r->io_header.driver_status = 0;
193 r->io_header.status = 0;
194 r->io_header.dxfer_len =
195 scsi_device_get_sense(&s->qdev, r->buf, r->req.cmd.xfer,
196 (r->req.cmd.buf[1] & 1) == 0);
197 r->len = -1;
198 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, r->io_header.dxfer_len);
199 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
200 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
201 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
202 scsi_req_data(&r->req, r->io_header.dxfer_len);
203 /* The sense buffer is cleared when we return GOOD */
204 return;
207 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
208 if (ret < 0) {
209 scsi_command_complete(r, ret);
210 return;
214 static void scsi_write_complete(void * opaque, int ret)
216 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
217 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
219 DPRINTF("scsi_write_complete() ret = %d\n", ret);
220 r->req.aiocb = NULL;
221 if (ret) {
222 DPRINTF("IO error\n");
223 scsi_command_complete(r, ret);
224 return;
227 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
228 s->qdev.type == TYPE_TAPE) {
229 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
230 DPRINTF("block size %d\n", s->qdev.blocksize);
233 scsi_command_complete(r, ret);
236 /* Write data to a scsi device. Returns nonzero on failure.
237 The transfer may complete asynchronously. */
238 static void scsi_write_data(SCSIRequest *req)
240 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
241 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
242 int ret;
244 DPRINTF("scsi_write_data 0x%x\n", req->tag);
245 if (r->len == 0) {
246 r->len = r->buflen;
247 scsi_req_data(&r->req, r->len);
248 return;
251 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
252 if (ret < 0) {
253 scsi_command_complete(r, ret);
257 /* Return a pointer to the data buffer. */
258 static uint8_t *scsi_get_buf(SCSIRequest *req)
260 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
262 return r->buf;
265 static void scsi_req_fixup(SCSIRequest *req)
267 switch(req->cmd.buf[0]) {
268 case WRITE_10:
269 req->cmd.buf[1] &= ~0x08; /* disable FUA */
270 break;
271 case READ_10:
272 req->cmd.buf[1] &= ~0x08; /* disable FUA */
273 break;
274 case REWIND:
275 case START_STOP:
276 if (req->dev->type == TYPE_TAPE) {
277 /* force IMMED, otherwise qemu waits end of command */
278 req->cmd.buf[1] = 0x01;
280 break;
284 /* Execute a scsi command. Returns the length of the data expected by the
285 command. This will be Positive for data transfers from the device
286 (eg. disk reads), negative for transfers to the device (eg. disk writes),
287 and zero if the command does not transfer any data. */
289 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
291 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
292 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
293 int ret;
295 if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
296 DPRINTF("Unimplemented LUN %d\n", req->lun);
297 scsi_req_build_sense(&r->req, SENSE_CODE(LUN_NOT_SUPPORTED));
298 scsi_req_complete(&r->req, CHECK_CONDITION);
299 return 0;
302 if (-1 == scsi_req_parse(&r->req, cmd)) {
303 BADF("Unsupported command length, command %x\n", cmd[0]);
304 scsi_command_complete(r, -EINVAL);
305 return 0;
307 scsi_req_fixup(&r->req);
309 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
310 r->req.cmd.xfer, cmd[0]);
312 #ifdef DEBUG_SCSI
314 int i;
315 for (i = 1; i < r->req.cmd.len; i++) {
316 printf(" 0x%02x", cmd[i]);
318 printf("\n");
320 #endif
322 if (r->req.cmd.xfer == 0) {
323 if (r->buf != NULL)
324 qemu_free(r->buf);
325 r->buflen = 0;
326 r->buf = NULL;
327 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
328 if (ret < 0) {
329 scsi_command_complete(r, ret);
330 return 0;
332 return 0;
335 if (r->buflen != r->req.cmd.xfer) {
336 if (r->buf != NULL)
337 qemu_free(r->buf);
338 r->buf = qemu_malloc(r->req.cmd.xfer);
339 r->buflen = r->req.cmd.xfer;
342 memset(r->buf, 0, r->buflen);
343 r->len = r->req.cmd.xfer;
344 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
345 r->len = 0;
346 return -r->req.cmd.xfer;
347 } else {
348 return r->req.cmd.xfer;
352 static int get_blocksize(BlockDriverState *bdrv)
354 uint8_t cmd[10];
355 uint8_t buf[8];
356 uint8_t sensebuf[8];
357 sg_io_hdr_t io_header;
358 int ret;
360 memset(cmd, 0, sizeof(cmd));
361 memset(buf, 0, sizeof(buf));
362 cmd[0] = READ_CAPACITY_10;
364 memset(&io_header, 0, sizeof(io_header));
365 io_header.interface_id = 'S';
366 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
367 io_header.dxfer_len = sizeof(buf);
368 io_header.dxferp = buf;
369 io_header.cmdp = cmd;
370 io_header.cmd_len = sizeof(cmd);
371 io_header.mx_sb_len = sizeof(sensebuf);
372 io_header.sbp = sensebuf;
373 io_header.timeout = 6000; /* XXX */
375 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
376 if (ret < 0)
377 return -1;
379 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
382 static int get_stream_blocksize(BlockDriverState *bdrv)
384 uint8_t cmd[6];
385 uint8_t buf[12];
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] = MODE_SENSE;
393 cmd[4] = sizeof(buf);
395 memset(&io_header, 0, sizeof(io_header));
396 io_header.interface_id = 'S';
397 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
398 io_header.dxfer_len = sizeof(buf);
399 io_header.dxferp = buf;
400 io_header.cmdp = cmd;
401 io_header.cmd_len = sizeof(cmd);
402 io_header.mx_sb_len = sizeof(sensebuf);
403 io_header.sbp = sensebuf;
404 io_header.timeout = 6000; /* XXX */
406 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
407 if (ret < 0)
408 return -1;
410 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
413 static void scsi_generic_reset(DeviceState *dev)
415 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
417 scsi_device_purge_requests(&s->qdev);
420 static void scsi_destroy(SCSIDevice *d)
422 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
424 scsi_device_purge_requests(&s->qdev);
425 blockdev_mark_auto_del(s->qdev.conf.bs);
428 static int scsi_generic_initfn(SCSIDevice *dev)
430 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
431 int sg_version;
432 struct sg_scsi_id scsiid;
434 if (!s->qdev.conf.bs) {
435 error_report("scsi-generic: drive property not set");
436 return -1;
438 s->bs = s->qdev.conf.bs;
440 /* check we are really using a /dev/sg* file */
441 if (!bdrv_is_sg(s->bs)) {
442 error_report("scsi-generic: not /dev/sg*");
443 return -1;
446 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
447 error_report("Device doesn't support drive option werror");
448 return -1;
450 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
451 error_report("Device doesn't support drive option rerror");
452 return -1;
455 /* check we are using a driver managing SG_IO (version 3 and after */
456 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
457 sg_version < 30000) {
458 error_report("scsi-generic: scsi generic interface too old");
459 return -1;
462 /* get LUN of the /dev/sg? */
463 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
464 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
465 return -1;
468 /* define device state */
469 s->lun = scsiid.lun;
470 DPRINTF("LUN %d\n", s->lun);
471 s->qdev.type = scsiid.scsi_type;
472 DPRINTF("device type %d\n", s->qdev.type);
473 if (s->qdev.type == TYPE_TAPE) {
474 s->qdev.blocksize = get_stream_blocksize(s->bs);
475 if (s->qdev.blocksize == -1)
476 s->qdev.blocksize = 0;
477 } else {
478 s->qdev.blocksize = get_blocksize(s->bs);
479 /* removable media returns 0 if not present */
480 if (s->qdev.blocksize <= 0) {
481 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
482 s->qdev.blocksize = 2048;
483 else
484 s->qdev.blocksize = 512;
487 DPRINTF("block size %d\n", s->qdev.blocksize);
488 bdrv_set_removable(s->bs, 0);
489 return 0;
492 static SCSIReqOps scsi_generic_req_ops = {
493 .size = sizeof(SCSIGenericReq),
494 .free_req = scsi_free_request,
495 .send_command = scsi_send_command,
496 .read_data = scsi_read_data,
497 .write_data = scsi_write_data,
498 .cancel_io = scsi_cancel_io,
499 .get_buf = scsi_get_buf,
502 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
503 void *hba_private)
505 SCSIRequest *req;
507 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
508 return req;
511 static SCSIDeviceInfo scsi_generic_info = {
512 .qdev.name = "scsi-generic",
513 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
514 .qdev.size = sizeof(SCSIGenericState),
515 .qdev.reset = scsi_generic_reset,
516 .init = scsi_generic_initfn,
517 .destroy = scsi_destroy,
518 .alloc_req = scsi_new_request,
519 .qdev.props = (Property[]) {
520 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
521 DEFINE_PROP_END_OF_LIST(),
525 static void scsi_generic_register_devices(void)
527 scsi_qdev_register(&scsi_generic_info);
529 device_init(scsi_generic_register_devices)
531 #endif /* __linux__ */