scsi-disk.c 40.3 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;
74
    SCSISense sense;
P
pbrook 已提交
75 76
};

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

80
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
81
                                     uint32_t lun, void *hba_private)
P
pbrook 已提交
82
{
83
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
84
    SCSIRequest *req;
85
    SCSIDiskReq *r;
P
pbrook 已提交
86

87
    req = scsi_req_alloc(sizeof(SCSIDiskReq), &s->qdev, tag, lun, hba_private);
88
    r = DO_UPCAST(SCSIDiskReq, req, req);
89
    r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
90
    return req;
P
pbrook 已提交
91 92
}

P
Paolo Bonzini 已提交
93
static void scsi_free_request(SCSIRequest *req)
P
pbrook 已提交
94
{
P
Paolo Bonzini 已提交
95 96
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

97
    qemu_vfree(r->iov.iov_base);
P
pbrook 已提交
98 99
}

100
static void scsi_disk_clear_sense(SCSIDiskState *s)
G
Gerd Hoffmann 已提交
101
{
102 103 104
    memset(&s->sense, 0, sizeof(s->sense));
}

P
pbrook 已提交
105
/* Helper function for command completion.  */
106
static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense)
P
pbrook 已提交
107
{
108 109
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

110 111
    DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
            r->req.tag, status, sense.key, sense.asc, sense.ascq);
112 113
    s->sense = sense;
    scsi_req_complete(&r->req, status);
P
pbrook 已提交
114 115 116
}

/* Cancel a pending data transfer.  */
117
static void scsi_cancel_io(SCSIRequest *req)
P
pbrook 已提交
118
{
119 120 121 122 123
    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 已提交
124
    }
125
    r->req.aiocb = NULL;
P
pbrook 已提交
126 127 128 129
}

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

133 134
    r->req.aiocb = NULL;

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

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

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

K
Kevin Wolf 已提交
149

150 151
/* Read more data from scsi device into buffer.  */
static void scsi_read_data(SCSIRequest *req)
P
pbrook 已提交
152
{
153
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
K
Kevin Wolf 已提交
154
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
P
pbrook 已提交
155 156
    uint32_t n;

P
pbrook 已提交
157
    if (r->sector_count == (uint32_t)-1) {
158
        DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
P
pbrook 已提交
159
        r->sector_count = 0;
P
Paolo Bonzini 已提交
160
        scsi_req_data(&r->req, r->iov.iov_len);
P
pbrook 已提交
161
        return;
P
pbrook 已提交
162
    }
P
pbrook 已提交
163 164
    DPRINTF("Read sector_count=%d\n", r->sector_count);
    if (r->sector_count == 0) {
165
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
P
pbrook 已提交
166
        return;
P
pbrook 已提交
167 168
    }

169 170 171
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

172 173 174 175 176 177
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_read_complete(r, -EINVAL);
        return;
    }

P
pbrook 已提交
178 179 180 181
    n = r->sector_count;
    if (n > SCSI_DMA_BUF_SIZE / 512)
        n = SCSI_DMA_BUF_SIZE / 512;

182 183
    r->iov.iov_len = n * 512;
    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
184
    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
185
                              scsi_read_complete, r);
186 187 188
    if (r->req.aiocb == NULL) {
        scsi_read_complete(r, -EIO);
    }
P
pbrook 已提交
189 190
}

K
Kevin Wolf 已提交
191 192 193
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
{
    int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
194
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
K
Kevin Wolf 已提交
195
    BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
196

197
    if (action == BLOCK_ERR_IGNORE) {
K
Kevin Wolf 已提交
198
        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
199
        return 0;
200
    }
201 202 203

    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
            || action == BLOCK_ERR_STOP_ANY) {
K
Kevin Wolf 已提交
204 205 206 207 208

        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 已提交
209
        vm_stop(VMSTOP_DISKFULL);
210
    } else {
211 212
        switch (error) {
        case ENOMEM:
213 214
            scsi_command_complete(r, CHECK_CONDITION,
                                  SENSE_CODE(TARGET_FAILURE));
215 216 217 218 219 220
            break;
        case EINVAL:
            scsi_command_complete(r, CHECK_CONDITION,
                                  SENSE_CODE(INVALID_FIELD));
            break;
        default:
221 222
            scsi_command_complete(r, CHECK_CONDITION,
                                  SENSE_CODE(IO_ERROR));
223
            break;
224
        }
K
Kevin Wolf 已提交
225
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
226 227 228 229
    }
    return 1;
}

