scsi-disk.c 36.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 15
 *
 * This code is licenced 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

44 45
#define SCSI_REQ_STATUS_RETRY 0x01

46 47
typedef struct SCSIDiskState SCSIDiskState;

48 49
typedef struct SCSIDiskReq {
    SCSIRequest req;
50
    /* ??? We should probably keep track of whether the data transfer is
P
pbrook 已提交
51
       a read or a write.  Currently we rely on the host getting it right.  */
P
pbrook 已提交
52
    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
53 54
    uint64_t sector;
    uint32_t sector_count;
55 56
    struct iovec iov;
    QEMUIOVector qiov;
57
    uint32_t status;
58
} SCSIDiskReq;
P
pbrook 已提交
59

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

73 74
static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag,
        uint32_t lun)
P
pbrook 已提交
75
{
76
    SCSIRequest *req;
77
    SCSIDiskReq *r;
P
pbrook 已提交
78

79
    req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun);
80
    r = DO_UPCAST(SCSIDiskReq, req, req);
81
    r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
P
pbrook 已提交
82
    return r;
P
pbrook 已提交
83 84
}

85
static void scsi_remove_request(SCSIDiskReq *r)
P
pbrook 已提交
86
{
87
    qemu_vfree(r->iov.iov_base);
88
    scsi_req_free(&r->req);
P
pbrook 已提交
89 90
}

91
static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
P
pbrook 已提交
92
{
93
    return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
P
pbrook 已提交
94 95
}

G
Gerd Hoffmann 已提交
96 97 98 99 100 101
static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
{
    req->status = status;
    scsi_dev_set_sense(req->dev, sense_code);
}

P
pbrook 已提交
102
/* Helper function for command completion.  */
103
static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
P
pbrook 已提交
104
{
105 106
    DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
            r->req.tag, status, sense);
G
Gerd Hoffmann 已提交
107 108
    scsi_req_set_status(&r->req, status, sense);
    scsi_req_complete(&r->req);
109
    scsi_remove_request(r);
P
pbrook 已提交
110 111 112
}

/* Cancel a pending data transfer.  */
T
ths 已提交
113
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
P
pbrook 已提交
114
{
115
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
116
    SCSIDiskReq *r;
P
pbrook 已提交
117 118 119
    DPRINTF("Cancel tag=0x%x\n", tag);
    r = scsi_find_request(s, tag);
    if (r) {
120 121 122
        if (r->req.aiocb)
            bdrv_aio_cancel(r->req.aiocb);
        r->req.aiocb = NULL;
P
pbrook 已提交
123 124 125 126 127 128
        scsi_remove_request(r);
    }
}

static void scsi_read_complete(void * opaque, int ret)
{
129
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
P
pbrook 已提交
130

131 132
    r->req.aiocb = NULL;

P
pbrook 已提交
133 134
    if (ret) {
        DPRINTF("IO error\n");
135
        r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
G
Gerd Hoffmann 已提交
136
        scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
P
pbrook 已提交
137 138
        return;
    }
139
    DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
P
pbrook 已提交
140

141
    r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
P
pbrook 已提交
142 143
}

P
pbrook 已提交
144
/* Read more data from scsi device into buffer.  */
T
ths 已提交
145
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
P
pbrook 已提交
146
{
147
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
148
    SCSIDiskReq *r;
P
pbrook 已提交
149 150
    uint32_t n;

P
pbrook 已提交
151 152 153
    r = scsi_find_request(s, tag);
    if (!r) {
        BADF("Bad read tag 0x%x\n", tag);
B
blueswir1 已提交
154
        /* ??? This is the wrong error.  */
G
Gerd Hoffmann 已提交
155
        scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
P
pbrook 已提交
156
        return;
P
pbrook 已提交
157
    }
P
pbrook 已提交
158
    if (r->sector_count == (uint32_t)-1) {
159
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
P
pbrook 已提交
160
        r->sector_count = 0;
161
        r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
P
pbrook 已提交
162
        return;
P
pbrook 已提交
163
    }
P
pbrook 已提交
164 165
    DPRINTF("Read sector_count=%d\n", r->sector_count);
    if (r->sector_count == 0) {
G
Gerd Hoffmann 已提交
166
        scsi_command_complete(r, GOOD, NO_SENSE);
P
pbrook 已提交
167
        return;
P
pbrook 已提交
168 169
    }

P
pbrook 已提交
170 171 172 173
    n = r->sector_count;
    if (n > SCSI_DMA_BUF_SIZE / 512)
        n = SCSI_DMA_BUF_SIZE / 512;

174 175
    r->iov.iov_len = n * 512;
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
176
    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
177
                              scsi_read_complete, r);
