2 * SCSI Device emulation
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
7 * Written by Paul Brook
9 * 2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
10 * when the allocation length of CDB is smaller
12 * 2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
13 * MODE SENSE response.
15 * This code is licenced under the LGPL.
17 * Note that this file only handles the SCSI architecture model and device
18 * commands. Emulation of interface/link layer protocols is handled by
19 * the host adapter emulator.
22 #include <qemu-common.h>
27 #define DPRINTF(fmt, ...) \
28 do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
30 #define DPRINTF(fmt, ...) do {} while(0)
33 #define BADF(fmt, ...) \
34 do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
36 #include "qemu-common.h"
39 #include "scsi-defs.h"
41 #define SCSI_DMA_BUF_SIZE 131072
42 #define SCSI_MAX_INQUIRY_LEN 256
44 #define SCSI_REQ_STATUS_RETRY 0x01
46 typedef struct SCSIDiskState SCSIDiskState
;
48 typedef struct SCSIDiskReq
{
50 /* ??? We should probably keep track of whether the data transfer is
51 a read or a write. Currently we rely on the host getting it right. */
52 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
54 uint32_t sector_count
;
63 /* The qemu block layer uses a fixed 512 byte sector size.
64 This is the number of 512 byte blocks in a single scsi sector. */
70 static SCSIDiskReq
*scsi_new_request(SCSIDevice
*d
, uint32_t tag
, uint32_t lun
)
75 req
= scsi_req_alloc(sizeof(SCSIDiskReq
), d
, tag
, lun
);
76 r
= DO_UPCAST(SCSIDiskReq
, req
, req
);
77 r
->iov
.iov_base
= qemu_memalign(512, SCSI_DMA_BUF_SIZE
);
81 static void scsi_remove_request(SCSIDiskReq
*r
)
83 qemu_free(r
->iov
.iov_base
);
84 scsi_req_free(&r
->req
);
87 static SCSIDiskReq
*scsi_find_request(SCSIDiskState
*s
, uint32_t tag
)
89 return DO_UPCAST(SCSIDiskReq
, req
, scsi_req_find(&s
->qdev
, tag
));
92 static void scsi_req_set_status(SCSIRequest
*req
, int status
, int sense_code
)
95 scsi_dev_set_sense(req
->dev
, sense_code
);
98 /* Helper function for command completion. */
99 static void scsi_command_complete(SCSIDiskReq
*r
, int status
, int sense
)
101 DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
102 r
->req
.tag
, status
, sense
);
103 scsi_req_set_status(&r
->req
, status
, sense
);
104 scsi_req_complete(&r
->req
);
105 scsi_remove_request(r
);
108 /* Cancel a pending data transfer. */
109 static void scsi_cancel_io(SCSIDevice
*d
, uint32_t tag
)
111 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, d
);
113 DPRINTF("Cancel tag=0x%x\n", tag
);
114 r
= scsi_find_request(s
, tag
);
117 bdrv_aio_cancel(r
->req
.aiocb
);
119 scsi_remove_request(r
);
123 static void scsi_read_complete(void * opaque
, int ret
)
125 SCSIDiskReq
*r
= (SCSIDiskReq
*)opaque
;
128 DPRINTF("IO error\n");
129 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, 0);
130 scsi_command_complete(r
, CHECK_CONDITION
, NO_SENSE
);
133 DPRINTF("Data ready tag=0x%x len=%" PRId64
"\n", r
->req
.tag
, r
->iov
.iov_len
);
135 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, r
->iov
.iov_len
);
138 /* Read more data from scsi device into buffer. */
139 static void scsi_read_data(SCSIDevice
*d
, uint32_t tag
)
141 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, d
);
145 r
= scsi_find_request(s
, tag
);
147 BADF("Bad read tag 0x%x\n", tag
);
148 /* ??? This is the wrong error. */
149 scsi_command_complete(r
, CHECK_CONDITION
, HARDWARE_ERROR
);
152 if (r
->sector_count
== (uint32_t)-1) {
153 DPRINTF("Read buf_len=%" PRId64
"\n", r
->iov
.iov_len
);
155 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, r
->iov
.iov_len
);
158 DPRINTF("Read sector_count=%d\n", r
->sector_count
);
159 if (r
->sector_count
== 0) {
160 scsi_command_complete(r
, GOOD
, NO_SENSE
);
165 if (n
> SCSI_DMA_BUF_SIZE
/ 512)
166 n
= SCSI_DMA_BUF_SIZE
/ 512;
168 r
->iov
.iov_len
= n
* 512;
169 qemu_iovec_init_external(&r
->qiov
, &r
->iov
, 1);
170 r
->req
.aiocb
= bdrv_aio_readv(s
->qdev
.dinfo
->bdrv
, r
->sector
, &r
->qiov
, n
,
171 scsi_read_complete
, r
);
172 if (r
->req
.aiocb
== NULL
)
173 scsi_command_complete(r
, CHECK_CONDITION
, HARDWARE_ERROR
);
175 r
->sector_count
-= n
;
178 static int scsi_handle_write_error(SCSIDiskReq
*r
, int error
)
180 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, r
->req
.dev
);
181 BlockInterfaceErrorAction action
=
182 drive_get_on_error(s
->qdev
.dinfo
->bdrv
, 0);
184 if (action
== BLOCK_ERR_IGNORE
)
187 if ((error
== ENOSPC
&& action
== BLOCK_ERR_STOP_ENOSPC
)
188 || action
== BLOCK_ERR_STOP_ANY
) {
189 r
->status
|= SCSI_REQ_STATUS_RETRY
;
192 scsi_command_complete(r
, CHECK_CONDITION
,
199 static void scsi_write_complete(void * opaque
, int ret
)
201 SCSIDiskReq
*r
= (SCSIDiskReq
*)opaque
;
208 if (scsi_handle_write_error(r
, -ret
))
212 n
= r
->iov
.iov_len
/ 512;
214 r
->sector_count
-= n
;
215 if (r
->sector_count
== 0) {
216 scsi_command_complete(r
, GOOD
, NO_SENSE
);
218 len
= r
->sector_count
* 512;
219 if (len
> SCSI_DMA_BUF_SIZE
) {
220 len
= SCSI_DMA_BUF_SIZE
;
222 r
->iov
.iov_len
= len
;
223 DPRINTF("Write complete tag=0x%x more=%d\n", r
->req
.tag
, len
);
224 r
->req
.bus
->complete(r
->req
.bus
, SCSI_REASON_DATA
, r
->req
.tag
, len
);
228 static void scsi_write_request(SCSIDiskReq
*r
)
230 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, r
->req
.dev
);
233 n
= r
->iov
.iov_len
/ 512;
235 qemu_iovec_init_external(&r
->qiov
, &r
->iov
, 1);
236 r
->req
.aiocb
= bdrv_aio_writev(s
->qdev
.dinfo
->bdrv
, r
->sector
, &r
->qiov
, n
,
237 scsi_write_complete
, r
);
238 if (r
->req
.aiocb
== NULL
)
239 scsi_command_complete(r
, CHECK_CONDITION
,
242 /* Invoke completion routine to fetch data from host. */
243 scsi_write_complete(r
, 0);
247 /* Write data to a scsi device. Returns nonzero on failure.
248 The transfer may complete asynchronously. */
249 static int scsi_write_data(SCSIDevice
*d
, uint32_t tag
)
251 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, d
);
254 DPRINTF("Write data tag=0x%x\n", tag
);
255 r
= scsi_find_request(s
, tag
);
257 BADF("Bad write tag 0x%x\n", tag
);
258 scsi_command_complete(r
, CHECK_CONDITION
, HARDWARE_ERROR
);
263 BADF("Data transfer already in progress\n");
265 scsi_write_request(r
);
270 static void scsi_dma_restart_bh(void *opaque
)
272 SCSIDiskState
*s
= opaque
;
276 qemu_bh_delete(s
->bh
);
279 QTAILQ_FOREACH(req
, &s
->qdev
.requests
, next
) {
280 r
= DO_UPCAST(SCSIDiskReq
, req
, req
);
281 if (r
->status
& SCSI_REQ_STATUS_RETRY
) {
282 r
->status
&= ~SCSI_REQ_STATUS_RETRY
;
283 scsi_write_request(r
);
288 static void scsi_dma_restart_cb(void *opaque
, int running
, int reason
)
290 SCSIDiskState
*s
= opaque
;
296 s
->bh
= qemu_bh_new(scsi_dma_restart_bh
, s
);
297 qemu_bh_schedule(s
->bh
);
301 /* Return a pointer to the data buffer. */
302 static uint8_t *scsi_get_buf(SCSIDevice
*d
, uint32_t tag
)
304 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, d
);
307 r
= scsi_find_request(s
, tag
);
309 BADF("Bad buffer tag 0x%x\n", tag
);
312 return (uint8_t *)r
->iov
.iov_base
;
315 static int scsi_disk_emulate_inquiry(SCSIRequest
*req
, uint8_t *outbuf
)
317 BlockDriverState
*bdrv
= req
->dev
->dinfo
->bdrv
;
320 if (req
->cmd
.buf
[1] & 0x2) {
321 /* Command support data - optional, not implemented */
322 BADF("optional INQUIRY command support request not implemented\n");
326 if (req
->cmd
.buf
[1] & 0x1) {
327 /* Vital product data */
328 uint8_t page_code
= req
->cmd
.buf
[2];
329 if (req
->cmd
.xfer
< 4) {
330 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
331 "less than 4\n", page_code
, req
->cmd
.xfer
);
335 if (bdrv_get_type_hint(bdrv
) == BDRV_TYPE_CDROM
) {
336 outbuf
[buflen
++] = 5;
338 outbuf
[buflen
++] = 0;
340 outbuf
[buflen
++] = page_code
; // this page
341 outbuf
[buflen
++] = 0x00;
344 case 0x00: /* Supported page codes, mandatory */
345 DPRINTF("Inquiry EVPD[Supported pages] "
346 "buffer size %zd\n", req
->cmd
.xfer
);
347 outbuf
[buflen
++] = 3; // number of pages
348 outbuf
[buflen
++] = 0x00; // list of supported pages (this page)
349 outbuf
[buflen
++] = 0x80; // unit serial number
350 outbuf
[buflen
++] = 0x83; // device identification
353 case 0x80: /* Device serial number, optional */
355 const char *serial
= req
->dev
->dinfo
->serial
?
356 req
->dev
->dinfo
->serial
: "0";
357 int l
= strlen(serial
);
359 if (l
> req
->cmd
.xfer
)
364 DPRINTF("Inquiry EVPD[Serial number] "
365 "buffer size %zd\n", req
->cmd
.xfer
);
366 outbuf
[buflen
++] = l
;
367 memcpy(outbuf
+buflen
, serial
, l
);
372 case 0x83: /* Device identification page, mandatory */
374 int max_len
= 255 - 8;
375 int id_len
= strlen(bdrv_get_device_name(bdrv
));
377 if (id_len
> max_len
)
379 DPRINTF("Inquiry EVPD[Device identification] "
380 "buffer size %zd\n", req
->cmd
.xfer
);
382 outbuf
[buflen
++] = 3 + id_len
;
383 outbuf
[buflen
++] = 0x2; // ASCII
384 outbuf
[buflen
++] = 0; // not officially assigned
385 outbuf
[buflen
++] = 0; // reserved
386 outbuf
[buflen
++] = id_len
; // length of data following
388 memcpy(outbuf
+buflen
, bdrv_get_device_name(bdrv
), id_len
);
393 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
394 "buffer size %zd\n", page_code
, req
->cmd
.xfer
);
401 /* Standard INQUIRY data */
402 if (req
->cmd
.buf
[2] != 0) {
403 BADF("Error: Inquiry (STANDARD) page or code "
404 "is non-zero [%02X]\n", req
->cmd
.buf
[2]);
409 if (req
->cmd
.xfer
< 5) {
410 BADF("Error: Inquiry (STANDARD) buffer size %zd "
411 "is less than 5\n", req
->cmd
.xfer
);
415 buflen
= req
->cmd
.xfer
;
416 if (buflen
> SCSI_MAX_INQUIRY_LEN
)
417 buflen
= SCSI_MAX_INQUIRY_LEN
;
419 memset(outbuf
, 0, buflen
);
421 if (req
->lun
|| req
->cmd
.buf
[1] >> 5) {
422 outbuf
[0] = 0x7f; /* LUN not supported */
426 if (bdrv_get_type_hint(bdrv
) == BDRV_TYPE_CDROM
) {
429 memcpy(&outbuf
[16], "QEMU CD-ROM ", 16);
432 memcpy(&outbuf
[16], "QEMU HARDDISK ", 16);
434 memcpy(&outbuf
[8], "QEMU ", 8);
435 memcpy(&outbuf
[32], QEMU_VERSION
, 4);
436 /* Identify device as SCSI-3 rev 1.
437 Some later commands are also implemented. */
439 outbuf
[3] = 2; /* Format 2 */
442 outbuf
[4] = buflen
- 5; /* Additional Length = (Len - 1) - 4 */
444 /* If the allocation length of CDB is too small,
445 the additional length is not adjusted */
449 /* Sync data transfer and TCQ. */
450 outbuf
[7] = 0x10 | (req
->bus
->tcq
? 0x02 : 0);
454 static int mode_sense_page(SCSIRequest
*req
, int page
, uint8_t *p
)
456 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, req
->dev
);
457 BlockDriverState
*bdrv
= req
->dev
->dinfo
->bdrv
;
458 int cylinders
, heads
, secs
;
461 case 4: /* Rigid disk device geometry page. */
464 /* if a geometry hint is available, use it */
465 bdrv_get_geometry_hint(bdrv
, &cylinders
, &heads
, &secs
);
466 p
[2] = (cylinders
>> 16) & 0xff;
467 p
[3] = (cylinders
>> 8) & 0xff;
468 p
[4] = cylinders
& 0xff;
470 /* Write precomp start cylinder, disabled */
471 p
[6] = (cylinders
>> 16) & 0xff;
472 p
[7] = (cylinders
>> 8) & 0xff;
473 p
[8] = cylinders
& 0xff;
474 /* Reduced current start cylinder, disabled */
475 p
[9] = (cylinders
>> 16) & 0xff;
476 p
[10] = (cylinders
>> 8) & 0xff;
477 p
[11] = cylinders
& 0xff;
478 /* Device step rate [ns], 200ns */
481 /* Landing zone cylinder */
485 /* Medium rotation rate [rpm], 5400 rpm */
486 p
[20] = (5400 >> 8) & 0xff;
490 case 5: /* Flexible disk device geometry page. */
493 /* Transfer rate [kbit/s], 5Mbit/s */
496 /* if a geometry hint is available, use it */
497 bdrv_get_geometry_hint(bdrv
, &cylinders
, &heads
, &secs
);
500 p
[6] = s
->cluster_size
* 2;
501 p
[8] = (cylinders
>> 8) & 0xff;
502 p
[9] = cylinders
& 0xff;
503 /* Write precomp start cylinder, disabled */
504 p
[10] = (cylinders
>> 8) & 0xff;
505 p
[11] = cylinders
& 0xff;
506 /* Reduced current start cylinder, disabled */
507 p
[12] = (cylinders
>> 8) & 0xff;
508 p
[13] = cylinders
& 0xff;
509 /* Device step rate [100us], 100us */
512 /* Device step pulse width [us], 1us */
514 /* Device head settle delay [100us], 100us */
517 /* Motor on delay [0.1s], 0.1s */
519 /* Motor off delay [0.1s], 0.1s */
521 /* Medium rotation rate [rpm], 5400 rpm */
522 p
[28] = (5400 >> 8) & 0xff;
526 case 8: /* Caching page. */
529 if (bdrv_enable_write_cache(s
->qdev
.dinfo
->bdrv
)) {
534 case 0x2a: /* CD Capabilities and Mechanical Status page. */
535 if (bdrv_get_type_hint(bdrv
) != BDRV_TYPE_CDROM
)
539 p
[2] = 3; // CD-R & CD-RW read
540 p
[3] = 0; // Writing not supported
541 p
[4] = 0x7f; /* Audio, composite, digital out,
542 mode 2 form 1&2, multi session */
543 p
[5] = 0xff; /* CD DA, DA accurate, RW supported,
544 RW corrected, C2 errors, ISRC,
546 p
[6] = 0x2d | (bdrv_is_locked(s
->qdev
.dinfo
->bdrv
)? 2 : 0);
547 /* Locking supported, jumper present, eject, tray */
548 p
[7] = 0; /* no volume & mute control, no
550 p
[8] = (50 * 176) >> 8; // 50x read speed
551 p
[9] = (50 * 176) & 0xff;
552 p
[10] = 0 >> 8; // No volume
554 p
[12] = 2048 >> 8; // 2M buffer
556 p
[14] = (16 * 176) >> 8; // 16x read speed current
557 p
[15] = (16 * 176) & 0xff;
558 p
[18] = (16 * 176) >> 8; // 16x write speed
559 p
[19] = (16 * 176) & 0xff;
560 p
[20] = (16 * 176) >> 8; // 16x write speed current
561 p
[21] = (16 * 176) & 0xff;
569 static int scsi_disk_emulate_mode_sense(SCSIRequest
*req
, uint8_t *outbuf
)
571 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, req
->dev
);
572 BlockDriverState
*bdrv
= req
->dev
->dinfo
->bdrv
;
574 int page
, dbd
, buflen
;
577 dbd
= req
->cmd
.buf
[1] & 0x8;
578 page
= req
->cmd
.buf
[2] & 0x3f;
579 DPRINTF("Mode Sense (page %d, len %zd)\n", page
, req
->cmd
.xfer
);
580 memset(outbuf
, 0, req
->cmd
.xfer
);
583 p
[1] = 0; /* Default media type. */
584 p
[3] = 0; /* Block descriptor length. */
585 if (bdrv_get_type_hint(bdrv
) == BDRV_TYPE_CDROM
||
586 bdrv_is_read_only(bdrv
)) {
587 p
[2] = 0x80; /* Readonly. */
591 bdrv_get_geometry(bdrv
, &nb_sectors
);
592 if ((~dbd
) & nb_sectors
) {
593 outbuf
[3] = 8; /* Block descriptor length */
594 nb_sectors
/= s
->cluster_size
;
596 if (nb_sectors
> 0xffffff)
597 nb_sectors
= 0xffffff;
598 p
[0] = 0; /* media density code */
599 p
[1] = (nb_sectors
>> 16) & 0xff;
600 p
[2] = (nb_sectors
>> 8) & 0xff;
601 p
[3] = nb_sectors
& 0xff;
602 p
[4] = 0; /* reserved */
603 p
[5] = 0; /* bytes 5-7 are the sector size in bytes */
604 p
[6] = s
->cluster_size
* 2;
614 p
+= mode_sense_page(req
, page
, p
);
617 p
+= mode_sense_page(req
, 0x08, p
);
618 p
+= mode_sense_page(req
, 0x2a, p
);
623 outbuf
[0] = buflen
- 4;
624 if (buflen
> req
->cmd
.xfer
)
625 buflen
= req
->cmd
.xfer
;
629 static int scsi_disk_emulate_read_toc(SCSIRequest
*req
, uint8_t *outbuf
)
631 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, req
->dev
);
632 BlockDriverState
*bdrv
= req
->dev
->dinfo
->bdrv
;
633 int start_track
, format
, msf
, toclen
;
636 msf
= req
->cmd
.buf
[1] & 2;
637 format
= req
->cmd
.buf
[2] & 0xf;
638 start_track
= req
->cmd
.buf
[6];
639 bdrv_get_geometry(bdrv
, &nb_sectors
);
640 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track
, format
, msf
>> 1);
641 nb_sectors
/= s
->cluster_size
;
644 toclen
= cdrom_read_toc(nb_sectors
, outbuf
, msf
, start_track
);
647 /* multi session : only a single session defined */
649 memset(outbuf
, 0, 12);
655 toclen
= cdrom_read_toc_raw(nb_sectors
, outbuf
, msf
, start_track
);
660 if (toclen
> req
->cmd
.xfer
)
661 toclen
= req
->cmd
.xfer
;
665 static int scsi_disk_emulate_command(SCSIRequest
*req
, uint8_t *outbuf
)
667 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, req
->dev
);
668 BlockDriverState
*bdrv
= req
->dev
->dinfo
->bdrv
;
672 switch (req
->cmd
.buf
[0]) {
673 case TEST_UNIT_READY
:
674 if (!bdrv_is_inserted(bdrv
))
678 if (req
->cmd
.xfer
< 4)
679 goto illegal_request
;
680 memset(outbuf
, 0, 4);
682 if (req
->dev
->sense
.key
== NOT_READY
&& req
->cmd
.xfer
>= 18) {
683 memset(outbuf
, 0, 18);
686 /* asc 0x3a, ascq 0: Medium not present */
692 outbuf
[2] = req
->dev
->sense
.key
;
693 scsi_dev_clear_sense(req
->dev
);
696 buflen
= scsi_disk_emulate_inquiry(req
, outbuf
);
698 goto illegal_request
;
702 buflen
= scsi_disk_emulate_mode_sense(req
, outbuf
);
704 goto illegal_request
;
707 buflen
= scsi_disk_emulate_read_toc(req
, outbuf
);
709 goto illegal_request
;
712 if (req
->cmd
.buf
[1] & 1)
713 goto illegal_request
;
716 if (req
->cmd
.buf
[1] & 3)
717 goto illegal_request
;
720 if (req
->cmd
.buf
[1] & 1)
721 goto illegal_request
;
724 if (req
->cmd
.buf
[1] & 3)
725 goto illegal_request
;
728 if (bdrv_get_type_hint(bdrv
) == BDRV_TYPE_CDROM
&& (req
->cmd
.buf
[4] & 2)) {
729 /* load/eject medium */
730 bdrv_eject(bdrv
, !(req
->cmd
.buf
[4] & 1));
733 case ALLOW_MEDIUM_REMOVAL
:
734 bdrv_set_locked(bdrv
, req
->cmd
.buf
[4] & 1);
737 /* The normal LEN field for this command is zero. */
738 memset(outbuf
, 0, 8);
739 bdrv_get_geometry(bdrv
, &nb_sectors
);
742 nb_sectors
/= s
->cluster_size
;
743 /* Returned value is the address of the last sector. */
745 /* Remember the new size for read/write sanity checking. */
746 s
->max_lba
= nb_sectors
;
747 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
748 if (nb_sectors
> UINT32_MAX
)
749 nb_sectors
= UINT32_MAX
;
750 outbuf
[0] = (nb_sectors
>> 24) & 0xff;
751 outbuf
[1] = (nb_sectors
>> 16) & 0xff;
752 outbuf
[2] = (nb_sectors
>> 8) & 0xff;
753 outbuf
[3] = nb_sectors
& 0xff;
756 outbuf
[6] = s
->cluster_size
* 2;
760 case SYNCHRONIZE_CACHE
:
763 case GET_CONFIGURATION
:
764 memset(outbuf
, 0, 8);
765 /* ??? This should probably return much more information. For now
766 just return the basic header indicating the CD-ROM profile. */
767 outbuf
[7] = 8; // CD-ROM
770 case SERVICE_ACTION_IN
:
771 /* Service Action In subcommands. */
772 if ((req
->cmd
.buf
[1] & 31) == 0x10) {
773 DPRINTF("SAI READ CAPACITY(16)\n");
774 memset(outbuf
, 0, req
->cmd
.xfer
);
775 bdrv_get_geometry(bdrv
, &nb_sectors
);
778 nb_sectors
/= s
->cluster_size
;
779 /* Returned value is the address of the last sector. */
781 /* Remember the new size for read/write sanity checking. */
782 s
->max_lba
= nb_sectors
;
783 outbuf
[0] = (nb_sectors
>> 56) & 0xff;
784 outbuf
[1] = (nb_sectors
>> 48) & 0xff;
785 outbuf
[2] = (nb_sectors
>> 40) & 0xff;
786 outbuf
[3] = (nb_sectors
>> 32) & 0xff;
787 outbuf
[4] = (nb_sectors
>> 24) & 0xff;
788 outbuf
[5] = (nb_sectors
>> 16) & 0xff;
789 outbuf
[6] = (nb_sectors
>> 8) & 0xff;
790 outbuf
[7] = nb_sectors
& 0xff;
793 outbuf
[10] = s
->cluster_size
* 2;
795 /* Protection, exponent and lowest lba field left blank. */
796 buflen
= req
->cmd
.xfer
;
799 DPRINTF("Unsupported Service Action In\n");
800 goto illegal_request
;
802 if (req
->cmd
.xfer
< 16)
803 goto illegal_request
;
804 memset(outbuf
, 0, 16);
811 goto illegal_request
;
813 scsi_req_set_status(req
, GOOD
, NO_SENSE
);
817 scsi_req_set_status(req
, CHECK_CONDITION
, NOT_READY
);
821 scsi_req_set_status(req
, CHECK_CONDITION
, ILLEGAL_REQUEST
);
825 /* Execute a scsi command. Returns the length of the data expected by the
826 command. This will be Positive for data transfers from the device
827 (eg. disk reads), negative for transfers to the device (eg. disk writes),
828 and zero if the command does not transfer any data. */
830 static int32_t scsi_send_command(SCSIDevice
*d
, uint32_t tag
,
831 uint8_t *buf
, int lun
)
833 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, d
);
844 r
= scsi_find_request(s
, tag
);
846 BADF("Tag 0x%x already in use\n", tag
);
847 scsi_cancel_io(d
, tag
);
849 /* ??? Tags are not unique for different luns. We only implement a
850 single lun, so this should not matter. */
851 r
= scsi_new_request(d
, tag
, lun
);
852 outbuf
= (uint8_t *)r
->iov
.iov_base
;
854 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun
, tag
, buf
[0]);
855 switch (command
>> 5) {
857 lba
= (uint64_t) buf
[3] | ((uint64_t) buf
[2] << 8) |
858 (((uint64_t) buf
[1] & 0x1f) << 16);
864 lba
= (uint64_t) buf
[5] | ((uint64_t) buf
[4] << 8) |
865 ((uint64_t) buf
[3] << 16) | ((uint64_t) buf
[2] << 24);
866 len
= buf
[8] | (buf
[7] << 8);
870 lba
= (uint64_t) buf
[9] | ((uint64_t) buf
[8] << 8) |
871 ((uint64_t) buf
[7] << 16) | ((uint64_t) buf
[6] << 24) |
872 ((uint64_t) buf
[5] << 32) | ((uint64_t) buf
[4] << 40) |
873 ((uint64_t) buf
[3] << 48) | ((uint64_t) buf
[2] << 56);
874 len
= buf
[13] | (buf
[12] << 8) | (buf
[11] << 16) | (buf
[10] << 24);
878 lba
= (uint64_t) buf
[5] | ((uint64_t) buf
[4] << 8) |
879 ((uint64_t) buf
[3] << 16) | ((uint64_t) buf
[2] << 24);
880 len
= buf
[9] | (buf
[8] << 8) | (buf
[7] << 16) | (buf
[6] << 24);
884 BADF("Unsupported command length, command %x\n", command
);
890 for (i
= 1; i
< cmdlen
; i
++) {
891 printf(" 0x%02x", buf
[i
]);
897 if (scsi_req_parse(&r
->req
, buf
) != 0) {
898 BADF("Unsupported command length, command %x\n", command
);
901 assert(r
->req
.cmd
.len
== cmdlen
);
902 assert(r
->req
.cmd
.lba
== lba
);
904 if (lun
|| buf
[1] >> 5) {
905 /* Only LUN 0 supported. */
906 DPRINTF("Unimplemented LUN %d\n", lun
? lun
: buf
[1] >> 5);
907 if (command
!= REQUEST_SENSE
&& command
!= INQUIRY
)
911 case TEST_UNIT_READY
:
921 case ALLOW_MEDIUM_REMOVAL
:
923 case SYNCHRONIZE_CACHE
:
925 case GET_CONFIGURATION
:
926 case SERVICE_ACTION_IN
:
929 rc
= scsi_disk_emulate_command(&r
->req
, outbuf
);
933 scsi_req_complete(&r
->req
);
934 scsi_remove_request(r
);
942 DPRINTF("Read (sector %" PRId64
", count %d)\n", lba
, len
);
943 if (lba
> s
->max_lba
)
945 r
->sector
= lba
* s
->cluster_size
;
946 r
->sector_count
= len
* s
->cluster_size
;
952 DPRINTF("Write (sector %" PRId64
", count %d)\n", lba
, len
);
953 if (lba
> s
->max_lba
)
955 r
->sector
= lba
* s
->cluster_size
;
956 r
->sector_count
= len
* s
->cluster_size
;
960 DPRINTF("Unknown SCSI command (%2.2x)\n", buf
[0]);
962 scsi_command_complete(r
, CHECK_CONDITION
, ILLEGAL_REQUEST
);
965 scsi_command_complete(r
, CHECK_CONDITION
, HARDWARE_ERROR
);
968 if (r
->sector_count
== 0 && r
->iov
.iov_len
== 0) {
969 scsi_command_complete(r
, GOOD
, NO_SENSE
);
971 len
= r
->sector_count
* 512 + r
->iov
.iov_len
;
975 if (!r
->sector_count
)
976 r
->sector_count
= -1;
981 static void scsi_destroy(SCSIDevice
*dev
)
983 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, dev
);
986 while (!QTAILQ_EMPTY(&s
->qdev
.requests
)) {
987 r
= DO_UPCAST(SCSIDiskReq
, req
, QTAILQ_FIRST(&s
->qdev
.requests
));
988 scsi_remove_request(r
);
990 drive_uninit(s
->qdev
.dinfo
);
993 static int scsi_disk_initfn(SCSIDevice
*dev
)
995 SCSIDiskState
*s
= DO_UPCAST(SCSIDiskState
, qdev
, dev
);
998 if (!s
->qdev
.dinfo
|| !s
->qdev
.dinfo
->bdrv
) {
999 qemu_error("scsi-disk: drive property not set\n");
1003 if (bdrv_get_type_hint(s
->qdev
.dinfo
->bdrv
) == BDRV_TYPE_CDROM
) {
1004 s
->cluster_size
= 4;
1006 s
->cluster_size
= 1;
1008 s
->qdev
.blocksize
= 512 * s
->cluster_size
;
1009 s
->qdev
.type
= TYPE_DISK
;
1010 bdrv_get_geometry(s
->qdev
.dinfo
->bdrv
, &nb_sectors
);
1011 nb_sectors
/= s
->cluster_size
;
1014 s
->max_lba
= nb_sectors
;
1015 qemu_add_vm_change_state_handler(scsi_dma_restart_cb
, s
);
1019 static SCSIDeviceInfo scsi_disk_info
= {
1020 .qdev
.name
= "scsi-disk",
1021 .qdev
.desc
= "virtual scsi disk or cdrom",
1022 .qdev
.size
= sizeof(SCSIDiskState
),
1023 .init
= scsi_disk_initfn
,
1024 .destroy
= scsi_destroy
,
1025 .send_command
= scsi_send_command
,
1026 .read_data
= scsi_read_data
,
1027 .write_data
= scsi_write_data
,
1028 .cancel_io
= scsi_cancel_io
,
1029 .get_buf
= scsi_get_buf
,
1030 .qdev
.props
= (Property
[]) {
1031 DEFINE_PROP_DRIVE("drive", SCSIDiskState
, qdev
.dinfo
),
1032 DEFINE_PROP_END_OF_LIST(),
1036 static void scsi_disk_register_devices(void)
1038 scsi_qdev_register(&scsi_disk_info
);
1040 device_init(scsi_disk_register_devices
)