P
pbrook 已提交
230 231
static void scsi_write_complete(void * opaque, int ret)
{
232
    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
P
pbrook 已提交
233
    uint32_t len;
234 235
    uint32_t n;

236
    r->req.aiocb = NULL;
P
pbrook 已提交
237 238

    if (ret) {
K
Kevin Wolf 已提交
239
        if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
240
            return;
K
Kevin Wolf 已提交
241
        }
P
pbrook 已提交
242 243
    }

244
    n = r->iov.iov_len / 512;
245 246
    r->sector += n;
    r->sector_count -= n;
P
pbrook 已提交
247
    if (r->sector_count == 0) {
248
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
P
pbrook 已提交
249 250 251 252 253
    } else {
        len = r->sector_count * 512;
        if (len > SCSI_DMA_BUF_SIZE) {
            len = SCSI_DMA_BUF_SIZE;
        }
254
        r->iov.iov_len = len;
255
        DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
P
Paolo Bonzini 已提交
256
        scsi_req_data(&r->req, len);
P
pbrook 已提交
257 258 259
    }
}

260
static void scsi_write_data(SCSIRequest *req)
261
{
262
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
263
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
264 265
    uint32_t n;

266 267 268
    /* No data transfer may already be in progress */
    assert(r->req.aiocb == NULL);

269 270 271
    if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
        DPRINTF("Data transfer direction invalid\n");
        scsi_write_complete(r, -EINVAL);
272
        return;
273 274
    }

275
    n = r->iov.iov_len / 512;
276
    if (n) {
277
        qemu_iovec_init_external(&r->qiov, &r->iov, 1);
278
        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
279
                                   scsi_write_complete, r);
280
        if (r->req.aiocb == NULL) {
281
            scsi_write_complete(r, -ENOMEM);
282
        }
283 284 285 286
    } else {
        /* Invoke completion routine to fetch data from host.  */
        scsi_write_complete(r, 0);
    }
P
pbrook 已提交
287
}
P
pbrook 已提交
288

289
static void scsi_dma_restart_bh(void *opaque)
290
{
291
    SCSIDiskState *s = opaque;
292 293
    SCSIRequest *req;
    SCSIDiskReq *r;
294 295 296

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

298 299
    QTAILQ_FOREACH(req, &s->qdev.requests, next) {
        r = DO_UPCAST(SCSIDiskReq, req, req);
300
        if (r->status & SCSI_REQ_STATUS_RETRY) {
K
Kevin Wolf 已提交
301
            int status = r->status;
302 303
            int ret;

K
Kevin Wolf 已提交
304 305 306 307 308
            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:
309
                scsi_read_data(&r->req);
K
Kevin Wolf 已提交
310 311
                break;
            case SCSI_REQ_STATUS_RETRY_WRITE:
312
                scsi_write_data(&r->req);
K
Kevin Wolf 已提交
313
                break;
314 315 316
            case SCSI_REQ_STATUS_RETRY_FLUSH:
                ret = scsi_disk_emulate_command(r, r->iov.iov_base);
                if (ret == 0) {
317
                    scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
318
                }
K
Kevin Wolf 已提交
319
            }
320 321 322 323
        }
    }
}

