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:
|