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