scsi-disk.c 50.0 KB
Newer Older
P
pbrook 已提交
1 2 3 4 5 6 7
/*
 * SCSI Device emulation
 *
 * Copyright (c) 2006 CodeSourcery.
 * Based on code by Fabrice Bellard
 *
 * Written by Paul Brook
8 9 10 11 12 13
 * Modifications:
 *  2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
 *                                 when the allocation length of CDB is smaller
 *                                 than 36.
 *  2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
 *                                 MODE SENSE response.
P
pbrook 已提交
14
 *
M
Matthew Fernandez 已提交
15
 * This code is licensed under the LGPL.
P
pbrook 已提交
16 17
 *
 * Note that this file only handles the SCSI architecture model and device
18 19
 * commands.  Emulation of interface/link layer protocols is handled by
 * the host adapter emulator.
P
pbrook 已提交
20 21 22 23 24
 */

//#define DEBUG_SCSI

#ifdef DEBUG_SCSI
25 26
#define DPRINTF(fmt, ...) \
do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
P
pbrook 已提交
27
#else
28
#define DPRINTF(fmt, ...) do {} while(0)
P
pbrook 已提交
29 30
#endif

31 32
#define BADF(fmt, ...) \
do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
P
pbrook 已提交
33

P
pbrook 已提交
34
#include "qemu-common.h"
35
#include "qemu-error.h"
G
Gerd Hoffmann 已提交
36
#include "scsi.h"
G
Gerd Hoffmann 已提交
37
#include "scsi-defs.h"
38
#include "sysemu.h"
B
Blue Swirl 已提交
39
#include "blockdev.h"
40
#include "block_int.h"
41

42
#define SCSI_DMA_BUF_SIZE    131072
43
#define SCSI_MAX_INQUIRY_LEN 256
P
pbrook 已提交
44

K
Kevin Wolf 已提交
45 46 47 48
#define SCSI_REQ_STATUS_RETRY           0x01
#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
#define SCSI_REQ_STATUS_RETRY_READ      0x00
#define SCSI_REQ_STATUS_RETRY_WRITE     0x02
49
#define SCSI_REQ_STATUS_RETRY_FLUSH     0x04
50

51 52
typedef struct SCSIDiskState SCSIDiskState;

53 54
typedef struct SCSIDiskReq {
    SCSIRequest req;
P
pbrook 已提交
55
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
56 57
    uint64_t sector;
    uint32_t sector_count;
58
    uint32_t buflen;
59 60
    struct iovec iov;
    QEMUIOVector qiov;
61
    uint32_t status;
62
    BlockAcctCookie acct;
63
} SCSIDiskReq;
P
pbrook 已提交
64

65
struct SCSIDiskState
P
pbrook 已提交
66
{
67
    SCSIDevice qdev;
68
    uint32_t removable;
69
    uint64_t max_lba;
70
    bool media_changed;
71
    bool media_event;
72
    QEMUBH *bh;
G
Gerd Hoffmann 已提交
73
    char *version;
74
    char *serial;
75
    bool tray_open;
76
    bool tray_locked;
P
pbrook 已提交
77 78
};

K
Kevin Wolf 已提交
79
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
P
Paolo Bonzini 已提交
80
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf);
K
Kevin Wolf 已提交
81

P
Paolo Bonzini 已提交
82
static void scsi_free_request(SCSIRequest *req)
P
pbrook 已提交
83
{
P
Paolo Bonzini 已提交
84 85
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

86 87 88
    if (r->iov.iov_base) {
        qemu_vfree(r->iov.iov_base);
    }
P
pbrook 已提交
89 90
}

91 92
/* Helper function for command completion with sense.  */
static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
G
Gerd Hoffmann 已提交
93
{
B
Blue Swirl 已提交
94 95
    DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
            r->req.tag, sense.key, sense.asc, sense.ascq);
96 97
    scsi_req_build_sense(&r->req, sense);
    scsi_req_complete(&r->req, CHECK_CONDITION);
P
pbrook 已提交
98 99 100
}

/* Cancel a pending data transfer.  */
101
static void scsi_cancel_io(SCSIRequest *req)
P
pbrook 已提交
102
{
103 104 105 106 107
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

    DPRINTF("Cancel tag=0x%x\n", req->tag);
    if (r->req.aiocb) {
        bdrv_aio_cancel(r->req.aiocb);
P
pbrook 已提交
108
    }
109
    r->req.aiocb = NULL;
P
pbrook 已提交
110 111
}

112 113
static uint32_t scsi_init_iovec(SCSIDiskReq *r)
{
114 115 116 117
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    if (!r->iov.iov_base) {
        r->buflen = SCSI_DMA_BUF_SIZE;
118
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
119 120
    }
    r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
121 122 123 124
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
    return r->qiov.size / 512;
}

P
pbrook 已提交
125 126
static void scsi_read_complete(void * opaque, int ret)
{
127
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
128
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
K
Kevin Wolf 已提交
129
    int n;
P
pbrook 已提交
130

P
Paolo Bonzini 已提交
131 132
    if (r->req.aiocb != NULL) {
        r->req.aiocb = NULL;
133
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
P
Paolo Bonzini 已提交
134
    }
135

P
pbrook 已提交
136
    if (ret) {
K
Kevin Wolf 已提交
137 138 139
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
            return;
        }
P
pbrook 已提交
140
    }
K
Kevin Wolf 已提交
141

142
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
P
pbrook 已提交
143

144
    n = r->qiov.size / 512;
K
Kevin Wolf 已提交
145 146
    r->sector += n;
    r->sector_count -= n;
147
    scsi_req_data(&r->req, r->qiov.size);
P
pbrook 已提交
148 149
}

150 151 152 153 154 155 156
static void scsi_flush_complete(void * opaque, int ret)
{
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    if (r->req.aiocb != NULL) {
        r->req.aiocb = NULL;
157
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
158 159 160 161 162 163 164 165 166 167
    }

    if (ret < 0) {
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
            return;
        }
    }

    scsi_req_complete(&r->req, GOOD);
}
K
Kevin Wolf 已提交
168

169 170
/* Read more data from scsi device into buffer.  */
static void scsi_read_data(SCSIRequest *req)
P
pbrook 已提交
171
{
172
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
K
Kevin Wolf 已提交
173
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
P
pbrook 已提交
174 175
    uint32_t n;

P
pbrook 已提交
176
    if (r->sector_count == (uint32_t)-1) {
177
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
P
pbrook 已提交
178
        r->sector_count = 0;
P
Paolo Bonzini 已提交
179
        scsi_req_data(&r->req, r->iov.iov_len);
P
pbrook 已提交
180
        return;
P
pbrook 已提交
181
    }
P
pbrook 已提交
182 183
    DPRINTF("Read sector_count=%d\n", r->sector_count);
    if (r->sector_count == 0) {
184 185
        /* This also clears the sense buffer for REQUEST SENSE.  */
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
186
        return;
P
pbrook 已提交
187 188
    }

189 190 191
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

192 193 194 195 196 197
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_read_complete(r, -EINVAL);
        return;
    }

