scsi: add xfer mode
[qemu/kraxel.git] / hw / scsi-generic.c
blobe81facc7b6b1add1e6fc1b38a4a2404234cce68a
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 "block.h"
16 #include "scsi.h"
18 #ifdef __linux__
20 //#define DEBUG_SCSI
22 #ifdef DEBUG_SCSI
23 #define DPRINTF(fmt, ...) \
24 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
25 #else
26 #define DPRINTF(fmt, ...) do {} while(0)
27 #endif
29 #define BADF(fmt, ...) \
30 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <scsi/sg.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
44 #ifndef MAX_UINT
45 #define MAX_UINT ((unsigned int)-1)
46 #endif
48 typedef struct SCSIGenericState SCSIGenericState;
50 typedef struct SCSIGenericReq {
51 SCSIRequest req;
52 uint8_t *buf;
53 int buflen;
54 int len;
55 sg_io_hdr_t io_header;
56 } SCSIGenericReq;
58 struct SCSIGenericState
60 SCSIDevice qdev;
61 DriveInfo *dinfo;
62 int lun;
63 int driver_status;
64 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
65 uint8_t senselen;
68 static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
70 SCSIRequest *req;
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)
78 qemu_free(r->buf);
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);
92 uint32_t tag;
93 int status;
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;
99 if (ret != 0)
100 status = BUSY << 1;
101 else {
102 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
103 status = BUSY << 1;
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;
109 else
110 status = GOOD << 1;
112 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113 r, r->req.tag, status);
114 tag = r->req.tag;
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);
124 SCSIGenericReq *r;
125 DPRINTF("Cancel tag=0x%x\n", tag);
126 r = scsi_find_request(s, tag);
127 if (r) {
128 if (r->req.aiocb)
129 bdrv_aio_cancel(r->req.aiocb);
130 r->req.aiocb = NULL;
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");
156 return -1;
159 return 0;
162 static void scsi_read_complete(void * opaque, int ret)
164 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
165 int len;
167 if (ret) {
168 DPRINTF("IO error\n");
169 scsi_command_complete(r, ret);
170 return;
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);
175 r->len = -1;
176 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
177 if (len == 0)
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);
185 SCSIGenericReq *r;
186 int ret;
188 DPRINTF("scsi_read_data 0x%x\n", tag);
189 r = scsi_find_request(s, tag);
190 if (!r) {
191 BADF("Bad read tag 0x%x\n", tag);
192 /* ??? This is the wrong error. */
193 scsi_command_complete(r, -EINVAL);
194 return;
197 if (r->len == -1) {
198 scsi_command_complete(r, 0);
199 return;
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;
209 r->len = -1;
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);
215 return;
218 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
219 if (ret == -1) {
220 scsi_command_complete(r, -EINVAL);
221 return;
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);
231 if (ret) {
232 DPRINTF("IO error\n");
233 scsi_command_complete(r, ret);
234 return;
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);
251 SCSIGenericReq *r;
252 int ret;
254 DPRINTF("scsi_write_data 0x%x\n", tag);
255 r = scsi_find_request(s, tag);
256 if (!r) {
257 BADF("Bad write tag 0x%x\n", tag);
258 /* ??? This is the wrong error. */
259 scsi_command_complete(r, -EINVAL);
260 return 0;
263 if (r->len == 0) {
264 r->len = r->buflen;
265 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
266 return 0;
269 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
270 if (ret == -1) {
271 scsi_command_complete(r, -EINVAL);
272 return 1;
275 return 0;
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);
282 SCSIGenericReq *r;
283 r = scsi_find_request(s, tag);
284 if (!r) {
285 BADF("Bad buffer tag 0x%x\n", tag);
286 return NULL;
288 return r->buf;
291 static void scsi_req_fixup(SCSIRequest *req)
293 switch(req->cmd.buf[0]) {
294 case WRITE_10:
295 req->cmd.buf[1] &= ~0x08; /* disable FUA */
296 break;
297 case READ_10:
298 req->cmd.buf[1] &= ~0x08; /* disable FUA */
299 break;
300 case REWIND:
301 case START_STOP:
302 if (req->dev->type == TYPE_TAPE) {
303 /* force IMMED, otherwise qemu waits end of command */
304 req->cmd.buf[1] = 0x01;
306 break;
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);
319 SCSIGenericReq *r;
320 SCSIBus *bus;
321 int ret;
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;
334 s->senselen = 7;
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);
338 return 0;
341 r = scsi_find_request(s, tag);
342 if (r) {
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);
351 return 0;
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) {
359 if (r->buf != NULL)
360 qemu_free(r->buf);
361 r->buflen = 0;
362 r->buf = NULL;
363 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
364 if (ret == -1) {
365 scsi_command_complete(r, -EINVAL);
366 return 0;
368 return 0;
371 if (r->buflen != r->req.cmd.xfer) {
372 if (r->buf != NULL)
373 qemu_free(r->buf);
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) {
381 r->len = 0;
382 return -r->req.cmd.xfer;
385 return r->req.cmd.xfer;
388 static int get_blocksize(BlockDriverState *bdrv)
390 uint8_t cmd[10];
391 uint8_t buf[8];
392 uint8_t sensebuf[8];
393 sg_io_hdr_t io_header;
394 int ret;
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);
412 if (ret < 0)
413 return -1;
415 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
418 static int get_stream_blocksize(BlockDriverState *bdrv)
420 uint8_t cmd[6];
421 uint8_t buf[12];
422 uint8_t sensebuf[8];
423 sg_io_hdr_t io_header;
424 int ret;
426 memset(cmd, 0, sizeof(cmd));
427 memset(buf, 0, sizeof(buf));
428 cmd[0] = MODE_SENSE;
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);
443 if (ret < 0)
444 return -1;
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);
452 SCSIGenericReq *r;
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);
464 int sg_version;
465 struct sg_scsi_id scsiid;
467 if (!s->dinfo || !s->dinfo->bdrv) {
468 qemu_error("scsi-generic: drive property not set\n");
469 return -1;
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");
475 return -1;
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");
482 return -1;
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");
488 return -1;
491 /* define device state */
492 s->lun = scsiid.lun;
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;
500 } else {
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;
506 else
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));
513 return 0;
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__ */