178
    if (r->req.aiocb == NULL)
G
Gerd Hoffmann 已提交
179
        scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
P
pbrook 已提交
180 181
    r->sector += n;
    r->sector_count -= n;
P
pbrook 已提交
182 183
}

184
static int scsi_handle_write_error(SCSIDiskReq *r, int error)
185
{
186
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
187
    BlockErrorAction action = bdrv_get_on_error(s->bs, 0);
188

189
    if (action == BLOCK_ERR_IGNORE) {
190
        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0);
191
        return 0;
192
    }
193 194 195 196

    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
            || action == BLOCK_ERR_STOP_ANY) {
        r->status |= SCSI_REQ_STATUS_RETRY;
197
        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0);
198
        vm_stop(0);
199
    } else {
G
Gerd Hoffmann 已提交
200 201
        scsi_command_complete(r, CHECK_CONDITION,
                HARDWARE_ERROR);
202
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0);
203 204 205 206 207
    }

    return 1;
}

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

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

    if (ret) {
217 218
        if (scsi_handle_write_error(r, -ret))
            return;
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) {
G
Gerd Hoffmann 已提交
225
        scsi_command_complete(r, GOOD, NO_SENSE);
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 233
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
        r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
P
pbrook 已提交
234 235 236
    }
}

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

242
    n = r->iov.iov_len / 512;
243
    if (n) {
244
        qemu_iovec_init_external(&r->qiov, &r->iov, 1);
245
        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
246
                                   scsi_write_complete, r);
247
        if (r->req.aiocb == NULL)
G
Gerd Hoffmann 已提交
248 249
            scsi_command_complete(r, CHECK_CONDITION,
                                  HARDWARE_ERROR);
250 251 252 253 254 255
    } else {
        /* Invoke completion routine to fetch data from host.  */
        scsi_write_complete(r, 0);
    }
}

P
pbrook 已提交
256 257
/* Write data to a scsi device.  Returns nonzero on failure.
   The transfer may complete asynchronously.  */
T
ths 已提交
258
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
P
pbrook 已提交
259
{
260
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
261
    SCSIDiskReq *r;
P
pbrook 已提交
262

P
pbrook 已提交
263 264 265 266
    DPRINTF("Write data tag=0x%x\n", tag);
    r = scsi_find_request(s, tag);
    if (!r) {
        BADF("Bad write tag 0x%x\n", tag);
G
Gerd Hoffmann 已提交
267
        scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
P
pbrook 已提交
268 269
        return 1;
    }
270

271
    if (r->req.aiocb)
P
pbrook 已提交
272
        BADF("Data transfer already in progress\n");
273 274

    scsi_write_request(r);
P
pbrook 已提交
275

P
pbrook 已提交
276 277
    return 0;
}
P
pbrook 已提交
278

279
static void scsi_dma_restart_bh(void *opaque)
280
{
281
    SCSIDiskState *s = opaque;
282 283
    SCSIRequest *req;
    SCSIDiskReq *r;
284 285 286

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

288 289
    QTAILQ_FOREACH(req, &s->qdev.requests, next) {
        r = DO_UPCAST(SCSIDiskReq, req, req);
290 291 292 293 294 295 296
        if (r->status & SCSI_REQ_STATUS_RETRY) {
            r->status &= ~SCSI_REQ_STATUS_RETRY;
            scsi_write_request(r); 
        }
    }
}