198 199 200
    if (s->tray_open) {
        scsi_read_complete(r, -ENOMEDIUM);
    }
201
    n = scsi_init_iovec(r);
202 203
    bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
    r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
204
                              scsi_read_complete, r);
205 206 207
    if (r->req.aiocb == NULL) {
        scsi_read_complete(r, -EIO);
    }
P
pbrook 已提交
208 209
}

K
Kevin Wolf 已提交
210 211 212
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
{
    int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
213
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
214
    BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
215

216
    if (action == BLOCK_ERR_IGNORE) {
217
        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read);
218
        return 0;
219
    }
220 221 222

    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
            || action == BLOCK_ERR_STOP_ANY) {
K
Kevin Wolf 已提交
223 224 225 226

        type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
        r->status |= SCSI_REQ_STATUS_RETRY | type;

227
        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
228
        vm_stop(RUN_STATE_IO_ERROR);
229
        bdrv_iostatus_set_err(s->qdev.conf.bs, error);
230
    } else {
231
        switch (error) {
232 233 234
        case ENOMEDIUM:
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
            break;
235
        case ENOMEM:
236
            scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
237 238
            break;
        case EINVAL:
239
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
240 241
            break;
        default:
242
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
243
            break;
244
        }
245
        bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read);
246 247 248 249
    }
    return 1;
}

P
pbrook 已提交
250 251
static void scsi_write_complete(void * opaque, int ret)
{
252
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
253
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
254 255
    uint32_t n;

P
Paolo Bonzini 已提交
256 257
    if (r->req.aiocb != NULL) {
        r->req.aiocb = NULL;
258
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
P
Paolo Bonzini 已提交
259
    }
260

P
pbrook 已提交
261
    if (ret) {
K
Kevin Wolf 已提交
262
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
263
            return;
K
Kevin Wolf 已提交
264
        }
P
pbrook 已提交
265 266
    }

267
    n = r->qiov.size / 512;
268 269
    r->sector += n;
    r->sector_count -= n;
P
pbrook 已提交
270
    if (r->sector_count == 0) {
271
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
272
    } else {
273 274 275
        scsi_init_iovec(r);
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
        scsi_req_data(&r->req, r->qiov.size);
P
pbrook 已提交
276 277 278
    }
}

279
static void scsi_write_data(SCSIRequest *req)
280
{
281
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
282
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
283 284
    uint32_t n;

285 286 287
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

288 289 290
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_write_complete(r, -EINVAL);
291
        return;
292 293
    }

294
    n = r->qiov.size / 512;
295
    if (n) {
296 297 298
        if (s->tray_open) {
            scsi_write_complete(r, -ENOMEDIUM);
        }
299 300
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
301
                                       scsi_write_complete, r);
302
        if (r->req.aiocb == NULL) {
303
            scsi_write_complete(r, -ENOMEM);
304
        }
305
    } else {
306
        /* Called for the first time.  Ask the driver to send us more data.  */
307 308
        scsi_write_complete(r, 0);
    }
P
pbrook 已提交
309
}
P
pbrook 已提交
310

311
static void scsi_dma_restart_bh(void *opaque)
312
{
313
    SCSIDiskState *s = opaque;
314 315
    SCSIRequest *req;
    SCSIDiskReq *r;
316 317 318

    qemu_bh_delete(s->bh);
    s->bh = NULL;
319

320 321
    QTAILQ_FOREACH(req, &s->qdev.requests, next) {
        r = DO_UPCAST(SCSIDiskReq, req, req);
322
        if (r->status & SCSI_REQ_STATUS_RETRY) {
K
Kevin Wolf 已提交
323
            int status = r->status;
324

K
Kevin Wolf 已提交
325 326 327 328 329
            r->status &=
                ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);

            switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
            case SCSI_REQ_STATUS_RETRY_READ:
330
                scsi_read_data(&r->req);
K
Kevin Wolf 已提交
331 332
                break;
            case SCSI_REQ_STATUS_RETRY_WRITE:
333
                scsi_write_data(&r->req);
K
Kevin Wolf 已提交
334
                break;
335
            case SCSI_REQ_STATUS_RETRY_FLUSH:
P
Paolo Bonzini 已提交
336 337
                scsi_send_command(&r->req, r->req.cmd.buf);
                break;
K
Kevin Wolf 已提交
338
            }
339 340 341 342
        }
    }
}

343
static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
344
{
345
    SCSIDiskState *s = opaque;
346

347
    if (!running) {
348
        return;
349
    }
350 351 352 353 354 355
    if (!s->bh) {
        s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
        qemu_bh_schedule(s->bh);
    }
}

