scsi-disk.c 50.1 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;
P
pbrook 已提交
68 69 70
    /* The qemu block layer uses a fixed 512 byte sector size.
       This is the number of 512 byte blocks in a single scsi sector.  */
    int cluster_size;
71
    uint32_t removable;
72
    uint64_t max_lba;
73
    bool media_changed;
74
    bool media_event;
75
    QEMUBH *bh;
G
Gerd Hoffmann 已提交
76
    char *version;
77
    char *serial;
78
    bool tray_open;
79
    bool tray_locked;
P
pbrook 已提交
80 81
};

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

P
Paolo Bonzini 已提交
85
static void scsi_free_request(SCSIRequest *req)
P
pbrook 已提交
86
{
P
Paolo Bonzini 已提交
87 88
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

89 90 91
    if (r->iov.iov_base) {
        qemu_vfree(r->iov.iov_base);
    }
P
pbrook 已提交
92 93
}

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

/* Cancel a pending data transfer.  */
104
static void scsi_cancel_io(SCSIRequest *req)
P
pbrook 已提交
105
{
106 107 108 109 110
    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 已提交
111
    }
112
    r->req.aiocb = NULL;
P
pbrook 已提交
113 114
}

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

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

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

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

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

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

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

153 154 155 156 157 158 159
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;
160
        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
161 162 163 164 165 166 167 168 169 170
    }

    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 已提交
171

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

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

192 193 194
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

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

201 202 203
    if (s->tray_open) {
        scsi_read_complete(r, -ENOMEDIUM);
    }
204
    n = scsi_init_iovec(r);
205 206
    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,
207
                              scsi_read_complete, r);
208 209 210
    if (r->req.aiocb == NULL) {
        scsi_read_complete(r, -EIO);
    }
P
pbrook 已提交
211 212
}

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

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

    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
            || action == BLOCK_ERR_STOP_ANY) {
K
Kevin Wolf 已提交
226 227 228 229

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

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

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

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

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

270
    n = r->qiov.size / 512;
271 272
    r->sector += n;
    r->sector_count -= n;
P
pbrook 已提交
273
    if (r->sector_count == 0) {
274
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
275
    } else {
276 277 278
        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 已提交
279 280 281
    }
}

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

288 289 290
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

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

297
    n = r->qiov.size / 512;
298
    if (n) {
299 300 301
        if (s->tray_open) {
            scsi_write_complete(r, -ENOMEDIUM);
        }
302 303
        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,
304
                                       scsi_write_complete, r);
305
        if (r->req.aiocb == NULL) {
306
            scsi_write_complete(r, -ENOMEM);
307
        }
308
    } else {
309
        /* Called for the first time.  Ask the driver to send us more data.  */
310 311
        scsi_write_complete(r, 0);
    }
P
pbrook 已提交
312
}
P
pbrook 已提交
313

314
static void scsi_dma_restart_bh(void *opaque)
315
{
316
    SCSIDiskState *s = opaque;
317 318
    SCSIRequest *req;
    SCSIDiskReq *r;
319 320 321

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

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

K
Kevin Wolf 已提交
328 329 330 331 332
            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:
333
                scsi_read_data(&r->req);
K
Kevin Wolf 已提交
334 335
                break;
            case SCSI_REQ_STATUS_RETRY_WRITE:
336
                scsi_write_data(&r->req);
K
Kevin Wolf 已提交
337
                break;
338
            case SCSI_REQ_STATUS_RETRY_FLUSH:
P
Paolo Bonzini 已提交
339 340
                scsi_send_command(&r->req, r->req.cmd.buf);
                break;
K
Kevin Wolf 已提交
341
            }
342 343 344 345
        }
    }
}