297 298
static void scsi_dma_restart_cb(void *opaque, int running, int reason)
{
299
    SCSIDiskState *s = opaque;
300 301 302 303 304 305 306 307 308 309

    if (!running)
        return;

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

P
pbrook 已提交
310
/* Return a pointer to the data buffer.  */
T
ths 已提交
311
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
P
pbrook 已提交
312
{
313
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
314
    SCSIDiskReq *r;
P
pbrook 已提交
315

P
pbrook 已提交
316 317 318 319
    r = scsi_find_request(s, tag);
    if (!r) {
        BADF("Bad buffer tag 0x%x\n", tag);
        return NULL;
P
pbrook 已提交
320
    }
321
    return (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
322 323
}

324 325
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
G
Gerd Hoffmann 已提交
326
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    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;
        }

344
        if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
345 346 347 348 349 350 351 352 353 354 355
            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 */
            DPRINTF("Inquiry EVPD[Supported pages] "
                    "buffer size %zd\n", req->cmd.xfer);
C
Christoph Hellwig 已提交
356
            outbuf[buflen++] = 4;    // number of pages
357 358 359
            outbuf[buflen++] = 0x00; // list of supported pages (this page)
            outbuf[buflen++] = 0x80; // unit serial number
            outbuf[buflen++] = 0x83; // device identification
C
Christoph Hellwig 已提交
360
            outbuf[buflen++] = 0xb0; // block device characteristics
361 362 363 364
            break;

        case 0x80: /* Device serial number, optional */
        {
365
            int l = strlen(s->serial);
366 367 368 369 370 371 372 373 374

            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;
375
            memcpy(outbuf+buflen, s->serial, l);
376 377 378 379 380 381 382
            buflen += l;
            break;
        }

        case 0x83: /* Device identification page, mandatory */
        {
            int max_len = 255 - 8;
383
            int id_len = strlen(bdrv_get_device_name(s->bs));
384 385 386 387 388 389 390 391 392 393 394 395

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

            outbuf[buflen++] = 3 + id_len;
            outbuf[buflen++] = 0x2; // ASCII
            outbuf[buflen++] = 0;   // not officially assigned
            outbuf[buflen++] = 0;   // reserved
            outbuf[buflen++] = id_len; // length of data following

396
            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
397 398 399
            buflen += id_len;
            break;
        }
C
Christoph Hellwig 已提交
400 401
        case 0xb0: /* block device characteristics */
        {
402 403 404 405
            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 已提交
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422

            /* 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;
            break;
        }
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
        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);

    if (req->lun || req->cmd.buf[1] >> 5) {
        outbuf[0] = 0x7f;	/* LUN not supported */
        return buflen;
    }

457
    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
458 459
        outbuf[0] = 5;
        outbuf[1] = 0x80;
L
Laszlo Ast 已提交
460
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
461 462
    } else {
        outbuf[0] = 0;
L
Laszlo Ast 已提交
463
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
464
    }
L
Laszlo Ast 已提交
465
    memcpy(&outbuf[8], "QEMU    ", 8);
G
Gerd Hoffmann 已提交
466
    memset(&outbuf[32], 0, 4);
467
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
468 469 470 471 472 473
    /*
     * 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 已提交
474
    outbuf[2] = 5;
475
    outbuf[3] = 2; /* Format 2 */
476 477 478 479 480 481 482 483 484

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

485 486 487 488 489
    /* Sync data transfer and TCQ.  */
    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
    return buflen;
}

490 491
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
                           int page_control)
492 493
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
494
    BlockDriverState *bdrv = s->bs;
495 496
    int cylinders, heads, secs;

497 498 499 500 501 502
    /*
     * 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.
     */