P
pbrook 已提交
356
/* Return a pointer to the data buffer.  */
357
static uint8_t *scsi_get_buf(SCSIRequest *req)
P
pbrook 已提交
358
{
359
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
P
pbrook 已提交
360

361
    return (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
362 363
}

364 365
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
G
Gerd Hoffmann 已提交
366
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
    int buflen = 0;

    if (req->cmd.buf[1] & 0x2) {
        /* Command support data - optional, not implemented */
        BADF("optional INQUIRY command support request not implemented\n");
        return -1;
    }

    if (req->cmd.buf[1] & 0x1) {
        /* Vital product data */
        uint8_t page_code = req->cmd.buf[2];
        if (req->cmd.xfer < 4) {
            BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
                 "less than 4\n", page_code, req->cmd.xfer);
            return -1;
        }

H
Hannes Reinecke 已提交
384
        if (s->qdev.type == TYPE_ROM) {
385 386 387 388 389 390 391 392 393
            outbuf[buflen++] = 5;
        } else {
            outbuf[buflen++] = 0;
        }
        outbuf[buflen++] = page_code ; // this page
        outbuf[buflen++] = 0x00;

        switch (page_code) {
        case 0x00: /* Supported page codes, mandatory */
H
Hannes Reinecke 已提交
394 395
        {
            int pages;
396 397
            DPRINTF("Inquiry EVPD[Supported pages] "
                    "buffer size %zd\n", req->cmd.xfer);
H
Hannes Reinecke 已提交
398
            pages = buflen++;
399
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
400
            if (s->serial) {
401
                outbuf[buflen++] = 0x80; // unit serial number
402
            }
403
            outbuf[buflen++] = 0x83; // device identification
H
Hannes Reinecke 已提交
404
            if (s->qdev.type == TYPE_DISK) {
405 406
                outbuf[buflen++] = 0xb0; // block limits
                outbuf[buflen++] = 0xb2; // thin provisioning
H
Hannes Reinecke 已提交
407 408
            }
            outbuf[pages] = buflen - pages - 1; // number of pages
409
            break;
H
Hannes Reinecke 已提交
410
        }
411 412
        case 0x80: /* Device serial number, optional */
        {
413
            int l;
414

415 416 417 418 419 420
            if (!s->serial) {
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
                return -1;
            }

            l = strlen(s->serial);
421
            if (l > req->cmd.xfer) {
422
                l = req->cmd.xfer;
423 424
            }
            if (l > 20) {
425
                l = 20;
426
            }
427 428 429 430

            DPRINTF("Inquiry EVPD[Serial number] "
                    "buffer size %zd\n", req->cmd.xfer);
            outbuf[buflen++] = l;
431
            memcpy(outbuf+buflen, s->serial, l);
432 433 434 435 436 437 438
            buflen += l;
            break;
        }

        case 0x83: /* Device identification page, mandatory */
        {
            int max_len = 255 - 8;
439
            int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
440

441
            if (id_len > max_len) {
442
                id_len = max_len;
443
            }
444 445 446
            DPRINTF("Inquiry EVPD[Device identification] "
                    "buffer size %zd\n", req->cmd.xfer);

H
Hannes Reinecke 已提交
447
            outbuf[buflen++] = 4 + id_len;
448 449 450 451 452
            outbuf[buflen++] = 0x2; // ASCII
            outbuf[buflen++] = 0;   // not officially assigned
            outbuf[buflen++] = 0;   // reserved
            outbuf[buflen++] = id_len; // length of data following

453
            memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
454 455 456
            buflen += id_len;
            break;
        }
457
        case 0xb0: /* block limits */
C
Christoph Hellwig 已提交
458
        {
459 460
            unsigned int unmap_sectors =
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
461 462 463 464
            unsigned int min_io_size =
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
            unsigned int opt_io_size =
                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
C
Christoph Hellwig 已提交
465

H
Hannes Reinecke 已提交
466
            if (s->qdev.type == TYPE_ROM) {
H
Hannes Reinecke 已提交
467 468 469 470
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
                        page_code);
                return -1;
            }
C
Christoph Hellwig 已提交
471 472 473 474 475 476 477 478 479 480 481 482 483 484
            /* required VPD size with unmap support */
            outbuf[3] = buflen = 0x3c;

            memset(outbuf + 4, 0, buflen - 4);

            /* optimal transfer length granularity */
            outbuf[6] = (min_io_size >> 8) & 0xff;
            outbuf[7] = min_io_size & 0xff;

            /* optimal transfer length */
            outbuf[12] = (opt_io_size >> 24) & 0xff;
            outbuf[13] = (opt_io_size >> 16) & 0xff;
            outbuf[14] = (opt_io_size >> 8) & 0xff;
            outbuf[15] = opt_io_size & 0xff;
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499

            /* optimal unmap granularity */
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
            outbuf[31] = unmap_sectors & 0xff;
            break;
        }
        case 0xb2: /* thin provisioning */
        {
            outbuf[3] = buflen = 8;
            outbuf[4] = 0;
            outbuf[5] = 0x40; /* write same with unmap supported */
            outbuf[6] = 0;
            outbuf[7] = 0;
C
Christoph Hellwig 已提交
500 501
            break;
        }
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
        default:
            BADF("Error: unsupported Inquiry (EVPD[%02X]) "
                 "buffer size %zd\n", page_code, req->cmd.xfer);
            return -1;
        }
        /* done with EVPD */
        return buflen;
    }

    /* Standard INQUIRY data */
    if (req->cmd.buf[2] != 0) {
        BADF("Error: Inquiry (STANDARD) page or code "
             "is non-zero [%02X]\n", req->cmd.buf[2]);
        return -1;
    }

    /* PAGE CODE == 0 */
    if (req->cmd.xfer < 5) {
        BADF("Error: Inquiry (STANDARD) buffer size %zd "
             "is less than 5\n", req->cmd.xfer);
        return -1;
    }

    buflen = req->cmd.xfer;
526
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
527
        buflen = SCSI_MAX_INQUIRY_LEN;
528
    }
529 530
    memset(outbuf, 0, buflen);

H
Hannes Reinecke 已提交
531 532
    outbuf[0] = s->qdev.type & 0x1f;
    if (s->qdev.type == TYPE_ROM) {
533
        outbuf[1] = 0x80;
L
Laszlo Ast 已提交
534
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
535
    } else {
536
        outbuf[1] = s->removable ? 0x80 : 0;
L
Laszlo Ast 已提交
537
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
538
    }
L
Laszlo Ast 已提交
539
    memcpy(&outbuf[8], "QEMU    ", 8);
G
Gerd Hoffmann 已提交
540
    memset(&outbuf[32], 0, 4);
541
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
542 543 544 545 546 547
    /*
     * We claim conformance to SPC-3, which is required for guests
     * to ask for modern features like READ CAPACITY(16) or the
     * block characteristics VPD page by default.  Not all of SPC-3
     * is actually implemented, but we're good enough.
     */
C
Christoph Hellwig 已提交
548
    outbuf[2] = 5;
549
    outbuf[3] = 2; /* Format 2 */
550 551 552 553 554 555 556 557 558

    if (buflen > 36) {
        outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
    } else {
        /* If the allocation length of CDB is too small,
               the additional length is not adjusted */
        outbuf[4] = 36 - 5;
    }

559
    /* Sync data transfer and TCQ.  */
560
    outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
561 562 563
    return buflen;
}

564 565 566 567 568 569
static inline bool media_is_dvd(SCSIDiskState *s)
{
    uint64_t nb_sectors;
    if (s->qdev.type != TYPE_ROM) {
        return false;
    }
570
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
571 572
        return false;
    }
573
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
574 575 576
    return nb_sectors > CD_MAX_SECTORS;
}

577 578 579 580 581 582
static inline bool media_is_cd(SCSIDiskState *s)
{
    uint64_t nb_sectors;
    if (s->qdev.type != TYPE_ROM) {
        return false;
    }
583
    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
584 585
        return false;
    }
586
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
587 588 589
    return nb_sectors <= CD_MAX_SECTORS;
}

590 591 592
static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                   uint8_t *outbuf)
{
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
    static const int rds_caps_size[5] = {
        [0] = 2048 + 4,
        [1] = 4 + 4,
        [3] = 188 + 4,
        [4] = 2048 + 4,
    };

    uint8_t media = r->req.cmd.buf[1];
    uint8_t layer = r->req.cmd.buf[6];
    uint8_t format = r->req.cmd.buf[7];
    int size = -1;

    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }
    if (media != 0) {
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
        return -1;
    }

    if (format != 0xff) {
614
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
            return -1;
        }
        if (media_is_cd(s)) {
            scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT));
            return -1;
        }
        if (format >= ARRAY_SIZE(rds_caps_size)) {
            return -1;
        }
        size = rds_caps_size[format];
        memset(outbuf, 0, size);
    }

    switch (format) {
    case 0x00: {
        /* Physical format information */
        uint64_t nb_sectors;
        if (layer != 0) {
            goto fail;
        }
636
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680

        outbuf[4] = 1;   /* DVD-ROM, part version 1 */
        outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
        outbuf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
        outbuf[7] = 0;   /* default densities */

        stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */
        stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */
        break;
    }

    case 0x01: /* DVD copyright information, all zeros */
        break;

    case 0x03: /* BCA information - invalid field for no BCA info */
        return -1;

    case 0x04: /* DVD disc manufacturing information, all zeros */
        break;

    case 0xff: { /* List capabilities */
        int i;
        size = 4;
        for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) {
            if (!rds_caps_size[i]) {
                continue;
            }
            outbuf[size] = i;
            outbuf[size + 1] = 0x40; /* Not writable, readable */
            stw_be_p(&outbuf[size + 2], rds_caps_size[i]);
            size += 4;
        }
        break;
     }

    default:
        return -1;
    }

    /* Size of buffer, not including 2 byte size field */
    stw_be_p(outbuf, size - 2);
    return size;