346
static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
347
{
348
    SCSIDiskState *s = opaque;
349

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

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

364
    return (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
365 366
}

367 368
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
G
Gerd Hoffmann 已提交
369
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    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 已提交
387
        if (s->qdev.type == TYPE_ROM) {
388 389 390 391 392 393 394 395 396
            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 已提交
397 398
        {
            int pages;
399 400
            DPRINTF("Inquiry EVPD[Supported pages] "
                    "buffer size %zd\n", req->cmd.xfer);
H
Hannes Reinecke 已提交
401
            pages = buflen++;
402
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
403
            if (s->serial) {
404
                outbuf[buflen++] = 0x80; // unit serial number
405
            }
406
            outbuf[buflen++] = 0x83; // device identification
H
Hannes Reinecke 已提交
407
            if (s->qdev.type == TYPE_DISK) {
408 409
                outbuf[buflen++] = 0xb0; // block limits
                outbuf[buflen++] = 0xb2; // thin provisioning
H
Hannes Reinecke 已提交
410 411
            }
            outbuf[pages] = buflen - pages - 1; // number of pages
412
            break;
H
Hannes Reinecke 已提交
413
        }
414 415
        case 0x80: /* Device serial number, optional */
        {
416
            int l;
417

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

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

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

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

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

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

456
            memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
457 458 459
            buflen += id_len;
            break;
        }
460
        case 0xb0: /* block limits */
C
Christoph Hellwig 已提交
461
        {
462 463
            unsigned int unmap_sectors =
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
464 465 466 467
            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 已提交
468

H
Hannes Reinecke 已提交
469
            if (s->qdev.type == TYPE_ROM) {
H
Hannes Reinecke 已提交
470 471 472 473
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
                        page_code);
                return -1;
            }
C
Christoph Hellwig 已提交
474 475 476 477 478 479 480 481 482 483 484 485 486 487
            /* 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;
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502

            /* 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 已提交
503 504
            break;
        }
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
        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;
529
    if (buflen > SCSI_MAX_INQUIRY_LEN) {
530
        buflen = SCSI_MAX_INQUIRY_LEN;
531
    }
532 533
    memset(outbuf, 0, buflen);

H
Hannes Reinecke 已提交
534 535
    outbuf[0] = s->qdev.type & 0x1f;
    if (s->qdev.type == TYPE_ROM) {
536
        outbuf[1] = 0x80;
L
Laszlo Ast 已提交
537
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
538
    } else {
539
        outbuf[1] = s->removable ? 0x80 : 0;
L
Laszlo Ast 已提交
540
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
541
    }
L
Laszlo Ast 已提交
542
    memcpy(&outbuf[8], "QEMU    ", 8);
G
Gerd Hoffmann 已提交
543
    memset(&outbuf[32], 0, 4);
544
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
545 546 547 548 549 550
    /*
     * 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 已提交
551
    outbuf[2] = 5;
552
    outbuf[3] = 2; /* Format 2 */
553 554 555 556 557 558 559 560 561

    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;
    }

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

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

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

593 594 595
static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                   uint8_t *outbuf)
{
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
    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) {
617
        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
            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;
        }
639
        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
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 681 682 683

        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:
684 685 686
    return -1;
}

687
static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
688
{
689 690 691 692 693
    uint8_t event_code, media_status;

    media_status = 0;
    if (s->tray_open) {
        media_status = MS_TRAY_OPEN;
694
    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
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 736 737 738
        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;
739 740
}

741
static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
742
{
743 744
    int current;

745 746 747
    if (s->qdev.type != TYPE_ROM) {
        return -1;
    }
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    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;
773 774 775 776 777 778 779 780 781 782 783 784
}

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;
}

785
static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
786
                           int page_control)
787
{
788 789 790 791
    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),
792 793
        [MODE_PAGE_R_W_ERROR]              = (1 << TYPE_DISK) | (1 << TYPE_ROM),
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
794 795 796
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
    };

797
    BlockDriverState *bdrv = s->qdev.conf.bs;
798
    int cylinders, heads, secs;
799
    uint8_t *p = *p_outbuf;
800

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

    p[0] = page;

807 808 809 810 811 812
    /*
     * 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.
     */
813
    switch (page) {
814
    case MODE_PAGE_HD_GEOMETRY:
815
        p[1] = 0x16;
816
        if (page_control == 1) { /* Changeable Values */
817
            break;
818
        }
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
        /* 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;
843
        break;
844

845
    case MODE_PAGE_FLEXIBLE_DISK_GEOMETRY:
846
        p[1] = 0x1e;
847
        if (page_control == 1) { /* Changeable Values */
848
            break;
849
        }
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
        /* 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[6] = s->cluster_size * 2;
        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;
881
        break;
882

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

894 895 896 897 898 899 900 901 902 903 904 905
    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;

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

        p[2] = 0x3b; /* CD-R & CD-RW read */
        p[3] = 0; /* Writing not supported */
914 915 916 917 918
        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 */
919
        p[6] = 0x2d | (s->tray_locked ? 2 : 0);
920 921 922
        /* Locking supported, jumper present, eject, tray */
        p[7] = 0; /* no volume & mute control, no
                     changer */
923
        p[8] = (50 * 176) >> 8; /* 50x read speed */
924
        p[9] = (50 * 176) & 0xff;
925 926 927
        p[10] = 2 >> 8; /* Two volume levels */
        p[11] = 2 & 0xff;
        p[12] = 2048 >> 8; /* 2M buffer */
928
        p[13] = 2048 & 0xff;
929
        p[14] = (16 * 176) >> 8; /* 16x read speed current */
930
        p[15] = (16 * 176) & 0xff;
931
        p[18] = (16 * 176) >> 8; /* 16x write speed */
932
        p[19] = (16 * 176) & 0xff;
933
        p[20] = (16 * 176) >> 8; /* 16x write speed current */
934
        p[21] = (16 * 176) & 0xff;
935
        break;
936 937

    default:
938
        return -1;
939
    }
