]> Git Repo - qemu.git/blame - hw/scsi-generic.c
vmstate: port dma device
[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 <[email protected]>
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
d52affa7 18#ifdef __linux__
2cc977e2
TS
19
20//#define DEBUG_SCSI
21
22#ifdef DEBUG_SCSI
001faf32
BS
23#define DPRINTF(fmt, ...) \
24do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2 25#else
001faf32 26#define DPRINTF(fmt, ...) do {} while(0)
2cc977e2
TS
27#endif
28
001faf32
BS
29#define BADF(fmt, ...) \
30do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2
TS
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
a9dd6843
AL
39#define REWIND 0x01
40#define REPORT_DENSITY_SUPPORT 0x44
2cc977e2
TS
41#define LOAD_UNLOAD 0xa6
42#define SET_CD_SPEED 0xbb
43#define BLANK 0xa1
44
45#define SCSI_CMD_BUF_SIZE 16
a9dd6843 46#define SCSI_SENSE_BUF_SIZE 96
2cc977e2
TS
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
d52affa7
GH
55typedef struct SCSIGenericState SCSIGenericState;
56
2cc977e2
TS
57typedef struct SCSIRequest {
58 BlockDriverAIOCB *aiocb;
59 struct SCSIRequest *next;
d52affa7
GH
60 SCSIBus *bus;
61 SCSIGenericState *dev;
2cc977e2
TS
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
d52affa7 71struct SCSIGenericState
2cc977e2 72{
d52affa7 73 SCSIDevice qdev;
2cc977e2 74 SCSIRequest *requests;
d52affa7 75 DriveInfo *dinfo;
a9dd6843 76 int type;
2cc977e2
TS
77 int blocksize;
78 int lun;
2cc977e2
TS
79 int driver_status;
80 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
89c0f643 81 uint8_t senselen;
2cc977e2
TS
82};
83
84/* Global pool of SCSIRequest structures. */
85static SCSIRequest *free_requests = NULL;
86
d52affa7 87static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag)
2cc977e2 88{
d52affa7 89 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
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 }
d52affa7 100 r->bus = scsi_bus_from_device(d);
2cc977e2
TS
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
116static void scsi_remove_request(SCSIRequest *r)
117{
118 SCSIRequest *last;
d52affa7 119 SCSIGenericState *s = r->dev;
2cc977e2
TS
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
d52affa7 137static SCSIRequest *scsi_find_request(SCSIGenericState *s, uint32_t tag)
2cc977e2
TS
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. */
149static void scsi_command_complete(void *opaque, int ret)
150{
151 SCSIRequest *r = (SCSIRequest *)opaque;
d52affa7 152 SCSIGenericState *s = r->dev;
2cc977e2 153 uint32_t tag;
89c0f643 154 int status;
2cc977e2
TS
155
156 s->driver_status = r->io_header.driver_status;
89c0f643
AJ
157 if (s->driver_status & SG_ERR_DRIVER_SENSE)
158 s->senselen = r->io_header.sb_len_wr;
159
2cc977e2 160 if (ret != 0)
89c0f643 161 status = BUSY << 1;
2cc977e2
TS
162 else {
163 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
89c0f643 164 status = BUSY << 1;
2cc977e2 165 BADF("Driver Timeout\n");
89c0f643
AJ
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;
2cc977e2 170 else
89c0f643 171 status = GOOD << 1;
2cc977e2 172 }
89c0f643
AJ
173 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
174 r, r->tag, status);
2cc977e2
TS
175 tag = r->tag;
176 scsi_remove_request(r);
d52affa7 177 r->bus->complete(r->bus, SCSI_REASON_DONE, tag, status);
2cc977e2
TS
178}
179
180/* Cancel a pending data transfer. */
181static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
182{
183 DPRINTF("scsi_cancel_io 0x%x\n", tag);
d52affa7 184 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
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
196static int execute_command(BlockDriverState *bdrv,
197 SCSIRequest *r, int direction,
198 BlockDriverCompletionFunc *complete)
199{
2cc977e2
TS
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
221f715d 212 r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
2cc977e2
TS
213 if (r->aiocb == NULL) {
214 BADF("execute_command: read failed !\n");
215 return -1;
216 }
217
218 return 0;
219}
220
221static void scsi_read_complete(void * opaque, int ret)
222{
223 SCSIRequest *r = (SCSIRequest *)opaque;
2cc977e2
TS
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;
d52affa7 235 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, len);
89c0f643
AJ
236 if (len == 0)
237 scsi_command_complete(r, 0);
2cc977e2
TS
238}
239
240/* Read more data from scsi device into buffer. */
241static void scsi_read_data(SCSIDevice *d, uint32_t tag)
242{
d52affa7 243 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
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 {
89c0f643
AJ
263 s->senselen = MIN(r->len, s->senselen);
264 memcpy(r->buf, s->sensebuf, s->senselen);
2cc977e2 265 r->io_header.driver_status = 0;
89c0f643
AJ
266 r->io_header.status = 0;
267 r->io_header.dxfer_len = s->senselen;
2cc977e2 268 r->len = -1;
89c0f643 269 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, s->senselen);
a9dd6843
AL
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]);
d52affa7 273 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, s->senselen);
2cc977e2
TS
274 return;
275 }
276
d52affa7 277 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
2cc977e2
TS
278 if (ret == -1) {
279 scsi_command_complete(r, -EINVAL);
280 return;
281 }
282}
283
284static 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
89c0f643
AJ
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
2cc977e2
TS
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. */
306static int scsi_write_data(SCSIDevice *d, uint32_t tag)
307{
d52affa7 308 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
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;
d52affa7 323 r->bus->complete(r->bus, SCSI_REASON_DATA, r->tag, r->len);
2cc977e2
TS
324 return 0;
325 }
326
d52affa7 327 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
2cc977e2
TS
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. */
337static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
338{
d52affa7 339 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
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
349static 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;
72ecb8d9
AL
355 /* length 0 means 256 blocks */
356 if (*len == 0)
357 *len = 256;
2cc977e2
TS
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;
89c0f643
AJ
433 case INQUIRY:
434 *len = cmd[4] | (cmd[3] << 8);
435 break;
2cc977e2
TS
436 }
437 return 0;
438}
439
a9dd6843
AL
440static 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
2cc977e2
TS
466static 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
509static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
510 uint8_t *cmd, int lun)
511{
d52affa7 512 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
37e828b4
AJ
513 uint32_t len=0;
514 int cmdlen=0;
2cc977e2 515 SCSIRequest *r;
d52affa7 516 SCSIBus *bus;
2cc977e2
TS
517 int ret;
518
a9dd6843
AL
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 }
2cc977e2
TS
529 }
530
531 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
532 cmd[0], len);
533
89c0f643
AJ
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;
d52affa7
GH
547 bus = scsi_bus_from_device(d);
548 bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
89c0f643
AJ
549 return 0;
550 }
551
2cc977e2
TS
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 }
d52affa7 557 r = scsi_new_request(d, tag);
2cc977e2
TS
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;
d52affa7 567 ret = execute_command(s->dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
2cc977e2
TS
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
592static 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
4f26a486
AL
600 memset(cmd, 0, sizeof(cmd));
601 memset(buf, 0, sizeof(buf));
2cc977e2
TS
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
221f715d 615 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 616 if (ret < 0)
2cc977e2
TS
617 return -1;
618
619 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
620}
621
89c0f643
AJ
622static 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
221f715d 646 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 647 if (ret < 0)
89c0f643
AJ
648 return -1;
649
650 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
651}
652
2cc977e2
TS
653static void scsi_destroy(SCSIDevice *d)
654{
d52affa7 655 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
2cc977e2
TS
656 SCSIRequest *r, *n;
657
d52affa7 658 r = s->requests;
2cc977e2
TS
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
2cc977e2
TS
672 qemu_free(d);
673}
674
d52affa7 675static int scsi_generic_initfn(SCSIDevice *dev)
2cc977e2 676{
d52affa7 677 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
2cc977e2 678 int sg_version;
2cc977e2
TS
679 struct sg_scsi_id scsiid;
680
d52affa7
GH
681 if (!s->dinfo || !s->dinfo->bdrv) {
682 qemu_error("scsi-generic: drive property not set\n");
683 return -1;
684 }
2cc977e2 685
d52affa7
GH
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 }
2cc977e2
TS
691
692 /* check we are using a driver managing SG_IO (version 3 and after */
d52affa7
GH
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 }
2cc977e2
TS
698
699 /* get LUN of the /dev/sg? */
d52affa7
GH
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 }
2cc977e2
TS
704
705 /* define device state */
2cc977e2 706 s->lun = scsiid.lun;
89c0f643 707 DPRINTF("LUN %d\n", s->lun);
a9dd6843 708 s->type = scsiid.scsi_type;
89c0f643
AJ
709 DPRINTF("device type %d\n", s->type);
710 if (s->type == TYPE_TAPE) {
d52affa7 711 s->blocksize = get_stream_blocksize(s->dinfo->bdrv);
89c0f643
AJ
712 if (s->blocksize == -1)
713 s->blocksize = 0;
714 } else {
d52affa7 715 s->blocksize = get_blocksize(s->dinfo->bdrv);
89c0f643
AJ
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);
2cc977e2
TS
725 s->driver_status = 0;
726 memset(s->sensebuf, 0, sizeof(s->sensebuf));
d52affa7
GH
727 return 0;
728}
2cc977e2 729
d52affa7
GH
730static 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};
2cc977e2 746
d52affa7
GH
747static void scsi_generic_register_devices(void)
748{
749 scsi_qdev_register(&scsi_generic_info);
2cc977e2 750}
d52affa7
GH
751device_init(scsi_generic_register_devices)
752
2cc977e2 753#endif /* __linux__ */
This page took 0.357925 seconds and 4 git commands to generate.