503 504 505 506
    switch (page) {
    case 4: /* Rigid disk device geometry page. */
        p[0] = 4;
        p[1] = 0x16;
507 508 509
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
        /* 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;
534
        return p[1] + 2;
535 536 537 538

    case 5: /* Flexible disk device geometry page. */
        p[0] = 5;
        p[1] = 0x1e;
539 540 541
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
        /* 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;
573
        return p[1] + 2;
574 575 576 577

    case 8: /* Caching page.  */
        p[0] = 8;
        p[1] = 0x12;
578 579 580
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
581
        if (bdrv_enable_write_cache(s->bs)) {
582 583
            p[2] = 4; /* WCE */
        }
584
        return p[1] + 2;
585 586 587 588 589 590

    case 0x2a: /* CD Capabilities and Mechanical Status page. */
        if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
            return 0;
        p[0] = 0x2a;
        p[1] = 0x14;
591 592 593
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
594 595 596 597 598 599 600
        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 */
601
        p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
        /* 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;
617
        return p[1] + 2;
618 619 620 621 622 623 624 625 626 627

    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;
628
    int page, dbd, buflen, page_control;
629
    uint8_t *p;
630
    uint8_t dev_specific_param;
631 632 633

    dbd = req->cmd.buf[1]  & 0x8;
    page = req->cmd.buf[2] & 0x3f;
634
    page_control = (req->cmd.buf[2] & 0xc0) >> 6;
635 636
    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);
637 638 639
    memset(outbuf, 0, req->cmd.xfer);
    p = outbuf;

640
    if (bdrv_is_read_only(s->bs)) {
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        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;
656 657
    }

658
    bdrv_get_geometry(s->bs, &nb_sectors);
659
    if (!dbd && nb_sectors) {
660 661 662 663 664
        if (req->cmd.buf[0] == MODE_SENSE) {
            outbuf[3] = 8; /* Block descriptor length  */
        } else { /* MODE_SENSE_10 */
            outbuf[7] = 8; /* Block descriptor length  */
        }
665 666
        nb_sectors /= s->cluster_size;
        if (nb_sectors > 0xffffff)
667
            nb_sectors = 0;
668 669 670 671 672 673 674 675 676 677 678
        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;
    }

679 680 681 682
    if (page_control == 3) { /* Saved Values */
        return -1; /* ILLEGAL_REQUEST */
    }

683 684 685 686 687
    switch (page) {
    case 0x04:
    case 0x05:
    case 0x08:
    case 0x2a:
688
        p += mode_sense_page(req, page, p, page_control);
689 690
        break;
    case 0x3f:
691 692
        p += mode_sense_page(req, 0x08, p, page_control);
        p += mode_sense_page(req, 0x2a, p, page_control);
693
        break;
694 695
    default:
        return -1; /* ILLEGAL_REQUEST */
696 697 698
    }

    buflen = p - outbuf;
699 700 701 702 703 704 705 706 707 708 709
    /*
     * 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;
    }
710 711 712 713 714
    if (buflen > req->cmd.xfer)
        buflen = req->cmd.xfer;
    return buflen;
}

715 716 717 718 719 720 721 722 723
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];
724
    bdrv_get_geometry(s->bs, &nb_sectors);
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
    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;
}

750 751
static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
{
752 753
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    uint64_t nb_sectors;
754 755 756 757
    int buflen = 0;

    switch (req->cmd.buf[0]) {
    case TEST_UNIT_READY:
758
        if (!bdrv_is_inserted(s->bs))
759 760
            goto not_ready;
	break;
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
    case REQUEST_SENSE:
        if (req->cmd.xfer < 4)
            goto illegal_request;
        memset(outbuf, 0, 4);
        buflen = 4;
        if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
            memset(outbuf, 0, 18);
            buflen = 18;
            outbuf[7] = 10;
            /* asc 0x3a, ascq 0: Medium not present */
            outbuf[12] = 0x3a;
            outbuf[13] = 0;
        }
        outbuf[0] = 0xf0;
        outbuf[1] = 0;
        outbuf[2] = req->dev->sense.key;
        scsi_dev_clear_sense(req->dev);
        break;
779 780 781 782 783
    case INQUIRY:
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
	break;
784 785 786 787 788 789
    case MODE_SENSE:
    case MODE_SENSE_10:
        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
790 791 792 793 794
    case READ_TOC:
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
    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;
