scsi-disk.c 38.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

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

K
Kevin Wolf 已提交
44 45 46 47
#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
48
#define SCSI_REQ_STATUS_RETRY_FLUSH     0x04
49

50 51
typedef struct SCSIDiskState SCSIDiskState;

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

62
struct SCSIDiskState
P
pbrook 已提交
63
{
64
    SCSIDevice qdev;
65
    BlockDriverState *bs;
P
pbrook 已提交
66 67 68
    /* 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;
69
    uint32_t removable;
70
    uint64_t max_lba;
71
    QEMUBH *bh;
G
Gerd Hoffmann 已提交
72
    char *version;
73
    char *serial;
P
pbrook 已提交
74 75
};

K
Kevin Wolf 已提交
76
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
77
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
K
Kevin Wolf 已提交
78

P
Paolo Bonzini 已提交
79
static void scsi_free_request(SCSIRequest *req)
P
pbrook 已提交
80
{
P
Paolo Bonzini 已提交
81 82
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

83
    qemu_vfree(r->iov.iov_base);
P
pbrook 已提交
84 85
}

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

/* Cancel a pending data transfer.  */
96
static void scsi_cancel_io(SCSIRequest *req)
P
pbrook 已提交
97
{
98 99 100 101 102
    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 已提交
103
    }
104
    r->req.aiocb = NULL;
P
pbrook 已提交
105 106 107 108
}

static void scsi_read_complete(void * opaque, int ret)
{
109
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
K
Kevin Wolf 已提交
110
    int n;
P
pbrook 已提交
111

112 113
    r->req.aiocb = NULL;

P
pbrook 已提交
114
    if (ret) {
K
Kevin Wolf 已提交
115 116 117
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
            return;
        }
P
pbrook 已提交
118
    }
K
Kevin Wolf 已提交
119

120
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
P
pbrook 已提交
121

K
Kevin Wolf 已提交
122 123 124
    n = r->iov.iov_len / 512;
    r->sector += n;
    r->sector_count -= n;
P
Paolo Bonzini 已提交
125
    scsi_req_data(&r->req, r->iov.iov_len);
P
pbrook 已提交
126 127
}

K
Kevin Wolf 已提交
128

129 130
/* Read more data from scsi device into buffer.  */
static void scsi_read_data(SCSIRequest *req)
P
pbrook 已提交
131
{
132
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
K
Kevin Wolf 已提交
133
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
P
pbrook 已提交
134 135
    uint32_t n;

P
pbrook 已提交
136
    if (r->sector_count == (uint32_t)-1) {
137
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
P
pbrook 已提交
138
        r->sector_count = 0;
P
Paolo Bonzini 已提交
139
        scsi_req_data(&r->req, r->iov.iov_len);
P
pbrook 已提交
140
        return;
P
pbrook 已提交
141
    }
P
pbrook 已提交
142 143
    DPRINTF("Read sector_count=%d\n", r->sector_count);
    if (r->sector_count == 0) {
144 145
        /* This also clears the sense buffer for REQUEST SENSE.  */
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
146
        return;
P
pbrook 已提交
147 148
    }

149 150 151
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

152 153 154 155 156 157
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_read_complete(r, -EINVAL);
        return;
    }

P
pbrook 已提交
158 159 160 161
    n = r->sector_count;
    if (n > SCSI_DMA_BUF_SIZE / 512)
        n = SCSI_DMA_BUF_SIZE / 512;

162 163
    r->iov.iov_len = n * 512;
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
164
    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
165
                              scsi_read_complete, r);
166 167 168
    if (r->req.aiocb == NULL) {
        scsi_read_complete(r, -EIO);
    }
P
pbrook 已提交
169 170
}

K
Kevin Wolf 已提交
171 172 173
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
{
    int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
174
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
K
Kevin Wolf 已提交
175
    BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
176

177
    if (action == BLOCK_ERR_IGNORE) {
K
Kevin Wolf 已提交
178
        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
179
        return 0;
180
    }
181 182 183

    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
            || action == BLOCK_ERR_STOP_ANY) {
K
Kevin Wolf 已提交
184 185 186 187 188

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

        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
J
Jan Kiszka 已提交
189
        vm_stop(VMSTOP_DISKFULL);
190
    } else {
191 192
        switch (error) {
        case ENOMEM:
193
            scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
194 195
            break;
        case EINVAL:
196
            scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
197 198
            break;
        default:
199
            scsi_check_condition(r, SENSE_CODE(IO_ERROR));
200
            break;
201
        }
K
Kevin Wolf 已提交
202
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
203 204 205 206
    }
    return 1;
}