fail:
681 682 683
    return -1;
}

684
static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
685
{
686 687 688 689 690
    uint8_t event_code, media_status;

    media_status = 0;
    if (s->tray_open) {
        media_status = MS_TRAY_OPEN;
691
    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
        media_status = MS_MEDIA_PRESENT;
    }

    /* Event notification descriptor */
    event_code = MEC_NO_CHANGE;
    if (media_status != MS_TRAY_OPEN && s->media_event) {
        event_code = MEC_NEW_MEDIA;
        s->media_event = false;
    }

    outbuf[0] = event_code;
    outbuf[1] = media_status;

    /* These fields are reserved, just clear them. */
    outbuf[2] = 0;
    outbuf[3] = 0;
    return 4;
}

static int scsi_get_event_status_notification(SCSIDiskState *s, SCSIDiskReq *r,
                                              uint8_t *outbuf)
{
    int size;
    uint8_t *buf = r->req.cmd.buf;
    uint8_t notification_class_request = buf[4];
    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }
    if ((buf[1] & 1) == 0) {
        /* asynchronous */
        return -1;
    }

    size = 4;
    outbuf[0] = outbuf[1] = 0;
    outbuf[3] = 1 << GESN_MEDIA; /* supported events */
    if (notification_class_request & (1 << GESN_MEDIA)) {
        outbuf[2] = GESN_MEDIA;
        size += scsi_event_status_media(s, &outbuf[size]);
    } else {
        outbuf[2] = 0x80;
    }
    stw_be_p(outbuf, size - 4);
    return size;
736 737
}

738
static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
739
{
740 741
    int current;

742 743 744
    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
    memset(outbuf, 0, 40);
    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
    stw_be_p(&outbuf[6], current);
    /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
    outbuf[10] = 0x03; /* persistent, current */
    outbuf[11] = 8; /* two profiles */
    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
    stw_be_p(&outbuf[20], 1);
    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
    outbuf[23] = 8;
    stl_be_p(&outbuf[24], 1); /* SCSI */
    outbuf[28] = 1; /* DBE = 1, mandatory */
    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
    stw_be_p(&outbuf[32], 3);
    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
    outbuf[35] = 4;
    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
    /* TODO: Random readable, CD read, DVD read, drive serial number,
       power management */
    return 40;
770 771 772 773 774 775 776 777 778 779 780 781
}

static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
{
    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }
    memset(outbuf, 0, 8);
    outbuf[5] = 1; /* CD-ROM */
    return 8;
}

782
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
783
                           int page_control)
784
{
785 786 787 788
    static const int mode_sense_valid[0x3f] = {
        [MODE_PAGE_HD_GEOMETRY]            = (1 << TYPE_DISK),
        [MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
        [MODE_PAGE_CACHING]                = (1 << TYPE_DISK) | (1 << TYPE_ROM),
789 790
        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
791 792 793
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
    };

794
    BlockDriverState *bdrv = s->qdev.conf.bs;
795
    int cylinders, heads, secs;
796
    uint8_t *p = *p_outbuf;
797

798 799 800 801 802 803
    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
        return -1;
    }

    p[0] = page;

804 805 806 807 808 809
    /*
     * If Changeable Values are requested, a mask denoting those mode parameters
     * that are changeable shall be returned. As we currently don't support
     * parameter changes via MODE_SELECT all bits are returned set to zero.
     * The buffer was already menset to zero by the caller of this function.
     */
810
    switch (page) {
811
    case MODE_PAGE_HD_GEOMETRY:
812
        p[1] = 0x16;
813
        if (page_control == 1) { /* Changeable Values */
814
            break;
815
        }
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
        /* if a geometry hint is available, use it */
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
        p[2] = (cylinders >> 16) & 0xff;
        p[3] = (cylinders >> 8) & 0xff;
        p[4] = cylinders & 0xff;
        p[5] = heads & 0xff;
        /* Write precomp start cylinder, disabled */
        p[6] = (cylinders >> 16) & 0xff;
        p[7] = (cylinders >> 8) & 0xff;
        p[8] = cylinders & 0xff;
        /* Reduced current start cylinder, disabled */
        p[9] = (cylinders >> 16) & 0xff;
        p[10] = (cylinders >> 8) & 0xff;
        p[11] = cylinders & 0xff;
        /* Device step rate [ns], 200ns */
        p[12] = 0;
        p[13] = 200;
        /* Landing zone cylinder */
        p[14] = 0xff;
        p[15] =  0xff;
        p[16] = 0xff;
        /* Medium rotation rate [rpm], 5400 rpm */
        p[20] = (5400 >> 8) & 0xff;
        p[21] = 5400 & 0xff;
840
        break;
841

842
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
843
        p[1] = 0x1e;
844
        if (page_control == 1) { /* Changeable Values */
845
            break;
846
        }
847 848 849 850 851 852 853
        /* Transfer rate [kbit/s], 5Mbit/s */
        p[2] = 5000 >> 8;
        p[3] = 5000 & 0xff;
        /* if a geometry hint is available, use it */
        bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
        p[4] = heads & 0xff;
        p[5] = secs & 0xff;
P
Paolo Bonzini 已提交
854
        p[6] = s->qdev.blocksize >> 8;
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
        p[8] = (cylinders >> 8) & 0xff;
        p[9] = cylinders & 0xff;
        /* Write precomp start cylinder, disabled */
        p[10] = (cylinders >> 8) & 0xff;
        p[11] = cylinders & 0xff;
        /* Reduced current start cylinder, disabled */
        p[12] = (cylinders >> 8) & 0xff;
        p[13] = cylinders & 0xff;
        /* Device step rate [100us], 100us */
        p[14] = 0;
        p[15] = 1;
        /* Device step pulse width [us], 1us */
        p[16] = 1;
        /* Device head settle delay [100us], 100us */
        p[17] = 0;
        p[18] = 1;
        /* Motor on delay [0.1s], 0.1s */
        p[19] = 1;
        /* Motor off delay [0.1s], 0.1s */
        p[20] = 1;
        /* Medium rotation rate [rpm], 5400 rpm */
        p[28] = (5400 >> 8) & 0xff;
        p[29] = 5400 & 0xff;
878
        break;
879

880
    case MODE_PAGE_CACHING:
881 882
        p[0] = 8;
        p[1] = 0x12;
883
        if (page_control == 1) { /* Changeable Values */
884
            break;
885
        }
886
        if (bdrv_enable_write_cache(s->qdev.conf.bs)) {
887 888
            p[2] = 4; /* WCE */
        }
889
        break;
890

891 892 893 894 895 896 897 898 899 900 901 902
    case MODE_PAGE_R_W_ERROR:
        p[1] = 10;
        p[2] = 0x80; /* Automatic Write Reallocation Enabled */
        if (s->qdev.type == TYPE_ROM) {
            p[3] = 0x20; /* Read Retry Count */
        }
        break;

    case MODE_PAGE_AUDIO_CTL:
        p[1] = 14;
        break;

903
    case MODE_PAGE_CAPABILITIES:
904
        p[1] = 0x14;
905
        if (page_control == 1) { /* Changeable Values */
906
            break;
907
        }
908 909 910

        p[2] = 0x3b; /* CD-R & CD-RW read */
        p[3] = 0; /* Writing not supported */
911 912 913 914 915
        p[4] = 0x7f; /* Audio, composite, digital out,
                        mode 2 form 1&2, multi session */
        p[5] = 0xff; /* CD DA, DA accurate, RW supported,
                        RW corrected, C2 errors, ISRC,
                        UPC, Bar code */
916
        p[6] = 0x2d | (s->tray_locked ? 2 : 0);
917 918 919
        /* Locking supported, jumper present, eject, tray */
        p[7] = 0; /* no volume & mute control, no
                     changer */
920
        p[8] = (50 * 176) >> 8; /* 50x read speed */
921
        p[9] = (50 * 176) & 0xff;
922 923 924
        p[10] = 2 >> 8; /* Two volume levels */
        p[11] = 2 & 0xff;
        p[12] = 2048 >> 8; /* 2M buffer */
925
        p[13] = 2048 & 0xff;
926
        p[14] = (16 * 176) >> 8; /* 16x read speed current */
927
        p[15] = (16 * 176) & 0xff;
928
        p[18] = (16 * 176) >> 8; /* 16x write speed */
929
        p[19] = (16 * 176) & 0xff;
930
        p[20] = (16 * 176) >> 8; /* 16x write speed current */
931
        p[21] = (16 * 176) & 0xff;
932
        break;
933 934

    default:
935
        return -1;
936
    }
937 938 939

    *p_outbuf += p[1] + 2;
    return p[1] + 2;
940 941
}