811
    case START_STOP:
812
        if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
813
            /* load/eject medium */
814
            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
815 816
        }
	break;
817
    case ALLOW_MEDIUM_REMOVAL:
818
        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
819
	break;
820 821 822
    case READ_CAPACITY:
        /* The normal LEN field for this command is zero.  */
	memset(outbuf, 0, 8);
823
	bdrv_get_geometry(s->bs, &nb_sectors);
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
        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;
	break;
844
    case SYNCHRONIZE_CACHE:
845
        bdrv_flush(s->bs);
846
        break;
847 848 849 850 851 852 853
    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;
854 855 856 857 858
    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);
859
            bdrv_get_geometry(s->bs, &nb_sectors);
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
            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 已提交
879 880
            outbuf[12] = 0;
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
881 882 883 884 885 886
            /* Protection, exponent and lowest lba field left blank. */
            buflen = req->cmd.xfer;
            break;
        }
        DPRINTF("Unsupported Service Action In\n");
        goto illegal_request;
887 888 889 890 891 892 893
    case REPORT_LUNS:
        if (req->cmd.xfer < 16)
            goto illegal_request;
        memset(outbuf, 0, 16);
        outbuf[3] = 8;
        buflen = 16;
        break;
894 895
    case VERIFY:
        break;
896 897 898 899 900 901
    case REZERO_UNIT:
        DPRINTF("Rezero Unit\n");
        if (!bdrv_is_inserted(s->bs)) {
            goto not_ready;
        }
        break;
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
    default:
        goto illegal_request;
    }
    scsi_req_set_status(req, GOOD, NO_SENSE);
    return buflen;

not_ready:
    scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
    return 0;

illegal_request:
    scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
    return 0;
}

P
pbrook 已提交
917 918 919 920 921
/* 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.  */

T
ths 已提交
922 923
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
                                 uint8_t *buf, int lun)
