diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-06-14 16:13:49 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-07-02 11:27:00 +0200 |
commit | 28b70c9dbdce0d517ade9c04c7d7ae05c8b76d2f (patch) | |
tree | 6c2e8468c635621eea39493a08c84291ef2c3433 /hw/scsi-bus.c | |
parent | 15e58a21a8f48b6a00081587fa1fa23aa9159dfd (diff) | |
download | qemu-28b70c9dbdce0d517ade9c04c7d7ae05c8b76d2f.zip qemu-28b70c9dbdce0d517ade9c04c7d7ae05c8b76d2f.tar.gz qemu-28b70c9dbdce0d517ade9c04c7d7ae05c8b76d2f.tar.bz2 |
scsi: Ensure command and transfer lengths are set for all SCSI devices
scsi-generic relies on those values to be correct, so it is important that
those values are initialized properly for all device types.
Reported-by: Christian Hoff <christian.hoff@de.ibm.com>
Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi-bus.c')
-rw-r--r-- | hw/scsi-bus.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 2d4429c..4ec9b52 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -734,20 +734,16 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) switch (buf[0] >> 5) { case 0: cmd->xfer = buf[4]; - cmd->len = 6; break; case 1: case 2: cmd->xfer = lduw_be_p(&buf[7]); - cmd->len = 10; break; case 4: cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL; - cmd->len = 16; break; case 5: cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL; - cmd->len = 12; break; default: return -1; @@ -884,7 +880,6 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu case READ_REVERSE: case RECOVER_BUFFERED_DATA: case WRITE_6: - cmd->len = 6; cmd->xfer = buf[4] | (buf[3] << 8) | (buf[2] << 16); if (buf[1] & 0x01) { /* fixed */ cmd->xfer *= dev->blocksize; @@ -894,7 +889,6 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu case READ_REVERSE_16: case VERIFY_16: case WRITE_16: - cmd->len = 16; cmd->xfer = buf[14] | (buf[13] << 8) | (buf[12] << 16); if (buf[1] & 0x01) { /* fixed */ cmd->xfer *= dev->blocksize; @@ -902,7 +896,6 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu break; case REWIND: case LOAD_UNLOAD: - cmd->len = 6; cmd->xfer = 0; break; case SPACE_16: @@ -1000,6 +993,24 @@ int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) { int rc; + switch (buf[0] >> 5) { + case 0: + cmd->len = 6; + break; + case 1: + case 2: + cmd->len = 10; + break; + case 4: + cmd->len = 16; + break; + case 5: + cmd->len = 12; + break; + default: + return -1; + } + if (dev->type == TYPE_TAPE) { rc = scsi_req_stream_length(cmd, dev, buf); } else { |