P
pbrook 已提交
207 208
static void scsi_write_complete(void * opaque, int ret)
{
209
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
P
pbrook 已提交
210
    uint32_t len;
211 212
    uint32_t n;

213
    r->req.aiocb = NULL;
P
pbrook 已提交
214 215

    if (ret) {
K
Kevin Wolf 已提交
216
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
217
            return;
K
Kevin Wolf 已提交
218
        }
P
pbrook 已提交
219 220
    }

221
    n = r->iov.iov_len / 512;
222 223
    r->sector += n;
    r->sector_count -= n;
P
pbrook 已提交
224
    if (r->sector_count == 0) {
225
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
226 227 228 229 230
    } else {
        len = r->sector_count * 512;
        if (len > SCSI_DMA_BUF_SIZE) {
            len = SCSI_DMA_BUF_SIZE;
        }
231
        r->iov.iov_len = len;
232
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
P
Paolo Bonzini 已提交
233
        scsi_req_data(&r->req, len);
P
pbrook 已提交
234 235 236
    }
}

237
static void scsi_write_data(SCSIRequest *req)
238
{
239
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
240
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
241 242
    uint32_t n;

243 244 245
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

246 247 248
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_write_complete(r, -EINVAL);
249
        return;
250 251
    }

252
    n = r->iov.iov_len / 512;
253
    if (n) {
254
        qemu_iovec_init_external(&r->qiov, &r->iov, 1);
255
        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
256
                                   scsi_write_complete, r);
257
        if (r->req.aiocb == NULL) {
258
            scsi_write_complete(r, -ENOMEM);
259
        }
260 261 262 263
    } else {
        /* Invoke completion routine to fetch data from host.  */
        scsi_write_complete(r, 0);
    }
P
pbrook 已提交
264
}
P
pbrook 已提交
265

266
static void scsi_dma_restart_bh(void *opaque)
267
{
268
    SCSIDiskState *s = opaque;
269 270
    SCSIRequest *req;
    SCSIDiskReq *r;
271 272 273

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

275 276
    QTAILQ_FOREACH(req, &s->qdev.requests, next) {
        r = DO_UPCAST(SCSIDiskReq, req, req);
277
        if (r->status & SCSI_REQ_STATUS_RETRY) {
K
Kevin Wolf 已提交
278
            int status = r->status;
279 280
            int ret;

K
Kevin Wolf 已提交
281 282 283 284 285
            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:
286
                scsi_read_data(&r->req);
K
Kevin Wolf 已提交
287 288
                break;
            case SCSI_REQ_STATUS_RETRY_WRITE:
289
                scsi_write_data(&r->req);
K
Kevin Wolf 已提交
290
                break;
291 292 293
            case SCSI_REQ_STATUS_RETRY_FLUSH:
                ret = scsi_disk_emulate_command(r, r->iov.iov_base);
                if (ret == 0) {
294
                    scsi_req_complete(&r->req, GOOD);
295
                }
K
Kevin Wolf 已提交
296
            }
297 298 299 300
        }
    }
}

301 302
static void scsi_dma_restart_cb(void *opaque, int running, int reason)
{
303
    SCSIDiskState *s = opaque;
304 305 306 307 308 309 310 311 312 313

    if (!running)
        return;

    if (!s->bh) {
        s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
        qemu_bh_schedule(s->bh);
    }
}

