scsi-disk.c 38.2 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
{
89 90
    DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
            r->req.tag, status, 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
    case REQUEST_SENSE:
        if (req->cmd.xfer < 4)
            goto illegal_request;
794 795
        buflen = scsi_device_get_sense(&s->qdev, outbuf, req->cmd.xfer,
                                       (req->cmd.buf[1] & 1) == 0);
796
        break;
797 798 799 800
    case INQUIRY:
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
H
Hannes Reinecke 已提交
801
        break;
802 803 804 805 806 807
    case MODE_SENSE:
    case MODE_SENSE_10:
        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
808 809 810 811 812
    case READ_TOC:
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
    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;
829
    case START_STOP:
H
Hannes Reinecke 已提交
830
        if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
831
            /* load/eject medium */
832
            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
833
        }
H
Hannes Reinecke 已提交
834
        break;
835
    case ALLOW_MEDIUM_REMOVAL:
836
        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
H
Hannes Reinecke 已提交
837
        break;
838
    case READ_CAPACITY_10:
839
        /* The normal LEN field for this command is zero.  */
H
Hannes Reinecke 已提交
840 841
        memset(outbuf, 0, 8);
        bdrv_get_geometry(s->bs, &nb_sectors);
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
        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 已提交
861
        break;
862
    case SYNCHRONIZE_CACHE:
863 864 865 866 867 868
        ret = bdrv_flush(s->bs);
        if (ret < 0) {
            if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
                return -1;
            }
        }
869
        break;
870 871 872 873 874 875 876
    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;
877 878 879 880 881
    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);
882
            bdrv_get_geometry(s->bs, &nb_sectors);
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
            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 已提交
902 903
            outbuf[12] = 0;
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
904 905 906 907 908 909

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

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

not_ready:
925
    if (!bdrv_is_inserted(s->bs)) {
926
        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
927
    } else {
928
        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
929
    }
930
    return -1;
931 932

illegal_request:
933
    scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
934
    return -1;
935 936
}

P
pbrook 已提交
937 938 939 940 941
/* 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.  */

942
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
P
pbrook 已提交
943
{
944 945
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
P
Paolo Bonzini 已提交
946
    int32_t len;
P
pbrook 已提交
947 948
    uint8_t command;
    uint8_t *outbuf;
949
    int rc;
P
pbrook 已提交
950 951

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

P
pbrook 已提交
955 956 957
#ifdef DEBUG_SCSI
    {
        int i;
958
        for (i = 1; i < r->req.cmd.len; i++) {
P
pbrook 已提交
959 960 961 962 963
            printf(" 0x%02x", buf[i]);
        }
        printf("\n");
    }
#endif
964

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

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

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

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

J
Jan Kiszka 已提交
1090 1091 1092 1093 1094
static void scsi_disk_reset(DeviceState *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
    uint64_t nb_sectors;

P
Paolo Bonzini 已提交
1095
    scsi_device_purge_requests(&s->qdev);
J
Jan Kiszka 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108

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

P
Paolo Bonzini 已提交
1109
    scsi_device_purge_requests(&s->qdev);
1110
    blockdev_mark_auto_del(s->qdev.conf.bs);
G
Gerd Hoffmann 已提交
1111 1112
}

H
Hannes Reinecke 已提交
1113
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
P
pbrook 已提交
1114
{
1115
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1116
    DriveInfo *dinfo;
P
pbrook 已提交
1117

1118
    if (!s->qdev.conf.bs) {
1119
        error_report("scsi-disk: drive property not set");
1120 1121
        return -1;
    }
1122
    s->bs = s->qdev.conf.bs;
1123

H
Hannes Reinecke 已提交
1124
    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
1125 1126 1127 1128
        error_report("Device needs media, but drive is empty");
        return -1;
    }

1129
    if (!s->serial) {
1130 1131
        /* try to fall back to value set with legacy -drive serial=... */
        dinfo = drive_get_by_blockdev(s->bs);
1132 1133 1134
        if (*dinfo->serial) {
            s->serial = qemu_strdup(dinfo->serial);
        }
1135 1136
    }

1137 1138 1139 1140
    if (!s->version) {
        s->version = qemu_strdup(QEMU_VERSION);
    }

1141
    if (bdrv_is_sg(s->bs)) {
1142
        error_report("scsi-disk: unwanted /dev/sg*");
1143 1144 1145
        return -1;
    }

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

H
Hannes Reinecke 已提交
1157
    s->qdev.type = scsi_type;
1158
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
H
Hannes Reinecke 已提交
1159
    bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
1160
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
1161 1162 1163
    return 0;
}

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

static int scsi_cd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1171
    return scsi_initfn(dev, TYPE_ROM);
1172 1173 1174 1175
}

static int scsi_disk_initfn(SCSIDevice *dev)
{
1176
    DriveInfo *dinfo;
H
Hannes Reinecke 已提交
1177
    uint8_t scsi_type;
1178 1179

    if (!dev->conf.bs) {
H
Hannes Reinecke 已提交
1180
        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
1181
    } else {
1182
        dinfo = drive_get_by_blockdev(dev->conf.bs);
H
Hannes Reinecke 已提交
1183
        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
1184 1185
    }

H
Hannes Reinecke 已提交
1186
    return scsi_initfn(dev, scsi_type);
1187 1188
}

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

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

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

static void scsi_disk_register_devices(void)
{
1264 1265 1266 1267 1268
    int i;

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