324 325
static void scsi_dma_restart_cb(void *opaque, int running, int reason)
{
326
    SCSIDiskState *s = opaque;
327 328 329 330 331 332 333 334 335 336

    if (!running)
        return;

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

P
pbrook 已提交
337
/* Return a pointer to the data buffer.  */
338
static uint8_t *scsi_get_buf(SCSIRequest *req)
P
pbrook 已提交
339
{
340
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
P
pbrook 已提交
341

342
    return (uint8_t *)r->iov.iov_base;
P
pbrook 已提交
343 344
}

345 346 347 348 349 350 351 352
/* Copy sense information into the provided buffer */
static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);

    return scsi_build_sense(s->sense, outbuf, len, len > 14);
}

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

403 404 405 406 407 408
            if (!s->serial) {
                DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
                return -1;
            }

            l = strlen(s->serial);
409 410 411 412 413 414 415 416
            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;
417
            memcpy(outbuf+buflen, s->serial, l);
418 419 420 421 422 423 424
            buflen += l;
            break;
        }

        case 0x83: /* Device identification page, mandatory */
        {
            int max_len = 255 - 8;
425
            int id_len = strlen(bdrv_get_device_name(s->bs));
426 427 428 429 430 431

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

H
Hannes Reinecke 已提交
432
            outbuf[buflen++] = 4 + id_len;
433 434 435 436 437
            outbuf[buflen++] = 0x2; // ASCII
            outbuf[buflen++] = 0;   // not officially assigned
            outbuf[buflen++] = 0;   // reserved
            outbuf[buflen++] = id_len; // length of data following

438
            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
439 440 441
            buflen += id_len;
            break;
        }
442
        case 0xb0: /* block limits */
C
Christoph Hellwig 已提交
443
        {
444 445
            unsigned int unmap_sectors =
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
446 447 448 449
            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 已提交
450

H
Hannes Reinecke 已提交
451
            if (s->qdev.type == TYPE_ROM) {
H
Hannes Reinecke 已提交
452 453 454 455
                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
                        page_code);
                return -1;
            }
C
Christoph Hellwig 已提交
456 457 458 459 460 461 462 463 464 465 466 467 468 469
            /* 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;
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484

            /* 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 已提交
485 486
            break;
        }
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
        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);

516
    if (req->lun) {
H
Hannes Reinecke 已提交
517
        outbuf[0] = 0x7f;       /* LUN not supported */
518 519 520
        return buflen;
    }

H
Hannes Reinecke 已提交
521 522
    outbuf[0] = s->qdev.type & 0x1f;
    if (s->qdev.type == TYPE_ROM) {
523
        outbuf[1] = 0x80;
L
Laszlo Ast 已提交
524
        memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
525
    } else {
526
        outbuf[1] = s->removable ? 0x80 : 0;
L
Laszlo Ast 已提交
527
        memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
528
    }
L
Laszlo Ast 已提交
529
    memcpy(&outbuf[8], "QEMU    ", 8);
G
Gerd Hoffmann 已提交
530
    memset(&outbuf[32], 0, 4);
531
    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
532 533 534 535 536 537
    /*
     * 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 已提交
538
    outbuf[2] = 5;
539
    outbuf[3] = 2; /* Format 2 */
540 541 542 543 544 545 546 547 548

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

549 550 551 552 553
    /* Sync data transfer and TCQ.  */
    outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
    return buflen;
}

554 555
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
                           int page_control)
556 557
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
558
    BlockDriverState *bdrv = s->bs;
559 560
    int cylinders, heads, secs;

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

    case 5: /* Flexible disk device geometry page. */
        p[0] = 5;
        p[1] = 0x1e;
603 604 605
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
        /* 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;
637
        return p[1] + 2;
638 639 640 641

    case 8: /* Caching page.  */
        p[0] = 8;
        p[1] = 0x12;
642 643 644
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
645
        if (bdrv_enable_write_cache(s->bs)) {
646 647
            p[2] = 4; /* WCE */
        }
648
        return p[1] + 2;
649 650

    case 0x2a: /* CD Capabilities and Mechanical Status page. */
H
Hannes Reinecke 已提交
651
        if (s->qdev.type != TYPE_ROM)
