Revision ea3bd56f

b/hw/scsi-defs.h
84 84
#define MODE_SENSE_10         0x5a
85 85
#define PERSISTENT_RESERVE_IN 0x5e
86 86
#define PERSISTENT_RESERVE_OUT 0x5f
87
#define WRITE_SAME_16         0x93
87 88
#define MAINTENANCE_IN        0xa3
88 89
#define MAINTENANCE_OUT       0xa4
89 90
#define MOVE_MEDIUM           0xa5
b/hw/scsi-disk.c
424 424
            outbuf[buflen++] = 0x80; // unit serial number
425 425
            outbuf[buflen++] = 0x83; // device identification
426 426
            if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) {
427
                outbuf[buflen++] = 0xb0; // block device characteristics
427
                outbuf[buflen++] = 0xb0; // block limits
428
                outbuf[buflen++] = 0xb2; // thin provisioning
428 429
            }
429 430
            outbuf[pages] = buflen - pages - 1; // number of pages
430 431
            break;
......
466 467
            buflen += id_len;
467 468
            break;
468 469
        }
469
        case 0xb0: /* block device characteristics */
470
        case 0xb0: /* block limits */
470 471
        {
472
            unsigned int unmap_sectors =
473
                    s->qdev.conf.discard_granularity / s->qdev.blocksize;
471 474
            unsigned int min_io_size =
472 475
                    s->qdev.conf.min_io_size / s->qdev.blocksize;
473 476
            unsigned int opt_io_size =
......
492 495
            outbuf[13] = (opt_io_size >> 16) & 0xff;
493 496
            outbuf[14] = (opt_io_size >> 8) & 0xff;
494 497
            outbuf[15] = opt_io_size & 0xff;
498

  
499
            /* optimal unmap granularity */
500
            outbuf[28] = (unmap_sectors >> 24) & 0xff;
501
            outbuf[29] = (unmap_sectors >> 16) & 0xff;
502
            outbuf[30] = (unmap_sectors >> 8) & 0xff;
503
            outbuf[31] = unmap_sectors & 0xff;
504
            break;
505
        }
506
        case 0xb2: /* thin provisioning */
507
        {
508
            outbuf[3] = buflen = 8;
509
            outbuf[4] = 0;
510
            outbuf[5] = 0x40; /* write same with unmap supported */
511
            outbuf[6] = 0;
512
            outbuf[7] = 0;
495 513
            break;
496 514
        }
497 515
        default:
......
959 977
            outbuf[11] = 0;
960 978
            outbuf[12] = 0;
961 979
            outbuf[13] = get_physical_block_exp(&s->qdev.conf);
980

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

  
962 986
            /* Protection, exponent and lowest lba field left blank. */
963 987
            buflen = req->cmd.xfer;
964 988
            break;
......
1123 1147
            goto illegal_lba;
1124 1148
        }
1125 1149
        break;
1150
    case WRITE_SAME_16:
1151
        len = r->req.cmd.xfer / d->blocksize;
1152

  
1153
        DPRINTF("WRITE SAME(16) (sector %" PRId64 ", count %d)\n",
1154
                r->req.cmd.lba, len);
1155

  
1156
        if (r->req.cmd.lba > s->max_lba) {
1157
            goto illegal_lba;
1158
        }
1159

  
1160
        /*
1161
         * We only support WRITE SAME with the unmap bit set for now.
1162
         */
1163
        if (!(buf[1] & 0x8)) {
1164
            goto fail;
1165
        }
1166

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

  
1174
        break;
1126 1175
    default:
1127 1176
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
1128 1177
    fail:

Also available in: Unified diff