mipsnet: Fix compiler warning in debug code
[qemu/lumag.git] / hw / scsi-generic.c
blob7212091695f3f9970478c2364bf699576f67030e
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 SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
71 SCSIRequest *req;
73 req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
74 return DO_UPCAST(SCSIGenericReq, req, req);
77 static void scsi_remove_request(SCSIGenericReq *r)
79 qemu_free(r->buf);
80 scsi_req_free(&r->req);
83 static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
85 return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag));
88 /* Helper function for command completion. */
89 static void scsi_command_complete(void *opaque, int ret)
91 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
92 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
94 s->driver_status = r->io_header.driver_status;
95 if (s->driver_status & SG_ERR_DRIVER_SENSE)
96 s->senselen = r->io_header.sb_len_wr;
98 if (ret != 0)
99 r->req.status = BUSY << 1;
100 else {
101 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
102 r->req.status = BUSY << 1;
103 BADF("Driver Timeout\n");
104 } else if (r->io_header.status)
105 r->req.status = r->io_header.status;
106 else if (s->driver_status & SG_ERR_DRIVER_SENSE)
107 r->req.status = CHECK_CONDITION << 1;
108 else
109 r->req.status = GOOD << 1;
111 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
112 r, r->req.tag, r->req.status);
114 scsi_req_complete(&r->req);
115 scsi_remove_request(r);
118 /* Cancel a pending data transfer. */
119 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
121 DPRINTF("scsi_cancel_io 0x%x\n", tag);
122 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
123 SCSIGenericReq *r;
124 DPRINTF("Cancel tag=0x%x\n", tag);
125 r = scsi_find_request(s, tag);
126 if (r) {
127 if (r->req.aiocb)
128 bdrv_aio_cancel(r->req.aiocb);
129 r->req.aiocb = NULL;
130 scsi_remove_request(r);
134 static int execute_command(BlockDriverState *bdrv,
135 SCSIGenericReq *r, int direction,
136 BlockDriverCompletionFunc *complete)
138 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
140 r->io_header.interface_id = 'S';
141 r->io_header.dxfer_direction = direction;
142 r->io_header.dxferp = r->buf;
143 r->io_header.dxfer_len = r->buflen;
144 r->io_header.cmdp = r->req.cmd.buf;
145 r->io_header.cmd_len = r->req.cmd.len;
146 r->io_header.mx_sb_len = sizeof(s->sensebuf);
147 r->io_header.sbp = s->sensebuf;
148 r->io_header.timeout = MAX_UINT;
149 r->io_header.usr_ptr = r;
150 r->io_header.flags |= SG_FLAG_DIRECT_IO;
152 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
153 if (r->req.aiocb == NULL) {
154 BADF("execute_command: read failed !\n");
155 return -1;
158 return 0;
161 static void scsi_read_complete(void * opaque, int ret)
163 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
164 int len;
166 if (ret) {
167 DPRINTF("IO error ret %d\n", ret);
168 scsi_command_complete(r, ret);
169 return;
171 len = r->io_header.dxfer_len - r->io_header.resid;
172 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
174 r->len = -1;
175 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
176 if (len == 0)
177 scsi_command_complete(r, 0);
180 /* Read more data from scsi device into buffer. */
181 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
183 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
184 SCSIGenericReq *r;
185 int ret;
187 DPRINTF("scsi_read_data 0x%x\n", tag);
188 r = scsi_find_request(s, tag);
189 if (!r) {
190 BADF("Bad read tag 0x%x\n", tag);
191 /* ??? This is the wrong error. */
192 scsi_command_complete(r, -EINVAL);
193 return;
196 if (r->len == -1) {
197 scsi_command_complete(r, 0);
198 return;
201 if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
203 s->senselen = MIN(r->len, s->senselen);
204 memcpy(r->buf, s->sensebuf, s->senselen);
205 r->io_header.driver_status = 0;
206 r->io_header.status = 0;
207 r->io_header.dxfer_len = s->senselen;
208 r->len = -1;
209 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
210 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
211 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
212 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
213 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, s->senselen);
214 return;
217 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
218 if (ret == -1) {
219 scsi_command_complete(r, -EINVAL);
220 return;
224 static void scsi_write_complete(void * opaque, int ret)
226 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
227 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
229 DPRINTF("scsi_write_complete() ret = %d\n", ret);
230 if (ret) {
231 DPRINTF("IO error\n");
232 scsi_command_complete(r, ret);
233 return;
236 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
237 s->qdev.type == TYPE_TAPE) {
238 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
239 DPRINTF("block size %d\n", s->qdev.blocksize);
242 scsi_command_complete(r, ret);
245 /* Write data to a scsi device. Returns nonzero on failure.
246 The transfer may complete asynchronously. */
247 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
249 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
250 SCSIGenericReq *r;
251 int ret;
253 DPRINTF("scsi_write_data 0x%x\n", tag);
254 r = scsi_find_request(s, tag);
255 if (!r) {
256 BADF("Bad write tag 0x%x\n", tag);
257 /* ??? This is the wrong error. */
258 scsi_command_complete(r, -EINVAL);
259 return 0;
262 if (r->len == 0) {
263 r->len = r->buflen;
264 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
265 return 0;
268 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
269 if (ret == -1) {
270 scsi_command_complete(r, -EINVAL);
271 return 1;
274 return 0;
277 /* Return a pointer to the data buffer. */
278 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
280 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
281 SCSIGenericReq *r;
282 r = scsi_find_request(s, tag);
283 if (!r) {
284 BADF("Bad buffer tag 0x%x\n", tag);
285 return NULL;
287 return r->buf;
290 static void scsi_req_fixup(SCSIRequest *req)
292 switch(req->cmd.buf[0]) {
293 case WRITE_10:
294 req->cmd.buf[1] &= ~0x08; /* disable FUA */
295 break;
296 case READ_10:
297 req->cmd.buf[1] &= ~0x08; /* disable FUA */
298 break;
299 case REWIND:
300 case START_STOP:
301 if (req->dev->type == TYPE_TAPE) {
302 /* force IMMED, otherwise qemu waits end of command */
303 req->cmd.buf[1] = 0x01;
305 break;
309 /* Execute a scsi command. Returns the length of the data expected by the
310 command. This will be Positive for data transfers from the device
311 (eg. disk reads), negative for transfers to the device (eg. disk writes),
312 and zero if the command does not transfer any data. */
314 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
315 uint8_t *cmd, int lun)
317 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
318 SCSIGenericReq *r;
319 SCSIBus *bus;
320 int ret;
322 if (cmd[0] != REQUEST_SENSE &&
323 (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
324 DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
326 s->sensebuf[0] = 0x70;
327 s->sensebuf[1] = 0x00;
328 s->sensebuf[2] = ILLEGAL_REQUEST;
329 s->sensebuf[3] = 0x00;
330 s->sensebuf[4] = 0x00;
331 s->sensebuf[5] = 0x00;
332 s->sensebuf[6] = 0x00;
333 s->senselen = 7;
334 s->driver_status = SG_ERR_DRIVER_SENSE;
335 bus = scsi_bus_from_device(d);
336 bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
337 return 0;
340 r = scsi_find_request(s, tag);
341 if (r) {
342 BADF("Tag 0x%x already in use %p\n", tag, r);
343 scsi_cancel_io(d, tag);
345 r = scsi_new_request(d, tag, lun);
347 if (-1 == scsi_req_parse(&r->req, cmd)) {
348 BADF("Unsupported command length, command %x\n", cmd[0]);
349 scsi_remove_request(r);
350 return 0;
352 scsi_req_fixup(&r->req);
354 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
355 r->req.cmd.xfer, cmd[0]);
357 #ifdef DEBUG_SCSI
359 int i;
360 for (i = 1; i < r->req.cmd.len; i++) {
361 printf(" 0x%02x", cmd[i]);
363 printf("\n");
365 #endif
367 if (r->req.cmd.xfer == 0) {
368 if (r->buf != NULL)
369 qemu_free(r->buf);
370 r->buflen = 0;
371 r->buf = NULL;
372 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
373 if (ret == -1) {
374 scsi_command_complete(r, -EINVAL);
375 return 0;
377 return 0;
380 if (r->buflen != r->req.cmd.xfer) {
381 if (r->buf != NULL)
382 qemu_free(r->buf);
383 r->buf = qemu_malloc(r->req.cmd.xfer);
384 r->buflen = r->req.cmd.xfer;
387 memset(r->buf, 0, r->buflen);
388 r->len = r->req.cmd.xfer;
389 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
390 r->len = 0;
391 return -r->req.cmd.xfer;
394 return r->req.cmd.xfer;
397 static int get_blocksize(BlockDriverState *bdrv)
399 uint8_t cmd[10];
400 uint8_t buf[8];
401 uint8_t sensebuf[8];
402 sg_io_hdr_t io_header;
403 int ret;
405 memset(cmd, 0, sizeof(cmd));
406 memset(buf, 0, sizeof(buf));
407 cmd[0] = READ_CAPACITY;
409 memset(&io_header, 0, sizeof(io_header));
410 io_header.interface_id = 'S';
411 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
412 io_header.dxfer_len = sizeof(buf);
413 io_header.dxferp = buf;
414 io_header.cmdp = cmd;
415 io_header.cmd_len = sizeof(cmd);
416 io_header.mx_sb_len = sizeof(sensebuf);
417 io_header.sbp = sensebuf;
418 io_header.timeout = 6000; /* XXX */
420 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
421 if (ret < 0)
422 return -1;
424 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
427 static int get_stream_blocksize(BlockDriverState *bdrv)
429 uint8_t cmd[6];
430 uint8_t buf[12];
431 uint8_t sensebuf[8];
432 sg_io_hdr_t io_header;
433 int ret;
435 memset(cmd, 0, sizeof(cmd));
436 memset(buf, 0, sizeof(buf));
437 cmd[0] = MODE_SENSE;
438 cmd[4] = sizeof(buf);
440 memset(&io_header, 0, sizeof(io_header));
441 io_header.interface_id = 'S';
442 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
443 io_header.dxfer_len = sizeof(buf);
444 io_header.dxferp = buf;
445 io_header.cmdp = cmd;
446 io_header.cmd_len = sizeof(cmd);
447 io_header.mx_sb_len = sizeof(sensebuf);
448 io_header.sbp = sensebuf;
449 io_header.timeout = 6000; /* XXX */
451 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
452 if (ret < 0)
453 return -1;
455 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
458 static void scsi_generic_purge_requests(SCSIGenericState *s)
460 SCSIGenericReq *r;
462 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
463 r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
464 if (r->req.aiocb) {
465 bdrv_aio_cancel(r->req.aiocb);
467 scsi_remove_request(r);
471 static void scsi_generic_reset(DeviceState *dev)
473 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
475 scsi_generic_purge_requests(s);
478 static void scsi_destroy(SCSIDevice *d)
480 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
482 scsi_generic_purge_requests(s);
483 blockdev_mark_auto_del(s->qdev.conf.bs);
486 static int scsi_generic_initfn(SCSIDevice *dev)
488 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
489 int sg_version;
490 struct sg_scsi_id scsiid;
492 if (!s->qdev.conf.bs) {
493 error_report("scsi-generic: drive property not set");
494 return -1;
496 s->bs = s->qdev.conf.bs;
498 /* check we are really using a /dev/sg* file */
499 if (!bdrv_is_sg(s->bs)) {
500 error_report("scsi-generic: not /dev/sg*");
501 return -1;
504 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
505 error_report("Device doesn't support drive option werror");
506 return -1;
508 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
509 error_report("Device doesn't support drive option rerror");
510 return -1;
513 /* check we are using a driver managing SG_IO (version 3 and after */
514 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
515 sg_version < 30000) {
516 error_report("scsi-generic: scsi generic interface too old");
517 return -1;
520 /* get LUN of the /dev/sg? */
521 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
522 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
523 return -1;
526 /* define device state */
527 s->lun = scsiid.lun;
528 DPRINTF("LUN %d\n", s->lun);
529 s->qdev.type = scsiid.scsi_type;
530 DPRINTF("device type %d\n", s->qdev.type);
531 if (s->qdev.type == TYPE_TAPE) {
532 s->qdev.blocksize = get_stream_blocksize(s->bs);
533 if (s->qdev.blocksize == -1)
534 s->qdev.blocksize = 0;
535 } else {
536 s->qdev.blocksize = get_blocksize(s->bs);
537 /* removable media returns 0 if not present */
538 if (s->qdev.blocksize <= 0) {
539 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
540 s->qdev.blocksize = 2048;
541 else
542 s->qdev.blocksize = 512;
545 DPRINTF("block size %d\n", s->qdev.blocksize);
546 s->driver_status = 0;
547 memset(s->sensebuf, 0, sizeof(s->sensebuf));
548 bdrv_set_removable(s->bs, 0);
549 return 0;
552 static SCSIDeviceInfo scsi_generic_info = {
553 .qdev.name = "scsi-generic",
554 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
555 .qdev.size = sizeof(SCSIGenericState),
556 .qdev.reset = scsi_generic_reset,
557 .init = scsi_generic_initfn,
558 .destroy = scsi_destroy,
559 .send_command = scsi_send_command,
560 .read_data = scsi_read_data,
561 .write_data = scsi_write_data,
562 .cancel_io = scsi_cancel_io,
563 .get_buf = scsi_get_buf,
564 .qdev.props = (Property[]) {
565 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
566 DEFINE_PROP_END_OF_LIST(),
570 static void scsi_generic_register_devices(void)
572 scsi_qdev_register(&scsi_generic_info);
574 device_init(scsi_generic_register_devices)
576 #endif /* __linux__ */