Fix preprocessor guard condition
[qemu/mini2440.git] / hw / scsi-generic.c
blob60084cff6428936bb15d6975fdf5a8979cc32e20
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-disk.h"
18 #ifndef __linux__
20 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
21 scsi_completionfn completion, void *opaque)
23 return NULL;
26 #else /* __linux__ */
28 //#define DEBUG_SCSI
30 #ifdef DEBUG_SCSI
31 #define DPRINTF(fmt, args...) \
32 do { printf("scsi-generic: " fmt , ##args); } while (0)
33 #else
34 #define DPRINTF(fmt, args...) do {} while(0)
35 #endif
37 #define BADF(fmt, args...) \
38 do { fprintf(stderr, "scsi-generic: " fmt , ##args); } while (0)
40 #include <stdio.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <scsi/sg.h>
45 #include <scsi/scsi.h>
47 #define LOAD_UNLOAD 0xa6
48 #define SET_CD_SPEED 0xbb
49 #define BLANK 0xa1
51 #define SCSI_CMD_BUF_SIZE 16
52 #define SCSI_SENSE_BUF_SIZE 32
54 #define SG_ERR_DRIVER_TIMEOUT 0x06
55 #define SG_ERR_DRIVER_SENSE 0x08
57 #ifndef MAX_UINT
58 #define MAX_UINT ((unsigned int)-1)
59 #endif
61 typedef struct SCSIRequest {
62 BlockDriverAIOCB *aiocb;
63 struct SCSIRequest *next;
64 SCSIDeviceState *dev;
65 uint32_t tag;
66 uint8_t cmd[SCSI_CMD_BUF_SIZE];
67 int cmdlen;
68 uint8_t *buf;
69 int buflen;
70 int len;
71 sg_io_hdr_t io_header;
72 } SCSIRequest;
74 struct SCSIDeviceState
76 SCSIRequest *requests;
77 BlockDriverState *bdrv;
78 int blocksize;
79 int lun;
80 scsi_completionfn completion;
81 void *opaque;
82 int driver_status;
83 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
86 /* Global pool of SCSIRequest structures. */
87 static SCSIRequest *free_requests = NULL;
89 static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
91 SCSIRequest *r;
93 if (free_requests) {
94 r = free_requests;
95 free_requests = r->next;
96 } else {
97 r = qemu_malloc(sizeof(SCSIRequest));
98 r->buf = NULL;
99 r->buflen = 0;
101 r->dev = s;
102 r->tag = tag;
103 memset(r->cmd, 0, sizeof(r->cmd));
104 memset(&r->io_header, 0, sizeof(r->io_header));
105 r->cmdlen = 0;
106 r->len = 0;
107 r->aiocb = NULL;
109 /* link */
111 r->next = s->requests;
112 s->requests = r;
113 return r;
116 static void scsi_remove_request(SCSIRequest *r)
118 SCSIRequest *last;
119 SCSIDeviceState *s = r->dev;
121 if (s->requests == r) {
122 s->requests = r->next;
123 } else {
124 last = s->requests;
125 while (last && last->next != r)
126 last = last->next;
127 if (last) {
128 last->next = r->next;
129 } else {
130 BADF("Orphaned request\n");
133 r->next = free_requests;
134 free_requests = r;
137 static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
139 SCSIRequest *r;
141 r = s->requests;
142 while (r && r->tag != tag)
143 r = r->next;
145 return r;
148 /* Helper function for command completion. */
149 static void scsi_command_complete(void *opaque, int ret)
151 SCSIRequest *r = (SCSIRequest *)opaque;
152 SCSIDeviceState *s = r->dev;
153 uint32_t tag;
154 int sense;
156 s->driver_status = r->io_header.driver_status;
157 if (ret != 0)
158 sense = HARDWARE_ERROR;
159 else {
160 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
161 sense = HARDWARE_ERROR;
162 BADF("Driver Timeout\n");
163 } else if ((s->driver_status & SG_ERR_DRIVER_SENSE) == 0)
164 sense = NO_SENSE;
165 else
166 sense = s->sensebuf[2] & 0x0f;
169 DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r, r->tag, sense);
170 tag = r->tag;
171 scsi_remove_request(r);
172 s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
175 /* Cancel a pending data transfer. */
176 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
178 DPRINTF("scsi_cancel_io 0x%x\n", tag);
179 SCSIDeviceState *s = d->state;
180 SCSIRequest *r;
181 DPRINTF("Cancel tag=0x%x\n", tag);
182 r = scsi_find_request(s, tag);
183 if (r) {
184 if (r->aiocb)
185 bdrv_aio_cancel(r->aiocb);
186 r->aiocb = NULL;
187 scsi_remove_request(r);
191 static int execute_command(BlockDriverState *bdrv,
192 SCSIRequest *r, int direction,
193 BlockDriverCompletionFunc *complete)
196 r->io_header.interface_id = 'S';
197 r->io_header.dxfer_direction = direction;
198 r->io_header.dxferp = r->buf;
199 r->io_header.dxfer_len = r->buflen;
200 r->io_header.cmdp = r->cmd;
201 r->io_header.cmd_len = r->cmdlen;
202 r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
203 r->io_header.sbp = r->dev->sensebuf;
204 r->io_header.timeout = MAX_UINT;
205 r->io_header.usr_ptr = r;
206 r->io_header.flags |= SG_FLAG_DIRECT_IO;
208 if (bdrv_pwrite(bdrv, -1, &r->io_header, sizeof(r->io_header)) == -1) {
209 BADF("execute_command: write failed ! (%d)\n", errno);
210 return -1;
212 if (complete == NULL) {
213 int ret;
214 r->aiocb = NULL;
215 while ((ret = bdrv_pread(bdrv, -1, &r->io_header,
216 sizeof(r->io_header))) == -1 &&
217 errno == EINTR);
218 if (ret == -1) {
219 BADF("execute_command: read failed !\n");
220 return -1;
222 return 0;
225 r->aiocb = bdrv_aio_read(bdrv, 0, (uint8_t*)&r->io_header,
226 -(int64_t)sizeof(r->io_header), complete, r);
227 if (r->aiocb == NULL) {
228 BADF("execute_command: read failed !\n");
229 return -1;
232 return 0;
235 static void scsi_read_complete(void * opaque, int ret)
237 SCSIRequest *r = (SCSIRequest *)opaque;
238 SCSIDeviceState *s = r->dev;
239 int len;
241 if (ret) {
242 DPRINTF("IO error\n");
243 scsi_command_complete(r, ret);
244 return;
246 len = r->io_header.dxfer_len - r->io_header.resid;
247 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
249 r->len = -1;
250 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
253 /* Read more data from scsi device into buffer. */
254 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
256 SCSIDeviceState *s = d->state;
257 SCSIRequest *r;
258 int ret;
260 DPRINTF("scsi_read_data 0x%x\n", tag);
261 r = scsi_find_request(s, tag);
262 if (!r) {
263 BADF("Bad read tag 0x%x\n", tag);
264 /* ??? This is the wrong error. */
265 scsi_command_complete(r, -EINVAL);
266 return;
269 if (r->len == -1) {
270 scsi_command_complete(r, 0);
271 return;
274 if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
276 memcpy(r->buf, s->sensebuf, 16);
277 r->io_header.driver_status = 0;
278 r->len = -1;
279 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16);
280 return;
283 ret = execute_command(s->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
284 if (ret == -1) {
285 scsi_command_complete(r, -EINVAL);
286 return;
290 static void scsi_write_complete(void * opaque, int ret)
292 SCSIRequest *r = (SCSIRequest *)opaque;
294 DPRINTF("scsi_write_complete() ret = %d\n", ret);
295 if (ret) {
296 DPRINTF("IO error\n");
297 scsi_command_complete(r, ret);
298 return;
301 scsi_command_complete(r, ret);
304 /* Write data to a scsi device. Returns nonzero on failure.
305 The transfer may complete asynchronously. */
306 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
308 SCSIDeviceState *s = d->state;
309 SCSIRequest *r;
310 int ret;
312 DPRINTF("scsi_write_data 0x%x\n", tag);
313 r = scsi_find_request(s, tag);
314 if (!r) {
315 BADF("Bad write tag 0x%x\n", tag);
316 /* ??? This is the wrong error. */
317 scsi_command_complete(r, -EINVAL);
318 return 0;
321 if (r->len == 0) {
322 r->len = r->buflen;
323 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len);
324 return 0;
327 ret = execute_command(s->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
328 if (ret == -1) {
329 scsi_command_complete(r, -EINVAL);
330 return 1;
333 return 0;
336 /* Return a pointer to the data buffer. */
337 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
339 SCSIDeviceState *s = d->state;
340 SCSIRequest *r;
341 r = scsi_find_request(s, tag);
342 if (!r) {
343 BADF("Bad buffer tag 0x%x\n", tag);
344 return NULL;
346 return r->buf;
349 static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
351 switch (cmd[0] >> 5) {
352 case 0:
353 *len = cmd[4];
354 *cmdlen = 6;
355 break;
356 case 1:
357 case 2:
358 *len = cmd[8] | (cmd[7] << 8);
359 *cmdlen = 10;
360 break;
361 case 4:
362 *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
363 *cmdlen = 16;
364 break;
365 case 5:
366 *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
367 *cmdlen = 12;
368 break;
369 default:
370 return -1;
373 switch(cmd[0]) {
374 case TEST_UNIT_READY:
375 case REZERO_UNIT:
376 case START_STOP:
377 case SEEK_6:
378 case WRITE_FILEMARKS:
379 case SPACE:
380 case ERASE:
381 case ALLOW_MEDIUM_REMOVAL:
382 case VERIFY:
383 case SEEK_10:
384 case SYNCHRONIZE_CACHE:
385 case LOCK_UNLOCK_CACHE:
386 case LOAD_UNLOAD:
387 case SET_CD_SPEED:
388 case SET_LIMITS:
389 case WRITE_LONG:
390 case MOVE_MEDIUM:
391 case UPDATE_BLOCK:
392 *len = 0;
393 break;
394 case MODE_SENSE:
395 break;
396 case WRITE_SAME:
397 *len = 1;
398 break;
399 case READ_CAPACITY:
400 *len = 8;
401 break;
402 case READ_BLOCK_LIMITS:
403 *len = 6;
404 break;
405 case READ_POSITION:
406 *len = 20;
407 break;
408 case SEND_VOLUME_TAG:
409 *len *= 40;
410 break;
411 case MEDIUM_SCAN:
412 *len *= 8;
413 break;
414 case WRITE_10:
415 cmd[1] &= ~0x08; /* disable FUA */
416 case WRITE_VERIFY:
417 case WRITE_6:
418 case WRITE_12:
419 case WRITE_VERIFY_12:
420 *len *= blocksize;
421 break;
422 case READ_10:
423 cmd[1] &= ~0x08; /* disable FUA */
424 case READ_6:
425 case READ_REVERSE:
426 case RECOVER_BUFFERED_DATA:
427 case READ_12:
428 *len *= blocksize;
429 break;
431 return 0;
434 static int is_write(int command)
436 switch (command) {
437 case COPY:
438 case COPY_VERIFY:
439 case COMPARE:
440 case CHANGE_DEFINITION:
441 case LOG_SELECT:
442 case MODE_SELECT:
443 case MODE_SELECT_10:
444 case SEND_DIAGNOSTIC:
445 case WRITE_BUFFER:
446 case FORMAT_UNIT:
447 case REASSIGN_BLOCKS:
448 case RESERVE:
449 case SEARCH_EQUAL:
450 case SEARCH_HIGH:
451 case SEARCH_LOW:
452 case WRITE_6:
453 case WRITE_10:
454 case WRITE_VERIFY:
455 case UPDATE_BLOCK:
456 case WRITE_LONG:
457 case WRITE_SAME:
458 case SEARCH_HIGH_12:
459 case SEARCH_EQUAL_12:
460 case SEARCH_LOW_12:
461 case WRITE_12:
462 case WRITE_VERIFY_12:
463 case SET_WINDOW:
464 case MEDIUM_SCAN:
465 case SEND_VOLUME_TAG:
466 case WRITE_LONG_2:
467 return 1;
469 return 0;
472 /* Execute a scsi command. Returns the length of the data expected by the
473 command. This will be Positive for data transfers from the device
474 (eg. disk reads), negative for transfers to the device (eg. disk writes),
475 and zero if the command does not transfer any data. */
477 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
478 uint8_t *cmd, int lun)
480 SCSIDeviceState *s = d->state;
481 uint32_t len;
482 int cmdlen;
483 SCSIRequest *r;
484 int ret;
486 /* ??? Tags are not unique for different luns. We only implement a
487 single lun, so this should not matter. */
489 if (lun != s->lun || (cmd[1] >> 5) != s->lun) {
490 DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
491 s->completion(s->opaque, SCSI_REASON_DONE, tag, ILLEGAL_REQUEST);
492 return 0;
495 if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
496 BADF("Unsupported command length, command %x\n", cmd[0]);
497 return 0;
500 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
501 cmd[0], len);
503 r = scsi_find_request(s, tag);
504 if (r) {
505 BADF("Tag 0x%x already in use %p\n", tag, r);
506 scsi_cancel_io(d, tag);
508 r = scsi_new_request(s, tag);
510 memcpy(r->cmd, cmd, cmdlen);
511 r->cmdlen = cmdlen;
513 if (len == 0) {
514 if (r->buf != NULL)
515 free(r->buf);
516 r->buflen = 0;
517 r->buf = NULL;
518 ret = execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
519 if (ret == -1) {
520 scsi_command_complete(r, -EINVAL);
521 return 0;
523 return 0;
526 if (r->buflen != len) {
527 if (r->buf != NULL)
528 free(r->buf);
529 r->buf = qemu_malloc(len);
530 r->buflen = len;
533 memset(r->buf, 0, r->buflen);
534 r->len = len;
535 if (is_write(cmd[0])) {
536 r->len = 0;
537 return -len;
540 return len;
543 static int get_blocksize(BlockDriverState *bdrv)
545 uint8_t cmd[10];
546 uint8_t buf[8];
547 uint8_t sensebuf[8];
548 sg_io_hdr_t io_header;
549 int ret;
551 memset(cmd, sizeof(cmd), 0);
552 memset(buf, sizeof(buf), 0);
553 cmd[0] = READ_CAPACITY;
555 memset(&io_header, 0, sizeof(io_header));
556 io_header.interface_id = 'S';
557 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
558 io_header.dxfer_len = sizeof(buf);
559 io_header.dxferp = buf;
560 io_header.cmdp = cmd;
561 io_header.cmd_len = sizeof(cmd);
562 io_header.mx_sb_len = sizeof(sensebuf);
563 io_header.sbp = sensebuf;
564 io_header.timeout = 6000; /* XXX */
566 ret = bdrv_pwrite(bdrv, -1, &io_header, sizeof(io_header));
567 if (ret == -1)
568 return -1;
570 while ((ret = bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) == -1 &&
571 errno == EINTR);
573 if (ret == -1)
574 return -1;
576 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
579 static void scsi_destroy(SCSIDevice *d)
581 SCSIRequest *r, *n;
583 r = d->state->requests;
584 while (r) {
585 n = r->next;
586 qemu_free(r);
587 r = n;
590 r = free_requests;
591 while (r) {
592 n = r->next;
593 qemu_free(r);
594 r = n;
597 qemu_free(d->state);
598 qemu_free(d);
601 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
602 scsi_completionfn completion, void *opaque)
604 int sg_version;
605 SCSIDevice *d;
606 SCSIDeviceState *s;
607 struct sg_scsi_id scsiid;
609 /* check we are really using a /dev/sg* file */
611 if (!bdrv_is_sg(bdrv))
612 return NULL;
614 /* check we are using a driver managing SG_IO (version 3 and after */
616 if (bdrv_ioctl(bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
617 sg_version < 30000)
618 return NULL;
620 /* get LUN of the /dev/sg? */
622 if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid))
623 return NULL;
625 /* define device state */
627 s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
628 s->bdrv = bdrv;
629 s->requests = NULL;
630 s->completion = completion;
631 s->opaque = opaque;
632 s->lun = scsiid.lun;
633 s->blocksize = get_blocksize(s->bdrv);
634 s->driver_status = 0;
635 memset(s->sensebuf, 0, sizeof(s->sensebuf));
636 /* removable media returns 0 if not present */
637 if (s->blocksize <= 0)
638 s->blocksize = 2048;
640 /* define function to manage device */
642 d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
643 d->state = s;
644 d->destroy = scsi_destroy;
645 d->send_command = scsi_send_command;
646 d->read_data = scsi_read_data;
647 d->write_data = scsi_write_data;
648 d->cancel_io = scsi_cancel_io;
649 d->get_buf = scsi_get_buf;
651 return d;
653 #endif /* __linux__ */