652 653 654
            return 0;
        p[0] = 0x2a;
        p[1] = 0x14;
655 656 657
        if (page_control == 1) { /* Changeable Values */
            return p[1] + 2;
        }
658 659 660 661 662 663 664
        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 */
665
        p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
        /* 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;
681
        return p[1] + 2;
682 683 684 685 686 687 688 689 690 691

    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;
692
    int page, dbd, buflen, page_control;
693
    uint8_t *p;
694
    uint8_t dev_specific_param;
695 696 697

    dbd = req->cmd.buf[1]  & 0x8;
    page = req->cmd.buf[2] & 0x3f;
698
    page_control = (req->cmd.buf[2] & 0xc0) >> 6;
699 700
    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);
701 702 703
    memset(outbuf, 0, req->cmd.xfer);
    p = outbuf;

704
    if (bdrv_is_read_only(s->bs)) {
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
        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;
720 721
    }

722
    bdrv_get_geometry(s->bs, &nb_sectors);
723
    if (!dbd && nb_sectors) {
724 725 726 727 728
        if (req->cmd.buf[0] == MODE_SENSE) {
            outbuf[3] = 8; /* Block descriptor length  */
        } else { /* MODE_SENSE_10 */
            outbuf[7] = 8; /* Block descriptor length  */
        }
729 730
        nb_sectors /= s->cluster_size;
        if (nb_sectors > 0xffffff)
731
            nb_sectors = 0;
732 733 734 735 736 737 738 739 740 741 742
        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;
    }

743 744 745 746
    if (page_control == 3) { /* Saved Values */
        return -1; /* ILLEGAL_REQUEST */
    }

747 748 749 750 751
    switch (page) {
    case 0x04:
    case 0x05:
    case 0x08:
    case 0x2a:
752
        p += mode_sense_page(req, page, p, page_control);
753 754
        break;
    case 0x3f:
755 756
        p += mode_sense_page(req, 0x08, p, page_control);
        p += mode_sense_page(req, 0x2a, p, page_control);
757
        break;
758 759
    default:
        return -1; /* ILLEGAL_REQUEST */
760 761 762
    }

    buflen = p - outbuf;
763 764 765 766 767 768 769 770 771 772 773
    /*
     * 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;
    }
774 775 776 777 778
    if (buflen > req->cmd.xfer)
        buflen = req->cmd.xfer;
    return buflen;
}

779 780 781 782 783 784 785 786 787
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];
788
    bdrv_get_geometry(s->bs, &nb_sectors);
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
    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;
}

814
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
815
{
816
    SCSIRequest *req = &r->req;
817 818
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
    uint64_t nb_sectors;
819
    int buflen = 0;
820
    int ret;
821 822 823

    switch (req->cmd.buf[0]) {
    case TEST_UNIT_READY:
824
        if (!bdrv_is_inserted(s->bs))
825
            goto not_ready;
H
Hannes Reinecke 已提交
826
        break;
827 828 829
    case REQUEST_SENSE:
        if (req->cmd.xfer < 4)
            goto illegal_request;
830 831
        buflen = scsi_build_sense(s->sense, outbuf, req->cmd.xfer,
                                  req->cmd.xfer > 13);
832
        scsi_disk_clear_sense(s);
833
        break;
834 835 836 837
    case INQUIRY:
        buflen = scsi_disk_emulate_inquiry(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
H
Hannes Reinecke 已提交
838
        break;
839 840 841 842 843 844
    case MODE_SENSE:
    case MODE_SENSE_10:
        buflen = scsi_disk_emulate_mode_sense(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
845 846 847 848 849
    case READ_TOC:
        buflen = scsi_disk_emulate_read_toc(req, outbuf);
        if (buflen < 0)
            goto illegal_request;
        break;
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
    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;
866
    case START_STOP:
H
Hannes Reinecke 已提交
867
        if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
868
            /* load/eject medium */
869
            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
870
        }
H
Hannes Reinecke 已提交
871
        break;