P
pbrook 已提交
924
{
925
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
926
    uint64_t lba;
P
pbrook 已提交
927 928 929
    uint32_t len;
    int cmdlen;
    int is_write;
P
pbrook 已提交
930 931
    uint8_t command;
    uint8_t *outbuf;
932
    SCSIDiskReq *r;
933
    int rc;
P
pbrook 已提交
934 935 936 937 938

    command = buf[0];
    r = scsi_find_request(s, tag);
    if (r) {
        BADF("Tag 0x%x already in use\n", tag);
T
ths 已提交
939
        scsi_cancel_io(d, tag);
P
pbrook 已提交
940 941 942
    }
    /* ??? Tags are not unique for different luns.  We only implement a
       single lun, so this should not matter.  */
943
    r = scsi_new_request(s, tag, lun);
944
    outbuf = (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
945
    is_write = 0;
P
pbrook 已提交
946 947
    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
    switch (command >> 5) {
P
pbrook 已提交
948
    case 0:
949 950
        lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
              (((uint64_t) buf[1] & 0x1f) << 16);
P
pbrook 已提交
951 952 953 954 955
        len = buf[4];
        cmdlen = 6;
        break;
    case 1:
    case 2:
956 957
        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
P
pbrook 已提交
958 959 960 961
        len = buf[8] | (buf[7] << 8);
        cmdlen = 10;
        break;
    case 4:
962 963 964 965
        lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
              ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
              ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
              ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
P
pbrook 已提交
966 967 968 969
        len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
        cmdlen = 16;
        break;
    case 5:
970 971
        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
P
pbrook 已提交
972 973 974 975
        len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
        cmdlen = 12;
        break;
    default:
P
pbrook 已提交
976
        BADF("Unsupported command length, command %x\n", command);
P
pbrook 已提交
977 978 979 980 981 982 983 984 985 986 987
        goto fail;
    }
#ifdef DEBUG_SCSI
    {
        int i;
        for (i = 1; i < cmdlen; i++) {
            printf(" 0x%02x", buf[i]);
        }
        printf("\n");
    }
#endif
988 989 990 991 992 993 994 995

    if (scsi_req_parse(&r->req, buf) != 0) {
        BADF("Unsupported command length, command %x\n", command);
        goto fail;
    }
    assert(r->req.cmd.len == cmdlen);
    assert(r->req.cmd.lba == lba);

P
pbrook 已提交
996
    if (lun || buf[1] >> 5) {
P
pbrook 已提交
997
        /* Only LUN 0 supported.  */
P
pbrook 已提交
998
        DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
999
        if (command != REQUEST_SENSE && command != INQUIRY)
1000
            goto fail;
P
pbrook 已提交
1001
    }
P
pbrook 已提交
1002
    switch (command) {
1003
    case TEST_UNIT_READY:
1004
    case REQUEST_SENSE:
1005
    case INQUIRY:
1006 1007
    case MODE_SENSE:
    case MODE_SENSE_10:
1008 1009 1010 1011
    case RESERVE:
    case RESERVE_10:
    case RELEASE:
    case RELEASE_10:
1012
    case START_STOP:
1013
    case ALLOW_MEDIUM_REMOVAL:
1014
    case READ_CAPACITY:
1015
    case SYNCHRONIZE_CACHE:
1016
    case READ_TOC:
1017
    case GET_CONFIGURATION:
1018
    case SERVICE_ACTION_IN:
1019
    case REPORT_LUNS:
1020
    case VERIFY:
1021
    case REZERO_UNIT:
1022 1023 1024 1025 1026 1027
        rc = scsi_disk_emulate_command(&r->req, outbuf);
        if (rc > 0) {
            r->iov.iov_len = rc;
        } else {
            scsi_req_complete(&r->req);
            scsi_remove_request(r);
1028
            return 0;
1029
        }
1030
        break;
1031 1032
    case READ_6:
    case READ_10:
G
Gerd Hoffmann 已提交
1033 1034
    case READ_12:
    case READ_16:
1035
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
1036 1037
        if (lba > s->max_lba)
            goto illegal_lba;
P
pbrook 已提交
1038 1039
        r->sector = lba * s->cluster_size;
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
1040
        break;
1041 1042
    case WRITE_6:
    case WRITE_10:
G
Gerd Hoffmann 已提交
1043 1044
    case WRITE_12:
    case WRITE_16:
1045 1046 1047 1048 1049
    case WRITE_VERIFY:
    case WRITE_VERIFY_12:
    case WRITE_VERIFY_16:
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
                (command & 0xe) == 0xe ? "And Verify " : "", lba, len);
1050 1051
        if (lba > s->max_lba)
            goto illegal_lba;
P
pbrook 已提交
1052 1053
        r->sector = lba * s->cluster_size;
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
1054 1055
        is_write = 1;
        break;
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
    case MODE_SELECT:
        DPRINTF("Mode Select(6) (len %d)\n", len);
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
        if (len > 12) {
            goto fail;
        }
        break;
    case MODE_SELECT_10:
        DPRINTF("Mode Select(10) (len %d)\n", len);
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
        if (len > 16) {
            goto fail;
        }
        break;
    case SEEK_6:
    case SEEK_10:
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba);
        if (lba > s->max_lba) {
            goto illegal_lba;
        }
        break;
P
pbrook 已提交
1079 1080 1081
    default:
	DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
    fail:
G
Gerd Hoffmann 已提交
1082
        scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
P
pbrook 已提交
1083
	return 0;
1084
    illegal_lba:
G
Gerd Hoffmann 已提交
1085
        scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
1086
        return 0;
P
pbrook 已提交
1087
    }
1088
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
G
Gerd Hoffmann 已提交
1089
        scsi_command_complete(r, GOOD, NO_SENSE);
P
pbrook 已提交
1090
    }
1091
    len = r->sector_count * 512 + r->iov.iov_len;
P
pbrook 已提交
1092 1093 1094 1095 1096 1097
    if (is_write) {
        return -len;
    } else {
        if (!r->sector_count)
            r->sector_count = -1;
        return len;
P
pbrook 已提交
1098 1099 1100
    }
}

