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