P
pbrook 已提交
314
/* Return a pointer to the data buffer.  */
315
static uint8_t *scsi_get_buf(SCSIRequest *req)
P
pbrook 已提交
316
{
317
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
P
pbrook 已提交
318

319
    return (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
320 321
}

322 323
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
G
Gerd Hoffmann 已提交
324
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
    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 已提交
342
        if (s->qdev.type == TYPE_ROM) {
343 344 345 346 347 348 349 350 351
            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 已提交
352 353
        {
            int pages;
354 355
            DPRINTF("Inquiry EVPD[Supported pages] "
                    "buffer size %zd\n", req->cmd.xfer);
H
Hannes Reinecke 已提交
356
            pages = buflen++;
357
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
358 359
            if (s->serial)
                outbuf[buflen++] = 0x80; // unit serial number
360
            outbuf[buflen++] = 0x83; // device identification
H
Hannes Reinecke 已提交
361
            if (s->qdev.type == TYPE_DISK) {
362 363
                outbuf[buflen++] = 0xb0; // block limits
                outbuf[buflen++] = 0xb2; // thin provisioning
H
Hannes Reinecke 已提交
364 365
            }
            outbuf[pages] = buflen - pages - 1; // number of pages
366
            break;
H
Hannes Reinecke 已提交
367
        }
368 369
        case 0x80: /* Device serial number, optional */
        {
370
            int l;
371

372 373 374 375 376 377
            if (!s->serial) {
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
                return -1;
            }

            l = strlen(s->serial);
378 379 380 381 382 383 384 385
            if (l > req->cmd.xfer)
                l = req->cmd.xfer;
            if (l > 20)
                l = 20;

            DPRINTF("Inquiry EVPD[Serial number] "
                    "buffer size %zd\n", req->cmd.xfer);
            outbuf[buflen++] = l;
386
            memcpy(outbuf+buflen, s->serial, l);
387 388 389 390 391 392 393
            buflen += l;
            break;
        }

        case 0x83: /* Device identification page, mandatory */
        {
            int max_len = 255 - 8;
394
            int id_len = strlen(bdrv_get_device_name(s->bs));
395 396 397 398 399 400

            if (id_len > max_len)
                id_len = max_len;
            DPRINTF("Inquiry EVPD[Device identification] "
                    "buffer size %zd\n", req->cmd.xfer);

H
Hannes Reinecke 已提交
401
            outbuf[buflen++] = 4 + id_len;
402 403 404 405 406
            outbuf[buflen++] = 0x2; // ASCII
            outbuf[buflen++] = 0;   // not officially assigned
            outbuf[buflen++] = 0;   // reserved
            outbuf[buflen++] = id_len; // length of data following

407
            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
408 409 410
            buflen += id_len;
            break;
        }
411
        case 0xb0: /* block limits */
C
Christoph Hellwig 已提交
412
        {
413 414
            unsigned int unmap_sectors =
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
415 416 417 418
            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 已提交
419

H
Hannes Reinecke 已提交
420
            if (s->qdev.type == TYPE_ROM) {
H
Hannes Reinecke 已提交
421 422 423 424
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
                        page_code);
                return -1;
            }
C
Christoph Hellwig 已提交
425 426 427 428 429 430 431 432 433 434 435 436 437 438
            /* 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;
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453

            /* 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 已提交
454 455
            break;
        }
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
        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;
    if (buflen > SCSI_MAX_INQUIRY_LEN)
        buflen = SCSI_MAX_INQUIRY_LEN;

    memset(outbuf, 0, buflen);

H
Hannes Reinecke 已提交
485 486
    outbuf[0] = s->qdev.type & 0x1f;
    if (s->qdev.type == TYPE_ROM) {
487
        outbuf[1] = 0x80;
L
Laszlo Ast 已提交
488
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
489
    } else {
490
        outbuf[1] = s->removable ? 0x80 : 0;
L
Laszlo Ast 已提交
491
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
492
    }
L
Laszlo Ast 已提交
493
    memcpy(&outbuf[8], "QEMU    ", 8);
G
Gerd Hoffmann 已提交
494
    memset(&outbuf[32], 0, 4);
495
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
496 497 498 499 500 501
    /*
     * 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 已提交
502
    outbuf[2] = 5;
503
    outbuf[3] = 2; /* Format 2 */
504 505 506 507 508 509 510 511 512

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

513 514 515 516 517
    /* Sync data transfer and TCQ.  */
    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
    return buflen;
}

518 519
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
                           int page_control)
520 521
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
522
    BlockDriverState *bdrv = s->bs;
523 524
    int cylinders, heads, secs;

525 526 527 528 529 530
    /*
     * 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.
     */