942
static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
943
{
944
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
945
    uint64_t nb_sectors;
946
    int page, dbd, buflen, ret, page_control;
947
    uint8_t *p;
948
    uint8_t dev_specific_param;
949

950 951 952
    dbd = r->req.cmd.buf[1]  & 0x8;
    page = r->req.cmd.buf[2] & 0x3f;
    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
953
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
954 955
        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
    memset(outbuf, 0, r->req.cmd.xfer);
956 957
    p = outbuf;

958
    if (bdrv_is_read_only(s->qdev.conf.bs)) {
959 960 961 962 963
        dev_specific_param = 0x80; /* Readonly.  */
    } else {
        dev_specific_param = 0x00;
    }

964
    if (r->req.cmd.buf[0] == MODE_SENSE) {
965 966 967 968 969 970 971 972 973
        p[1] = 0; /* Default media type.  */
        p[2] = dev_specific_param;
        p[3] = 0; /* Block descriptor length.  */
        p += 4;
    } else { /* MODE_SENSE_10 */
        p[2] = 0; /* Default media type.  */
        p[3] = dev_specific_param;
        p[6] = p[7] = 0; /* Block descriptor length.  */
        p += 8;
974 975
    }

976
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
977
    if (!dbd && nb_sectors) {
978
        if (r->req.cmd.buf[0] == MODE_SENSE) {
979 980 981 982
            outbuf[3] = 8; /* Block descriptor length  */
        } else { /* MODE_SENSE_10 */
            outbuf[7] = 8; /* Block descriptor length  */
        }
P
Paolo Bonzini 已提交
983
        nb_sectors /= (s->qdev.blocksize / 512);
984
        if (nb_sectors > 0xffffff) {
985
            nb_sectors = 0;
986
        }
987 988 989 990 991 992
        p[0] = 0; /* media density code */
        p[1] = (nb_sectors >> 16) & 0xff;
        p[2] = (nb_sectors >> 8) & 0xff;
        p[3] = nb_sectors & 0xff;
        p[4] = 0; /* reserved */
        p[5] = 0; /* bytes 5-7 are the sector size in bytes */
P
Paolo Bonzini 已提交
993
        p[6] = s->qdev.blocksize >> 8;
994 995 996 997
        p[7] = 0;
        p += 8;
    }

998 999 1000 1001
    if (page_control == 3) {
        /* Saved Values */
        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));
        return -1;
1002 1003
    }

1004 1005 1006 1007 1008 1009 1010 1011 1012
    if (page == 0x3f) {
        for (page = 0; page <= 0x3e; page++) {
            mode_sense_page(s, page, &p, page_control);
        }
    } else {
        ret = mode_sense_page(s, page, &p, page_control);
        if (ret == -1) {
            return -1;
        }
1013 1014 1015
    }

    buflen = p - outbuf;
1016 1017 1018 1019 1020
    /*
     * The mode data length field specifies the length in bytes of the
     * following data that is available to be transferred. The mode data
     * length does not include itself.
     */
1021
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1022 1023 1024 1025 1026
        outbuf[0] = buflen - 1;
    } else { /* MODE_SENSE_10 */
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
        outbuf[1] = (buflen - 2) & 0xff;
    }
1027
    if (buflen > r->req.cmd.xfer) {
1028
        buflen = r->req.cmd.xfer;
1029
    }
1030 1031 1032
    return buflen;
}

1033 1034 1035 1036 1037 1038 1039 1040 1041
static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    int start_track, format, msf, toclen;
    uint64_t nb_sectors;

    msf = req->cmd.buf[1] & 2;
    format = req->cmd.buf[2] & 0xf;
    start_track = req->cmd.buf[6];
1042
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1043
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
P
Paolo Bonzini 已提交
1044
    nb_sectors /= s->qdev.blocksize / 512;
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    switch (format) {
    case 0:
        toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
        break;
    case 1:
        /* multi session : only a single session defined */
        toclen = 12;
        memset(outbuf, 0, 12);
        outbuf[1] = 0x0a;
        outbuf[2] = 0x01;
        outbuf[3] = 0x01;
        break;
    case 2:
        toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
        break;
    default:
        return -1;
    }
1063
    if (toclen > req->cmd.xfer) {
1064
        toclen = req->cmd.xfer;
1065
    }
1066 1067 1068
    return toclen;
}

