]> git.proxmox.com Git - qemu.git/blame - hw/scsi-disk.c
microblaze: target-ify target_ucontext
[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
ad3cea42
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
22//#define DEBUG_SCSI
23
24#ifdef DEBUG_SCSI
001faf32
BS
25#define DPRINTF(fmt, ...) \
26do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 27#else
001faf32 28#define DPRINTF(fmt, ...) do {} while(0)
2e5d83bb
PB
29#endif
30
001faf32
BS
31#define BADF(fmt, ...) \
32do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 33
87ecb68b 34#include "qemu-common.h"
2f792016 35#include "qemu-error.h"
43b443b6 36#include "scsi.h"
0d65e1f8 37#include "scsi-defs.h"
666daa68 38#include "sysemu.h"
2446333c 39#include "blockdev.h"
22864256 40
f0f72ffe 41#define SCSI_DMA_BUF_SIZE 131072
57575058 42#define SCSI_MAX_INQUIRY_LEN 256
a917d384 43
5dba48a8
KW
44#define SCSI_REQ_STATUS_RETRY 0x01
45#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
46#define SCSI_REQ_STATUS_RETRY_READ 0x00
47#define SCSI_REQ_STATUS_RETRY_WRITE 0x02
78ced65e 48#define SCSI_REQ_STATUS_RETRY_FLUSH 0x04
ea8a5d7f 49
d52affa7
GH
50typedef struct SCSIDiskState SCSIDiskState;
51
4c41d2ef
GH
52typedef struct SCSIDiskReq {
53 SCSIRequest req;
e035b43d 54 /* ??? We should probably keep track of whether the data transfer is
2e5d83bb 55 a read or a write. Currently we rely on the host getting it right. */
a917d384 56 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
e035b43d
AL
57 uint64_t sector;
58 uint32_t sector_count;
c87c0672
AL
59 struct iovec iov;
60 QEMUIOVector qiov;
ea8a5d7f 61 uint32_t status;
4c41d2ef 62} SCSIDiskReq;
a917d384 63
d52affa7 64struct SCSIDiskState
a917d384 65{
d52affa7 66 SCSIDevice qdev;
428c149b 67 BlockDriverState *bs;
a917d384
PB
68 /* The qemu block layer uses a fixed 512 byte sector size.
69 This is the number of 512 byte blocks in a single scsi sector. */
70 int cluster_size;
274fb0e1 71 uint64_t max_lba;
213189ab 72 QEMUBH *bh;
383b4d9b 73 char *version;
a0fef654 74 char *serial;
2e5d83bb
PB
75};
76
5dba48a8 77static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
78ced65e 78static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
5dba48a8 79
72aef731
CH
80static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag,
81 uint32_t lun)
2e5d83bb 82{
89b08ae1 83 SCSIRequest *req;
4c41d2ef 84 SCSIDiskReq *r;
a917d384 85
72aef731 86 req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun);
89b08ae1 87 r = DO_UPCAST(SCSIDiskReq, req, req);
72aef731 88 r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
a917d384 89 return r;
2e5d83bb
PB
90}
91
4c41d2ef 92static void scsi_remove_request(SCSIDiskReq *r)
4d611c9a 93{
f8a83245 94 qemu_vfree(r->iov.iov_base);
89b08ae1 95 scsi_req_free(&r->req);
4d611c9a
PB
96}
97
4c41d2ef 98static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
4d611c9a 99{
89b08ae1 100 return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
a917d384
PB
101}
102
ed3a34a3
GH
103static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
104{
105 req->status = status;
106 scsi_dev_set_sense(req->dev, sense_code);
107}
108
a917d384 109/* Helper function for command completion. */
4c41d2ef 110static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
a917d384 111{
4c41d2ef
GH
112 DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
113 r->req.tag, status, sense);
ed3a34a3
GH
114 scsi_req_set_status(&r->req, status, sense);
115 scsi_req_complete(&r->req);
89b08ae1 116 scsi_remove_request(r);
4d611c9a
PB
117}
118
119/* Cancel a pending data transfer. */
8ccc2ace 120static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
4d611c9a 121{
d52affa7 122 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 123 SCSIDiskReq *r;
a917d384
PB
124 DPRINTF("Cancel tag=0x%x\n", tag);
125 r = scsi_find_request(s, tag);
126 if (r) {
4c41d2ef
GH
127 if (r->req.aiocb)
128 bdrv_aio_cancel(r->req.aiocb);
129 r->req.aiocb = NULL;
a917d384
PB
130 scsi_remove_request(r);
131 }
132}
133
134static void scsi_read_complete(void * opaque, int ret)
135{
4c41d2ef 136 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
5dba48a8 137 int n;
a917d384 138
3e94cb02
JK
139 r->req.aiocb = NULL;
140
a917d384 141 if (ret) {
5dba48a8
KW
142 if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
143 return;
144 }
4d611c9a 145 }
5dba48a8 146
aa2b1e89 147 DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
a917d384 148
5dba48a8
KW
149 n = r->iov.iov_len / 512;
150 r->sector += n;
151 r->sector_count -= n;
4c41d2ef 152 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
4d611c9a
PB
153}
154
5dba48a8
KW
155
156static void scsi_read_request(SCSIDiskReq *r)
2e5d83bb 157{
5dba48a8 158 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
2e5d83bb
PB
159 uint32_t n;
160
a917d384 161 if (r->sector_count == (uint32_t)-1) {
aa2b1e89 162 DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
a917d384 163 r->sector_count = 0;
4c41d2ef 164 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
a917d384 165 return;
2e5d83bb 166 }
a917d384
PB
167 DPRINTF("Read sector_count=%d\n", r->sector_count);
168 if (r->sector_count == 0) {
0d65e1f8 169 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 170 return;
2e5d83bb
PB
171 }
172
a917d384
PB
173 n = r->sector_count;
174 if (n > SCSI_DMA_BUF_SIZE / 512)
175 n = SCSI_DMA_BUF_SIZE / 512;
176
c87c0672
AL
177 r->iov.iov_len = n * 512;
178 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
428c149b 179 r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
c87c0672 180 scsi_read_complete, r);
d33ea50a
KW
181 if (r->req.aiocb == NULL) {
182 scsi_read_complete(r, -EIO);
183 }
2e5d83bb
PB
184}
185
5dba48a8
KW
186/* Read more data from scsi device into buffer. */
187static void scsi_read_data(SCSIDevice *d, uint32_t tag)
ea8a5d7f 188{
5dba48a8
KW
189 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
190 SCSIDiskReq *r;
191
192 r = scsi_find_request(s, tag);
193 if (!r) {
194 BADF("Bad read tag 0x%x\n", tag);
195 /* ??? This is the wrong error. */
196 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
197 return;
198 }
199
200 /* No data transfer may already be in progress */
201 assert(r->req.aiocb == NULL);
202
203 scsi_read_request(r);
204}
205
206static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
207{
208 int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
4c41d2ef 209 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
5dba48a8 210 BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
ea8a5d7f 211
380f640f 212 if (action == BLOCK_ERR_IGNORE) {
5dba48a8 213 bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
ea8a5d7f 214 return 0;
380f640f 215 }
ea8a5d7f
AL
216
217 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
218 || action == BLOCK_ERR_STOP_ANY) {
5dba48a8
KW
219
220 type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
221 r->status |= SCSI_REQ_STATUS_RETRY | type;
222
223 bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
554a310b 224 vm_stop(0);
ea8a5d7f 225 } else {
5dba48a8
KW
226 if (type == SCSI_REQ_STATUS_RETRY_READ) {
227 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
228 }
0d65e1f8
GH
229 scsi_command_complete(r, CHECK_CONDITION,
230 HARDWARE_ERROR);
5dba48a8 231 bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
ea8a5d7f
AL
232 }
233
234 return 1;
235}
236
4d611c9a
PB
237static void scsi_write_complete(void * opaque, int ret)
238{
4c41d2ef 239 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
a917d384 240 uint32_t len;
ea8a5d7f
AL
241 uint32_t n;
242
4c41d2ef 243 r->req.aiocb = NULL;
4d611c9a
PB
244
245 if (ret) {
5dba48a8 246 if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
ea8a5d7f 247 return;
5dba48a8 248 }
4d611c9a
PB
249 }
250
c87c0672 251 n = r->iov.iov_len / 512;
ea8a5d7f
AL
252 r->sector += n;
253 r->sector_count -= n;
a917d384 254 if (r->sector_count == 0) {
0d65e1f8 255 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384
PB
256 } else {
257 len = r->sector_count * 512;
258 if (len > SCSI_DMA_BUF_SIZE) {
259 len = SCSI_DMA_BUF_SIZE;
260 }
c87c0672 261 r->iov.iov_len = len;
4c41d2ef
GH
262 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
263 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
4d611c9a 264 }
4d611c9a
PB
265}
266
4c41d2ef 267static void scsi_write_request(SCSIDiskReq *r)
ea8a5d7f 268{
4c41d2ef 269 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
ea8a5d7f
AL
270 uint32_t n;
271
c87c0672 272 n = r->iov.iov_len / 512;
ea8a5d7f 273 if (n) {
c87c0672 274 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
428c149b 275 r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
c87c0672 276 scsi_write_complete, r);
d33ea50a
KW
277 if (r->req.aiocb == NULL) {
278 scsi_write_complete(r, -EIO);
279 }
ea8a5d7f
AL
280 } else {
281 /* Invoke completion routine to fetch data from host. */
282 scsi_write_complete(r, 0);
283 }
284}
285
4d611c9a
PB
286/* Write data to a scsi device. Returns nonzero on failure.
287 The transfer may complete asynchronously. */
8ccc2ace 288static int scsi_write_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 289{
d52affa7 290 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 291 SCSIDiskReq *r;
2e5d83bb 292
a917d384
PB
293 DPRINTF("Write data tag=0x%x\n", tag);
294 r = scsi_find_request(s, tag);
295 if (!r) {
296 BADF("Bad write tag 0x%x\n", tag);
0d65e1f8 297 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
2e5d83bb
PB
298 return 1;
299 }
ea8a5d7f 300
5dba48a8
KW
301 /* No data transfer may already be in progress */
302 assert(r->req.aiocb == NULL);
ea8a5d7f
AL
303
304 scsi_write_request(r);
2e5d83bb 305
a917d384
PB
306 return 0;
307}
2e5d83bb 308
213189ab 309static void scsi_dma_restart_bh(void *opaque)
ea8a5d7f 310{
d52affa7 311 SCSIDiskState *s = opaque;
9af99d98
GH
312 SCSIRequest *req;
313 SCSIDiskReq *r;
213189ab
MA
314
315 qemu_bh_delete(s->bh);
316 s->bh = NULL;
ea8a5d7f 317
9af99d98
GH
318 QTAILQ_FOREACH(req, &s->qdev.requests, next) {
319 r = DO_UPCAST(SCSIDiskReq, req, req);
ea8a5d7f 320 if (r->status & SCSI_REQ_STATUS_RETRY) {
5dba48a8 321 int status = r->status;
78ced65e
KW
322 int ret;
323
5dba48a8
KW
324 r->status &=
325 ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
326
327 switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
328 case SCSI_REQ_STATUS_RETRY_READ:
329 scsi_read_request(r);
330 break;
331 case SCSI_REQ_STATUS_RETRY_WRITE:
332 scsi_write_request(r);
333 break;
78ced65e
KW
334 case SCSI_REQ_STATUS_RETRY_FLUSH:
335 ret = scsi_disk_emulate_command(r, r->iov.iov_base);
336 if (ret == 0) {
337 scsi_command_complete(r, GOOD, NO_SENSE);
338 }
5dba48a8 339 }
ea8a5d7f 340 }
ea8a5d7f
AL
341 }
342}
343
213189ab
MA
344static void scsi_dma_restart_cb(void *opaque, int running, int reason)
345{
d52affa7 346 SCSIDiskState *s = opaque;
213189ab
MA
347
348 if (!running)
349 return;
350
351 if (!s->bh) {
352 s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
353 qemu_bh_schedule(s->bh);
354 }
355}
356
a917d384 357/* Return a pointer to the data buffer. */
8ccc2ace 358static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
a917d384 359{
d52affa7 360 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 361 SCSIDiskReq *r;
2e5d83bb 362
a917d384
PB
363 r = scsi_find_request(s, tag);
364 if (!r) {
365 BADF("Bad buffer tag 0x%x\n", tag);
366 return NULL;
4d611c9a 367 }
3f4cb3d3 368 return (uint8_t *)r->iov.iov_base;
2e5d83bb
PB
369}
370
0b06c059
GH
371static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
372{
383b4d9b 373 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
0b06c059
GH
374 int buflen = 0;
375
376 if (req->cmd.buf[1] & 0x2) {
377 /* Command support data - optional, not implemented */
378 BADF("optional INQUIRY command support request not implemented\n");
379 return -1;
380 }
381
382 if (req->cmd.buf[1] & 0x1) {
383 /* Vital product data */
384 uint8_t page_code = req->cmd.buf[2];
385 if (req->cmd.xfer < 4) {
386 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
387 "less than 4\n", page_code, req->cmd.xfer);
388 return -1;
389 }
390
428c149b 391 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
0b06c059
GH
392 outbuf[buflen++] = 5;
393 } else {
394 outbuf[buflen++] = 0;
395 }
396 outbuf[buflen++] = page_code ; // this page
397 outbuf[buflen++] = 0x00;
398
399 switch (page_code) {
400 case 0x00: /* Supported page codes, mandatory */
401 DPRINTF("Inquiry EVPD[Supported pages] "
402 "buffer size %zd\n", req->cmd.xfer);
ee3659e3 403 outbuf[buflen++] = 4; // number of pages
0b06c059
GH
404 outbuf[buflen++] = 0x00; // list of supported pages (this page)
405 outbuf[buflen++] = 0x80; // unit serial number
406 outbuf[buflen++] = 0x83; // device identification
ee3659e3 407 outbuf[buflen++] = 0xb0; // block device characteristics
0b06c059
GH
408 break;
409
410 case 0x80: /* Device serial number, optional */
411 {
a0fef654 412 int l = strlen(s->serial);
0b06c059
GH
413
414 if (l > req->cmd.xfer)
415 l = req->cmd.xfer;
416 if (l > 20)
417 l = 20;
418
419 DPRINTF("Inquiry EVPD[Serial number] "
420 "buffer size %zd\n", req->cmd.xfer);
421 outbuf[buflen++] = l;
a0fef654 422 memcpy(outbuf+buflen, s->serial, l);
0b06c059
GH
423 buflen += l;
424 break;
425 }
426
427 case 0x83: /* Device identification page, mandatory */
428 {
429 int max_len = 255 - 8;
428c149b 430 int id_len = strlen(bdrv_get_device_name(s->bs));
0b06c059
GH
431
432 if (id_len > max_len)
433 id_len = max_len;
434 DPRINTF("Inquiry EVPD[Device identification] "
435 "buffer size %zd\n", req->cmd.xfer);
436
437 outbuf[buflen++] = 3 + id_len;
438 outbuf[buflen++] = 0x2; // ASCII
439 outbuf[buflen++] = 0; // not officially assigned
440 outbuf[buflen++] = 0; // reserved
441 outbuf[buflen++] = id_len; // length of data following
442
428c149b 443 memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
0b06c059
GH
444 buflen += id_len;
445 break;
446 }
ee3659e3
CH
447 case 0xb0: /* block device characteristics */
448 {
8cfacf07
CH
449 unsigned int min_io_size =
450 s->qdev.conf.min_io_size / s->qdev.blocksize;
451 unsigned int opt_io_size =
452 s->qdev.conf.opt_io_size / s->qdev.blocksize;
ee3659e3
CH
453
454 /* required VPD size with unmap support */
455 outbuf[3] = buflen = 0x3c;
456
457 memset(outbuf + 4, 0, buflen - 4);
458
459 /* optimal transfer length granularity */
460 outbuf[6] = (min_io_size >> 8) & 0xff;
461 outbuf[7] = min_io_size & 0xff;
462
463 /* optimal transfer length */
464 outbuf[12] = (opt_io_size >> 24) & 0xff;
465 outbuf[13] = (opt_io_size >> 16) & 0xff;
466 outbuf[14] = (opt_io_size >> 8) & 0xff;
467 outbuf[15] = opt_io_size & 0xff;
468 break;
469 }
0b06c059
GH
470 default:
471 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
472 "buffer size %zd\n", page_code, req->cmd.xfer);
473 return -1;
474 }
475 /* done with EVPD */
476 return buflen;
477 }
478
479 /* Standard INQUIRY data */
480 if (req->cmd.buf[2] != 0) {
481 BADF("Error: Inquiry (STANDARD) page or code "
482 "is non-zero [%02X]\n", req->cmd.buf[2]);
483 return -1;
484 }
485
486 /* PAGE CODE == 0 */
487 if (req->cmd.xfer < 5) {
488 BADF("Error: Inquiry (STANDARD) buffer size %zd "
489 "is less than 5\n", req->cmd.xfer);
490 return -1;
491 }
492
0b06c059
GH
493 buflen = req->cmd.xfer;
494 if (buflen > SCSI_MAX_INQUIRY_LEN)
495 buflen = SCSI_MAX_INQUIRY_LEN;
496
497 memset(outbuf, 0, buflen);
498
499 if (req->lun || req->cmd.buf[1] >> 5) {
500 outbuf[0] = 0x7f; /* LUN not supported */
501 return buflen;
502 }
503
428c149b 504 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
0b06c059
GH
505 outbuf[0] = 5;
506 outbuf[1] = 0x80;
550fe6c6 507 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
0b06c059
GH
508 } else {
509 outbuf[0] = 0;
550fe6c6 510 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
0b06c059 511 }
550fe6c6 512 memcpy(&outbuf[8], "QEMU ", 8);
314b1811 513 memset(&outbuf[32], 0, 4);
552fee93 514 memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
99aba0c4
CH
515 /*
516 * We claim conformance to SPC-3, which is required for guests
517 * to ask for modern features like READ CAPACITY(16) or the
518 * block characteristics VPD page by default. Not all of SPC-3
519 * is actually implemented, but we're good enough.
520 */
ee3659e3 521 outbuf[2] = 5;
0b06c059 522 outbuf[3] = 2; /* Format 2 */
ad3cea42
AT
523
524 if (buflen > 36) {
525 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
526 } else {
527 /* If the allocation length of CDB is too small,
528 the additional length is not adjusted */
529 outbuf[4] = 36 - 5;
530 }
531
0b06c059
GH
532 /* Sync data transfer and TCQ. */
533 outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
534 return buflen;
535}
536
282ab04e
BK
537static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
538 int page_control)
ebddfcbe
GH
539{
540 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
428c149b 541 BlockDriverState *bdrv = s->bs;
ebddfcbe
GH
542 int cylinders, heads, secs;
543
282ab04e
BK
544 /*
545 * If Changeable Values are requested, a mask denoting those mode parameters
546 * that are changeable shall be returned. As we currently don't support
547 * parameter changes via MODE_SELECT all bits are returned set to zero.
548 * The buffer was already menset to zero by the caller of this function.
549 */
ebddfcbe
GH
550 switch (page) {
551 case 4: /* Rigid disk device geometry page. */
552 p[0] = 4;
553 p[1] = 0x16;
282ab04e
BK
554 if (page_control == 1) { /* Changeable Values */
555 return p[1] + 2;
556 }
ebddfcbe
GH
557 /* if a geometry hint is available, use it */
558 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
559 p[2] = (cylinders >> 16) & 0xff;
560 p[3] = (cylinders >> 8) & 0xff;
561 p[4] = cylinders & 0xff;
562 p[5] = heads & 0xff;
563 /* Write precomp start cylinder, disabled */
564 p[6] = (cylinders >> 16) & 0xff;
565 p[7] = (cylinders >> 8) & 0xff;
566 p[8] = cylinders & 0xff;
567 /* Reduced current start cylinder, disabled */
568 p[9] = (cylinders >> 16) & 0xff;
569 p[10] = (cylinders >> 8) & 0xff;
570 p[11] = cylinders & 0xff;
571 /* Device step rate [ns], 200ns */
572 p[12] = 0;
573 p[13] = 200;
574 /* Landing zone cylinder */
575 p[14] = 0xff;
576 p[15] = 0xff;
577 p[16] = 0xff;
578 /* Medium rotation rate [rpm], 5400 rpm */
579 p[20] = (5400 >> 8) & 0xff;
580 p[21] = 5400 & 0xff;
282ab04e 581 return p[1] + 2;
ebddfcbe
GH
582
583 case 5: /* Flexible disk device geometry page. */
584 p[0] = 5;
585 p[1] = 0x1e;
282ab04e
BK
586 if (page_control == 1) { /* Changeable Values */
587 return p[1] + 2;
588 }
ebddfcbe
GH
589 /* Transfer rate [kbit/s], 5Mbit/s */
590 p[2] = 5000 >> 8;
591 p[3] = 5000 & 0xff;
592 /* if a geometry hint is available, use it */
593 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
594 p[4] = heads & 0xff;
595 p[5] = secs & 0xff;
596 p[6] = s->cluster_size * 2;
597 p[8] = (cylinders >> 8) & 0xff;
598 p[9] = cylinders & 0xff;
599 /* Write precomp start cylinder, disabled */
600 p[10] = (cylinders >> 8) & 0xff;
601 p[11] = cylinders & 0xff;
602 /* Reduced current start cylinder, disabled */
603 p[12] = (cylinders >> 8) & 0xff;
604 p[13] = cylinders & 0xff;
605 /* Device step rate [100us], 100us */
606 p[14] = 0;
607 p[15] = 1;
608 /* Device step pulse width [us], 1us */
609 p[16] = 1;
610 /* Device head settle delay [100us], 100us */
611 p[17] = 0;
612 p[18] = 1;
613 /* Motor on delay [0.1s], 0.1s */
614 p[19] = 1;
615 /* Motor off delay [0.1s], 0.1s */
616 p[20] = 1;
617 /* Medium rotation rate [rpm], 5400 rpm */
618 p[28] = (5400 >> 8) & 0xff;
619 p[29] = 5400 & 0xff;
282ab04e 620 return p[1] + 2;
ebddfcbe
GH
621
622 case 8: /* Caching page. */
623 p[0] = 8;
624 p[1] = 0x12;
282ab04e
BK
625 if (page_control == 1) { /* Changeable Values */
626 return p[1] + 2;
627 }
428c149b 628 if (bdrv_enable_write_cache(s->bs)) {
ebddfcbe
GH
629 p[2] = 4; /* WCE */
630 }
282ab04e 631 return p[1] + 2;
ebddfcbe
GH
632
633 case 0x2a: /* CD Capabilities and Mechanical Status page. */
634 if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
635 return 0;
636 p[0] = 0x2a;
637 p[1] = 0x14;
282ab04e
BK
638 if (page_control == 1) { /* Changeable Values */
639 return p[1] + 2;
640 }
ebddfcbe
GH
641 p[2] = 3; // CD-R & CD-RW read
642 p[3] = 0; // Writing not supported
643 p[4] = 0x7f; /* Audio, composite, digital out,
644 mode 2 form 1&2, multi session */
645 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
646 RW corrected, C2 errors, ISRC,
647 UPC, Bar code */
428c149b 648 p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
ebddfcbe
GH
649 /* Locking supported, jumper present, eject, tray */
650 p[7] = 0; /* no volume & mute control, no
651 changer */
652 p[8] = (50 * 176) >> 8; // 50x read speed
653 p[9] = (50 * 176) & 0xff;
654 p[10] = 0 >> 8; // No volume
655 p[11] = 0 & 0xff;
656 p[12] = 2048 >> 8; // 2M buffer
657 p[13] = 2048 & 0xff;
658 p[14] = (16 * 176) >> 8; // 16x read speed current
659 p[15] = (16 * 176) & 0xff;
660 p[18] = (16 * 176) >> 8; // 16x write speed
661 p[19] = (16 * 176) & 0xff;
662 p[20] = (16 * 176) >> 8; // 16x write speed current
663 p[21] = (16 * 176) & 0xff;
282ab04e 664 return p[1] + 2;
ebddfcbe
GH
665
666 default:
667 return 0;
668 }
669}
670
671static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
672{
673 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
ebddfcbe 674 uint64_t nb_sectors;
282ab04e 675 int page, dbd, buflen, page_control;
ebddfcbe 676 uint8_t *p;
ce512ee1 677 uint8_t dev_specific_param;
ebddfcbe
GH
678
679 dbd = req->cmd.buf[1] & 0x8;
680 page = req->cmd.buf[2] & 0x3f;
282ab04e 681 page_control = (req->cmd.buf[2] & 0xc0) >> 6;
aa2b1e89
BK
682 DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
683 (req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, req->cmd.xfer, page_control);
ebddfcbe
GH
684 memset(outbuf, 0, req->cmd.xfer);
685 p = outbuf;
686
0056dcc1 687 if (bdrv_is_read_only(s->bs)) {
ce512ee1
BK
688 dev_specific_param = 0x80; /* Readonly. */
689 } else {
690 dev_specific_param = 0x00;
691 }
692
693 if (req->cmd.buf[0] == MODE_SENSE) {
694 p[1] = 0; /* Default media type. */
695 p[2] = dev_specific_param;
696 p[3] = 0; /* Block descriptor length. */
697 p += 4;
698 } else { /* MODE_SENSE_10 */
699 p[2] = 0; /* Default media type. */
700 p[3] = dev_specific_param;
701 p[6] = p[7] = 0; /* Block descriptor length. */
702 p += 8;
ebddfcbe 703 }
ebddfcbe 704
428c149b 705 bdrv_get_geometry(s->bs, &nb_sectors);
333d50fe 706 if (!dbd && nb_sectors) {
ce512ee1
BK
707 if (req->cmd.buf[0] == MODE_SENSE) {
708 outbuf[3] = 8; /* Block descriptor length */
709 } else { /* MODE_SENSE_10 */
710 outbuf[7] = 8; /* Block descriptor length */
711 }
ebddfcbe 712 nb_sectors /= s->cluster_size;
ebddfcbe 713 if (nb_sectors > 0xffffff)
2488b740 714 nb_sectors = 0;
ebddfcbe
GH
715 p[0] = 0; /* media density code */
716 p[1] = (nb_sectors >> 16) & 0xff;
717 p[2] = (nb_sectors >> 8) & 0xff;
718 p[3] = nb_sectors & 0xff;
719 p[4] = 0; /* reserved */
720 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
721 p[6] = s->cluster_size * 2;
722 p[7] = 0;
723 p += 8;
724 }
725
282ab04e
BK
726 if (page_control == 3) { /* Saved Values */
727 return -1; /* ILLEGAL_REQUEST */
728 }
729
ebddfcbe
GH
730 switch (page) {
731 case 0x04:
732 case 0x05:
733 case 0x08:
734 case 0x2a:
282ab04e 735 p += mode_sense_page(req, page, p, page_control);
ebddfcbe
GH
736 break;
737 case 0x3f:
282ab04e
BK
738 p += mode_sense_page(req, 0x08, p, page_control);
739 p += mode_sense_page(req, 0x2a, p, page_control);
ebddfcbe 740 break;
a9c17b2b
BK
741 default:
742 return -1; /* ILLEGAL_REQUEST */
ebddfcbe
GH
743 }
744
745 buflen = p - outbuf;
ce512ee1
BK
746 /*
747 * The mode data length field specifies the length in bytes of the
748 * following data that is available to be transferred. The mode data
749 * length does not include itself.
750 */
751 if (req->cmd.buf[0] == MODE_SENSE) {
752 outbuf[0] = buflen - 1;
753 } else { /* MODE_SENSE_10 */
754 outbuf[0] = ((buflen - 2) >> 8) & 0xff;
755 outbuf[1] = (buflen - 2) & 0xff;
756 }
ebddfcbe
GH
757 if (buflen > req->cmd.xfer)
758 buflen = req->cmd.xfer;
759 return buflen;
760}
761
02880f43
GH
762static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
763{
764 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
02880f43
GH
765 int start_track, format, msf, toclen;
766 uint64_t nb_sectors;
767
768 msf = req->cmd.buf[1] & 2;
769 format = req->cmd.buf[2] & 0xf;
770 start_track = req->cmd.buf[6];
428c149b 771 bdrv_get_geometry(s->bs, &nb_sectors);
02880f43
GH
772 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
773 nb_sectors /= s->cluster_size;
774 switch (format) {
775 case 0:
776 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
777 break;
778 case 1:
779 /* multi session : only a single session defined */
780 toclen = 12;
781 memset(outbuf, 0, 12);
782 outbuf[1] = 0x0a;
783 outbuf[2] = 0x01;
784 outbuf[3] = 0x01;
785 break;
786 case 2:
787 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
788 break;
789 default:
790 return -1;
791 }
792 if (toclen > req->cmd.xfer)
793 toclen = req->cmd.xfer;
794 return toclen;
795}
796
8af7a3ab 797static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
aa5dbdc1 798{
8af7a3ab 799 SCSIRequest *req = &r->req;
e7e25e32 800 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
e7e25e32 801 uint64_t nb_sectors;
aa5dbdc1 802 int buflen = 0;
78ced65e 803 int ret;
aa5dbdc1
GH
804
805 switch (req->cmd.buf[0]) {
806 case TEST_UNIT_READY:
428c149b 807 if (!bdrv_is_inserted(s->bs))
aa5dbdc1
GH
808 goto not_ready;
809 break;
51ad87c9
GH
810 case REQUEST_SENSE:
811 if (req->cmd.xfer < 4)
812 goto illegal_request;
813 memset(outbuf, 0, 4);
814 buflen = 4;
815 if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
816 memset(outbuf, 0, 18);
817 buflen = 18;
818 outbuf[7] = 10;
819 /* asc 0x3a, ascq 0: Medium not present */
820 outbuf[12] = 0x3a;
821 outbuf[13] = 0;
822 }
823 outbuf[0] = 0xf0;
824 outbuf[1] = 0;
825 outbuf[2] = req->dev->sense.key;
826 scsi_dev_clear_sense(req->dev);
827 break;
0b06c059
GH
828 case INQUIRY:
829 buflen = scsi_disk_emulate_inquiry(req, outbuf);
830 if (buflen < 0)
831 goto illegal_request;
832 break;
ebddfcbe
GH
833 case MODE_SENSE:
834 case MODE_SENSE_10:
835 buflen = scsi_disk_emulate_mode_sense(req, outbuf);
836 if (buflen < 0)
837 goto illegal_request;
838 break;
02880f43
GH
839 case READ_TOC:
840 buflen = scsi_disk_emulate_read_toc(req, outbuf);
841 if (buflen < 0)
842 goto illegal_request;
843 break;
3d53ba18
GH
844 case RESERVE:
845 if (req->cmd.buf[1] & 1)
846 goto illegal_request;
847 break;
848 case RESERVE_10:
849 if (req->cmd.buf[1] & 3)
850 goto illegal_request;
851 break;
852 case RELEASE:
853 if (req->cmd.buf[1] & 1)
854 goto illegal_request;
855 break;
856 case RELEASE_10:
857 if (req->cmd.buf[1] & 3)
858 goto illegal_request;
859 break;
8d3628ff 860 case START_STOP:
428c149b 861 if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
8d3628ff 862 /* load/eject medium */
428c149b 863 bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
8d3628ff
GH
864 }
865 break;
c68b9f34 866 case ALLOW_MEDIUM_REMOVAL:
428c149b 867 bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
c68b9f34 868 break;
e7e25e32
GH
869 case READ_CAPACITY:
870 /* The normal LEN field for this command is zero. */
871 memset(outbuf, 0, 8);
428c149b 872 bdrv_get_geometry(s->bs, &nb_sectors);
e7e25e32
GH
873 if (!nb_sectors)
874 goto not_ready;
875 nb_sectors /= s->cluster_size;
876 /* Returned value is the address of the last sector. */
877 nb_sectors--;
878 /* Remember the new size for read/write sanity checking. */
879 s->max_lba = nb_sectors;
880 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
881 if (nb_sectors > UINT32_MAX)
882 nb_sectors = UINT32_MAX;
883 outbuf[0] = (nb_sectors >> 24) & 0xff;
884 outbuf[1] = (nb_sectors >> 16) & 0xff;
885 outbuf[2] = (nb_sectors >> 8) & 0xff;
886 outbuf[3] = nb_sectors & 0xff;
887 outbuf[4] = 0;
888 outbuf[5] = 0;
889 outbuf[6] = s->cluster_size * 2;
890 outbuf[7] = 0;
891 buflen = 8;
892 break;
fc903943 893 case SYNCHRONIZE_CACHE:
78ced65e
KW
894 ret = bdrv_flush(s->bs);
895 if (ret < 0) {
896 if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
897 return -1;
898 }
899 }
fc903943 900 break;
38215553
GH
901 case GET_CONFIGURATION:
902 memset(outbuf, 0, 8);
903 /* ??? This should probably return much more information. For now
904 just return the basic header indicating the CD-ROM profile. */
905 outbuf[7] = 8; // CD-ROM
906 buflen = 8;
907 break;
5dd90e2a
GH
908 case SERVICE_ACTION_IN:
909 /* Service Action In subcommands. */
910 if ((req->cmd.buf[1] & 31) == 0x10) {
911 DPRINTF("SAI READ CAPACITY(16)\n");
912 memset(outbuf, 0, req->cmd.xfer);
428c149b 913 bdrv_get_geometry(s->bs, &nb_sectors);
5dd90e2a
GH
914 if (!nb_sectors)
915 goto not_ready;
916 nb_sectors /= s->cluster_size;
917 /* Returned value is the address of the last sector. */
918 nb_sectors--;
919 /* Remember the new size for read/write sanity checking. */
920 s->max_lba = nb_sectors;
921 outbuf[0] = (nb_sectors >> 56) & 0xff;
922 outbuf[1] = (nb_sectors >> 48) & 0xff;
923 outbuf[2] = (nb_sectors >> 40) & 0xff;
924 outbuf[3] = (nb_sectors >> 32) & 0xff;
925 outbuf[4] = (nb_sectors >> 24) & 0xff;
926 outbuf[5] = (nb_sectors >> 16) & 0xff;
927 outbuf[6] = (nb_sectors >> 8) & 0xff;
928 outbuf[7] = nb_sectors & 0xff;
929 outbuf[8] = 0;
930 outbuf[9] = 0;
931 outbuf[10] = s->cluster_size * 2;
932 outbuf[11] = 0;
ee3659e3
CH
933 outbuf[12] = 0;
934 outbuf[13] = get_physical_block_exp(&s->qdev.conf);
5dd90e2a
GH
935 /* Protection, exponent and lowest lba field left blank. */
936 buflen = req->cmd.xfer;
937 break;
938 }
939 DPRINTF("Unsupported Service Action In\n");
940 goto illegal_request;
39ec9a50
GH
941 case REPORT_LUNS:
942 if (req->cmd.xfer < 16)
943 goto illegal_request;
944 memset(outbuf, 0, 16);
945 outbuf[3] = 8;
946 buflen = 16;
947 break;
88f8a5ed
GH
948 case VERIFY:
949 break;
ebef0bbb
BK
950 case REZERO_UNIT:
951 DPRINTF("Rezero Unit\n");
952 if (!bdrv_is_inserted(s->bs)) {
953 goto not_ready;
954 }
955 break;
aa5dbdc1
GH
956 default:
957 goto illegal_request;
958 }
959 scsi_req_set_status(req, GOOD, NO_SENSE);
960 return buflen;
961
962not_ready:
8af7a3ab
KW
963 scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
964 return -1;
aa5dbdc1
GH
965
966illegal_request:
8af7a3ab
KW
967 scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
968 return -1;
aa5dbdc1
GH
969}
970
2e5d83bb
PB
971/* Execute a scsi command. Returns the length of the data expected by the
972 command. This will be Positive for data transfers from the device
973 (eg. disk reads), negative for transfers to the device (eg. disk writes),
974 and zero if the command does not transfer any data. */
975
8ccc2ace
TS
976static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
977 uint8_t *buf, int lun)
2e5d83bb 978{
d52affa7 979 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
86106e59 980 uint64_t lba;
2e5d83bb
PB
981 uint32_t len;
982 int cmdlen;
983 int is_write;
a917d384
PB
984 uint8_t command;
985 uint8_t *outbuf;
4c41d2ef 986 SCSIDiskReq *r;
aa5dbdc1 987 int rc;
a917d384
PB
988
989 command = buf[0];
990 r = scsi_find_request(s, tag);
991 if (r) {
992 BADF("Tag 0x%x already in use\n", tag);
8ccc2ace 993 scsi_cancel_io(d, tag);
a917d384
PB
994 }
995 /* ??? Tags are not unique for different luns. We only implement a
996 single lun, so this should not matter. */
72aef731 997 r = scsi_new_request(s, tag, lun);
3f4cb3d3 998 outbuf = (uint8_t *)r->iov.iov_base;
2e5d83bb 999 is_write = 0;
a917d384
PB
1000 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
1001 switch (command >> 5) {
2e5d83bb 1002 case 0:
86106e59
AL
1003 lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
1004 (((uint64_t) buf[1] & 0x1f) << 16);
2e5d83bb
PB
1005 len = buf[4];
1006 cmdlen = 6;
1007 break;
1008 case 1:
1009 case 2:
86106e59
AL
1010 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
1011 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
1012 len = buf[8] | (buf[7] << 8);
1013 cmdlen = 10;
1014 break;
1015 case 4:
86106e59
AL
1016 lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
1017 ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
1018 ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
1019 ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
2e5d83bb
PB
1020 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
1021 cmdlen = 16;
1022 break;
1023 case 5:
86106e59
AL
1024 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
1025 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
1026 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
1027 cmdlen = 12;
1028 break;
1029 default:
a917d384 1030 BADF("Unsupported command length, command %x\n", command);
2e5d83bb
PB
1031 goto fail;
1032 }
1033#ifdef DEBUG_SCSI
1034 {
1035 int i;
1036 for (i = 1; i < cmdlen; i++) {
1037 printf(" 0x%02x", buf[i]);
1038 }
1039 printf("\n");
1040 }
1041#endif
aa5dbdc1
GH
1042
1043 if (scsi_req_parse(&r->req, buf) != 0) {
1044 BADF("Unsupported command length, command %x\n", command);
1045 goto fail;
1046 }
1047 assert(r->req.cmd.len == cmdlen);
1048 assert(r->req.cmd.lba == lba);
1049
0fc5c15a 1050 if (lun || buf[1] >> 5) {
2e5d83bb 1051 /* Only LUN 0 supported. */
0fc5c15a 1052 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
ebf46023 1053 if (command != REQUEST_SENSE && command != INQUIRY)
22864256 1054 goto fail;
2e5d83bb 1055 }
a917d384 1056 switch (command) {
ebf46023 1057 case TEST_UNIT_READY:
51ad87c9 1058 case REQUEST_SENSE:
0b06c059 1059 case INQUIRY:
ebddfcbe
GH
1060 case MODE_SENSE:
1061 case MODE_SENSE_10:
3d53ba18
GH
1062 case RESERVE:
1063 case RESERVE_10:
1064 case RELEASE:
1065 case RELEASE_10:
8d3628ff 1066 case START_STOP:
c68b9f34 1067 case ALLOW_MEDIUM_REMOVAL:
e7e25e32 1068 case READ_CAPACITY:
fc903943 1069 case SYNCHRONIZE_CACHE:
02880f43 1070 case READ_TOC:
38215553 1071 case GET_CONFIGURATION:
5dd90e2a 1072 case SERVICE_ACTION_IN:
39ec9a50 1073 case REPORT_LUNS:
88f8a5ed 1074 case VERIFY:
ebef0bbb 1075 case REZERO_UNIT:
8af7a3ab
KW
1076 rc = scsi_disk_emulate_command(r, outbuf);
1077 if (rc < 0) {
0b06c059 1078 return 0;
aa5dbdc1 1079 }
8af7a3ab
KW
1080
1081 r->iov.iov_len = rc;
0b06c059 1082 break;
ebf46023
GH
1083 case READ_6:
1084 case READ_10:
bd536cf3
GH
1085 case READ_12:
1086 case READ_16:
0bf9e31a 1087 DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
274fb0e1
AL
1088 if (lba > s->max_lba)
1089 goto illegal_lba;
a917d384
PB
1090 r->sector = lba * s->cluster_size;
1091 r->sector_count = len * s->cluster_size;
2e5d83bb 1092 break;
ebf46023
GH
1093 case WRITE_6:
1094 case WRITE_10:
bd536cf3
GH
1095 case WRITE_12:
1096 case WRITE_16:
ebef0bbb
BK
1097 case WRITE_VERIFY:
1098 case WRITE_VERIFY_12:
1099 case WRITE_VERIFY_16:
1100 DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1101 (command & 0xe) == 0xe ? "And Verify " : "", lba, len);
274fb0e1
AL
1102 if (lba > s->max_lba)
1103 goto illegal_lba;
a917d384
PB
1104 r->sector = lba * s->cluster_size;
1105 r->sector_count = len * s->cluster_size;
2e5d83bb
PB
1106 is_write = 1;
1107 break;
ebef0bbb
BK
1108 case MODE_SELECT:
1109 DPRINTF("Mode Select(6) (len %d)\n", len);
1110 /* We don't support mode parameter changes.
1111 Allow the mode parameter header + block descriptors only. */
1112 if (len > 12) {
1113 goto fail;
1114 }
1115 break;
1116 case MODE_SELECT_10:
1117 DPRINTF("Mode Select(10) (len %d)\n", len);
1118 /* We don't support mode parameter changes.
1119 Allow the mode parameter header + block descriptors only. */
1120 if (len > 16) {
1121 goto fail;
1122 }
1123 break;
1124 case SEEK_6:
1125 case SEEK_10:
1126 DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba);
1127 if (lba > s->max_lba) {
1128 goto illegal_lba;
1129 }
1130 break;
2e5d83bb
PB
1131 default:
1132 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1133 fail:
0d65e1f8 1134 scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
2e5d83bb 1135 return 0;
274fb0e1 1136 illegal_lba:
0d65e1f8 1137 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
274fb0e1 1138 return 0;
2e5d83bb 1139 }
c87c0672 1140 if (r->sector_count == 0 && r->iov.iov_len == 0) {
0d65e1f8 1141 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 1142 }
c87c0672 1143 len = r->sector_count * 512 + r->iov.iov_len;
a917d384
PB
1144 if (is_write) {
1145 return -len;
1146 } else {
1147 if (!r->sector_count)
1148 r->sector_count = -1;
1149 return len;
2e5d83bb 1150 }
2e5d83bb
PB
1151}
1152
e9447f35 1153static void scsi_disk_purge_requests(SCSIDiskState *s)
56a14938 1154{
9af99d98 1155 SCSIDiskReq *r;
56a14938 1156
9af99d98
GH
1157 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
1158 r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
e9447f35
JK
1159 if (r->req.aiocb) {
1160 bdrv_aio_cancel(r->req.aiocb);
1161 }
9af99d98
GH
1162 scsi_remove_request(r);
1163 }
e9447f35
JK
1164}
1165
1166static void scsi_disk_reset(DeviceState *dev)
1167{
1168 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1169 uint64_t nb_sectors;
1170
1171 scsi_disk_purge_requests(s);
1172
1173 bdrv_get_geometry(s->bs, &nb_sectors);
1174 nb_sectors /= s->cluster_size;
1175 if (nb_sectors) {
1176 nb_sectors--;
1177 }
1178 s->max_lba = nb_sectors;
1179}
1180
1181static void scsi_destroy(SCSIDevice *dev)
1182{
1183 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1184
1185 scsi_disk_purge_requests(s);
f8b6cc00 1186 blockdev_mark_auto_del(s->qdev.conf.bs);
56a14938
GH
1187}
1188
d52affa7 1189static int scsi_disk_initfn(SCSIDevice *dev)
2e5d83bb 1190{
d52affa7 1191 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
7d0d6950 1192 int is_cd;
f8b6cc00 1193 DriveInfo *dinfo;
2e5d83bb 1194
f8b6cc00 1195 if (!s->qdev.conf.bs) {
1ecda02b 1196 error_report("scsi-disk: drive property not set");
d52affa7
GH
1197 return -1;
1198 }
f8b6cc00 1199 s->bs = s->qdev.conf.bs;
7d0d6950 1200 is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM;
d52affa7 1201
98f28ad7
MA
1202 if (!is_cd && !bdrv_is_inserted(s->bs)) {
1203 error_report("Device needs media, but drive is empty");
1204 return -1;
1205 }
1206
a0fef654 1207 if (!s->serial) {
f8b6cc00
MA
1208 /* try to fall back to value set with legacy -drive serial=... */
1209 dinfo = drive_get_by_blockdev(s->bs);
1210 s->serial = qemu_strdup(*dinfo->serial ? dinfo->serial : "0");
a0fef654
MA
1211 }
1212
552fee93
MA
1213 if (!s->version) {
1214 s->version = qemu_strdup(QEMU_VERSION);
1215 }
1216
32bb404a 1217 if (bdrv_is_sg(s->bs)) {
1ecda02b 1218 error_report("scsi-disk: unwanted /dev/sg*");
32bb404a
MA
1219 return -1;
1220 }
1221
7d0d6950 1222 if (is_cd) {
8cfacf07 1223 s->qdev.blocksize = 2048;
2e5d83bb 1224 } else {
8cfacf07 1225 s->qdev.blocksize = s->qdev.conf.logical_block_size;
2e5d83bb 1226 }
8cfacf07 1227 s->cluster_size = s->qdev.blocksize / 512;
73fdb1e1 1228 s->bs->buffer_alignment = s->qdev.blocksize;
8cfacf07 1229
91376656 1230 s->qdev.type = TYPE_DISK;
ea8a5d7f 1231 qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
7d0d6950 1232 bdrv_set_removable(s->bs, is_cd);
d52affa7
GH
1233 return 0;
1234}
1235
1236static SCSIDeviceInfo scsi_disk_info = {
1237 .qdev.name = "scsi-disk",
1238 .qdev.desc = "virtual scsi disk or cdrom",
1239 .qdev.size = sizeof(SCSIDiskState),
e9447f35 1240 .qdev.reset = scsi_disk_reset,
d52affa7 1241 .init = scsi_disk_initfn,
56a14938 1242 .destroy = scsi_destroy,
d52affa7
GH
1243 .send_command = scsi_send_command,
1244 .read_data = scsi_read_data,
1245 .write_data = scsi_write_data,
1246 .cancel_io = scsi_cancel_io,
1247 .get_buf = scsi_get_buf,
1248 .qdev.props = (Property[]) {
428c149b 1249 DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
383b4d9b 1250 DEFINE_PROP_STRING("ver", SCSIDiskState, version),
a0fef654 1251 DEFINE_PROP_STRING("serial", SCSIDiskState, serial),
d52affa7
GH
1252 DEFINE_PROP_END_OF_LIST(),
1253 },
1254};
1255
1256static void scsi_disk_register_devices(void)
1257{
1258 scsi_qdev_register(&scsi_disk_info);
8ccc2ace 1259}
d52affa7 1260device_init(scsi_disk_register_devices)