scsi-disk: Remove duplicate cdb parsing

We parse the CDB twice, which is completely unnecessary.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Hannes Reinecke 2010-11-24 12:16:00 +01:00 committed by Kevin Wolf
parent a6d96eb78b
commit 2dd791b630

View File

@ -1004,9 +1004,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t *buf, int lun)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
uint64_t lba;
uint32_t len;
int cmdlen;
int is_write;
uint8_t command;
uint8_t *outbuf;
@ -1025,55 +1023,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf = (uint8_t *)r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
switch (command >> 5) {
case 0:
lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
(((uint64_t) buf[1] & 0x1f) << 16);
len = buf[4];
cmdlen = 6;
break;
case 1:
case 2:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[8] | (buf[7] << 8);
cmdlen = 10;
break;
case 4:
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);
len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmdlen = 16;
break;
case 5:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmdlen = 12;
break;
default:
if (scsi_req_parse(&r->req, buf) != 0) {
BADF("Unsupported command length, command %x\n", command);
goto fail;
}
#ifdef DEBUG_SCSI
{
int i;
for (i = 1; i < cmdlen; i++) {
for (i = 1; i < r->req.cmd.len; i++) {
printf(" 0x%02x", buf[i]);
}
printf("\n");
}
#endif
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);
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
@ -1111,10 +1075,11 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case READ_10:
case READ_12:
case READ_16:
DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
if (lba > s->max_lba)
len = r->req.cmd.xfer / d->blocksize;
DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
r->sector = lba * s->cluster_size;
r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
case WRITE_6:
@ -1124,42 +1089,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case WRITE_VERIFY:
case WRITE_VERIFY_12:
case WRITE_VERIFY_16:
len = r->req.cmd.xfer / d->blocksize;
DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
(command & 0xe) == 0xe ? "And Verify " : "", lba, len);
if (lba > s->max_lba)
(command & 0xe) == 0xe ? "And Verify " : "",
r->req.cmd.lba, len);
if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
r->sector = lba * s->cluster_size;
r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
case MODE_SELECT:
DPRINTF("Mode Select(6) (len %d)\n", len);
DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if (len > 12) {
if (r->req.cmd.xfer > 12) {
goto fail;
}
break;
case MODE_SELECT_10:
DPRINTF("Mode Select(10) (len %d)\n", len);
DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if (len > 16) {
if (r->req.cmd.xfer > 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) {
DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
r->req.cmd.lba);
if (r->req.cmd.lba > s->max_lba) {
goto illegal_lba;
}
break;
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
return 0;
return 0;
illegal_lba:
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return 0;