J
Jan Kiszka 已提交
1101
static void scsi_disk_purge_requests(SCSIDiskState *s)
G
Gerd Hoffmann 已提交
1102
{
1103
    SCSIDiskReq *r;
G
Gerd Hoffmann 已提交
1104

1105 1106
    while (!QTAILQ_EMPTY(&s->qdev.requests)) {
        r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
J
Jan Kiszka 已提交
1107 1108 1109
        if (r->req.aiocb) {
            bdrv_aio_cancel(r->req.aiocb);
        }
1110 1111
        scsi_remove_request(r);
    }
J
Jan Kiszka 已提交
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
}

static void scsi_disk_reset(DeviceState *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
    uint64_t nb_sectors;

    scsi_disk_purge_requests(s);

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

    scsi_disk_purge_requests(s);
1134
    blockdev_mark_auto_del(s->qdev.conf.bs);
G
Gerd Hoffmann 已提交
1135 1136
}

1137
static int scsi_disk_initfn(SCSIDevice *dev)
P
pbrook 已提交
1138
{
1139
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1140
    int is_cd;
1141
    DriveInfo *dinfo;
P
pbrook 已提交
1142

1143
    if (!s->qdev.conf.bs) {
1144
        error_report("scsi-disk: drive property not set");
1145 1146
        return -1;
    }
1147
    s->bs = s->qdev.conf.bs;
1148
    is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM;
1149

1150 1151 1152 1153 1154
    if (!is_cd && !bdrv_is_inserted(s->bs)) {
        error_report("Device needs media, but drive is empty");
        return -1;
    }

1155 1156 1157 1158 1159
    if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
        error_report("Device doesn't support drive option rerror");
        return -1;
    }

1160
    if (!s->serial) {
1161 1162 1163
        /* try to fall back to value set with legacy -drive serial=... */
        dinfo = drive_get_by_blockdev(s->bs);
        s->serial = qemu_strdup(*dinfo->serial ? dinfo->serial : "0");
1164 1165
    }

1166 1167 1168 1169
    if (!s->version) {
        s->version = qemu_strdup(QEMU_VERSION);
    }

1170
    if (bdrv_is_sg(s->bs)) {
1171
        error_report("scsi-disk: unwanted /dev/sg*");
1172 1173 1174
        return -1;
    }

1175
    if (is_cd) {
1176
        s->qdev.blocksize = 2048;
P
pbrook 已提交
1177
    } else {
1178
        s->qdev.blocksize = s->qdev.conf.logical_block_size;
P
pbrook 已提交
1179
    }
1180
    s->cluster_size = s->qdev.blocksize / 512;
1181
    s->bs->buffer_alignment = s->qdev.blocksize;
1182

1183
    s->qdev.type = TYPE_DISK;
1184
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
1185
    bdrv_set_removable(s->bs, is_cd);
1186 1187 1188 1189 1190 1191 1192
    return 0;
}

static SCSIDeviceInfo scsi_disk_info = {
    .qdev.name    = "scsi-disk",
    .qdev.desc    = "virtual scsi disk or cdrom",
    .qdev.size    = sizeof(SCSIDiskState),
J
Jan Kiszka 已提交
1193
    .qdev.reset   = scsi_disk_reset,
1194
    .init         = scsi_disk_initfn,
G
Gerd Hoffmann 已提交
1195
    .destroy      = scsi_destroy,
1196 1197 1198 1199 1200 1201
    .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,
    .qdev.props   = (Property[]) {
1202
        DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
G
Gerd Hoffmann 已提交
1203
        DEFINE_PROP_STRING("ver",  SCSIDiskState, version),
1204
        DEFINE_PROP_STRING("serial",  SCSIDiskState, serial),
1205 1206 1207 1208 1209 1210 1211
        DEFINE_PROP_END_OF_LIST(),
    },
};

static void scsi_disk_register_devices(void)
{
    scsi_qdev_register(&scsi_disk_info);
T
ths 已提交
1212
}
1213
device_init(scsi_disk_register_devices)