872
    case ALLOW_MEDIUM_REMOVAL:
873
        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
H
Hannes Reinecke 已提交
874
        break;
875
    case READ_CAPACITY_10:
876
        /* The normal LEN field for this command is zero.  */
H
Hannes Reinecke 已提交
877 878
        memset(outbuf, 0, 8);
        bdrv_get_geometry(s->bs, &nb_sectors);
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
        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 已提交
898
        break;
899
    case SYNCHRONIZE_CACHE:
900 901 902 903 904 905
        ret = bdrv_flush(s->bs);
        if (ret < 0) {
            if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
                return -1;
            }
        }
906
        break;
907 908 909 910 911 912 913
    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;
914 915 916 917 918
    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);
919
            bdrv_get_geometry(s->bs, &nb_sectors);
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
            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 已提交
939 940
            outbuf[12] = 0;
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
941 942 943 944 945 946

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

947 948 949 950 951 952
            /* Protection, exponent and lowest lba field left blank. */
            buflen = req->cmd.xfer;
            break;
        }
        DPRINTF("Unsupported Service Action In\n");
        goto illegal_request;
953 954 955 956 957 958 959
    case REPORT_LUNS:
        if (req->cmd.xfer < 16)
            goto illegal_request;
        memset(outbuf, 0, 16);
        outbuf[3] = 8;
        buflen = 16;
        break;
960
    case VERIFY_10:
961
        break;
962
    default:
963 964
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
        return -1;
965 966 967 968
    }
    return buflen;

not_ready:
969 970 971 972 973
    if (!bdrv_is_inserted(s->bs)) {
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(NO_MEDIUM));
    } else {
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LUN_NOT_READY));
    }
974
    return -1;
975 976

illegal_request:
977
    scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD));
978
    return -1;
979 980
}

P
pbrook 已提交
981 982 983 984 985
/* 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.  */