531 532 533 534
    switch (page) {
    case 4: /* Rigid disk device geometry page. */
        p[0] = 4;
        p[1] = 0x16;
535 536 537
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
        /* 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;
562
        return p[1] + 2;
563 564 565 566

    case 5: /* Flexible disk device geometry page. */
        p[0] = 5;
        p[1] = 0x1e;
567 568 569
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
        /* 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;
601
        return p[1] + 2;
602 603 604 605

    case 8: /* Caching page.  */
        p[0] = 8;
        p[1] = 0x12;
606 607 608
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
609
        if (bdrv_enable_write_cache(s->bs)) {
610 611
            p[2] = 4; /* WCE */
        }
612
        return p[1] + 2;
613 614

    case 0x2a: /* CD Capabilities and Mechanical Status page. */
H
Hannes Reinecke 已提交
615
        if (s->qdev.type != TYPE_ROM)
616 617 618
            return 0;
        p[0] = 0x2a;
        p[1] = 0x14;
619 620 621
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
622 623 624 625 626 627 628
        p[2] = 3; // CD-R & CD-RW read
        p[3] = 0; // Writing not supported
        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 */
629
        p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
        /* Locking supported, jumper present, eject, tray */
        p[7] = 0; /* no volume & mute control, no
                     changer */
        p[8] = (50 * 176) >> 8; // 50x read speed
        p[9] = (50 * 176) & 0xff;
        p[10] = 0 >> 8; // No volume
        p[11] = 0 & 0xff;
        p[12] = 2048 >> 8; // 2M buffer
        p[13] = 2048 & 0xff;
        p[14] = (16 * 176) >> 8; // 16x read speed current
        p[15] = (16 * 176) & 0xff;
        p[18] = (16 * 176) >> 8; // 16x write speed
        p[19] = (16 * 176) & 0xff;
        p[20] = (16 * 176) >> 8; // 16x write speed current
        p[21] = (16 * 176) & 0xff;
645
        return p[1] + 2;
646 647 648 649 650 651 652 653 654 655

    default:
        return 0;
    }
}

static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    uint64_t nb_sectors;
656
    int page, dbd, buflen, page_control;
657
    uint8_t *p;
658
    uint8_t dev_specific_param;
659 660 661

    dbd = req->cmd.buf[1]  & 0x8;
    page = req->cmd.buf[2] & 0x3f;
662
    page_control = (req->cmd.buf[2] & 0xc0) >> 6;
663 664
    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
        (req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, req->cmd.xfer, page_control);
665 666 667
    memset(outbuf, 0, req->cmd.xfer);
    p = outbuf;

668
    if (bdrv_is_read_only(s->bs)) {
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
        dev_specific_param = 0x80; /* Readonly.  */
    } else {
        dev_specific_param = 0x00;
    }

    if (req->cmd.buf[0] == MODE_SENSE) {
        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;
684 685
    }

686
    bdrv_get_geometry(s->bs, &nb_sectors);
687
    if (!dbd && nb_sectors) {
688 689 690 691 692
        if (req->cmd.buf[0] == MODE_SENSE) {
            outbuf[3] = 8; /* Block descriptor length  */
        } else { /* MODE_SENSE_10 */
            outbuf[7] = 8; /* Block descriptor length  */
        }
693 694
        nb_sectors /= s->cluster_size;
        if (nb_sectors > 0xffffff)
695
            nb_sectors = 0;
696 697 698 699 700 701 702 703 704 705 706
        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;
    }

707 708 709 710
    if (page_control == 3) { /* Saved Values */
        return -1; /* ILLEGAL_REQUEST */
    }

711 712 713 714 715
    switch (page) {
    case 0x04:
    case 0x05:
    case 0x08:
    case 0x2a:
716
        p += mode_sense_page(req, page, p, page_control);
717 718
        break;
    case 0x3f:
719 720
        p += mode_sense_page(req, 0x08, p, page_control);
        p += mode_sense_page(req, 0x2a, p, page_control);
721
        break;
722 723
    default:
        return -1; /* ILLEGAL_REQUEST */
724 725 726
    }

    buflen = p - outbuf;
727 728 729 730 731 732 733 734 735 736 737
    /*
     * 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.
     */
    if (req->cmd.buf[0] == MODE_SENSE) {
        outbuf[0] = buflen - 1;
    } else { /* MODE_SENSE_10 */
        outbuf[0] = ((buflen - 2) >> 8) & 0xff;
        outbuf[1] = (buflen - 2) & 0xff;
    }