1069
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
1070 1071 1072 1073 1074 1075 1076
{
    SCSIRequest *req = &r->req;
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    bool start = req->cmd.buf[4] & 1;
    bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */

    if (s->qdev.type == TYPE_ROM && loej) {
1077 1078
        if (!start && !s->tray_open && s->tray_locked) {
            scsi_check_condition(r,
1079
                                 bdrv_is_inserted(s->qdev.conf.bs)
1080 1081 1082
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
            return -1;
1083
        }
1084
        bdrv_eject(s->qdev.conf.bs, !start);
1085
        s->tray_open = !start;
1086
    }
1087
    return 0;
1088 1089
}

1090
static int scsi_disk_emulate_command(SCSIDiskReq *r)
1091
{
1092
    SCSIRequest *req = &r->req;
1093 1094
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    uint64_t nb_sectors;
1095
    uint8_t *outbuf;
1096 1097
    int buflen = 0;

1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    if (!r->iov.iov_base) {
        /*
         * FIXME: we shouldn't return anything bigger than 4k, but the code
         * requires the buffer to be as big as req->cmd.xfer in several
         * places.  So, do not allow CDBs with a very large ALLOCATION
         * LENGTH.  The real fix would be to modify scsi_read_data and
         * dma_buf_read, so that they return data beyond the buflen
         * as all zeros.
         */
        if (req->cmd.xfer > 65536) {
            goto illegal_request;
        }
        r->buflen = MAX(4096, req->cmd.xfer);
1111
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
1112 1113 1114
    }

    outbuf = r->iov.iov_base;
1115 1116
    switch (req->cmd.buf[0]) {
    case TEST_UNIT_READY:
1117
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1118
            goto not_ready;
1119
        }
H
Hannes Reinecke 已提交
1120
        break;
1121 1122
    case INQUIRY:
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
1123
        if (buflen < 0) {
1124
            goto illegal_request;
1125
        }
H
Hannes Reinecke 已提交
1126
        break;
1127 1128
    case MODE_SENSE:
    case MODE_SENSE_10:
1129
        buflen = scsi_disk_emulate_mode_sense(r, outbuf);
1130
        if (buflen < 0) {
1131
            goto illegal_request;
1132
        }
1133
        break;
1134 1135
    case READ_TOC:
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
1136
        if (buflen < 0) {
1137
            goto illegal_request;
1138
        }
1139
        break;
1140
    case RESERVE:
1141
        if (req->cmd.buf[1] & 1) {
1142
            goto illegal_request;
1143
        }
1144 1145
        break;
    case RESERVE_10:
1146
        if (req->cmd.buf[1] & 3) {
1147
            goto illegal_request;
1148
        }
1149 1150
        break;
    case RELEASE:
1151
        if (req->cmd.buf[1] & 1) {
1152
            goto illegal_request;
1153
        }
1154 1155
        break;
    case RELEASE_10:
1156
        if (req->cmd.buf[1] & 3) {
1157
            goto illegal_request;
1158
        }
1159
        break;
1160
    case START_STOP:
1161 1162 1163
        if (scsi_disk_emulate_start_stop(r) < 0) {
            return -1;
        }
H
Hannes Reinecke 已提交
1164
        break;
1165
    case ALLOW_MEDIUM_REMOVAL:
1166
        s->tray_locked = req->cmd.buf[4] & 1;
1167
        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
H
Hannes Reinecke 已提交
1168
        break;
1169
    case READ_CAPACITY_10:
1170
        /* The normal LEN field for this command is zero.  */
H
Hannes Reinecke 已提交
1171
        memset(outbuf, 0, 8);
1172
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1173
        if (!nb_sectors) {
1174
            goto not_ready;
1175
        }
1176 1177 1178
        if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
            goto illegal_request;
        }
P
Paolo Bonzini 已提交
1179
        nb_sectors /= s->qdev.blocksize / 512;
1180 1181 1182 1183 1184
        /* Returned value is the address of the last sector.  */
        nb_sectors--;
        /* Remember the new size for read/write sanity checking. */
        s->max_lba = nb_sectors;
        /* Clip to 2TB, instead of returning capacity modulo 2TB. */
1185
        if (nb_sectors > UINT32_MAX) {
1186
            nb_sectors = UINT32_MAX;
1187
        }
1188 1189 1190 1191 1192 1193
        outbuf[0] = (nb_sectors >> 24) & 0xff;
        outbuf[1] = (nb_sectors >> 16) & 0xff;
        outbuf[2] = (nb_sectors >> 8) & 0xff;
        outbuf[3] = nb_sectors & 0xff;
        outbuf[4] = 0;
        outbuf[5] = 0;
P
Paolo Bonzini 已提交
1194
        outbuf[6] = s->qdev.blocksize >> 8;
1195 1196
        outbuf[7] = 0;
        buflen = 8;
H
Hannes Reinecke 已提交
1197
        break;
1198 1199 1200 1201 1202 1203
    case MECHANISM_STATUS:
        buflen = scsi_emulate_mechanism_status(s, outbuf);
        if (buflen < 0) {
            goto illegal_request;
        }
        break;
1204
    case GET_CONFIGURATION:
1205
        buflen = scsi_get_configuration(s, outbuf);
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
        if (buflen < 0) {
            goto illegal_request;
        }
        break;
    case GET_EVENT_STATUS_NOTIFICATION:
        buflen = scsi_get_event_status_notification(s, r, outbuf);
        if (buflen < 0) {
            goto illegal_request;
        }
        break;
    case READ_DVD_STRUCTURE:
        buflen = scsi_read_dvd_structure(s, r, outbuf);
        if (buflen < 0) {
            goto illegal_request;
        }
1221
        break;
1222
    case SERVICE_ACTION_IN_16:
1223
        /* Service Action In subcommands. */
1224
        if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
1225 1226
            DPRINTF("SAI READ CAPACITY(16)\n");
            memset(outbuf, 0, req->cmd.xfer);
1227
            bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1228
            if (!nb_sectors) {
1229
                goto not_ready;
1230
            }
1231 1232 1233
            if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
                goto illegal_request;
            }
P
Paolo Bonzini 已提交
1234
            nb_sectors /= s->qdev.blocksize / 512;
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
            /* Returned value is the address of the last sector.  */
            nb_sectors--;
            /* Remember the new size for read/write sanity checking. */
            s->max_lba = nb_sectors;
            outbuf[0] = (nb_sectors >> 56) & 0xff;
            outbuf[1] = (nb_sectors >> 48) & 0xff;
            outbuf[2] = (nb_sectors >> 40) & 0xff;
            outbuf[3] = (nb_sectors >> 32) & 0xff;
            outbuf[4] = (nb_sectors >> 24) & 0xff;
            outbuf[5] = (nb_sectors >> 16) & 0xff;
            outbuf[6] = (nb_sectors >> 8) & 0xff;
            outbuf[7] = nb_sectors & 0xff;
            outbuf[8] = 0;
            outbuf[9] = 0;
P
Paolo Bonzini 已提交
1249
            outbuf[10] = s->qdev.blocksize >> 8;
1250
            outbuf[11] = 0;