986
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
P
pbrook 已提交
987
{
988 989
    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
P
Paolo Bonzini 已提交
990
    int32_t len;
P
pbrook 已提交
991 992
    uint8_t command;
    uint8_t *outbuf;
993
    int rc;
P
pbrook 已提交
994 995

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

    if (scsi_req_parse(&r->req, buf) != 0) {
P
pbrook 已提交
1000
        BADF("Unsupported command length, command %x\n", command);
1001 1002
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
        return 0;
P
pbrook 已提交
1003 1004 1005 1006
    }
#ifdef DEBUG_SCSI
    {
        int i;
1007
        for (i = 1; i < r->req.cmd.len; i++) {
P
pbrook 已提交
1008 1009 1010 1011 1012
            printf(" 0x%02x", buf[i]);
        }
        printf("\n");
    }
#endif
1013

1014
    if (req->lun) {
P
pbrook 已提交
1015
        /* Only LUN 0 supported.  */
1016
        DPRINTF("Unimplemented LUN %d\n", req->lun);
1017 1018 1019 1020 1021
        if (command != REQUEST_SENSE && command != INQUIRY) {
            scsi_command_complete(r, CHECK_CONDITION,
                                  SENSE_CODE(LUN_NOT_SUPPORTED));
            return 0;
        }
P
pbrook 已提交
1022
    }
P
pbrook 已提交
1023
    switch (command) {
1024
    case TEST_UNIT_READY:
1025
    case REQUEST_SENSE:
1026
    case INQUIRY:
1027 1028
    case MODE_SENSE:
    case MODE_SENSE_10:
1029 1030 1031 1032
    case RESERVE:
    case RESERVE_10:
    case RELEASE:
    case RELEASE_10:
1033
    case START_STOP:
1034
    case ALLOW_MEDIUM_REMOVAL:
1035
    case READ_CAPACITY_10:
1036
    case SYNCHRONIZE_CACHE:
1037
    case READ_TOC:
1038
    case GET_CONFIGURATION:
1039
    case SERVICE_ACTION_IN:
1040
    case REPORT_LUNS:
1041
    case VERIFY_10:
1042 1043
        rc = scsi_disk_emulate_command(r, outbuf);
        if (rc < 0) {
1044
            return 0;
1045
        }
1046 1047

        r->iov.iov_len = rc;
1048
        break;
1049 1050
    case READ_6:
    case READ_10:
G
Gerd Hoffmann 已提交
1051 1052
    case READ_12:
    case READ_16:
1053
        len = r->req.cmd.xfer / s->qdev.blocksize;
1054 1055
        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
        if (r->req.cmd.lba > s->max_lba)
1056
            goto illegal_lba;
1057
        r->sector = r->req.cmd.lba * s->cluster_size;
P
pbrook 已提交
1058
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
1059
        break;
1060 1061
    case WRITE_6:
    case WRITE_10:
G
Gerd Hoffmann 已提交
1062 1063
    case WRITE_12:
    case WRITE_16:
1064
    case WRITE_VERIFY_10:
1065 1066
    case WRITE_VERIFY_12:
    case WRITE_VERIFY_16:
1067
        len = r->req.cmd.xfer / s->qdev.blocksize;
1068
        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
1069 1070 1071
                (command & 0xe) == 0xe ? "And Verify " : "",
                r->req.cmd.lba, len);
        if (r->req.cmd.lba > s->max_lba)
1072
            goto illegal_lba;
1073
        r->sector = r->req.cmd.lba * s->cluster_size;
P
pbrook 已提交
1074
        r->sector_count = len * s->cluster_size;
P
pbrook 已提交
1075
        break;
1076
    case MODE_SELECT:
1077
        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
1078 1079
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1080
        if (r->req.cmd.xfer > 12) {
1081 1082 1083 1084
            goto fail;
        }
        break;
    case MODE_SELECT_10:
1085
        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
1086 1087
        /* We don't support mode parameter changes.
           Allow the mode parameter header + block descriptors only. */
1088
        if (r->req.cmd.xfer > 16) {
1089 1090 1091 1092 1093
            goto fail;
        }
        break;
    case SEEK_6:
    case SEEK_10:
1094 1095 1096
        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
                r->req.cmd.lba);
        if (r->req.cmd.lba > s->max_lba) {
1097 1098
            goto illegal_lba;
        }
1099 1100
        break;
    case WRITE_SAME_16:
1101
        len = r->req.cmd.xfer / s->qdev.blocksize;
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

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

1124
        break;
P
pbrook 已提交
1125
    default:
1126
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1127 1128
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
        return 0;
P
pbrook 已提交
1129
    fail:
1130
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_FIELD));
1131
        return 0;
1132
    illegal_lba:
1133
        scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(LBA_OUT_OF_RANGE));
1134
        return 0;
P
pbrook 已提交
1135
    }
1136
    if (r->sector_count == 0 && r->iov.iov_len == 0) {
1137
        scsi_command_complete(r, GOOD, SENSE_CODE(NO_SENSE));
P
pbrook 已提交
1138
    }
1139
    len = r->sector_count * 512 + r->iov.iov_len;
1140 1141
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        return -len;
P
pbrook 已提交
1142 1143 1144
    } else {
        if (!r->sector_count)
            r->sector_count = -1;
1145
        return len;
P
pbrook 已提交
1146 1147 1148
    }
}

J
Jan Kiszka 已提交
1149 1150 1151 1152 1153
static void scsi_disk_reset(DeviceState *dev)
{
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
    uint64_t nb_sectors;

P
Paolo Bonzini 已提交
1154
    scsi_device_purge_requests(&s->qdev);
J
Jan Kiszka 已提交
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167

    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 已提交
1168
    scsi_device_purge_requests(&s->qdev);
1169
    blockdev_mark_auto_del(s->qdev.conf.bs);
G
Gerd Hoffmann 已提交
1170 1171
}