738 739 740 741 742
    if (buflen > req->cmd.xfer)
        buflen = req->cmd.xfer;
    return buflen;
}

743 744 745 746 747 748 749 750 751
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];
752
    bdrv_get_geometry(s->bs, &nb_sectors);
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
    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;
    }
    if (toclen > req->cmd.xfer)
        toclen = req->cmd.xfer;
    return toclen;
}

778
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
779
{
780
    SCSIRequest *req = &r->req;
781 782
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    uint64_t nb_sectors;
783
    int buflen = 0;
784
    int ret;
785 786 787

    switch (req->cmd.buf[0]) {
    case TEST_UNIT_READY:
788
        if (!bdrv_is_inserted(s->bs))
789
            goto not_ready;
H
Hannes Reinecke 已提交
790
        break;
791 792 793 794
    case INQUIRY:
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
H
Hannes Reinecke 已提交
795
        break;
796 797 798 799 800 801
    case MODE_SENSE:
    case MODE_SENSE_10:
        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
802 803 804 805 806
    case READ_TOC:
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
    case RESERVE:
        if (req->cmd.buf[1] & 1)
            goto illegal_request;
        break;
    case RESERVE_10:
        if (req->cmd.buf[1] & 3)
            goto illegal_request;
        break;
    case RELEASE:
        if (req->cmd.buf[1] & 1)
            goto illegal_request;
        break;
    case RELEASE_10:
        if (req->cmd.buf[1] & 3)
            goto illegal_request;
        break;
823
    case START_STOP:
H
Hannes Reinecke 已提交
824
        if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
825
            /* load/eject medium */
826
            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
827
        }
H
Hannes Reinecke 已提交
828
        break;
829
    case ALLOW_MEDIUM_REMOVAL:
830
        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
H
Hannes Reinecke 已提交
831
        break;
832
    case READ_CAPACITY_10:
833
        /* The normal LEN field for this command is zero.  */
H
Hannes Reinecke 已提交
834 835
        memset(outbuf, 0, 8);
        bdrv_get_geometry(s->bs, &nb_sectors);
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
        if (!nb_sectors)
            goto not_ready;
        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. */
        if (nb_sectors > UINT32_MAX)
            nb_sectors = UINT32_MAX;
        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 已提交
855
        break;
856
    case SYNCHRONIZE_CACHE:
857 858 859 860 861 862
        ret = bdrv_flush(s->bs);
        if (ret < 0) {
            if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
                return -1;
            }
        }
863
        break;
864 865 866 867 868 869 870
    case GET_CONFIGURATION:
        memset(outbuf, 0, 8);
        /* ??? This should probably return much more information.  For now
           just return the basic header indicating the CD-ROM profile.  */
        outbuf[7] = 8; // CD-ROM
        buflen = 8;
        break;
871 872 873 874 875
    case SERVICE_ACTION_IN:
        /* Service Action In subcommands. */
        if ((req->cmd.buf[1] & 31) == 0x10) {
            DPRINTF("SAI READ CAPACITY(16)\n");
            memset(outbuf, 0, req->cmd.xfer);
876
            bdrv_get_geometry(s->bs, &nb_sectors);
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
            if (!nb_sectors)
                goto not_ready;
            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 已提交
896 897
            outbuf[12] = 0;
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
898 899 900 901 902 903

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

904 905 906 907 908 909
            /* Protection, exponent and lowest lba field left blank. */
            buflen = req->cmd.xfer;
            break;
        }
        DPRINTF("Unsupported Service Action In\n");
        goto illegal_request;
910
    case VERIFY_10:
911
        break;
912
    default:
913
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
914
        return -1;
915 916 917 918
    }
    return buflen;

not_ready:
919
    if (!bdrv_is_inserted(s->bs)) {
920
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
921
    } else {
922
        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
923
    }
924
    return -1;
925 926

illegal_request:
927
    scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
928
    return -1;
929 930
}

P
pbrook 已提交
931 932 933 934 935
/* 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.  */