C
Christoph Hellwig 已提交
1251 1252
            outbuf[12] = 0;
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
1253 1254 1255 1256 1257 1258

            /* set TPE bit if the format supports discard */
            if (s->qdev.conf.discard_granularity) {
                outbuf[14] = 0x80;
            }

1259 1260 1261 1262 1263 1264
            /* Protection, exponent and lowest lba field left blank. */
            buflen = req->cmd.xfer;
            break;
        }
        DPRINTF("Unsupported Service Action In\n");
        goto illegal_request;
1265
    case VERIFY_10:
1266
        break;
1267
    default:
1268
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1269
        return -1;
1270 1271 1272 1273
    }
    return buflen;

not_ready:
1274
    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
1275
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
1276
    } else {
1277
        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
1278
    }
1279
    return -1;
1280 1281

illegal_request:
1282 1283 1284
    if (r->req.status == -1) {
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
    }
1285
    return -1;
1286 1287
}

P
pbrook 已提交
1288 1289 1290 1291 1292
/* Execute a scsi command.  Returns the length of the data expected by the
   command.  This will be Positive for data transfers from the device
   (eg. disk reads), negative for transfers to the device (eg. disk writes),
   and zero if the command does not transfer any data.  */

1293
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
P
pbrook 已提交
1294
{
1295 1296
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
P
Paolo Bonzini 已提交
1297
    int32_t len;
P
pbrook 已提交
1298
    uint8_t command;
1299
    int rc;
P
pbrook 已提交
1300 1301

    command = buf[0];
1302
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
1303

P
pbrook 已提交
1304 1305 1306
#ifdef DEBUG_SCSI
    {
        int i;
1307
        for (i = 1; i < r->req.cmd.len; i++) {
P
pbrook 已提交
1308 1309 1310 1311 1312
            printf(" 0x%02x", buf[i]);
        }
        printf("\n");
    }
#endif
1313

P
pbrook 已提交
1314
    switch (command) {
1315
    case TEST_UNIT_READY:
1316
    case INQUIRY:
1317 1318
    case MODE_SENSE:
    case MODE_SENSE_10:
1319 1320 1321 1322
    case RESERVE:
    case RESERVE_10:
    case RELEASE:
    case RELEASE_10:
1323
    case START_STOP:
1324
    case ALLOW_MEDIUM_REMOVAL:
1325
    case READ_CAPACITY_10:
1326
    case READ_TOC:
1327
    case READ_DVD_STRUCTURE:
1328
    case GET_CONFIGURATION:
1329 1330
    case GET_EVENT_STATUS_NOTIFICATION:
    case MECHANISM_STATUS:
1331
    case SERVICE_ACTION_IN_16:
1332
    case VERIFY_10:
1333
        rc = scsi_disk_emulate_command(r);
1334
        if (rc < 0) {
1335
            return 0;
1336
        }
1337 1338

        r->iov.iov_len = rc;
1339
        break;
1340
    case SYNCHRONIZE_CACHE:
1341 1342
        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
1343 1344 1345 1346
        if (r->req.aiocb == NULL) {
            scsi_flush_complete(r, -EIO);
        }
        return 0;
1347 1348
    case READ_6:
    case READ_10:
G
Gerd Hoffmann 已提交
1349 1350
    case READ_12:
    case READ_16:
1351
        len = r->req.cmd.xfer / s->qdev.blocksize;
1352
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
1353
        if (r->req.cmd.lba > s->max_lba) {
1354
            goto illegal_lba;
1355
        }
P
Paolo Bonzini 已提交
1356 1357
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
        r->sector_count = len * (s->qdev.blocksize / 512);
P
pbrook 已提交
1358
        break;
1359 1360
    case WRITE_6:
    case WRITE_10:
G
Gerd Hoffmann 已提交
1361 1362
    case WRITE_12:
    case WRITE_16:
1363
    case WRITE_VERIFY_10:
1364 1365
    case WRITE_VERIFY_12:
    case WRITE_VERIFY_16:
1366
        len = r->req.cmd.xfer / s->qdev.blocksize;
1367
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1368 1369
                (command & 0xe) == 0xe ? "And Verify " : "",
                r->req.cmd.lba, len);
1370
        if (r->req.cmd.lba > s->max_lba) {
1371
            goto illegal_lba;
1372
        }
P
Paolo Bonzini 已提交
1373 1374
        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
        r->sector_count = len * (s->qdev.blocksize / 512);
P
pbrook 已提交
1375
        break;
1376
    case MODE_SELECT:
1377
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1378 1379
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1380
        if (r->req.cmd.xfer > 12) {
1381 1382 1383 1384
            goto fail;
        }
        break;
    case MODE_SELECT_10:
1385
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1386 1387
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1388
        if (r->req.cmd.xfer > 16) {
1389 1390 1391 1392 1393
            goto fail;
        }
        break;
    case SEEK_6:
    case SEEK_10:
1394 1395 1396
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
                r->req.cmd.lba);
        if (r->req.cmd.lba > s->max_lba) {
1397 1398
            goto illegal_lba;
        }
1399 1400
        break;
    case WRITE_SAME_16:
1401
        len = r->req.cmd.xfer / s->qdev.blocksize;
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416

        DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
                r->req.cmd.lba, len);

        if (r->req.cmd.lba > s->max_lba) {
            goto illegal_lba;
        }

        /*
         * We only support WRITE SAME with the unmap bit set for now.
         */
        if (!(buf[1] & 0x8)) {
            goto fail;
        }

P
Paolo Bonzini 已提交
1417 1418 1419
        rc = bdrv_discard(s->qdev.conf.bs,
                          r->req.cmd.lba * (s->qdev.blocksize / 512),
                          len * (s->qdev.blocksize / 512));
1420 1421 1422 1423 1424
        if (rc < 0) {
            /* XXX: better error code ?*/
            goto fail;
        }

1425
        break;
1426 1427
    case REQUEST_SENSE:
        abort();
P
pbrook 已提交
1428
    default:
1429
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1430
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1431
        return 0;
P
pbrook 已提交
1432
    fail:
1433
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1434
        return 0;
1435
    illegal_lba:
1436
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1437
        return 0;
P
pbrook 已提交
1438
    }
1439
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1440
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
1441
    }
1442
    len = r->sector_count * 512 + r->iov.iov_len;
1443 1444
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        return -len;
P
pbrook 已提交
1445
    } else {
1446
        if (!r->sector_count) {
P
pbrook 已提交
1447
            r->sector_count = -1;
1448
        }
1449
        return len;
P
pbrook 已提交
1450 1451 1452
    }
}

J
Jan Kiszka 已提交
1453 1454 1455 1456 1457
static void scsi_disk_reset(DeviceState *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
    uint64_t nb_sectors;

1458
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
J
Jan Kiszka 已提交
1459

1460
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
P
Paolo Bonzini 已提交
1461
    nb_sectors /= s->qdev.blocksize / 512;
J
Jan Kiszka 已提交
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
    if (nb_sectors) {
        nb_sectors--;
    }
    s->max_lba = nb_sectors;
}

