]> git.proxmox.com Git - mirror_qemu.git/blob - hw/scsi-generic.c
drive cleanup fixes.
[mirror_qemu.git] / hw / scsi-generic.c
1 /*
2 * Generic SCSI Device support
3 *
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
7 *
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
9 *
10 * This code is licenced under the LGPL.
11 *
12 */
13
14 #include "qemu-common.h"
15 #include "block.h"
16 #include "scsi-disk.h"
17
18 #ifdef __linux__
19
20 //#define DEBUG_SCSI
21
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
28
29 #define BADF(fmt, ...) \
30 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
31
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/scsi.h>
38
39 #define REWIND 0x01
40 #define REPORT_DENSITY_SUPPORT 0x44
41 #define LOAD_UNLOAD 0xa6
42 #define SET_CD_SPEED 0xbb
43 #define BLANK 0xa1
44
45 #define SCSI_CMD_BUF_SIZE 16
46 #define SCSI_SENSE_BUF_SIZE 96
47
48 #define SG_ERR_DRIVER_TIMEOUT 0x06
49 #define SG_ERR_DRIVER_SENSE 0x08
50
51 #ifndef MAX_UINT
52 #define MAX_UINT ((unsigned int)-1)
53 #endif
54
55 typedef struct SCSIGenericState SCSIGenericState;
56
57 typedef struct SCSIRequest {
58 BlockDriverAIOCB *aiocb;
59 struct SCSIRequest *next;
60 SCSIBus *bus;
61 SCSIGenericState *dev;
62 uint32_t tag;
63 uint8_t cmd[SCSI_CMD_BUF_SIZE];
64 int cmdlen;
65 uint8_t *buf;
66 int buflen;
67 int len;
68 sg_io_hdr_t io_header;
69 } SCSIRequest;
70
71 struct SCSIGenericState
72 {
73 SCSIDevice qdev;
74 SCSIRequest *requests;
75 DriveInfo *dinfo;
76 int type;
77 int blocksize;
78 int lun;
79 int driver_status;
80 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
81 uint8_t senselen;
82 };
83
84 /* Global pool of SCSIRequest structures. */
85 static SCSIRequest *free_requests = NULL;
86
87 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
88 {
89 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
90 SCSIRequest *r;
91
92 if (free_requests) {
93 r = free_requests;
94 free_requests = r->next;
95 } else {
96 r = qemu_malloc(sizeof(SCSIRequest));
97 r->buf = NULL;
98 r->buflen = 0;
99 }
100 r->bus = scsi_bus_from_device(d);
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;
108
109 /* link */
110
111 r->next = s->requests;
112 s->requests = r;
113 return r;
114 }
115
116 static void scsi_remove_request(SCSIRequest *r)
117 {
118 SCSIRequest *last;
119 SCSIGenericState *s = r->dev;
120
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");
131 }
132 }
133 r->next = free_requests;
134 free_requests = r;
135 }
136
137 static SCSIRequest *scsi_find_request(SCSIGenericState *s, uint32_t tag)
138 {
139 SCSIRequest *r;
140
141 r = s->requests;
142 while (r && r->tag != tag)
143 r = r->next;
144
145 return r;
146 }
147
148 /* Helper function for command completion. */
149 static void scsi_command_complete(void *opaque, int ret)
150 {
151 SCSIRequest *r = (SCSIRequest *)opaque;
152 SCSIGenericState *s = r->dev;
153 uint32_t tag;
154 int status;
155
156 s->driver_status = r->io_header.driver_status;
157 if (s->driver_status & SG_ERR_DRIVER_SENSE)
158 s->senselen = r->io_header.sb_len_wr;
159
160 if (ret != 0)
161 status = BUSY << 1;
162 else {
163 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
164 status = BUSY << 1;
165 BADF("Driver Timeout\n");
166 } else if (r->io_header.status)
167 status = r->io_header.status;
168 else if (s->driver_status & SG_ERR_DRIVER_SENSE)
169 status = CHECK_CONDITION << 1;
170 else
171 status = GOOD << 1;
172 }
173 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
174 r, r->tag, status);
175 tag = r->tag;
176 scsi_remove_request(r);
177 r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
178 }
179
180 /* Cancel a pending data transfer. */
181 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
182 {
183 DPRINTF("scsi_cancel_io 0x%x\n", tag);
184 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
185 SCSIRequest *r;
186 DPRINTF("Cancel tag=0x%x\n", tag);
187 r = scsi_find_request(s, tag);
188 if (r) {
189 if (r->aiocb)
190 bdrv_aio_cancel(r->aiocb);
191 r->aiocb = NULL;
192 scsi_remove_request(r);
193 }
194 }
195
196 static int execute_command(BlockDriverState *bdrv,
197 SCSIRequest *r, int direction,
198 BlockDriverCompletionFunc *complete)
199 {
200 r->io_header.interface_id = 'S';
201 r->io_header.dxfer_direction = direction;
202 r->io_header.dxferp = r->buf;
203 r->io_header.dxfer_len = r->buflen;
204 r->io_header.cmdp = r->cmd;
205 r->io_header.cmd_len = r->cmdlen;
206 r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
207 r->io_header.sbp = r->dev->sensebuf;
208 r->io_header.timeout = MAX_UINT;
209 r->io_header.usr_ptr = r;
210 r->io_header.flags |= SG_FLAG_DIRECT_IO;
211
212 r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
213 if (r->aiocb == NULL) {
214 BADF("execute_command: read failed !\n");
215 return -1;
216 }
217
218 return 0;
219 }
220
221 static void scsi_read_complete(void * opaque, int ret)
222 {
223 SCSIRequest *r = (SCSIRequest *)opaque;
224 int len;
225
226 if (ret) {
227 DPRINTF("IO error\n");
228 scsi_command_complete(r, ret);
229 return;
230 }
231 len = r->io_header.dxfer_len - r->io_header.resid;
232 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
233
234 r->len = -1;
235 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
236 if (len == 0)
237 scsi_command_complete(r, 0);
238 }
239
240 /* Read more data from scsi device into buffer. */
241 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
242 {
243 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
244 SCSIRequest *r;
245 int ret;
246
247 DPRINTF("scsi_read_data 0x%x\n", tag);
248 r = scsi_find_request(s, tag);
249 if (!r) {
250 BADF("Bad read tag 0x%x\n", tag);
251 /* ??? This is the wrong error. */
252 scsi_command_complete(r, -EINVAL);
253 return;
254 }
255
256 if (r->len == -1) {
257 scsi_command_complete(r, 0);
258 return;
259 }
260
261 if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
262 {
263 s->senselen = MIN(r->len, s->senselen);
264 memcpy(r->buf, s->sensebuf, s->senselen);
265 r->io_header.driver_status = 0;
266 r->io_header.status = 0;
267 r->io_header.dxfer_len = s->senselen;
268 r->len = -1;
269 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, s->senselen);
270 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
271 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
272 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
273 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, s->senselen);
274 return;
275 }
276
277 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
278 if (ret == -1) {
279 scsi_command_complete(r, -EINVAL);
280 return;
281 }
282 }
283
284 static void scsi_write_complete(void * opaque, int ret)
285 {
286 SCSIRequest *r = (SCSIRequest *)opaque;
287
288 DPRINTF("scsi_write_complete() ret = %d\n", ret);
289 if (ret) {
290 DPRINTF("IO error\n");
291 scsi_command_complete(r, ret);
292 return;
293 }
294
295 if (r->cmd[0] == MODE_SELECT && r->cmd[4] == 12 &&
296 r->dev->type == TYPE_TAPE) {
297 r->dev->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
298 DPRINTF("block size %d\n", r->dev->blocksize);
299 }
300
301 scsi_command_complete(r, ret);
302 }
303
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)
307 {
308 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
309 SCSIRequest *r;
310 int ret;
311
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;
319 }
320
321 if (r->len == 0) {
322 r->len = r->buflen;
323 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->len);
324 return 0;
325 }
326
327 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
328 if (ret == -1) {
329 scsi_command_complete(r, -EINVAL);
330 return 1;
331 }
332
333 return 0;
334 }
335
336 /* Return a pointer to the data buffer. */
337 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
338 {
339 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
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;
345 }
346 return r->buf;
347 }
348
349 static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
350 {
351 switch (cmd[0] >> 5) {
352 case 0:
353 *len = cmd[4];
354 *cmdlen = 6;
355 /* length 0 means 256 blocks */
356 if (*len == 0)
357 *len = 256;
358 break;
359 case 1:
360 case 2:
361 *len = cmd[8] | (cmd[7] << 8);
362 *cmdlen = 10;
363 break;
364 case 4:
365 *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
366 *cmdlen = 16;
367 break;
368 case 5:
369 *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
370 *cmdlen = 12;
371 break;
372 default:
373 return -1;
374 }
375
376 switch(cmd[0]) {
377 case TEST_UNIT_READY:
378 case REZERO_UNIT:
379 case START_STOP:
380 case SEEK_6:
381 case WRITE_FILEMARKS:
382 case SPACE:
383 case ERASE:
384 case ALLOW_MEDIUM_REMOVAL:
385 case VERIFY:
386 case SEEK_10:
387 case SYNCHRONIZE_CACHE:
388 case LOCK_UNLOCK_CACHE:
389 case LOAD_UNLOAD:
390 case SET_CD_SPEED:
391 case SET_LIMITS:
392 case WRITE_LONG:
393 case MOVE_MEDIUM:
394 case UPDATE_BLOCK:
395 *len = 0;
396 break;
397 case MODE_SENSE:
398 break;
399 case WRITE_SAME:
400 *len = 1;
401 break;
402 case READ_CAPACITY:
403 *len = 8;
404 break;
405 case READ_BLOCK_LIMITS:
406 *len = 6;
407 break;
408 case READ_POSITION:
409 *len = 20;
410 break;
411 case SEND_VOLUME_TAG:
412 *len *= 40;
413 break;
414 case MEDIUM_SCAN:
415 *len *= 8;
416 break;
417 case WRITE_10:
418 cmd[1] &= ~0x08; /* disable FUA */
419 case WRITE_VERIFY:
420 case WRITE_6:
421 case WRITE_12:
422 case WRITE_VERIFY_12:
423 *len *= blocksize;
424 break;
425 case READ_10:
426 cmd[1] &= ~0x08; /* disable FUA */
427 case READ_6:
428 case READ_REVERSE:
429 case RECOVER_BUFFERED_DATA:
430 case READ_12:
431 *len *= blocksize;
432 break;
433 case INQUIRY:
434 *len = cmd[4] | (cmd[3] << 8);
435 break;
436 }
437 return 0;
438 }
439
440 static int scsi_stream_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
441 {
442 switch(cmd[0]) {
443 /* stream commands */
444 case READ_6:
445 case READ_REVERSE:
446 case RECOVER_BUFFERED_DATA:
447 case WRITE_6:
448 *cmdlen = 6;
449 *len = cmd[4] | (cmd[3] << 8) | (cmd[2] << 16);
450 if (cmd[1] & 0x01) /* fixed */
451 *len *= blocksize;
452 break;
453 case REWIND:
454 case START_STOP:
455 *cmdlen = 6;
456 *len = 0;
457 cmd[1] = 0x01; /* force IMMED, otherwise qemu waits end of command */
458 break;
459 /* generic commands */
460 default:
461 return scsi_length(cmd, blocksize, cmdlen, len);
462 }
463 return 0;
464 }
465
466 static int is_write(int command)
467 {
468 switch (command) {
469 case COPY:
470 case COPY_VERIFY:
471 case COMPARE:
472 case CHANGE_DEFINITION:
473 case LOG_SELECT:
474 case MODE_SELECT:
475 case MODE_SELECT_10:
476 case SEND_DIAGNOSTIC:
477 case WRITE_BUFFER:
478 case FORMAT_UNIT:
479 case REASSIGN_BLOCKS:
480 case RESERVE:
481 case SEARCH_EQUAL:
482 case SEARCH_HIGH:
483 case SEARCH_LOW:
484 case WRITE_6:
485 case WRITE_10:
486 case WRITE_VERIFY:
487 case UPDATE_BLOCK:
488 case WRITE_LONG:
489 case WRITE_SAME:
490 case SEARCH_HIGH_12:
491 case SEARCH_EQUAL_12:
492 case SEARCH_LOW_12:
493 case WRITE_12:
494 case WRITE_VERIFY_12:
495 case SET_WINDOW:
496 case MEDIUM_SCAN:
497 case SEND_VOLUME_TAG:
498 case WRITE_LONG_2:
499 return 1;
500 }
501 return 0;
502 }
503
504 /* Execute a scsi command. Returns the length of the data expected by the
505 command. This will be Positive for data transfers from the device
506 (eg. disk reads), negative for transfers to the device (eg. disk writes),
507 and zero if the command does not transfer any data. */
508
509 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
510 uint8_t *cmd, int lun)
511 {
512 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
513 uint32_t len=0;
514 int cmdlen=0;
515 SCSIRequest *r;
516 SCSIBus *bus;
517 int ret;
518
519 if (s->type == TYPE_TAPE) {
520 if (scsi_stream_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
521 BADF("Unsupported command length, command %x\n", cmd[0]);
522 return 0;
523 }
524 } else {
525 if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
526 BADF("Unsupported command length, command %x\n", cmd[0]);
527 return 0;
528 }
529 }
530
531 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
532 cmd[0], len);
533
534 if (cmd[0] != REQUEST_SENSE &&
535 (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
536 DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
537
538 s->sensebuf[0] = 0x70;
539 s->sensebuf[1] = 0x00;
540 s->sensebuf[2] = ILLEGAL_REQUEST;
541 s->sensebuf[3] = 0x00;
542 s->sensebuf[4] = 0x00;
543 s->sensebuf[5] = 0x00;
544 s->sensebuf[6] = 0x00;
545 s->senselen = 7;
546 s->driver_status = SG_ERR_DRIVER_SENSE;
547 bus = scsi_bus_from_device(d);
548 bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
549 return 0;
550 }
551
552 r = scsi_find_request(s, tag);
553 if (r) {
554 BADF("Tag 0x%x already in use %p\n", tag, r);
555 scsi_cancel_io(d, tag);
556 }
557 r = scsi_new_request(d, tag);
558
559 memcpy(r->cmd, cmd, cmdlen);
560 r->cmdlen = cmdlen;
561
562 if (len == 0) {
563 if (r->buf != NULL)
564 free(r->buf);
565 r->buflen = 0;
566 r->buf = NULL;
567 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
568 if (ret == -1) {
569 scsi_command_complete(r, -EINVAL);
570 return 0;
571 }
572 return 0;
573 }
574
575 if (r->buflen != len) {
576 if (r->buf != NULL)
577 free(r->buf);
578 r->buf = qemu_malloc(len);
579 r->buflen = len;
580 }
581
582 memset(r->buf, 0, r->buflen);
583 r->len = len;
584 if (is_write(cmd[0])) {
585 r->len = 0;
586 return -len;
587 }
588
589 return len;
590 }
591
592 static int get_blocksize(BlockDriverState *bdrv)
593 {
594 uint8_t cmd[10];
595 uint8_t buf[8];
596 uint8_t sensebuf[8];
597 sg_io_hdr_t io_header;
598 int ret;
599
600 memset(cmd, 0, sizeof(cmd));
601 memset(buf, 0, sizeof(buf));
602 cmd[0] = READ_CAPACITY;
603
604 memset(&io_header, 0, sizeof(io_header));
605 io_header.interface_id = 'S';
606 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
607 io_header.dxfer_len = sizeof(buf);
608 io_header.dxferp = buf;
609 io_header.cmdp = cmd;
610 io_header.cmd_len = sizeof(cmd);
611 io_header.mx_sb_len = sizeof(sensebuf);
612 io_header.sbp = sensebuf;
613 io_header.timeout = 6000; /* XXX */
614
615 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
616 if (ret < 0)
617 return -1;
618
619 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
620 }
621
622 static int get_stream_blocksize(BlockDriverState *bdrv)
623 {
624 uint8_t cmd[6];
625 uint8_t buf[12];
626 uint8_t sensebuf[8];
627 sg_io_hdr_t io_header;
628 int ret;
629
630 memset(cmd, 0, sizeof(cmd));
631 memset(buf, 0, sizeof(buf));
632 cmd[0] = MODE_SENSE;
633 cmd[4] = sizeof(buf);
634
635 memset(&io_header, 0, sizeof(io_header));
636 io_header.interface_id = 'S';
637 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
638 io_header.dxfer_len = sizeof(buf);
639 io_header.dxferp = buf;
640 io_header.cmdp = cmd;
641 io_header.cmd_len = sizeof(cmd);
642 io_header.mx_sb_len = sizeof(sensebuf);
643 io_header.sbp = sensebuf;
644 io_header.timeout = 6000; /* XXX */
645
646 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
647 if (ret < 0)
648 return -1;
649
650 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
651 }
652
653 static void scsi_destroy(SCSIDevice *d)
654 {
655 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
656 SCSIRequest *r, *n;
657
658 r = s->requests;
659 while (r) {
660 n = r->next;
661 qemu_free(r);
662 r = n;
663 }
664
665 r = free_requests;
666 while (r) {
667 n = r->next;
668 qemu_free(r);
669 r = n;
670 }
671
672 drive_uninit(s->dinfo);
673 }
674
675 static int scsi_generic_initfn(SCSIDevice *dev)
676 {
677 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
678 int sg_version;
679 struct sg_scsi_id scsiid;
680
681 if (!s->dinfo || !s->dinfo->bdrv) {
682 qemu_error("scsi-generic: drive property not set\n");
683 return -1;
684 }
685
686 /* check we are really using a /dev/sg* file */
687 if (!bdrv_is_sg(s->dinfo->bdrv)) {
688 qemu_error("scsi-generic: not /dev/sg*\n");
689 return -1;
690 }
691
692 /* check we are using a driver managing SG_IO (version 3 and after */
693 if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
694 sg_version < 30000) {
695 qemu_error("scsi-generic: scsi generic interface too old\n");
696 return -1;
697 }
698
699 /* get LUN of the /dev/sg? */
700 if (bdrv_ioctl(s->dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
701 qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
702 return -1;
703 }
704
705 /* define device state */
706 s->lun = scsiid.lun;
707 DPRINTF("LUN %d\n", s->lun);
708 s->type = scsiid.scsi_type;
709 DPRINTF("device type %d\n", s->type);
710 if (s->type == TYPE_TAPE) {
711 s->blocksize = get_stream_blocksize(s->dinfo->bdrv);
712 if (s->blocksize == -1)
713 s->blocksize = 0;
714 } else {
715 s->blocksize = get_blocksize(s->dinfo->bdrv);
716 /* removable media returns 0 if not present */
717 if (s->blocksize <= 0) {
718 if (s->type == TYPE_ROM || s->type == TYPE_WORM)
719 s->blocksize = 2048;
720 else
721 s->blocksize = 512;
722 }
723 }
724 DPRINTF("block size %d\n", s->blocksize);
725 s->driver_status = 0;
726 memset(s->sensebuf, 0, sizeof(s->sensebuf));
727 return 0;
728 }
729
730 static SCSIDeviceInfo scsi_generic_info = {
731 .qdev.name = "scsi-generic",
732 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
733 .qdev.size = sizeof(SCSIGenericState),
734 .init = scsi_generic_initfn,
735 .destroy = scsi_destroy,
736 .send_command = scsi_send_command,
737 .read_data = scsi_read_data,
738 .write_data = scsi_write_data,
739 .cancel_io = scsi_cancel_io,
740 .get_buf = scsi_get_buf,
741 .qdev.props = (Property[]) {
742 DEFINE_PROP_DRIVE("drive", SCSIGenericState, dinfo),
743 DEFINE_PROP_END_OF_LIST(),
744 },
745 };
746
747 static void scsi_generic_register_devices(void)
748 {
749 scsi_qdev_register(&scsi_generic_info);
750 }
751 device_init(scsi_generic_register_devices)
752
753 #endif /* __linux__ */