936
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
P
pbrook 已提交
937
{
938 939
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
P
Paolo Bonzini 已提交
940
    int32_t len;
P
pbrook 已提交
941 942
    uint8_t command;
    uint8_t *outbuf;
943
    int rc;
P
pbrook 已提交
944 945

    command = buf[0];
946
    outbuf = (uint8_t *)r->iov.iov_base;
947
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
948

P
pbrook 已提交
949 950 951
#ifdef DEBUG_SCSI
    {
        int i;
952
        for (i = 1; i < r->req.cmd.len; i++) {
P
pbrook 已提交
953 954 955 956 957
            printf(" 0x%02x", buf[i]);
        }
        printf("\n");
    }
#endif
958

P
pbrook 已提交
959
    switch (command) {
960
    case TEST_UNIT_READY:
961
    case INQUIRY:
962 963
    case MODE_SENSE:
    case MODE_SENSE_10:
964 965 966 967
    case RESERVE:
    case RESERVE_10:
    case RELEASE:
    case RELEASE_10:
968
    case START_STOP:
969
    case ALLOW_MEDIUM_REMOVAL:
970
    case READ_CAPACITY_10:
971
    case SYNCHRONIZE_CACHE:
972
    case READ_TOC:
973
    case GET_CONFIGURATION:
974
    case SERVICE_ACTION_IN:
975
    case VERIFY_10:
976 977
        rc = scsi_disk_emulate_command(r, outbuf);
        if (rc < 0) {
978
            return 0;
979
        }
980 981

        r->iov.iov_len = rc;
982
        break;
983 984
    case READ_6:
    case READ_10:
G
Gerd Hoffmann 已提交
985 986
    case READ_12:
    case READ_16:
987
        len = r->req.cmd.xfer / s->qdev.blocksize;
988 989
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
        if (r->req.cmd.lba > s->max_lba)
990
            goto illegal_lba;
991
        r->sector = r->req.cmd.lba * s->cluster_size;
P
pbrook 已提交
992
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
993
        break;
994 995
    case WRITE_6:
    case WRITE_10:
G
Gerd Hoffmann 已提交
996 997
    case WRITE_12:
    case WRITE_16:
998
    case WRITE_VERIFY_10:
999 1000
    case WRITE_VERIFY_12:
    case WRITE_VERIFY_16:
1001
        len = r->req.cmd.xfer / s->qdev.blocksize;
1002
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1003 1004 1005
                (command & 0xe) == 0xe ? "And Verify " : "",
                r->req.cmd.lba, len);
        if (r->req.cmd.lba > s->max_lba)
1006
            goto illegal_lba;
1007
        r->sector = r->req.cmd.lba * s->cluster_size;
P
pbrook 已提交
1008
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
1009
        break;
1010
    case MODE_SELECT:
1011
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1012 1013
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1014
        if (r->req.cmd.xfer > 12) {
1015 1016 1017 1018
            goto fail;
        }
        break;
    case MODE_SELECT_10:
1019
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1020 1021
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1022
        if (r->req.cmd.xfer > 16) {
1023 1024 1025 1026 1027
            goto fail;
        }
        break;
    case SEEK_6:
    case SEEK_10:
1028 1029 1030
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
                r->req.cmd.lba);
        if (r->req.cmd.lba > s->max_lba) {
1031 1032
            goto illegal_lba;
        }
1033 1034
        break;
    case WRITE_SAME_16:
1035
        len = r->req.cmd.xfer / s->qdev.blocksize;
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

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

        rc = bdrv_discard(s->bs, r->req.cmd.lba * s->cluster_size,
                          len * s->cluster_size);
        if (rc < 0) {
            /* XXX: better error code ?*/
            goto fail;
        }

1058
        break;
1059 1060
    case REQUEST_SENSE:
        abort();
P
pbrook 已提交
1061
    default:
1062
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1063
        scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
1064
        return 0;
P
pbrook 已提交
1065
    fail:
1066
        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
1067
        return 0;
1068
    illegal_lba:
1069
        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
1070
        return 0;
P
pbrook 已提交
1071
    }
1072
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1073
        scsi_req_complete(&r->req, GOOD);
P
pbrook 已提交
1074
    }
1075
    len = r->sector_count * 512 + r->iov.iov_len;
1076 1077
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        return -len;
P
pbrook 已提交
1078 1079 1080
    } else {
        if (!r->sector_count)
            r->sector_count = -1;
1081
        return len;
P
pbrook 已提交
1082 1083 1084
    }
}