H
Hannes Reinecke 已提交
1172
static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
P
pbrook 已提交
1173
{
1174
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
1175
    DriveInfo *dinfo;
P
pbrook 已提交
1176

1177
    if (!s->qdev.conf.bs) {
1178
        error_report("scsi-disk: drive property not set");
1179 1180
        return -1;
    }
1181
    s->bs = s->qdev.conf.bs;
1182

H
Hannes Reinecke 已提交
1183
    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
1184 1185 1186 1187
        error_report("Device needs media, but drive is empty");
        return -1;
    }

1188
    if (!s->serial) {
1189 1190
        /* try to fall back to value set with legacy -drive serial=... */
        dinfo = drive_get_by_blockdev(s->bs);
1191 1192 1193
        if (*dinfo->serial) {
            s->serial = qemu_strdup(dinfo->serial);
        }
1194 1195
    }

1196 1197 1198 1199
    if (!s->version) {
        s->version = qemu_strdup(QEMU_VERSION);
    }

1200
    if (bdrv_is_sg(s->bs)) {
1201
        error_report("scsi-disk: unwanted /dev/sg*");
1202 1203 1204
        return -1;
    }

H
Hannes Reinecke 已提交
1205
    if (scsi_type == TYPE_ROM) {
1206
        s->qdev.blocksize = 2048;
H
Hannes Reinecke 已提交
1207
    } else if (scsi_type == TYPE_DISK) {
1208
        s->qdev.blocksize = s->qdev.conf.logical_block_size;
H
Hannes Reinecke 已提交
1209 1210 1211
    } else {
        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
        return -1;
P
pbrook 已提交
1212
    }
1213
    s->cluster_size = s->qdev.blocksize / 512;
1214
    s->bs->buffer_alignment = s->qdev.blocksize;
1215

H
Hannes Reinecke 已提交
1216
    s->qdev.type = scsi_type;
1217
    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
H
Hannes Reinecke 已提交
1218
    bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
1219
    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
1220 1221 1222
    return 0;
}

1223 1224
static int scsi_hd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1225
    return scsi_initfn(dev, TYPE_DISK);
1226 1227 1228 1229
}

static int scsi_cd_initfn(SCSIDevice *dev)
{
H
Hannes Reinecke 已提交
1230
    return scsi_initfn(dev, TYPE_ROM);
1231 1232 1233 1234
}

static int scsi_disk_initfn(SCSIDevice *dev)
{
1235
    DriveInfo *dinfo;
H
Hannes Reinecke 已提交
1236
    uint8_t scsi_type;
1237 1238

    if (!dev->conf.bs) {
H
Hannes Reinecke 已提交
1239
        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
1240
    } else {
1241
        dinfo = drive_get_by_blockdev(dev->conf.bs);
H
Hannes Reinecke 已提交
1242
        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
1243 1244
    }

H
Hannes Reinecke 已提交
1245
    return scsi_initfn(dev, scsi_type);
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
}

#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,
1262
        .alloc_req    = scsi_new_request,
P
Paolo Bonzini 已提交
1263
        .free_req     = scsi_free_request,
1264 1265 1266 1267 1268
        .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,
1269
        .get_sense    = scsi_get_sense,
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
        .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,
1283
        .alloc_req    = scsi_new_request,
P
Paolo Bonzini 已提交
1284
        .free_req     = scsi_free_request,
1285 1286 1287 1288 1289
        .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,
1290
        .get_sense    = scsi_get_sense,
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
        .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,
1303
        .alloc_req    = scsi_new_request,
P
Paolo Bonzini 已提交
1304
        .free_req     = scsi_free_request,
1305 1306 1307 1308 1309
        .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,
1310
        .get_sense    = scsi_get_sense,
1311 1312 1313 1314 1315 1316
        .qdev.props   = (Property[]) {
            DEFINE_SCSI_DISK_PROPERTIES(),
            DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
            DEFINE_PROP_END_OF_LIST(),
        }
    }
1317 1318 1319 1320
};

static void scsi_disk_register_devices(void)
{
1321 1322 1323 1324 1325
    int i;

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