]> git.proxmox.com Git - qemu.git/blame - hw/scsi-disk.c
Update for 0.12.4 release
[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
b60c2c74
AT
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.
2e5d83bb
PB
14 *
15 * This code is licenced under the LGPL.
a917d384
PB
16 *
17 * Note that this file only handles the SCSI architecture model and device
1d4db89c
AZ
18 * commands. Emulation of interface/link layer protocols is handled by
19 * the host adapter emulator.
2e5d83bb
PB
20 */
21
fa879c64
AL
22#include <qemu-common.h>
23#include <sysemu.h>
2e5d83bb
PB
24//#define DEBUG_SCSI
25
26#ifdef DEBUG_SCSI
001faf32
BS
27#define DPRINTF(fmt, ...) \
28do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 29#else
001faf32 30#define DPRINTF(fmt, ...) do {} while(0)
2e5d83bb
PB
31#endif
32
001faf32
BS
33#define BADF(fmt, ...) \
34do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 35
87ecb68b
PB
36#include "qemu-common.h"
37#include "block.h"
43b443b6 38#include "scsi.h"
0d65e1f8 39#include "scsi-defs.h"
22864256 40
f0f72ffe 41#define SCSI_DMA_BUF_SIZE 131072
57575058 42#define SCSI_MAX_INQUIRY_LEN 256
a917d384 43
ea8a5d7f
AL
44#define SCSI_REQ_STATUS_RETRY 0x01
45
d52affa7
GH
46typedef struct SCSIDiskState SCSIDiskState;
47
4c41d2ef
GH
48typedef struct SCSIDiskReq {
49 SCSIRequest req;
e035b43d 50 /* ??? We should probably keep track of whether the data transfer is
2e5d83bb 51 a read or a write. Currently we rely on the host getting it right. */
a917d384 52 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
e035b43d
AL
53 uint64_t sector;
54 uint32_t sector_count;
c87c0672
AL
55 struct iovec iov;
56 QEMUIOVector qiov;
ea8a5d7f 57 uint32_t status;
4c41d2ef 58} SCSIDiskReq;
a917d384 59
d52affa7 60struct SCSIDiskState
a917d384 61{
d52affa7 62 SCSIDevice qdev;
a917d384
PB
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. */
65 int cluster_size;
274fb0e1 66 uint64_t max_lba;
213189ab 67 QEMUBH *bh;
9525204c 68 char *version;
2e5d83bb
PB
69};
70
89b08ae1 71static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
2e5d83bb 72{
89b08ae1 73 SCSIRequest *req;
4c41d2ef 74 SCSIDiskReq *r;
a917d384 75
89b08ae1
GH
76 req = scsi_req_alloc(sizeof(SCSIDiskReq), d, tag, lun);
77 r = DO_UPCAST(SCSIDiskReq, req, req);
9af99d98 78 r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
a917d384 79 return r;
2e5d83bb
PB
80}
81
4c41d2ef 82static void scsi_remove_request(SCSIDiskReq *r)
4d611c9a 83{
a1a86bf9 84 qemu_vfree(r->iov.iov_base);
89b08ae1 85 scsi_req_free(&r->req);
4d611c9a
PB
86}
87
4c41d2ef 88static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
4d611c9a 89{
89b08ae1 90 return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
a917d384
PB
91}
92
ed3a34a3
GH
93static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
94{
95 req->status = status;
96 scsi_dev_set_sense(req->dev, sense_code);
97}
98
a917d384 99/* Helper function for command completion. */
4c41d2ef 100static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
a917d384 101{
4c41d2ef
GH
102 DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
103 r->req.tag, status, sense);
ed3a34a3
GH
104 scsi_req_set_status(&r->req, status, sense);
105 scsi_req_complete(&r->req);
89b08ae1 106 scsi_remove_request(r);
4d611c9a
PB
107}
108
109/* Cancel a pending data transfer. */
8ccc2ace 110static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
4d611c9a 111{
d52affa7 112 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 113 SCSIDiskReq *r;
a917d384
PB
114 DPRINTF("Cancel tag=0x%x\n", tag);
115 r = scsi_find_request(s, tag);
116 if (r) {
4c41d2ef
GH
117 if (r->req.aiocb)
118 bdrv_aio_cancel(r->req.aiocb);
119 r->req.aiocb = NULL;
a917d384
PB
120 scsi_remove_request(r);
121 }
122}
123
124static void scsi_read_complete(void * opaque, int ret)
125{
4c41d2ef 126 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
a917d384
PB
127
128 if (ret) {
129 DPRINTF("IO error\n");
4c41d2ef 130 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
0d65e1f8 131 scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
4d611c9a
PB
132 return;
133 }
4c41d2ef 134 DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->req.tag, r->iov.iov_len);
a917d384 135
4c41d2ef 136 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
4d611c9a
PB
137}
138
a917d384 139/* Read more data from scsi device into buffer. */
8ccc2ace 140static void scsi_read_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 141{
d52affa7 142 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 143 SCSIDiskReq *r;
2e5d83bb
PB
144 uint32_t n;
145
a917d384
PB
146 r = scsi_find_request(s, tag);
147 if (!r) {
148 BADF("Bad read tag 0x%x\n", tag);
b1fa7164 149 /* ??? This is the wrong error. */
0d65e1f8 150 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
a917d384 151 return;
2e5d83bb 152 }
a917d384 153 if (r->sector_count == (uint32_t)-1) {
0bf9e31a 154 DPRINTF("Read buf_len=%" PRId64 "\n", r->iov.iov_len);
a917d384 155 r->sector_count = 0;
4c41d2ef 156 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
a917d384 157 return;
2e5d83bb 158 }
a917d384
PB
159 DPRINTF("Read sector_count=%d\n", r->sector_count);
160 if (r->sector_count == 0) {
0d65e1f8 161 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 162 return;
2e5d83bb
PB
163 }
164
a917d384
PB
165 n = r->sector_count;
166 if (n > SCSI_DMA_BUF_SIZE / 512)
167 n = SCSI_DMA_BUF_SIZE / 512;
168
c87c0672
AL
169 r->iov.iov_len = n * 512;
170 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
251882b7 171 r->req.aiocb = bdrv_aio_readv(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
c87c0672 172 scsi_read_complete, r);
4c41d2ef 173 if (r->req.aiocb == NULL)
0d65e1f8 174 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
a917d384
PB
175 r->sector += n;
176 r->sector_count -= n;
2e5d83bb
PB
177}
178
4c41d2ef 179static int scsi_handle_write_error(SCSIDiskReq *r, int error)
ea8a5d7f 180{
4c41d2ef 181 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
f7850099
KW
182 BlockInterfaceErrorAction action =
183 drive_get_on_error(s->qdev.dinfo->bdrv, 0);
ea8a5d7f
AL
184
185 if (action == BLOCK_ERR_IGNORE)
186 return 0;
187
188 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
189 || action == BLOCK_ERR_STOP_ANY) {
190 r->status |= SCSI_REQ_STATUS_RETRY;
191 vm_stop(0);
192 } else {
0d65e1f8
GH
193 scsi_command_complete(r, CHECK_CONDITION,
194 HARDWARE_ERROR);
ea8a5d7f
AL
195 }
196
197 return 1;
198}
199
4d611c9a
PB
200static void scsi_write_complete(void * opaque, int ret)
201{
4c41d2ef 202 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
a917d384 203 uint32_t len;
ea8a5d7f
AL
204 uint32_t n;
205
4c41d2ef 206 r->req.aiocb = NULL;
4d611c9a
PB
207
208 if (ret) {
ea8a5d7f
AL
209 if (scsi_handle_write_error(r, -ret))
210 return;
4d611c9a
PB
211 }
212
c87c0672 213 n = r->iov.iov_len / 512;
ea8a5d7f
AL
214 r->sector += n;
215 r->sector_count -= n;
a917d384 216 if (r->sector_count == 0) {
0d65e1f8 217 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384
PB
218 } else {
219 len = r->sector_count * 512;
220 if (len > SCSI_DMA_BUF_SIZE) {
221 len = SCSI_DMA_BUF_SIZE;
222 }
c87c0672 223 r->iov.iov_len = len;
4c41d2ef
GH
224 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
225 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
4d611c9a 226 }
4d611c9a
PB
227}
228
4c41d2ef 229static void scsi_write_request(SCSIDiskReq *r)
ea8a5d7f 230{
4c41d2ef 231 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
ea8a5d7f
AL
232 uint32_t n;
233
c87c0672 234 n = r->iov.iov_len / 512;
ea8a5d7f 235 if (n) {
c87c0672 236 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
251882b7 237 r->req.aiocb = bdrv_aio_writev(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
c87c0672 238 scsi_write_complete, r);
4c41d2ef 239 if (r->req.aiocb == NULL)
0d65e1f8
GH
240 scsi_command_complete(r, CHECK_CONDITION,
241 HARDWARE_ERROR);
ea8a5d7f
AL
242 } else {
243 /* Invoke completion routine to fetch data from host. */
244 scsi_write_complete(r, 0);
245 }
246}
247
4d611c9a
PB
248/* Write data to a scsi device. Returns nonzero on failure.
249 The transfer may complete asynchronously. */
8ccc2ace 250static int scsi_write_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 251{
d52affa7 252 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 253 SCSIDiskReq *r;
2e5d83bb 254
a917d384
PB
255 DPRINTF("Write data tag=0x%x\n", tag);
256 r = scsi_find_request(s, tag);
257 if (!r) {
258 BADF("Bad write tag 0x%x\n", tag);
0d65e1f8 259 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
2e5d83bb
PB
260 return 1;
261 }
ea8a5d7f 262
4c41d2ef 263 if (r->req.aiocb)
a917d384 264 BADF("Data transfer already in progress\n");
ea8a5d7f
AL
265
266 scsi_write_request(r);
2e5d83bb 267
a917d384
PB
268 return 0;
269}
2e5d83bb 270
213189ab 271static void scsi_dma_restart_bh(void *opaque)
ea8a5d7f 272{
d52affa7 273 SCSIDiskState *s = opaque;
9af99d98
GH
274 SCSIRequest *req;
275 SCSIDiskReq *r;
213189ab
MA
276
277 qemu_bh_delete(s->bh);
278 s->bh = NULL;
ea8a5d7f 279
9af99d98
GH
280 QTAILQ_FOREACH(req, &s->qdev.requests, next) {
281 r = DO_UPCAST(SCSIDiskReq, req, req);
ea8a5d7f
AL
282 if (r->status & SCSI_REQ_STATUS_RETRY) {
283 r->status &= ~SCSI_REQ_STATUS_RETRY;
284 scsi_write_request(r);
285 }
ea8a5d7f
AL
286 }
287}
288
213189ab
MA
289static void scsi_dma_restart_cb(void *opaque, int running, int reason)
290{
d52affa7 291 SCSIDiskState *s = opaque;
213189ab
MA
292
293 if (!running)
294 return;
295
296 if (!s->bh) {
297 s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
298 qemu_bh_schedule(s->bh);
299 }
300}
301
a917d384 302/* Return a pointer to the data buffer. */
8ccc2ace 303static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
a917d384 304{
d52affa7 305 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 306 SCSIDiskReq *r;
2e5d83bb 307
a917d384
PB
308 r = scsi_find_request(s, tag);
309 if (!r) {
310 BADF("Bad buffer tag 0x%x\n", tag);
311 return NULL;
4d611c9a 312 }
3f4cb3d3 313 return (uint8_t *)r->iov.iov_base;
2e5d83bb
PB
314}
315
0b06c059
GH
316static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
317{
318 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
9525204c 319 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
0b06c059
GH
320 int buflen = 0;
321
322 if (req->cmd.buf[1] & 0x2) {
323 /* Command support data - optional, not implemented */
324 BADF("optional INQUIRY command support request not implemented\n");
325 return -1;
326 }
327
328 if (req->cmd.buf[1] & 0x1) {
329 /* Vital product data */
330 uint8_t page_code = req->cmd.buf[2];
331 if (req->cmd.xfer < 4) {
332 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
333 "less than 4\n", page_code, req->cmd.xfer);
334 return -1;
335 }
336
337 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
338 outbuf[buflen++] = 5;
339 } else {
340 outbuf[buflen++] = 0;
341 }
342 outbuf[buflen++] = page_code ; // this page
343 outbuf[buflen++] = 0x00;
344
345 switch (page_code) {
346 case 0x00: /* Supported page codes, mandatory */
347 DPRINTF("Inquiry EVPD[Supported pages] "
348 "buffer size %zd\n", req->cmd.xfer);
349 outbuf[buflen++] = 3; // number of pages
350 outbuf[buflen++] = 0x00; // list of supported pages (this page)
351 outbuf[buflen++] = 0x80; // unit serial number
352 outbuf[buflen++] = 0x83; // device identification
353 break;
354
355 case 0x80: /* Device serial number, optional */
356 {
407f879a
BS
357 const char *serial = req->dev->dinfo->serial ?
358 req->dev->dinfo->serial : "0";
0b06c059
GH
359 int l = strlen(serial);
360
361 if (l > req->cmd.xfer)
362 l = req->cmd.xfer;
363 if (l > 20)
364 l = 20;
365
366 DPRINTF("Inquiry EVPD[Serial number] "
367 "buffer size %zd\n", req->cmd.xfer);
368 outbuf[buflen++] = l;
369 memcpy(outbuf+buflen, serial, l);
370 buflen += l;
371 break;
372 }
373
374 case 0x83: /* Device identification page, mandatory */
375 {
376 int max_len = 255 - 8;
377 int id_len = strlen(bdrv_get_device_name(bdrv));
378
379 if (id_len > max_len)
380 id_len = max_len;
381 DPRINTF("Inquiry EVPD[Device identification] "
382 "buffer size %zd\n", req->cmd.xfer);
383
384 outbuf[buflen++] = 3 + id_len;
385 outbuf[buflen++] = 0x2; // ASCII
386 outbuf[buflen++] = 0; // not officially assigned
387 outbuf[buflen++] = 0; // reserved
388 outbuf[buflen++] = id_len; // length of data following
389
390 memcpy(outbuf+buflen, bdrv_get_device_name(bdrv), id_len);
391 buflen += id_len;
392 break;
393 }
394 default:
395 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
396 "buffer size %zd\n", page_code, req->cmd.xfer);
397 return -1;
398 }
399 /* done with EVPD */
400 return buflen;
401 }
402
403 /* Standard INQUIRY data */
404 if (req->cmd.buf[2] != 0) {
405 BADF("Error: Inquiry (STANDARD) page or code "
406 "is non-zero [%02X]\n", req->cmd.buf[2]);
407 return -1;
408 }
409
410 /* PAGE CODE == 0 */
411 if (req->cmd.xfer < 5) {
412 BADF("Error: Inquiry (STANDARD) buffer size %zd "
413 "is less than 5\n", req->cmd.xfer);
414 return -1;
415 }
416
0b06c059
GH
417 buflen = req->cmd.xfer;
418 if (buflen > SCSI_MAX_INQUIRY_LEN)
419 buflen = SCSI_MAX_INQUIRY_LEN;
420
421 memset(outbuf, 0, buflen);
422
423 if (req->lun || req->cmd.buf[1] >> 5) {
424 outbuf[0] = 0x7f; /* LUN not supported */
425 return buflen;
426 }
427
428 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
429 outbuf[0] = 5;
430 outbuf[1] = 0x80;
550fe6c6 431 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
0b06c059
GH
432 } else {
433 outbuf[0] = 0;
550fe6c6 434 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
0b06c059 435 }
550fe6c6 436 memcpy(&outbuf[8], "QEMU ", 8);
4f7cb969
GH
437 memset(&outbuf[32], 0, 4);
438 memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
439 MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
0b06c059
GH
440 /* Identify device as SCSI-3 rev 1.
441 Some later commands are also implemented. */
442 outbuf[2] = 3;
443 outbuf[3] = 2; /* Format 2 */
b60c2c74
AT
444
445 if (buflen > 36) {
446 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
447 } else {
448 /* If the allocation length of CDB is too small,
449 the additional length is not adjusted */
450 outbuf[4] = 36 - 5;
451 }
452
0b06c059
GH
453 /* Sync data transfer and TCQ. */
454 outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
455 return buflen;
456}
457
ebddfcbe
GH
458static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
459{
460 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
461 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
462 int cylinders, heads, secs;
463
464 switch (page) {
465 case 4: /* Rigid disk device geometry page. */
466 p[0] = 4;
467 p[1] = 0x16;
468 /* if a geometry hint is available, use it */
469 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
470 p[2] = (cylinders >> 16) & 0xff;
471 p[3] = (cylinders >> 8) & 0xff;
472 p[4] = cylinders & 0xff;
473 p[5] = heads & 0xff;
474 /* Write precomp start cylinder, disabled */
475 p[6] = (cylinders >> 16) & 0xff;
476 p[7] = (cylinders >> 8) & 0xff;
477 p[8] = cylinders & 0xff;
478 /* Reduced current start cylinder, disabled */
479 p[9] = (cylinders >> 16) & 0xff;
480 p[10] = (cylinders >> 8) & 0xff;
481 p[11] = cylinders & 0xff;
482 /* Device step rate [ns], 200ns */
483 p[12] = 0;
484 p[13] = 200;
485 /* Landing zone cylinder */
486 p[14] = 0xff;
487 p[15] = 0xff;
488 p[16] = 0xff;
489 /* Medium rotation rate [rpm], 5400 rpm */
490 p[20] = (5400 >> 8) & 0xff;
491 p[21] = 5400 & 0xff;
492 return 0x16;
493
494 case 5: /* Flexible disk device geometry page. */
495 p[0] = 5;
496 p[1] = 0x1e;
497 /* Transfer rate [kbit/s], 5Mbit/s */
498 p[2] = 5000 >> 8;
499 p[3] = 5000 & 0xff;
500 /* if a geometry hint is available, use it */
501 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
502 p[4] = heads & 0xff;
503 p[5] = secs & 0xff;
504 p[6] = s->cluster_size * 2;
505 p[8] = (cylinders >> 8) & 0xff;
506 p[9] = cylinders & 0xff;
507 /* Write precomp start cylinder, disabled */
508 p[10] = (cylinders >> 8) & 0xff;
509 p[11] = cylinders & 0xff;
510 /* Reduced current start cylinder, disabled */
511 p[12] = (cylinders >> 8) & 0xff;
512 p[13] = cylinders & 0xff;
513 /* Device step rate [100us], 100us */
514 p[14] = 0;
515 p[15] = 1;
516 /* Device step pulse width [us], 1us */
517 p[16] = 1;
518 /* Device head settle delay [100us], 100us */
519 p[17] = 0;
520 p[18] = 1;
521 /* Motor on delay [0.1s], 0.1s */
522 p[19] = 1;
523 /* Motor off delay [0.1s], 0.1s */
524 p[20] = 1;
525 /* Medium rotation rate [rpm], 5400 rpm */
526 p[28] = (5400 >> 8) & 0xff;
527 p[29] = 5400 & 0xff;
528 return 0x1e;
529
530 case 8: /* Caching page. */
531 p[0] = 8;
532 p[1] = 0x12;
533 if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
534 p[2] = 4; /* WCE */
535 }
536 return 20;
537
538 case 0x2a: /* CD Capabilities and Mechanical Status page. */
539 if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
540 return 0;
541 p[0] = 0x2a;
542 p[1] = 0x14;
543 p[2] = 3; // CD-R & CD-RW read
544 p[3] = 0; // Writing not supported
545 p[4] = 0x7f; /* Audio, composite, digital out,
546 mode 2 form 1&2, multi session */
547 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
548 RW corrected, C2 errors, ISRC,
549 UPC, Bar code */
550 p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
551 /* Locking supported, jumper present, eject, tray */
552 p[7] = 0; /* no volume & mute control, no
553 changer */
554 p[8] = (50 * 176) >> 8; // 50x read speed
555 p[9] = (50 * 176) & 0xff;
556 p[10] = 0 >> 8; // No volume
557 p[11] = 0 & 0xff;
558 p[12] = 2048 >> 8; // 2M buffer
559 p[13] = 2048 & 0xff;
560 p[14] = (16 * 176) >> 8; // 16x read speed current
561 p[15] = (16 * 176) & 0xff;
562 p[18] = (16 * 176) >> 8; // 16x write speed
563 p[19] = (16 * 176) & 0xff;
564 p[20] = (16 * 176) >> 8; // 16x write speed current
565 p[21] = (16 * 176) & 0xff;
566 return 22;
567
568 default:
569 return 0;
570 }
571}
572
573static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
574{
575 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
576 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
577 uint64_t nb_sectors;
578 int page, dbd, buflen;
579 uint8_t *p;
580
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;
586
587 p[1] = 0; /* Default media type. */
588 p[3] = 0; /* Block descriptor length. */
589 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM ||
590 bdrv_is_read_only(bdrv)) {
591 p[2] = 0x80; /* Readonly. */
592 }
593 p += 4;
594
595 bdrv_get_geometry(bdrv, &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;
611 }
612
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;
624 }
625
626 buflen = p - outbuf;
627 outbuf[0] = buflen - 4;
628 if (buflen > req->cmd.xfer)
629 buflen = req->cmd.xfer;
630 return buflen;
631}
632
02880f43
GH
633static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
634{
635 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
636 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
637 int start_track, format, msf, toclen;
638 uint64_t nb_sectors;
639
640 msf = req->cmd.buf[1] & 2;
641 format = req->cmd.buf[2] & 0xf;
642 start_track = req->cmd.buf[6];
643 bdrv_get_geometry(bdrv, &nb_sectors);
644 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
645 nb_sectors /= s->cluster_size;
646 switch (format) {
647 case 0:
648 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
649 break;
650 case 1:
651 /* multi session : only a single session defined */
652 toclen = 12;
653 memset(outbuf, 0, 12);
654 outbuf[1] = 0x0a;
655 outbuf[2] = 0x01;
656 outbuf[3] = 0x01;
657 break;
658 case 2:
659 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
660 break;
661 default:
662 return -1;
663 }
664 if (toclen > req->cmd.xfer)
665 toclen = req->cmd.xfer;
666 return toclen;
667}
668
aa5dbdc1
GH
669static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
670{
e7e25e32 671 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
aa5dbdc1 672 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
e7e25e32 673 uint64_t nb_sectors;
aa5dbdc1
GH
674 int buflen = 0;
675
676 switch (req->cmd.buf[0]) {
677 case TEST_UNIT_READY:
678 if (!bdrv_is_inserted(bdrv))
679 goto not_ready;
680 break;
51ad87c9
GH
681 case REQUEST_SENSE:
682 if (req->cmd.xfer < 4)
683 goto illegal_request;
684 memset(outbuf, 0, 4);
685 buflen = 4;
686 if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
687 memset(outbuf, 0, 18);
688 buflen = 18;
689 outbuf[7] = 10;
690 /* asc 0x3a, ascq 0: Medium not present */
691 outbuf[12] = 0x3a;
692 outbuf[13] = 0;
693 }
694 outbuf[0] = 0xf0;
695 outbuf[1] = 0;
696 outbuf[2] = req->dev->sense.key;
697 scsi_dev_clear_sense(req->dev);
698 break;
0b06c059
GH
699 case INQUIRY:
700 buflen = scsi_disk_emulate_inquiry(req, outbuf);
701 if (buflen < 0)
702 goto illegal_request;
703 break;
ebddfcbe
GH
704 case MODE_SENSE:
705 case MODE_SENSE_10:
706 buflen = scsi_disk_emulate_mode_sense(req, outbuf);
707 if (buflen < 0)
708 goto illegal_request;
709 break;
02880f43
GH
710 case READ_TOC:
711 buflen = scsi_disk_emulate_read_toc(req, outbuf);
712 if (buflen < 0)
713 goto illegal_request;
714 break;
3d53ba18
GH
715 case RESERVE:
716 if (req->cmd.buf[1] & 1)
717 goto illegal_request;
718 break;
719 case RESERVE_10:
720 if (req->cmd.buf[1] & 3)
721 goto illegal_request;
722 break;
723 case RELEASE:
724 if (req->cmd.buf[1] & 1)
725 goto illegal_request;
726 break;
727 case RELEASE_10:
728 if (req->cmd.buf[1] & 3)
729 goto illegal_request;
730 break;
8d3628ff
GH
731 case START_STOP:
732 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
733 /* load/eject medium */
734 bdrv_eject(bdrv, !(req->cmd.buf[4] & 1));
735 }
736 break;
c68b9f34
GH
737 case ALLOW_MEDIUM_REMOVAL:
738 bdrv_set_locked(bdrv, req->cmd.buf[4] & 1);
739 break;
e7e25e32
GH
740 case READ_CAPACITY:
741 /* The normal LEN field for this command is zero. */
742 memset(outbuf, 0, 8);
743 bdrv_get_geometry(bdrv, &nb_sectors);
744 if (!nb_sectors)
745 goto not_ready;
746 nb_sectors /= s->cluster_size;
747 /* Returned value is the address of the last sector. */
748 nb_sectors--;
749 /* Remember the new size for read/write sanity checking. */
750 s->max_lba = nb_sectors;
751 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
752 if (nb_sectors > UINT32_MAX)
753 nb_sectors = UINT32_MAX;
754 outbuf[0] = (nb_sectors >> 24) & 0xff;
755 outbuf[1] = (nb_sectors >> 16) & 0xff;
756 outbuf[2] = (nb_sectors >> 8) & 0xff;
757 outbuf[3] = nb_sectors & 0xff;
758 outbuf[4] = 0;
759 outbuf[5] = 0;
760 outbuf[6] = s->cluster_size * 2;
761 outbuf[7] = 0;
762 buflen = 8;
763 break;
fc903943
GH
764 case SYNCHRONIZE_CACHE:
765 bdrv_flush(bdrv);
766 break;
38215553
GH
767 case GET_CONFIGURATION:
768 memset(outbuf, 0, 8);
769 /* ??? This should probably return much more information. For now
770 just return the basic header indicating the CD-ROM profile. */
771 outbuf[7] = 8; // CD-ROM
772 buflen = 8;
773 break;
5dd90e2a
GH
774 case SERVICE_ACTION_IN:
775 /* Service Action In subcommands. */
776 if ((req->cmd.buf[1] & 31) == 0x10) {
777 DPRINTF("SAI READ CAPACITY(16)\n");
778 memset(outbuf, 0, req->cmd.xfer);
779 bdrv_get_geometry(bdrv, &nb_sectors);
780 if (!nb_sectors)
781 goto not_ready;
782 nb_sectors /= s->cluster_size;
783 /* Returned value is the address of the last sector. */
784 nb_sectors--;
785 /* Remember the new size for read/write sanity checking. */
786 s->max_lba = nb_sectors;
787 outbuf[0] = (nb_sectors >> 56) & 0xff;
788 outbuf[1] = (nb_sectors >> 48) & 0xff;
789 outbuf[2] = (nb_sectors >> 40) & 0xff;
790 outbuf[3] = (nb_sectors >> 32) & 0xff;
791 outbuf[4] = (nb_sectors >> 24) & 0xff;
792 outbuf[5] = (nb_sectors >> 16) & 0xff;
793 outbuf[6] = (nb_sectors >> 8) & 0xff;
794 outbuf[7] = nb_sectors & 0xff;
795 outbuf[8] = 0;
796 outbuf[9] = 0;
797 outbuf[10] = s->cluster_size * 2;
798 outbuf[11] = 0;
799 /* Protection, exponent and lowest lba field left blank. */
800 buflen = req->cmd.xfer;
801 break;
802 }
803 DPRINTF("Unsupported Service Action In\n");
804 goto illegal_request;
39ec9a50
GH
805 case REPORT_LUNS:
806 if (req->cmd.xfer < 16)
807 goto illegal_request;
808 memset(outbuf, 0, 16);
809 outbuf[3] = 8;
810 buflen = 16;
811 break;
88f8a5ed
GH
812 case VERIFY:
813 break;
aa5dbdc1
GH
814 default:
815 goto illegal_request;
816 }
817 scsi_req_set_status(req, GOOD, NO_SENSE);
818 return buflen;
819
820not_ready:
821 scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
822 return 0;
823
824illegal_request:
825 scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
826 return 0;
827}
828
2e5d83bb
PB
829/* Execute a scsi command. Returns the length of the data expected by the
830 command. This will be Positive for data transfers from the device
831 (eg. disk reads), negative for transfers to the device (eg. disk writes),
832 and zero if the command does not transfer any data. */
833
8ccc2ace
TS
834static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
835 uint8_t *buf, int lun)
2e5d83bb 836{
d52affa7 837 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
86106e59 838 uint64_t lba;
2e5d83bb
PB
839 uint32_t len;
840 int cmdlen;
841 int is_write;
a917d384
PB
842 uint8_t command;
843 uint8_t *outbuf;
4c41d2ef 844 SCSIDiskReq *r;
aa5dbdc1 845 int rc;
a917d384
PB
846
847 command = buf[0];
848 r = scsi_find_request(s, tag);
849 if (r) {
850 BADF("Tag 0x%x already in use\n", tag);
8ccc2ace 851 scsi_cancel_io(d, tag);
a917d384
PB
852 }
853 /* ??? Tags are not unique for different luns. We only implement a
854 single lun, so this should not matter. */
89b08ae1 855 r = scsi_new_request(d, tag, lun);
3f4cb3d3 856 outbuf = (uint8_t *)r->iov.iov_base;
2e5d83bb 857 is_write = 0;
a917d384
PB
858 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
859 switch (command >> 5) {
2e5d83bb 860 case 0:
86106e59
AL
861 lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
862 (((uint64_t) buf[1] & 0x1f) << 16);
2e5d83bb
PB
863 len = buf[4];
864 cmdlen = 6;
865 break;
866 case 1:
867 case 2:
86106e59
AL
868 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
869 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
870 len = buf[8] | (buf[7] << 8);
871 cmdlen = 10;
872 break;
873 case 4:
86106e59
AL
874 lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
875 ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
876 ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
877 ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
2e5d83bb
PB
878 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
879 cmdlen = 16;
880 break;
881 case 5:
86106e59
AL
882 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
883 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
884 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
885 cmdlen = 12;
886 break;
887 default:
a917d384 888 BADF("Unsupported command length, command %x\n", command);
2e5d83bb
PB
889 goto fail;
890 }
891#ifdef DEBUG_SCSI
892 {
893 int i;
894 for (i = 1; i < cmdlen; i++) {
895 printf(" 0x%02x", buf[i]);
896 }
897 printf("\n");
898 }
899#endif
aa5dbdc1
GH
900
901 if (scsi_req_parse(&r->req, buf) != 0) {
902 BADF("Unsupported command length, command %x\n", command);
903 goto fail;
904 }
905 assert(r->req.cmd.len == cmdlen);
906 assert(r->req.cmd.lba == lba);
907
0fc5c15a 908 if (lun || buf[1] >> 5) {
2e5d83bb 909 /* Only LUN 0 supported. */
0fc5c15a 910 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
ebf46023 911 if (command != REQUEST_SENSE && command != INQUIRY)
22864256 912 goto fail;
2e5d83bb 913 }
a917d384 914 switch (command) {
ebf46023 915 case TEST_UNIT_READY:
51ad87c9 916 case REQUEST_SENSE:
0b06c059 917 case INQUIRY:
ebddfcbe
GH
918 case MODE_SENSE:
919 case MODE_SENSE_10:
3d53ba18
GH
920 case RESERVE:
921 case RESERVE_10:
922 case RELEASE:
923 case RELEASE_10:
8d3628ff 924 case START_STOP:
c68b9f34 925 case ALLOW_MEDIUM_REMOVAL:
e7e25e32 926 case READ_CAPACITY:
fc903943 927 case SYNCHRONIZE_CACHE:
02880f43 928 case READ_TOC:
38215553 929 case GET_CONFIGURATION:
5dd90e2a 930 case SERVICE_ACTION_IN:
39ec9a50 931 case REPORT_LUNS:
88f8a5ed 932 case VERIFY:
aa5dbdc1
GH
933 rc = scsi_disk_emulate_command(&r->req, outbuf);
934 if (rc > 0) {
935 r->iov.iov_len = rc;
936 } else {
937 scsi_req_complete(&r->req);
938 scsi_remove_request(r);
0b06c059 939 return 0;
aa5dbdc1 940 }
0b06c059 941 break;
ebf46023
GH
942 case READ_6:
943 case READ_10:
bd536cf3
GH
944 case READ_12:
945 case READ_16:
0bf9e31a 946 DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
274fb0e1
AL
947 if (lba > s->max_lba)
948 goto illegal_lba;
a917d384
PB
949 r->sector = lba * s->cluster_size;
950 r->sector_count = len * s->cluster_size;
2e5d83bb 951 break;
ebf46023
GH
952 case WRITE_6:
953 case WRITE_10:
bd536cf3
GH
954 case WRITE_12:
955 case WRITE_16:
0bf9e31a 956 DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
274fb0e1
AL
957 if (lba > s->max_lba)
958 goto illegal_lba;
a917d384
PB
959 r->sector = lba * s->cluster_size;
960 r->sector_count = len * s->cluster_size;
2e5d83bb
PB
961 is_write = 1;
962 break;
2e5d83bb
PB
963 default:
964 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
965 fail:
0d65e1f8 966 scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
2e5d83bb 967 return 0;
274fb0e1 968 illegal_lba:
0d65e1f8 969 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
274fb0e1 970 return 0;
2e5d83bb 971 }
c87c0672 972 if (r->sector_count == 0 && r->iov.iov_len == 0) {
0d65e1f8 973 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 974 }
c87c0672 975 len = r->sector_count * 512 + r->iov.iov_len;
a917d384
PB
976 if (is_write) {
977 return -len;
978 } else {
979 if (!r->sector_count)
980 r->sector_count = -1;
981 return len;
2e5d83bb 982 }
2e5d83bb
PB
983}
984
56a14938
GH
985static void scsi_destroy(SCSIDevice *dev)
986{
987 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
9af99d98 988 SCSIDiskReq *r;
56a14938 989
9af99d98
GH
990 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
991 r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
992 scsi_remove_request(r);
993 }
251882b7 994 drive_uninit(s->qdev.dinfo);
56a14938
GH
995}
996
d52affa7 997static int scsi_disk_initfn(SCSIDevice *dev)
2e5d83bb 998{
d52affa7 999 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
274fb0e1 1000 uint64_t nb_sectors;
2e5d83bb 1001
251882b7 1002 if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
d52affa7
GH
1003 qemu_error("scsi-disk: drive property not set\n");
1004 return -1;
1005 }
1006
251882b7 1007 if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
7c22dd52 1008 s->cluster_size = 4;
2e5d83bb 1009 } else {
7c22dd52 1010 s->cluster_size = 1;
2e5d83bb 1011 }
b07995e3 1012 s->qdev.blocksize = 512 * s->cluster_size;
91376656 1013 s->qdev.type = TYPE_DISK;
251882b7 1014 bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
274fb0e1
AL
1015 nb_sectors /= s->cluster_size;
1016 if (nb_sectors)
1017 nb_sectors--;
1018 s->max_lba = nb_sectors;
ea8a5d7f 1019 qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
d52affa7
GH
1020 return 0;
1021}
1022
1023static SCSIDeviceInfo scsi_disk_info = {
1024 .qdev.name = "scsi-disk",
1025 .qdev.desc = "virtual scsi disk or cdrom",
1026 .qdev.size = sizeof(SCSIDiskState),
1027 .init = scsi_disk_initfn,
56a14938 1028 .destroy = scsi_destroy,
d52affa7
GH
1029 .send_command = scsi_send_command,
1030 .read_data = scsi_read_data,
1031 .write_data = scsi_write_data,
1032 .cancel_io = scsi_cancel_io,
1033 .get_buf = scsi_get_buf,
1034 .qdev.props = (Property[]) {
251882b7 1035 DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
9525204c 1036 DEFINE_PROP_STRING("ver", SCSIDiskState, version),
d52affa7
GH
1037 DEFINE_PROP_END_OF_LIST(),
1038 },
1039};
1040
1041static void scsi_disk_register_devices(void)
1042{
1043 scsi_qdev_register(&scsi_disk_info);
8ccc2ace 1044}
d52affa7 1045device_init(scsi_disk_register_devices)