block: add topology qdev properties
[qemu/cris-port.git] / hw / scsi-disk.c
blobd510da4aad505647d27dc5f8be2fb143a9beb94f
1 /*
2 * SCSI Device emulation
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
7 * Written by Paul Brook
8 * Modifications:
9 * 2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
10 * when the allocation length of CDB is smaller
11 * than 36.
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>
23 #include <sysemu.h>
24 //#define DEBUG_SCSI
26 #ifdef DEBUG_SCSI
27 #define DPRINTF(fmt, ...) \
28 do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
29 #else
30 #define DPRINTF(fmt, ...) do {} while(0)
31 #endif
33 #define BADF(fmt, ...) \
34 do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
36 #include "qemu-common.h"
37 #include "block.h"
38 #include "scsi.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 {
49 SCSIRequest req;
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. */
53 uint64_t sector;
54 uint32_t sector_count;
55 struct iovec iov;
56 QEMUIOVector qiov;
57 uint32_t status;
58 } SCSIDiskReq;
60 struct SCSIDiskState
62 SCSIDevice qdev;
63 BlockDriverState *bs;
64 /* The qemu block layer uses a fixed 512 byte sector size.
65 This is the number of 512 byte blocks in a single scsi sector. */
66 int cluster_size;
67 uint64_t max_lba;
68 QEMUBH *bh;
69 char *version;
72 static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
74 SCSIRequest *req;
75 SCSIDiskReq *r;
77 req = scsi_req_alloc(sizeof(SCSIDiskReq), d, tag, lun);
78 r = DO_UPCAST(SCSIDiskReq, req, req);
79 r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
80 return r;
83 static void scsi_remove_request(SCSIDiskReq *r)
85 qemu_vfree(r->iov.iov_base);
86 scsi_req_free(&r->req);
89 static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
91 return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
94 static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
96 req->status = status;
97 scsi_dev_set_sense(req->dev, sense_code);
100 /* Helper function for command completion. */
101 static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
103 DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
104 r->req.tag, status, sense);
105 scsi_req_set_status(&r->req, status, sense);
106 scsi_req_complete(&r->req);
107 scsi_remove_request(r);
110 /* Cancel a pending data transfer. */
111 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
113 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
114 SCSIDiskReq *r;
115 DPRINTF("Cancel tag=0x%x\n", tag);
116 r = scsi_find_request(s, tag);
117 if (r) {
118 if (r->req.aiocb)
119 bdrv_aio_cancel(r->req.aiocb);
120 r->req.aiocb = NULL;
121 scsi_remove_request(r);
125 static void scsi_read_complete(void * opaque, int ret)
127 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
129 if (ret) {
130 DPRINTF("IO error\n");
131 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
132 scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
133 return;
135 DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->req.tag, r->iov.iov_len);
137 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
140 /* Read more data from scsi device into buffer. */
141 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
143 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
144 SCSIDiskReq *r;
145 uint32_t n;
147 r = scsi_find_request(s, tag);
148 if (!r) {
149 BADF("Bad read tag 0x%x\n", tag);
150 /* ??? This is the wrong error. */
151 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
152 return;
154 if (r->sector_count == (uint32_t)-1) {
155 DPRINTF("Read buf_len=%" PRId64 "\n", r->iov.iov_len);
156 r->sector_count = 0;
157 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
158 return;
160 DPRINTF("Read sector_count=%d\n", r->sector_count);
161 if (r->sector_count == 0) {
162 scsi_command_complete(r, GOOD, NO_SENSE);
163 return;
166 n = r->sector_count;
167 if (n > SCSI_DMA_BUF_SIZE / 512)
168 n = SCSI_DMA_BUF_SIZE / 512;
170 r->iov.iov_len = n * 512;
171 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
172 r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
173 scsi_read_complete, r);
174 if (r->req.aiocb == NULL)
175 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
176 r->sector += n;
177 r->sector_count -= n;
180 static int scsi_handle_write_error(SCSIDiskReq *r, int error)
182 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
183 BlockInterfaceErrorAction action = drive_get_on_error(s->bs, 0);
185 if (action == BLOCK_ERR_IGNORE) {
186 bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0);
187 return 0;
190 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
191 || action == BLOCK_ERR_STOP_ANY) {
192 r->status |= SCSI_REQ_STATUS_RETRY;
193 vm_stop(0);
194 bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0);
195 } else {
196 scsi_command_complete(r, CHECK_CONDITION,
197 HARDWARE_ERROR);
198 bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0);
201 return 1;
204 static void scsi_write_complete(void * opaque, int ret)
206 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
207 uint32_t len;
208 uint32_t n;
210 r->req.aiocb = NULL;
212 if (ret) {
213 if (scsi_handle_write_error(r, -ret))
214 return;
217 n = r->iov.iov_len / 512;
218 r->sector += n;
219 r->sector_count -= n;
220 if (r->sector_count == 0) {
221 scsi_command_complete(r, GOOD, NO_SENSE);
222 } else {
223 len = r->sector_count * 512;
224 if (len > SCSI_DMA_BUF_SIZE) {
225 len = SCSI_DMA_BUF_SIZE;
227 r->iov.iov_len = len;
228 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
229 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
233 static void scsi_write_request(SCSIDiskReq *r)
235 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
236 uint32_t n;
238 n = r->iov.iov_len / 512;
239 if (n) {
240 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
241 r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
242 scsi_write_complete, r);
243 if (r->req.aiocb == NULL)
244 scsi_command_complete(r, CHECK_CONDITION,
245 HARDWARE_ERROR);
246 } else {
247 /* Invoke completion routine to fetch data from host. */
248 scsi_write_complete(r, 0);
252 /* Write data to a scsi device. Returns nonzero on failure.
253 The transfer may complete asynchronously. */
254 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
256 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
257 SCSIDiskReq *r;
259 DPRINTF("Write data tag=0x%x\n", tag);
260 r = scsi_find_request(s, tag);
261 if (!r) {
262 BADF("Bad write tag 0x%x\n", tag);
263 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
264 return 1;
267 if (r->req.aiocb)
268 BADF("Data transfer already in progress\n");
270 scsi_write_request(r);
272 return 0;
275 static void scsi_dma_restart_bh(void *opaque)
277 SCSIDiskState *s = opaque;
278 SCSIRequest *req;
279 SCSIDiskReq *r;
281 qemu_bh_delete(s->bh);
282 s->bh = NULL;
284 QTAILQ_FOREACH(req, &s->qdev.requests, next) {
285 r = DO_UPCAST(SCSIDiskReq, req, req);
286 if (r->status & SCSI_REQ_STATUS_RETRY) {
287 r->status &= ~SCSI_REQ_STATUS_RETRY;
288 scsi_write_request(r);
293 static void scsi_dma_restart_cb(void *opaque, int running, int reason)
295 SCSIDiskState *s = opaque;
297 if (!running)
298 return;
300 if (!s->bh) {
301 s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
302 qemu_bh_schedule(s->bh);
306 /* Return a pointer to the data buffer. */
307 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
309 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
310 SCSIDiskReq *r;
312 r = scsi_find_request(s, tag);
313 if (!r) {
314 BADF("Bad buffer tag 0x%x\n", tag);
315 return NULL;
317 return (uint8_t *)r->iov.iov_base;
320 static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
322 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
323 int buflen = 0;
325 if (req->cmd.buf[1] & 0x2) {
326 /* Command support data - optional, not implemented */
327 BADF("optional INQUIRY command support request not implemented\n");
328 return -1;
331 if (req->cmd.buf[1] & 0x1) {
332 /* Vital product data */
333 uint8_t page_code = req->cmd.buf[2];
334 if (req->cmd.xfer < 4) {
335 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
336 "less than 4\n", page_code, req->cmd.xfer);
337 return -1;
340 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
341 outbuf[buflen++] = 5;
342 } else {
343 outbuf[buflen++] = 0;
345 outbuf[buflen++] = page_code ; // this page
346 outbuf[buflen++] = 0x00;
348 switch (page_code) {
349 case 0x00: /* Supported page codes, mandatory */
350 DPRINTF("Inquiry EVPD[Supported pages] "
351 "buffer size %zd\n", req->cmd.xfer);
352 outbuf[buflen++] = 3; // number of pages
353 outbuf[buflen++] = 0x00; // list of supported pages (this page)
354 outbuf[buflen++] = 0x80; // unit serial number
355 outbuf[buflen++] = 0x83; // device identification
356 break;
358 case 0x80: /* Device serial number, optional */
360 const char *serial = req->dev->conf.dinfo->serial ?
361 req->dev->conf.dinfo->serial : "0";
362 int l = strlen(serial);
364 if (l > req->cmd.xfer)
365 l = req->cmd.xfer;
366 if (l > 20)
367 l = 20;
369 DPRINTF("Inquiry EVPD[Serial number] "
370 "buffer size %zd\n", req->cmd.xfer);
371 outbuf[buflen++] = l;
372 memcpy(outbuf+buflen, serial, l);
373 buflen += l;
374 break;
377 case 0x83: /* Device identification page, mandatory */
379 int max_len = 255 - 8;
380 int id_len = strlen(bdrv_get_device_name(s->bs));
382 if (id_len > max_len)
383 id_len = max_len;
384 DPRINTF("Inquiry EVPD[Device identification] "
385 "buffer size %zd\n", req->cmd.xfer);
387 outbuf[buflen++] = 3 + id_len;
388 outbuf[buflen++] = 0x2; // ASCII
389 outbuf[buflen++] = 0; // not officially assigned
390 outbuf[buflen++] = 0; // reserved
391 outbuf[buflen++] = id_len; // length of data following
393 memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
394 buflen += id_len;
395 break;
397 default:
398 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
399 "buffer size %zd\n", page_code, req->cmd.xfer);
400 return -1;
402 /* done with EVPD */
403 return buflen;
406 /* Standard INQUIRY data */
407 if (req->cmd.buf[2] != 0) {
408 BADF("Error: Inquiry (STANDARD) page or code "
409 "is non-zero [%02X]\n", req->cmd.buf[2]);
410 return -1;
413 /* PAGE CODE == 0 */
414 if (req->cmd.xfer < 5) {
415 BADF("Error: Inquiry (STANDARD) buffer size %zd "
416 "is less than 5\n", req->cmd.xfer);
417 return -1;
420 buflen = req->cmd.xfer;
421 if (buflen > SCSI_MAX_INQUIRY_LEN)
422 buflen = SCSI_MAX_INQUIRY_LEN;
424 memset(outbuf, 0, buflen);
426 if (req->lun || req->cmd.buf[1] >> 5) {
427 outbuf[0] = 0x7f; /* LUN not supported */
428 return buflen;
431 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
432 outbuf[0] = 5;
433 outbuf[1] = 0x80;
434 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
435 } else {
436 outbuf[0] = 0;
437 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
439 memcpy(&outbuf[8], "QEMU ", 8);
440 memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION, 4);
441 /* Identify device as SCSI-3 rev 1.
442 Some later commands are also implemented. */
443 outbuf[2] = 3;
444 outbuf[3] = 2; /* Format 2 */
446 if (buflen > 36) {
447 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
448 } else {
449 /* If the allocation length of CDB is too small,
450 the additional length is not adjusted */
451 outbuf[4] = 36 - 5;
454 /* Sync data transfer and TCQ. */
455 outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
456 return buflen;
459 static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
461 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
462 BlockDriverState *bdrv = s->bs;
463 int cylinders, heads, secs;
465 switch (page) {
466 case 4: /* Rigid disk device geometry page. */
467 p[0] = 4;
468 p[1] = 0x16;
469 /* if a geometry hint is available, use it */
470 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
471 p[2] = (cylinders >> 16) & 0xff;
472 p[3] = (cylinders >> 8) & 0xff;
473 p[4] = cylinders & 0xff;
474 p[5] = heads & 0xff;
475 /* Write precomp start cylinder, disabled */
476 p[6] = (cylinders >> 16) & 0xff;
477 p[7] = (cylinders >> 8) & 0xff;
478 p[8] = cylinders & 0xff;
479 /* Reduced current start cylinder, disabled */
480 p[9] = (cylinders >> 16) & 0xff;
481 p[10] = (cylinders >> 8) & 0xff;
482 p[11] = cylinders & 0xff;
483 /* Device step rate [ns], 200ns */
484 p[12] = 0;
485 p[13] = 200;
486 /* Landing zone cylinder */
487 p[14] = 0xff;
488 p[15] = 0xff;
489 p[16] = 0xff;
490 /* Medium rotation rate [rpm], 5400 rpm */
491 p[20] = (5400 >> 8) & 0xff;
492 p[21] = 5400 & 0xff;
493 return 0x16;
495 case 5: /* Flexible disk device geometry page. */
496 p[0] = 5;
497 p[1] = 0x1e;
498 /* Transfer rate [kbit/s], 5Mbit/s */
499 p[2] = 5000 >> 8;
500 p[3] = 5000 & 0xff;
501 /* if a geometry hint is available, use it */
502 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
503 p[4] = heads & 0xff;
504 p[5] = secs & 0xff;
505 p[6] = s->cluster_size * 2;
506 p[8] = (cylinders >> 8) & 0xff;
507 p[9] = cylinders & 0xff;
508 /* Write precomp start cylinder, disabled */
509 p[10] = (cylinders >> 8) & 0xff;
510 p[11] = cylinders & 0xff;
511 /* Reduced current start cylinder, disabled */
512 p[12] = (cylinders >> 8) & 0xff;
513 p[13] = cylinders & 0xff;
514 /* Device step rate [100us], 100us */
515 p[14] = 0;
516 p[15] = 1;
517 /* Device step pulse width [us], 1us */
518 p[16] = 1;
519 /* Device head settle delay [100us], 100us */
520 p[17] = 0;
521 p[18] = 1;
522 /* Motor on delay [0.1s], 0.1s */
523 p[19] = 1;
524 /* Motor off delay [0.1s], 0.1s */
525 p[20] = 1;
526 /* Medium rotation rate [rpm], 5400 rpm */
527 p[28] = (5400 >> 8) & 0xff;
528 p[29] = 5400 & 0xff;
529 return 0x1e;
531 case 8: /* Caching page. */
532 p[0] = 8;
533 p[1] = 0x12;
534 if (bdrv_enable_write_cache(s->bs)) {
535 p[2] = 4; /* WCE */
537 return 20;
539 case 0x2a: /* CD Capabilities and Mechanical Status page. */
540 if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
541 return 0;
542 p[0] = 0x2a;
543 p[1] = 0x14;
544 p[2] = 3; // CD-R & CD-RW read
545 p[3] = 0; // Writing not supported
546 p[4] = 0x7f; /* Audio, composite, digital out,
547 mode 2 form 1&2, multi session */
548 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
549 RW corrected, C2 errors, ISRC,
550 UPC, Bar code */
551 p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
552 /* Locking supported, jumper present, eject, tray */
553 p[7] = 0; /* no volume & mute control, no
554 changer */
555 p[8] = (50 * 176) >> 8; // 50x read speed
556 p[9] = (50 * 176) & 0xff;
557 p[10] = 0 >> 8; // No volume
558 p[11] = 0 & 0xff;
559 p[12] = 2048 >> 8; // 2M buffer
560 p[13] = 2048 & 0xff;
561 p[14] = (16 * 176) >> 8; // 16x read speed current
562 p[15] = (16 * 176) & 0xff;
563 p[18] = (16 * 176) >> 8; // 16x write speed
564 p[19] = (16 * 176) & 0xff;
565 p[20] = (16 * 176) >> 8; // 16x write speed current
566 p[21] = (16 * 176) & 0xff;
567 return 22;
569 default:
570 return 0;
574 static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
576 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
577 uint64_t nb_sectors;
578 int page, dbd, buflen;
579 uint8_t *p;
581 dbd = req->cmd.buf[1] & 0x8;
582 page = req->cmd.buf[2] & 0x3f;
583 DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer);
584 memset(outbuf, 0, req->cmd.xfer);
585 p = outbuf;
587 p[1] = 0; /* Default media type. */
588 p[3] = 0; /* Block descriptor length. */
589 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM ||
590 bdrv_is_read_only(s->bs)) {
591 p[2] = 0x80; /* Readonly. */
593 p += 4;
595 bdrv_get_geometry(s->bs, &nb_sectors);
596 if ((~dbd) & nb_sectors) {
597 outbuf[3] = 8; /* Block descriptor length */
598 nb_sectors /= s->cluster_size;
599 nb_sectors--;
600 if (nb_sectors > 0xffffff)
601 nb_sectors = 0xffffff;
602 p[0] = 0; /* media density code */
603 p[1] = (nb_sectors >> 16) & 0xff;
604 p[2] = (nb_sectors >> 8) & 0xff;
605 p[3] = nb_sectors & 0xff;
606 p[4] = 0; /* reserved */
607 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
608 p[6] = s->cluster_size * 2;
609 p[7] = 0;
610 p += 8;
613 switch (page) {
614 case 0x04:
615 case 0x05:
616 case 0x08:
617 case 0x2a:
618 p += mode_sense_page(req, page, p);
619 break;
620 case 0x3f:
621 p += mode_sense_page(req, 0x08, p);
622 p += mode_sense_page(req, 0x2a, p);
623 break;
626 buflen = p - outbuf;
627 outbuf[0] = buflen - 4;
628 if (buflen > req->cmd.xfer)
629 buflen = req->cmd.xfer;
630 return buflen;
633 static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
635 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
636 int start_track, format, msf, toclen;
637 uint64_t nb_sectors;
639 msf = req->cmd.buf[1] & 2;
640 format = req->cmd.buf[2] & 0xf;
641 start_track = req->cmd.buf[6];
642 bdrv_get_geometry(s->bs, &nb_sectors);
643 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
644 nb_sectors /= s->cluster_size;
645 switch (format) {
646 case 0:
647 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
648 break;
649 case 1:
650 /* multi session : only a single session defined */
651 toclen = 12;
652 memset(outbuf, 0, 12);
653 outbuf[1] = 0x0a;
654 outbuf[2] = 0x01;
655 outbuf[3] = 0x01;
656 break;
657 case 2:
658 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
659 break;
660 default:
661 return -1;
663 if (toclen > req->cmd.xfer)
664 toclen = req->cmd.xfer;
665 return toclen;
668 static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
670 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
671 uint64_t nb_sectors;
672 int buflen = 0;
674 switch (req->cmd.buf[0]) {
675 case TEST_UNIT_READY:
676 if (!bdrv_is_inserted(s->bs))
677 goto not_ready;
678 break;
679 case REQUEST_SENSE:
680 if (req->cmd.xfer < 4)
681 goto illegal_request;
682 memset(outbuf, 0, 4);
683 buflen = 4;
684 if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
685 memset(outbuf, 0, 18);
686 buflen = 18;
687 outbuf[7] = 10;
688 /* asc 0x3a, ascq 0: Medium not present */
689 outbuf[12] = 0x3a;
690 outbuf[13] = 0;
692 outbuf[0] = 0xf0;
693 outbuf[1] = 0;
694 outbuf[2] = req->dev->sense.key;
695 scsi_dev_clear_sense(req->dev);
696 break;
697 case INQUIRY:
698 buflen = scsi_disk_emulate_inquiry(req, outbuf);
699 if (buflen < 0)
700 goto illegal_request;
701 break;
702 case MODE_SENSE:
703 case MODE_SENSE_10:
704 buflen = scsi_disk_emulate_mode_sense(req, outbuf);
705 if (buflen < 0)
706 goto illegal_request;
707 break;
708 case READ_TOC:
709 buflen = scsi_disk_emulate_read_toc(req, outbuf);
710 if (buflen < 0)
711 goto illegal_request;
712 break;
713 case RESERVE:
714 if (req->cmd.buf[1] & 1)
715 goto illegal_request;
716 break;
717 case RESERVE_10:
718 if (req->cmd.buf[1] & 3)
719 goto illegal_request;
720 break;
721 case RELEASE:
722 if (req->cmd.buf[1] & 1)
723 goto illegal_request;
724 break;
725 case RELEASE_10:
726 if (req->cmd.buf[1] & 3)
727 goto illegal_request;
728 break;
729 case START_STOP:
730 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
731 /* load/eject medium */
732 bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
734 break;
735 case ALLOW_MEDIUM_REMOVAL:
736 bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
737 break;
738 case READ_CAPACITY:
739 /* The normal LEN field for this command is zero. */
740 memset(outbuf, 0, 8);
741 bdrv_get_geometry(s->bs, &nb_sectors);
742 if (!nb_sectors)
743 goto not_ready;
744 nb_sectors /= s->cluster_size;
745 /* Returned value is the address of the last sector. */
746 nb_sectors--;
747 /* Remember the new size for read/write sanity checking. */
748 s->max_lba = nb_sectors;
749 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
750 if (nb_sectors > UINT32_MAX)
751 nb_sectors = UINT32_MAX;
752 outbuf[0] = (nb_sectors >> 24) & 0xff;
753 outbuf[1] = (nb_sectors >> 16) & 0xff;
754 outbuf[2] = (nb_sectors >> 8) & 0xff;
755 outbuf[3] = nb_sectors & 0xff;
756 outbuf[4] = 0;
757 outbuf[5] = 0;
758 outbuf[6] = s->cluster_size * 2;
759 outbuf[7] = 0;
760 buflen = 8;
761 break;
762 case SYNCHRONIZE_CACHE:
763 bdrv_flush(s->bs);
764 break;
765 case GET_CONFIGURATION:
766 memset(outbuf, 0, 8);
767 /* ??? This should probably return much more information. For now
768 just return the basic header indicating the CD-ROM profile. */
769 outbuf[7] = 8; // CD-ROM
770 buflen = 8;
771 break;
772 case SERVICE_ACTION_IN:
773 /* Service Action In subcommands. */
774 if ((req->cmd.buf[1] & 31) == 0x10) {
775 DPRINTF("SAI READ CAPACITY(16)\n");
776 memset(outbuf, 0, req->cmd.xfer);
777 bdrv_get_geometry(s->bs, &nb_sectors);
778 if (!nb_sectors)
779 goto not_ready;
780 nb_sectors /= s->cluster_size;
781 /* Returned value is the address of the last sector. */
782 nb_sectors--;
783 /* Remember the new size for read/write sanity checking. */
784 s->max_lba = nb_sectors;
785 outbuf[0] = (nb_sectors >> 56) & 0xff;
786 outbuf[1] = (nb_sectors >> 48) & 0xff;
787 outbuf[2] = (nb_sectors >> 40) & 0xff;
788 outbuf[3] = (nb_sectors >> 32) & 0xff;
789 outbuf[4] = (nb_sectors >> 24) & 0xff;
790 outbuf[5] = (nb_sectors >> 16) & 0xff;
791 outbuf[6] = (nb_sectors >> 8) & 0xff;
792 outbuf[7] = nb_sectors & 0xff;
793 outbuf[8] = 0;
794 outbuf[9] = 0;
795 outbuf[10] = s->cluster_size * 2;
796 outbuf[11] = 0;
797 /* Protection, exponent and lowest lba field left blank. */
798 buflen = req->cmd.xfer;
799 break;
801 DPRINTF("Unsupported Service Action In\n");
802 goto illegal_request;
803 case REPORT_LUNS:
804 if (req->cmd.xfer < 16)
805 goto illegal_request;
806 memset(outbuf, 0, 16);
807 outbuf[3] = 8;
808 buflen = 16;
809 break;
810 case VERIFY:
811 break;
812 default:
813 goto illegal_request;
815 scsi_req_set_status(req, GOOD, NO_SENSE);
816 return buflen;
818 not_ready:
819 scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
820 return 0;
822 illegal_request:
823 scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
824 return 0;
827 /* Execute a scsi command. Returns the length of the data expected by the
828 command. This will be Positive for data transfers from the device
829 (eg. disk reads), negative for transfers to the device (eg. disk writes),
830 and zero if the command does not transfer any data. */
832 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
833 uint8_t *buf, int lun)
835 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
836 uint64_t lba;
837 uint32_t len;
838 int cmdlen;
839 int is_write;
840 uint8_t command;
841 uint8_t *outbuf;
842 SCSIDiskReq *r;
843 int rc;
845 command = buf[0];
846 r = scsi_find_request(s, tag);
847 if (r) {
848 BADF("Tag 0x%x already in use\n", tag);
849 scsi_cancel_io(d, tag);
851 /* ??? Tags are not unique for different luns. We only implement a
852 single lun, so this should not matter. */
853 r = scsi_new_request(d, tag, lun);
854 outbuf = (uint8_t *)r->iov.iov_base;
855 is_write = 0;
856 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
857 switch (command >> 5) {
858 case 0:
859 lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
860 (((uint64_t) buf[1] & 0x1f) << 16);
861 len = buf[4];
862 cmdlen = 6;
863 break;
864 case 1:
865 case 2:
866 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
867 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
868 len = buf[8] | (buf[7] << 8);
869 cmdlen = 10;
870 break;
871 case 4:
872 lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
873 ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
874 ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
875 ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
876 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
877 cmdlen = 16;
878 break;
879 case 5:
880 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
881 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
882 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
883 cmdlen = 12;
884 break;
885 default:
886 BADF("Unsupported command length, command %x\n", command);
887 goto fail;
889 #ifdef DEBUG_SCSI
891 int i;
892 for (i = 1; i < cmdlen; i++) {
893 printf(" 0x%02x", buf[i]);
895 printf("\n");
897 #endif
899 if (scsi_req_parse(&r->req, buf) != 0) {
900 BADF("Unsupported command length, command %x\n", command);
901 goto fail;
903 assert(r->req.cmd.len == cmdlen);
904 assert(r->req.cmd.lba == lba);
906 if (lun || buf[1] >> 5) {
907 /* Only LUN 0 supported. */
908 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
909 if (command != REQUEST_SENSE && command != INQUIRY)
910 goto fail;
912 switch (command) {
913 case TEST_UNIT_READY:
914 case REQUEST_SENSE:
915 case INQUIRY:
916 case MODE_SENSE:
917 case MODE_SENSE_10:
918 case RESERVE:
919 case RESERVE_10:
920 case RELEASE:
921 case RELEASE_10:
922 case START_STOP:
923 case ALLOW_MEDIUM_REMOVAL:
924 case READ_CAPACITY:
925 case SYNCHRONIZE_CACHE:
926 case READ_TOC:
927 case GET_CONFIGURATION:
928 case SERVICE_ACTION_IN:
929 case REPORT_LUNS:
930 case VERIFY:
931 rc = scsi_disk_emulate_command(&r->req, outbuf);
932 if (rc > 0) {
933 r->iov.iov_len = rc;
934 } else {
935 scsi_req_complete(&r->req);
936 scsi_remove_request(r);
937 return 0;
939 break;
940 case READ_6:
941 case READ_10:
942 case READ_12:
943 case READ_16:
944 DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
945 if (lba > s->max_lba)
946 goto illegal_lba;
947 r->sector = lba * s->cluster_size;
948 r->sector_count = len * s->cluster_size;
949 break;
950 case WRITE_6:
951 case WRITE_10:
952 case WRITE_12:
953 case WRITE_16:
954 DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
955 if (lba > s->max_lba)
956 goto illegal_lba;
957 r->sector = lba * s->cluster_size;
958 r->sector_count = len * s->cluster_size;
959 is_write = 1;
960 break;
961 default:
962 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
963 fail:
964 scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
965 return 0;
966 illegal_lba:
967 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
968 return 0;
970 if (r->sector_count == 0 && r->iov.iov_len == 0) {
971 scsi_command_complete(r, GOOD, NO_SENSE);
973 len = r->sector_count * 512 + r->iov.iov_len;
974 if (is_write) {
975 return -len;
976 } else {
977 if (!r->sector_count)
978 r->sector_count = -1;
979 return len;
983 static void scsi_destroy(SCSIDevice *dev)
985 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
986 SCSIDiskReq *r;
988 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
989 r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
990 scsi_remove_request(r);
992 drive_uninit(s->qdev.conf.dinfo);
995 static int scsi_disk_initfn(SCSIDevice *dev)
997 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
998 uint64_t nb_sectors;
1000 if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
1001 qemu_error("scsi-disk: drive property not set\n");
1002 return -1;
1004 s->bs = s->qdev.conf.dinfo->bdrv;
1006 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
1007 s->cluster_size = 4;
1008 } else {
1009 s->cluster_size = 1;
1011 s->qdev.blocksize = 512 * s->cluster_size;
1012 s->qdev.type = TYPE_DISK;
1013 bdrv_get_geometry(s->bs, &nb_sectors);
1014 nb_sectors /= s->cluster_size;
1015 if (nb_sectors)
1016 nb_sectors--;
1017 s->max_lba = nb_sectors;
1018 qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
1019 return 0;
1022 static SCSIDeviceInfo scsi_disk_info = {
1023 .qdev.name = "scsi-disk",
1024 .qdev.desc = "virtual scsi disk or cdrom",
1025 .qdev.size = sizeof(SCSIDiskState),
1026 .init = scsi_disk_initfn,
1027 .destroy = scsi_destroy,
1028 .send_command = scsi_send_command,
1029 .read_data = scsi_read_data,
1030 .write_data = scsi_write_data,
1031 .cancel_io = scsi_cancel_io,
1032 .get_buf = scsi_get_buf,
1033 .qdev.props = (Property[]) {
1034 DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
1035 DEFINE_PROP_STRING("ver", SCSIDiskState, version),
1036 DEFINE_PROP_END_OF_LIST(),
1040 static void scsi_disk_register_devices(void)
1042 scsi_qdev_register(&scsi_disk_info);
1044 device_init(scsi_disk_register_devices)