J
Jan Kiszka 已提交
1085 1086 1087 1088 1089
static void scsi_disk_reset(DeviceState *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
    uint64_t nb_sectors;

1090
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
J
Jan Kiszka 已提交
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103

    bdrv_get_geometry(s->bs, &nb_sectors);
    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);

1104
    scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
1105
    blockdev_mark_auto_del(s->qdev.conf.bs);
G
Gerd Hoffmann 已提交
1106 1107
}

H
Hannes Reinecke 已提交
1108
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
P
pbrook 已提交
1109
{
1110
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1111
    DriveInfo *dinfo;
P
pbrook 已提交
1112

1113
    if (!s->qdev.conf.bs) {
1114
        error_report("scsi-disk: drive property not set");
1115 1116
        return -1;
    }
1117
    s->bs = s->qdev.conf.bs;
1118

H
Hannes Reinecke 已提交
1119
    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
1120 1121 1122 1123
        error_report("Device needs media, but drive is empty");
        return -1;
    }

1124
    if (!s->serial) {
1125 1126
        /* try to fall back to value set with legacy -drive serial=... */
        dinfo = drive_get_by_blockdev(s->bs);
1127
        if (*dinfo->serial) {
1128
            s->serial = g_strdup(dinfo->serial);
1129
        }
1130 1131
    }

1132
    if (!s->version) {
1133
        s->version = g_strdup(QEMU_VERSION);
1134 1135
    }

1136
    if (bdrv_is_sg(s->bs)) {
1137
        error_report("scsi-disk: unwanted /dev/sg*");
1138 1139 1140
        return -1;
    }

H
Hannes Reinecke 已提交
1141
    if (scsi_type == TYPE_ROM) {
1142
        s->qdev.blocksize = 2048;
H
Hannes Reinecke 已提交
1143
    } else if (scsi_type == TYPE_DISK) {
1144
        s->qdev.blocksize = s->qdev.conf.logical_block_size;
H
Hannes Reinecke 已提交
1145 1146 1147
    } else {
        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
        return -1;
P
pbrook 已提交
1148
    }
1149
    s->cluster_size = s->qdev.blocksize / 512;
1150
    s->bs->buffer_alignment = s->qdev.blocksize;
1151

H
Hannes Reinecke 已提交
1152
    s->qdev.type = scsi_type;
1153
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
H
Hannes Reinecke 已提交
1154
    bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
1155
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
1156 1157 1158
    return 0;
}

1159 1160
static int scsi_hd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1161
    return scsi_initfn(dev, TYPE_DISK);
1162 1163 1164 1165
}

static int scsi_cd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1166
    return scsi_initfn(dev, TYPE_ROM);
1167 1168 1169 1170
}

static int scsi_disk_initfn(SCSIDevice *dev)
{
1171
    DriveInfo *dinfo;
H
Hannes Reinecke 已提交
1172
    uint8_t scsi_type;
1173 1174

    if (!dev->conf.bs) {
H
Hannes Reinecke 已提交
1175
        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
1176
    } else {
1177
        dinfo = drive_get_by_blockdev(dev->conf.bs);
H
Hannes Reinecke 已提交
1178
        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
1179 1180
    }

H
Hannes Reinecke 已提交
1181
    return scsi_initfn(dev, scsi_type);
1182 1183
}

P
Paolo Bonzini 已提交
1184 1185
static SCSIReqOps scsi_disk_reqops = {
    .size         = sizeof(SCSIDiskReq),
1186 1187 1188 1189 1190 1191
    .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 已提交
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
};

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;
    SCSIDiskReq *r;

    req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
    r = DO_UPCAST(SCSIDiskReq, req, req);
    r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
    return req;
}

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
#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,
1221
        .alloc_req    = scsi_new_request,
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
        .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,
1235
        .alloc_req    = scsi_new_request,
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
        .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,
1248
        .alloc_req    = scsi_new_request,
1249 1250 1251 1252 1253 1254
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
            DEFINE_PROP_END_OF_LIST(),
        }
    }
1255 1256 1257 1258
};

static void scsi_disk_register_devices(void)
{
1259 1260 1261 1262 1263
    int i;

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