]> Git Repo - qemu.git/blame - hw/scsi-disk.c
Fix miscellaneous minor things, by Andre Przywara.
[qemu.git] / hw / scsi-disk.c
CommitLineData
2e5d83bb
PB
1/*
2 * SCSI Device emulation
3 *
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
6 *
7 * Written by Paul Brook
8 *
9 * This code is licenced under the LGPL.
a917d384
PB
10 *
11 * Note that this file only handles the SCSI architecture model and device
12 * commands. Emultion of interface/link layer protocols is handled by
13 * the host adapter emulation.
2e5d83bb
PB
14 */
15
16//#define DEBUG_SCSI
17
18#ifdef DEBUG_SCSI
19#define DPRINTF(fmt, args...) \
20do { printf("scsi-disk: " fmt , ##args); } while (0)
21#else
22#define DPRINTF(fmt, args...) do {} while(0)
23#endif
24
25#define BADF(fmt, args...) \
26do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
27
87ecb68b
PB
28#include "qemu-common.h"
29#include "block.h"
30#include "scsi-disk.h"
2e5d83bb
PB
31
32#define SENSE_NO_SENSE 0
1aacf348 33#define SENSE_NOT_READY 2
4d611c9a 34#define SENSE_HARDWARE_ERROR 4
2e5d83bb
PB
35#define SENSE_ILLEGAL_REQUEST 5
36
a917d384
PB
37#define SCSI_DMA_BUF_SIZE 65536
38
39typedef struct SCSIRequest {
8ccc2ace 40 SCSIDeviceState *dev;
2e5d83bb 41 uint32_t tag;
2e5d83bb
PB
42 /* ??? We should probably keep track of whether the data trasfer is
43 a read or a write. Currently we rely on the host getting it right. */
a917d384 44 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
2e5d83bb
PB
45 int sector;
46 int sector_count;
a917d384 47 /* The amounnt of data in the buffer. */
2e5d83bb 48 int buf_len;
a917d384 49 uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
4d611c9a 50 BlockDriverAIOCB *aiocb;
a917d384
PB
51 struct SCSIRequest *next;
52} SCSIRequest;
53
8ccc2ace 54struct SCSIDeviceState
a917d384
PB
55{
56 BlockDriverState *bdrv;
57 SCSIRequest *requests;
58 /* The qemu block layer uses a fixed 512 byte sector size.
59 This is the number of 512 byte blocks in a single scsi sector. */
60 int cluster_size;
61 int sense;
62 int tcq;
4d611c9a
PB
63 /* Completion functions may be called from either scsi_{read,write}_data
64 or from the AIO completion routines. */
2e5d83bb
PB
65 scsi_completionfn completion;
66 void *opaque;
67};
68
a917d384
PB
69/* Global pool of SCSIRequest structures. */
70static SCSIRequest *free_requests = NULL;
71
8ccc2ace 72static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
2e5d83bb 73{
a917d384
PB
74 SCSIRequest *r;
75
76 if (free_requests) {
77 r = free_requests;
78 free_requests = r->next;
79 } else {
80 r = qemu_malloc(sizeof(SCSIRequest));
81 }
82 r->dev = s;
83 r->tag = tag;
84 r->sector_count = 0;
85 r->buf_len = 0;
86 r->aiocb = NULL;
87
88 r->next = s->requests;
89 s->requests = r;
90 return r;
2e5d83bb
PB
91}
92
a917d384 93static void scsi_remove_request(SCSIRequest *r)
4d611c9a 94{
a917d384 95 SCSIRequest *last;
8ccc2ace 96 SCSIDeviceState *s = r->dev;
a917d384
PB
97
98 if (s->requests == r) {
99 s->requests = r->next;
100 } else {
101 last = s->requests;
102 while (last && last->next != r)
103 last = last->next;
104 if (last) {
105 last->next = r->next;
106 } else {
107 BADF("Orphaned request\n");
108 }
109 }
110 r->next = free_requests;
111 free_requests = r;
4d611c9a
PB
112}
113
8ccc2ace 114static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
4d611c9a 115{
a917d384 116 SCSIRequest *r;
4d611c9a 117
a917d384
PB
118 r = s->requests;
119 while (r && r->tag != tag)
120 r = r->next;
4d611c9a 121
a917d384
PB
122 return r;
123}
124
125/* Helper function for command completion. */
126static void scsi_command_complete(SCSIRequest *r, int sense)
127{
8ccc2ace 128 SCSIDeviceState *s = r->dev;
a917d384
PB
129 uint32_t tag;
130 DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
131 s->sense = sense;
132 tag = r->tag;
133 scsi_remove_request(r);
134 s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
4d611c9a
PB
135}
136
137/* Cancel a pending data transfer. */
8ccc2ace 138static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
4d611c9a 139{
8ccc2ace 140 SCSIDeviceState *s = d->state;
a917d384
PB
141 SCSIRequest *r;
142 DPRINTF("Cancel tag=0x%x\n", tag);
143 r = scsi_find_request(s, tag);
144 if (r) {
145 if (r->aiocb)
146 bdrv_aio_cancel(r->aiocb);
147 r->aiocb = NULL;
148 scsi_remove_request(r);
149 }
150}
151
152static void scsi_read_complete(void * opaque, int ret)
153{
154 SCSIRequest *r = (SCSIRequest *)opaque;
8ccc2ace 155 SCSIDeviceState *s = r->dev;
a917d384
PB
156
157 if (ret) {
158 DPRINTF("IO error\n");
159 scsi_command_complete(r, SENSE_HARDWARE_ERROR);
4d611c9a
PB
160 return;
161 }
a917d384
PB
162 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
163
164 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
4d611c9a
PB
165}
166
a917d384 167/* Read more data from scsi device into buffer. */
8ccc2ace 168static void scsi_read_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 169{
8ccc2ace 170 SCSIDeviceState *s = d->state;
a917d384 171 SCSIRequest *r;
2e5d83bb
PB
172 uint32_t n;
173
a917d384
PB
174 r = scsi_find_request(s, tag);
175 if (!r) {
176 BADF("Bad read tag 0x%x\n", tag);
177 /* ??? This is the wrong error. */
178 scsi_command_complete(r, SENSE_HARDWARE_ERROR);
179 return;
2e5d83bb 180 }
a917d384
PB
181 if (r->sector_count == (uint32_t)-1) {
182 DPRINTF("Read buf_len=%d\n", r->buf_len);
183 r->sector_count = 0;
184 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
185 return;
2e5d83bb 186 }
a917d384
PB
187 DPRINTF("Read sector_count=%d\n", r->sector_count);
188 if (r->sector_count == 0) {
189 scsi_command_complete(r, SENSE_NO_SENSE);
190 return;
2e5d83bb
PB
191 }
192
a917d384
PB
193 n = r->sector_count;
194 if (n > SCSI_DMA_BUF_SIZE / 512)
195 n = SCSI_DMA_BUF_SIZE / 512;
196
197 r->buf_len = n * 512;
198 r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
199 scsi_read_complete, r);
200 if (r->aiocb == NULL)
201 scsi_command_complete(r, SENSE_HARDWARE_ERROR);
202 r->sector += n;
203 r->sector_count -= n;
2e5d83bb
PB
204}
205
4d611c9a
PB
206static void scsi_write_complete(void * opaque, int ret)
207{
a917d384 208 SCSIRequest *r = (SCSIRequest *)opaque;
8ccc2ace 209 SCSIDeviceState *s = r->dev;
a917d384 210 uint32_t len;
4d611c9a
PB
211
212 if (ret) {
213 fprintf(stderr, "scsi-disc: IO write error\n");
214 exit(1);
215 }
216
a917d384
PB
217 r->aiocb = NULL;
218 if (r->sector_count == 0) {
219 scsi_command_complete(r, SENSE_NO_SENSE);
220 } else {
221 len = r->sector_count * 512;
222 if (len > SCSI_DMA_BUF_SIZE) {
223 len = SCSI_DMA_BUF_SIZE;
224 }
225 r->buf_len = len;
226 DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
227 s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
4d611c9a 228 }
4d611c9a
PB
229}
230
231/* Write data to a scsi device. Returns nonzero on failure.
232 The transfer may complete asynchronously. */
8ccc2ace 233static int scsi_write_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 234{
8ccc2ace 235 SCSIDeviceState *s = d->state;
a917d384 236 SCSIRequest *r;
2e5d83bb
PB
237 uint32_t n;
238
a917d384
PB
239 DPRINTF("Write data tag=0x%x\n", tag);
240 r = scsi_find_request(s, tag);
241 if (!r) {
242 BADF("Bad write tag 0x%x\n", tag);
243 scsi_command_complete(r, SENSE_HARDWARE_ERROR);
2e5d83bb
PB
244 return 1;
245 }
a917d384
PB
246 if (r->aiocb)
247 BADF("Data transfer already in progress\n");
248 n = r->buf_len / 512;
249 if (n) {
250 r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
251 scsi_write_complete, r);
252 if (r->aiocb == NULL)
253 scsi_command_complete(r, SENSE_HARDWARE_ERROR);
254 r->sector += n;
255 r->sector_count -= n;
256 } else {
257 /* Invoke completion routine to fetch data from host. */
258 scsi_write_complete(r, 0);
2e5d83bb
PB
259 }
260
a917d384
PB
261 return 0;
262}
2e5d83bb 263
a917d384 264/* Return a pointer to the data buffer. */
8ccc2ace 265static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
a917d384 266{
8ccc2ace 267 SCSIDeviceState *s = d->state;
a917d384 268 SCSIRequest *r;
2e5d83bb 269
a917d384
PB
270 r = scsi_find_request(s, tag);
271 if (!r) {
272 BADF("Bad buffer tag 0x%x\n", tag);
273 return NULL;
4d611c9a 274 }
a917d384 275 return r->dma_buf;
2e5d83bb
PB
276}
277
278/* Execute a scsi command. Returns the length of the data expected by the
279 command. This will be Positive for data transfers from the device
280 (eg. disk reads), negative for transfers to the device (eg. disk writes),
281 and zero if the command does not transfer any data. */
282
8ccc2ace
TS
283static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
284 uint8_t *buf, int lun)
2e5d83bb 285{
8ccc2ace 286 SCSIDeviceState *s = d->state;
96b8f136 287 uint64_t nb_sectors;
2e5d83bb
PB
288 uint32_t lba;
289 uint32_t len;
290 int cmdlen;
291 int is_write;
a917d384
PB
292 uint8_t command;
293 uint8_t *outbuf;
294 SCSIRequest *r;
295
296 command = buf[0];
297 r = scsi_find_request(s, tag);
298 if (r) {
299 BADF("Tag 0x%x already in use\n", tag);
8ccc2ace 300 scsi_cancel_io(d, tag);
a917d384
PB
301 }
302 /* ??? Tags are not unique for different luns. We only implement a
303 single lun, so this should not matter. */
304 r = scsi_new_request(s, tag);
305 outbuf = r->dma_buf;
2e5d83bb 306 is_write = 0;
a917d384
PB
307 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
308 switch (command >> 5) {
2e5d83bb
PB
309 case 0:
310 lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
311 len = buf[4];
312 cmdlen = 6;
313 break;
314 case 1:
315 case 2:
316 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
317 len = buf[8] | (buf[7] << 8);
318 cmdlen = 10;
319 break;
320 case 4:
321 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
322 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
323 cmdlen = 16;
324 break;
325 case 5:
326 lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
327 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
328 cmdlen = 12;
329 break;
330 default:
a917d384 331 BADF("Unsupported command length, command %x\n", command);
2e5d83bb
PB
332 goto fail;
333 }
334#ifdef DEBUG_SCSI
335 {
336 int i;
337 for (i = 1; i < cmdlen; i++) {
338 printf(" 0x%02x", buf[i]);
339 }
340 printf("\n");
341 }
342#endif
0fc5c15a 343 if (lun || buf[1] >> 5) {
2e5d83bb 344 /* Only LUN 0 supported. */
0fc5c15a 345 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
2e5d83bb
PB
346 goto fail;
347 }
a917d384 348 switch (command) {
2e5d83bb
PB
349 case 0x0:
350 DPRINTF("Test Unit Ready\n");
351 break;
352 case 0x03:
353 DPRINTF("Request Sense (len %d)\n", len);
354 if (len < 4)
355 goto fail;
67cd24a8 356 memset(outbuf, 0, 4);
a917d384
PB
357 outbuf[0] = 0xf0;
358 outbuf[1] = 0;
359 outbuf[2] = s->sense;
360 r->buf_len = 4;
2e5d83bb
PB
361 break;
362 case 0x12:
7d8406be 363 DPRINTF("Inquiry (len %d)\n", len);
2e5d83bb
PB
364 if (len < 36) {
365 BADF("Inquiry buffer too small (%d)\n", len);
366 }
a917d384 367 memset(outbuf, 0, 36);
2e5d83bb 368 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
a917d384
PB
369 outbuf[0] = 5;
370 outbuf[1] = 0x80;
371 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
2e5d83bb 372 } else {
a917d384
PB
373 outbuf[0] = 0;
374 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
2e5d83bb 375 }
a917d384
PB
376 memcpy(&outbuf[8], "QEMU ", 8);
377 memcpy(&outbuf[32], QEMU_VERSION, 4);
17acfe32
PB
378 /* Identify device as SCSI-3 rev 1.
379 Some later commands are also implemented. */
a917d384
PB
380 outbuf[2] = 3;
381 outbuf[3] = 2; /* Format 2 */
67cd24a8 382 outbuf[4] = 31;
a917d384
PB
383 /* Sync data transfer and TCQ. */
384 outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
385 r->buf_len = 36;
2e5d83bb
PB
386 break;
387 case 0x16:
388 DPRINTF("Reserve(6)\n");
389 if (buf[1] & 1)
390 goto fail;
391 break;
392 case 0x17:
393 DPRINTF("Release(6)\n");
394 if (buf[1] & 1)
395 goto fail;
396 break;
397 case 0x1a:
7d8406be 398 case 0x5a:
17acfe32 399 {
a917d384 400 uint8_t *p;
17acfe32
PB
401 int page;
402
403 page = buf[2] & 0x3f;
404 DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
a917d384 405 p = outbuf;
17acfe32 406 memset(p, 0, 4);
a917d384
PB
407 outbuf[1] = 0; /* Default media type. */
408 outbuf[3] = 0; /* Block descriptor length. */
17acfe32 409 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
a917d384 410 outbuf[2] = 0x80; /* Readonly. */
17acfe32
PB
411 }
412 p += 4;
413 if ((page == 8 || page == 0x3f)) {
414 /* Caching page. */
67cd24a8 415 memset(p,0,20);
17acfe32
PB
416 p[0] = 8;
417 p[1] = 0x12;
418 p[2] = 4; /* WCE */
67cd24a8 419 p += 20;
17acfe32
PB
420 }
421 if ((page == 0x3f || page == 0x2a)
422 && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
423 /* CD Capabilities and Mechanical Status page. */
424 p[0] = 0x2a;
425 p[1] = 0x14;
426 p[2] = 3; // CD-R & CD-RW read
427 p[3] = 0; // Writing not supported
428 p[4] = 0x7f; /* Audio, composite, digital out,
429 mode 2 form 1&2, multi session */
430 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
431 RW corrected, C2 errors, ISRC,
432 UPC, Bar code */
433 p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
434 /* Locking supported, jumper present, eject, tray */
435 p[7] = 0; /* no volume & mute control, no
436 changer */
437 p[8] = (50 * 176) >> 8; // 50x read speed
438 p[9] = (50 * 176) & 0xff;
439 p[10] = 0 >> 8; // No volume
440 p[11] = 0 & 0xff;
441 p[12] = 2048 >> 8; // 2M buffer
442 p[13] = 2048 & 0xff;
443 p[14] = (16 * 176) >> 8; // 16x read speed current
444 p[15] = (16 * 176) & 0xff;
445 p[18] = (16 * 176) >> 8; // 16x write speed
446 p[19] = (16 * 176) & 0xff;
447 p[20] = (16 * 176) >> 8; // 16x write speed current
448 p[21] = (16 * 176) & 0xff;
67cd24a8 449 p += 22;
17acfe32 450 }
a917d384
PB
451 r->buf_len = p - outbuf;
452 outbuf[0] = r->buf_len - 4;
453 if (r->buf_len > len)
454 r->buf_len = len;
7d8406be 455 }
17acfe32
PB
456 break;
457 case 0x1b:
458 DPRINTF("Start Stop Unit\n");
459 break;
460 case 0x1e:
461 DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
462 bdrv_set_locked(s->bdrv, buf[4] & 1);
2e5d83bb
PB
463 break;
464 case 0x25:
465 DPRINTF("Read Capacity\n");
466 /* The normal LEN field for this command is zero. */
a917d384 467 memset(outbuf, 0, 8);
2e5d83bb 468 bdrv_get_geometry(s->bdrv, &nb_sectors);
51c1ebb1
PB
469 /* Returned value is the address of the last sector. */
470 if (nb_sectors) {
471 nb_sectors--;
a917d384
PB
472 outbuf[0] = (nb_sectors >> 24) & 0xff;
473 outbuf[1] = (nb_sectors >> 16) & 0xff;
474 outbuf[2] = (nb_sectors >> 8) & 0xff;
475 outbuf[3] = nb_sectors & 0xff;
476 outbuf[4] = 0;
477 outbuf[5] = 0;
478 outbuf[6] = s->cluster_size * 2;
479 outbuf[7] = 0;
480 r->buf_len = 8;
51c1ebb1 481 } else {
a917d384 482 scsi_command_complete(r, SENSE_NOT_READY);
35f1df84 483 return 0;
51c1ebb1 484 }
2e5d83bb
PB
485 break;
486 case 0x08:
487 case 0x28:
488 DPRINTF("Read (sector %d, count %d)\n", lba, len);
a917d384
PB
489 r->sector = lba * s->cluster_size;
490 r->sector_count = len * s->cluster_size;
2e5d83bb
PB
491 break;
492 case 0x0a:
493 case 0x2a:
494 DPRINTF("Write (sector %d, count %d)\n", lba, len);
a917d384
PB
495 r->sector = lba * s->cluster_size;
496 r->sector_count = len * s->cluster_size;
2e5d83bb
PB
497 is_write = 1;
498 break;
7d8406be 499 case 0x35:
e91c8a77 500 DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len);
7a6cba61 501 bdrv_flush(s->bdrv);
7d8406be 502 break;
2e5d83bb
PB
503 case 0x43:
504 {
7c22dd52 505 int start_track, format, msf, toclen;
2e5d83bb
PB
506
507 msf = buf[1] & 2;
508 format = buf[2] & 0xf;
509 start_track = buf[6];
510 bdrv_get_geometry(s->bdrv, &nb_sectors);
511 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
512 switch(format) {
513 case 0:
a917d384 514 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
2e5d83bb
PB
515 break;
516 case 1:
517 /* multi session : only a single session defined */
7c22dd52 518 toclen = 12;
a917d384
PB
519 memset(outbuf, 0, 12);
520 outbuf[1] = 0x0a;
521 outbuf[2] = 0x01;
522 outbuf[3] = 0x01;
2e5d83bb
PB
523 break;
524 case 2:
a917d384 525 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
2e5d83bb
PB
526 break;
527 default:
7c22dd52
PB
528 goto error_cmd;
529 }
530 if (toclen > 0) {
531 if (len > toclen)
532 len = toclen;
a917d384 533 r->buf_len = len;
7c22dd52 534 break;
2e5d83bb 535 }
7c22dd52
PB
536 error_cmd:
537 DPRINTF("Read TOC error\n");
538 goto fail;
2e5d83bb 539 }
17acfe32
PB
540 case 0x46:
541 DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
a917d384 542 memset(outbuf, 0, 8);
17acfe32
PB
543 /* ??? This shoud probably return much more information. For now
544 just return the basic header indicating the CD-ROM profile. */
a917d384
PB
545 outbuf[7] = 8; // CD-ROM
546 r->buf_len = 8;
17acfe32 547 break;
2e5d83bb
PB
548 case 0x56:
549 DPRINTF("Reserve(10)\n");
550 if (buf[1] & 3)
551 goto fail;
552 break;
553 case 0x57:
554 DPRINTF("Release(10)\n");
555 if (buf[1] & 3)
556 goto fail;
557 break;
558 case 0xa0:
559 DPRINTF("Report LUNs (len %d)\n", len);
560 if (len < 16)
561 goto fail;
a917d384
PB
562 memset(outbuf, 0, 16);
563 outbuf[3] = 8;
564 r->buf_len = 16;
2e5d83bb
PB
565 break;
566 default:
567 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
568 fail:
a917d384 569 scsi_command_complete(r, SENSE_ILLEGAL_REQUEST);
2e5d83bb
PB
570 return 0;
571 }
a917d384
PB
572 if (r->sector_count == 0 && r->buf_len == 0) {
573 scsi_command_complete(r, SENSE_NO_SENSE);
574 }
575 len = r->sector_count * 512 + r->buf_len;
576 if (is_write) {
577 return -len;
578 } else {
579 if (!r->sector_count)
580 r->sector_count = -1;
581 return len;
2e5d83bb 582 }
2e5d83bb
PB
583}
584
8ccc2ace 585static void scsi_destroy(SCSIDevice *d)
2e5d83bb 586{
8ccc2ace
TS
587 qemu_free(d->state);
588 qemu_free(d);
2e5d83bb
PB
589}
590
8ccc2ace
TS
591SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
592 scsi_completionfn completion, void *opaque)
2e5d83bb 593{
8ccc2ace
TS
594 SCSIDevice *d;
595 SCSIDeviceState *s;
2e5d83bb 596
8ccc2ace 597 s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
2e5d83bb 598 s->bdrv = bdrv;
a917d384 599 s->tcq = tcq;
2e5d83bb
PB
600 s->completion = completion;
601 s->opaque = opaque;
602 if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
7c22dd52 603 s->cluster_size = 4;
2e5d83bb 604 } else {
7c22dd52 605 s->cluster_size = 1;
2e5d83bb
PB
606 }
607
8ccc2ace
TS
608 d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
609 d->state = s;
610 d->destroy = scsi_destroy;
611 d->send_command = scsi_send_command;
612 d->read_data = scsi_read_data;
613 d->write_data = scsi_write_data;
614 d->cancel_io = scsi_cancel_io;
615 d->get_buf = scsi_get_buf;
2e5d83bb 616
8ccc2ace
TS
617 return d;
618}
This page took 0.184278 seconds and 4 git commands to generate.