940 941 942

    *p_outbuf += p[1] + 2;
    return p[1] + 2;
943 944
}

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

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

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

967
    if (r->req.cmd.buf[0] == MODE_SENSE) {
968 969 970 971 972 973 974 975 976
        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;
977 978
    }

979
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
980
    if (!dbd && nb_sectors) {
981
        if (r->req.cmd.buf[0] == MODE_SENSE) {
982 983 984 985
            outbuf[3] = 8; /* Block descriptor length  */
        } else { /* MODE_SENSE_10 */
            outbuf[7] = 8; /* Block descriptor length  */
        }
986
        nb_sectors /= s->cluster_size;
987
        if (nb_sectors > 0xffffff) {
988
            nb_sectors = 0;
989
        }
990 991 992 993 994 995 996 997 998 999 1000
        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[6] = s->cluster_size * 2;
        p[7] = 0;
        p += 8;
    }

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

1007 1008 1009 1010 1011 1012 1013 1014 1015
    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;
        }
1016 1017 1018
    }

    buflen = p - outbuf;
1019 1020 1021 1022 1023
    /*
     * 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.
     */
1024
    if (r->req.cmd.buf[0] == MODE_SENSE) {
1025 1026 1027 1028 1029
        outbuf[0] = buflen - 1;
    } else { /* MODE_SENSE_10 */
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
        outbuf[1] = (buflen - 2) & 0xff;
    }
1030
    if (buflen > r->req.cmd.xfer) {
1031
        buflen = r->req.cmd.xfer;
1032
    }
1033 1034 1035
    return buflen;
}

1036 1037 1038 1039 1040 1041 1042 1043 1044
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];
1045
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
    DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
    nb_sectors /= s->cluster_size;
    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;
    }
1066
    if (toclen > req->cmd.xfer) {
1067
        toclen = req->cmd.xfer;
1068
    }
1069 1070 1071
    return toclen;
}

1072
static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
1073 1074 1075 1076 1077 1078 1079
{
    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) {
1080 1081
        if (!start && !s->tray_open && s->tray_locked) {
            scsi_check_condition(r,
1082
                                 bdrv_is_inserted(s->qdev.conf.bs)
1083 1084 1085
                                 ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
                                 : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
            return -1;
1086
        }
1087
        bdrv_eject(s->qdev.conf.bs, !start);
1088
        s->tray_open = !start;
1089
    }
1090
    return 0;
1091 1092
}

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

1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
    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);
1114
        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
1115 1116 1117
    }

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

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

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

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

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

P
pbrook 已提交
1291 1292 1293 1294 1295
/* 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.  */

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

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

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

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

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

        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;
        }

1420
        rc = bdrv_discard(s->qdev.conf.bs, r->req.cmd.lba * s->cluster_size,
1421 1422 1423 1424 1425 1426
                          len * s->cluster_size);
        if (rc < 0) {
            /* XXX: better error code ?*/
            goto fail;
        }

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

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

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

1462
    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
J
Jan Kiszka 已提交
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
    nb_sectors /= s->cluster_size;
    if (nb_sectors) {
        nb_sectors--;
    }
    s->max_lba = nb_sectors;
}

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

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

1478
static void scsi_cd_change_media_cb(void *opaque, bool load)
1479
{
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
    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);
1495
    s->media_event = true;
1496 1497
}

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

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

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

1514 1515 1516 1517 1518 1519 1520 1521 1522
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 已提交
1523
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
P
pbrook 已提交
1524
{
1525
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1526
    DriveInfo *dinfo;
P
pbrook 已提交
1527

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

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

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

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

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

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

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

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

static int scsi_cd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1581
    return scsi_initfn(dev, TYPE_ROM);
1582 1583 1584 1585
}

static int scsi_disk_initfn(SCSIDevice *dev)
{
1586
    DriveInfo *dinfo;
H
Hannes Reinecke 已提交
1587
    uint8_t scsi_type;
1588 1589

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

H
Hannes Reinecke 已提交
1596
    return scsi_initfn(dev, scsi_type);
1597 1598
}

P
Paolo Bonzini 已提交
1599 1600
static SCSIReqOps scsi_disk_reqops = {
    .size         = sizeof(SCSIDiskReq),
1601 1602 1603 1604 1605 1606
    .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 已提交
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
};

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;
}

1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
#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,
1633
        .alloc_req    = scsi_new_request,
1634
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
        .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,
1648
        .alloc_req    = scsi_new_request,
1649
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
        .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,
1662
        .alloc_req    = scsi_new_request,
1663
        .unit_attention_reported = scsi_disk_unit_attention_reported,
1664 1665 1666 1667 1668 1669
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
            DEFINE_PROP_END_OF_LIST(),
        }
    }
1670 1671 1672 1673
};

static void scsi_disk_register_devices(void)
{
1674 1675 1676 1677 1678
    int i;

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