static void scsi_destroy(SCSIDevice *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);

1472
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1473
    blockdev_mark_auto_del(s->qdev.conf.bs);
G
Gerd Hoffmann 已提交
1474 1475
}

1476
static void scsi_cd_change_media_cb(void *opaque, bool load)
1477
{
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
    SCSIDiskState *s = opaque;

    /*
     * When a CD gets changed, we have to report an ejected state and
     * then a loaded state to guests so that they detect tray
     * open/close and media change events.  Guests that do not use
     * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
     * states rely on this behavior.
     *
     * media_changed governs the state machine used for unit attention
     * report.  media_event is used by GET EVENT STATUS NOTIFICATION.
     */
    s->media_changed = load;
    s->tray_open = !load;
    s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
1493
    s->media_event = true;
1494 1495
}

1496 1497 1498 1499 1500
static bool scsi_cd_is_tray_open(void *opaque)
{
    return ((SCSIDiskState *)opaque)->tray_open;
}

1501 1502 1503 1504 1505 1506
static bool scsi_cd_is_medium_locked(void *opaque)
{
    return ((SCSIDiskState *)opaque)->tray_locked;
}

static const BlockDevOps scsi_cd_block_ops = {
1507
    .change_media_cb = scsi_cd_change_media_cb,
1508
    .is_tray_open = scsi_cd_is_tray_open,
1509 1510 1511
    .is_medium_locked = scsi_cd_is_medium_locked,
};

1512 1513 1514 1515 1516 1517 1518 1519 1520
static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
    if (s->media_changed) {
        s->media_changed = false;
        s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
    }
}

H
Hannes Reinecke 已提交
1521
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
P
pbrook 已提交
1522
{
1523
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1524
    DriveInfo *dinfo;
P
pbrook 已提交
1525

1526
    if (!s->qdev.conf.bs) {
1527
        error_report("scsi-disk: drive property not set");
1528 1529 1530
        return -1;
    }

1531
    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->qdev.conf.bs)) {
1532 1533 1534 1535
        error_report("Device needs media, but drive is empty");
        return -1;
    }

1536
    if (!s->serial) {
1537
        /* try to fall back to value set with legacy -drive serial=... */
1538
        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
1539
        if (*dinfo->serial) {
1540
            s->serial = g_strdup(dinfo->serial);
1541
        }
1542 1543
    }

1544
    if (!s->version) {
1545
        s->version = g_strdup(QEMU_VERSION);
1546 1547
    }

1548
    if (bdrv_is_sg(s->qdev.conf.bs)) {
1549
        error_report("scsi-disk: unwanted /dev/sg*");
1550 1551 1552
        return -1;
    }

H
Hannes Reinecke 已提交
1553
    if (scsi_type == TYPE_ROM) {
1554
        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_cd_block_ops, s);
1555
        s->qdev.blocksize = 2048;
H
Hannes Reinecke 已提交
1556
    } else if (scsi_type == TYPE_DISK) {
1557
        s->qdev.blocksize = s->qdev.conf.logical_block_size;
H
Hannes Reinecke 已提交
1558 1559 1560
    } else {
        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
        return -1;
P
pbrook 已提交
1561
    }
1562
    bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
1563

H
Hannes Reinecke 已提交
1564
    s->qdev.type = scsi_type;
1565
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
1566
    bdrv_iostatus_enable(s->qdev.conf.bs);
1567
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
1568 1569 1570
    return 0;
}

1571 1572
static int scsi_hd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1573
    return scsi_initfn(dev, TYPE_DISK);
1574 1575 1576 1577
}

static int scsi_cd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1578
    return scsi_initfn(dev, TYPE_ROM);
1579 1580 1581 1582
}

static int scsi_disk_initfn(SCSIDevice *dev)
{
1583
    DriveInfo *dinfo;
H
Hannes Reinecke 已提交
1584
    uint8_t scsi_type;
1585 1586

    if (!dev->conf.bs) {
H
Hannes Reinecke 已提交
1587
        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
1588
    } else {
1589
        dinfo = drive_get_by_blockdev(dev->conf.bs);
H
Hannes Reinecke 已提交
1590
        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
1591 1592
    }

H
Hannes Reinecke 已提交
1593
    return scsi_initfn(dev, scsi_type);
1594 1595
}

P
Paolo Bonzini 已提交
1596 1597
static SCSIReqOps scsi_disk_reqops = {
    .size         = sizeof(SCSIDiskReq),
1598 1599 1600 1601 1602 1603
    .free_req     = scsi_free_request,
    .send_command = scsi_send_command,
    .read_data    = scsi_read_data,
    .write_data   = scsi_write_data,
    .cancel_io    = scsi_cancel_io,
    .get_buf      = scsi_get_buf,
P
Paolo Bonzini 已提交
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
};

static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
                                     uint32_t lun, void *hba_private)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
    SCSIRequest *req;

    req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
    return req;
}

1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
#define DEFINE_SCSI_DISK_PROPERTIES()                           \
    DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),          \
    DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
    DEFINE_PROP_STRING("serial",  SCSIDiskState, serial)

static SCSIDeviceInfo scsi_disk_info[] = {
    {
        .qdev.name    = "scsi-hd",
        .qdev.fw_name = "disk",
        .qdev.desc    = "virtual SCSI disk",
        .qdev.size    = sizeof(SCSIDiskState),
        .qdev.reset   = scsi_disk_reset,
        .init         = scsi_hd_initfn,
        .destroy      = scsi_destroy,
1630
        .alloc_req    = scsi_new_request,
1631
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
            DEFINE_PROP_END_OF_LIST(),
        }
    },{
        .qdev.name    = "scsi-cd",
        .qdev.fw_name = "disk",
        .qdev.desc    = "virtual SCSI CD-ROM",
        .qdev.size    = sizeof(SCSIDiskState),
        .qdev.reset   = scsi_disk_reset,
        .init         = scsi_cd_initfn,
        .destroy      = scsi_destroy,
1645
        .alloc_req    = scsi_new_request,
1646
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_END_OF_LIST(),
        },
    },{
        .qdev.name    = "scsi-disk", /* legacy -device scsi-disk */
        .qdev.fw_name = "disk",
        .qdev.desc    = "virtual SCSI disk or CD-ROM (legacy)",
        .qdev.size    = sizeof(SCSIDiskState),
        .qdev.reset   = scsi_disk_reset,
        .init         = scsi_disk_initfn,
        .destroy      = scsi_destroy,
1659
        .alloc_req    = scsi_new_request,
1660
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1661 1662 1663 1664 1665 1666
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
            DEFINE_PROP_END_OF_LIST(),
        }
    }
1667 1668 1669 1670
};

static void scsi_disk_register_devices(void)
{
1671 1672 1673 1674 1675
    int i;

    for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) {
        scsi_qdev_register(&scsi_disk_info[i]);
    }
T
ths 已提交
1676
}
1677
device_init(scsi_disk_register_devices)