scsi: Update sense code handling
[qemu/ar7.git] / hw / scsi-generic.c
blob64cbe8b8c07bb330e7806de6196ef110bb82c4fe
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 scsi_req_enqueue(req);
324 if (cmd[0] != REQUEST_SENSE &&
325 (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
326 DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
327 scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
328 r->req.status = CHECK_CONDITION;
329 scsi_req_complete(&r->req);
330 return 0;
333 if (-1 == scsi_req_parse(&r->req, cmd)) {
334 BADF("Unsupported command length, command %x\n", cmd[0]);
335 scsi_command_complete(r, -EINVAL);
336 return 0;
338 scsi_req_fixup(&r->req);
340 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
341 r->req.cmd.xfer, cmd[0]);
343 #ifdef DEBUG_SCSI
345 int i;
346 for (i = 1; i < r->req.cmd.len; i++) {
347 printf(" 0x%02x", cmd[i]);
349 printf("\n");
351 #endif
353 if (r->req.cmd.xfer == 0) {
354 if (r->buf != NULL)
355 qemu_free(r->buf);
356 r->buflen = 0;
357 r->buf = NULL;
358 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
359 if (ret < 0) {
360 scsi_command_complete(r, ret);
361 return 0;
363 return 0;
366 if (r->buflen != r->req.cmd.xfer) {
367 if (r->buf != NULL)
368 qemu_free(r->buf);
369 r->buf = qemu_malloc(r->req.cmd.xfer);
370 r->buflen = r->req.cmd.xfer;
373 memset(r->buf, 0, r->buflen);
374 r->len = r->req.cmd.xfer;
375 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
376 r->len = 0;
377 return -r->req.cmd.xfer;
378 } else {
379 return r->req.cmd.xfer;
383 static int get_blocksize(BlockDriverState *bdrv)
385 uint8_t cmd[10];
386 uint8_t buf[8];
387 uint8_t sensebuf[8];
388 sg_io_hdr_t io_header;
389 int ret;
391 memset(cmd, 0, sizeof(cmd));
392 memset(buf, 0, sizeof(buf));
393 cmd[0] = READ_CAPACITY;
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[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
413 static int get_stream_blocksize(BlockDriverState *bdrv)
415 uint8_t cmd[6];
416 uint8_t buf[12];
417 uint8_t sensebuf[8];
418 sg_io_hdr_t io_header;
419 int ret;
421 memset(cmd, 0, sizeof(cmd));
422 memset(buf, 0, sizeof(buf));
423 cmd[0] = MODE_SENSE;
424 cmd[4] = sizeof(buf);
426 memset(&io_header, 0, sizeof(io_header));
427 io_header.interface_id = 'S';
428 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
429 io_header.dxfer_len = sizeof(buf);
430 io_header.dxferp = buf;
431 io_header.cmdp = cmd;
432 io_header.cmd_len = sizeof(cmd);
433 io_header.mx_sb_len = sizeof(sensebuf);
434 io_header.sbp = sensebuf;
435 io_header.timeout = 6000; /* XXX */
437 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
438 if (ret < 0)
439 return -1;
441 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
444 static void scsi_generic_reset(DeviceState *dev)
446 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
448 scsi_device_purge_requests(&s->qdev);
451 static void scsi_destroy(SCSIDevice *d)
453 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
455 scsi_device_purge_requests(&s->qdev);
456 blockdev_mark_auto_del(s->qdev.conf.bs);
459 static int scsi_generic_initfn(SCSIDevice *dev)
461 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
462 int sg_version;
463 struct sg_scsi_id scsiid;
465 if (!s->qdev.conf.bs) {
466 error_report("scsi-generic: drive property not set");
467 return -1;
469 s->bs = s->qdev.conf.bs;
471 /* check we are really using a /dev/sg* file */
472 if (!bdrv_is_sg(s->bs)) {
473 error_report("scsi-generic: not /dev/sg*");
474 return -1;
477 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
478 error_report("Device doesn't support drive option werror");
479 return -1;
481 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
482 error_report("Device doesn't support drive option rerror");
483 return -1;
486 /* check we are using a driver managing SG_IO (version 3 and after */
487 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
488 sg_version < 30000) {
489 error_report("scsi-generic: scsi generic interface too old");
490 return -1;
493 /* get LUN of the /dev/sg? */
494 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
495 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
496 return -1;
499 /* define device state */
500 s->lun = scsiid.lun;
501 DPRINTF("LUN %d\n", s->lun);
502 s->qdev.type = scsiid.scsi_type;
503 DPRINTF("device type %d\n", s->qdev.type);
504 if (s->qdev.type == TYPE_TAPE) {
505 s->qdev.blocksize = get_stream_blocksize(s->bs);
506 if (s->qdev.blocksize == -1)
507 s->qdev.blocksize = 0;
508 } else {
509 s->qdev.blocksize = get_blocksize(s->bs);
510 /* removable media returns 0 if not present */
511 if (s->qdev.blocksize <= 0) {
512 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
513 s->qdev.blocksize = 2048;
514 else
515 s->qdev.blocksize = 512;
518 DPRINTF("block size %d\n", s->qdev.blocksize);
519 s->driver_status = 0;
520 memset(s->sensebuf, 0, sizeof(s->sensebuf));
521 bdrv_set_removable(s->bs, 0);
522 return 0;
525 static SCSIDeviceInfo scsi_generic_info = {
526 .qdev.name = "scsi-generic",
527 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
528 .qdev.size = sizeof(SCSIGenericState),
529 .qdev.reset = scsi_generic_reset,
530 .init = scsi_generic_initfn,
531 .destroy = scsi_destroy,
532 .alloc_req = scsi_new_request,
533 .free_req = scsi_free_request,
534 .send_command = scsi_send_command,
535 .read_data = scsi_read_data,
536 .write_data = scsi_write_data,
537 .cancel_io = scsi_cancel_io,
538 .get_buf = scsi_get_buf,
539 .qdev.props = (Property[]) {
540 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
541 DEFINE_PROP_END_OF_LIST(),
545 static void scsi_generic_register_devices(void)
547 scsi_qdev_register(&scsi_generic_info);
549 device_init(scsi_generic_register_devices)
551 #endif /* __linux__ */