From d12ad44cc4cc9142179e64295608611f118b8ad8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Nov 2013 11:01:13 +0100 Subject: scsi-bus: fix transfer length and direction for VERIFY command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The amount of bytes to transfer depends on the BYTCHK field. If any data is transferred, it is sent to the device. Cc: qemu-stable@nongnu.org Tested-by: Hervé Poussineau Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index ea916d1466..2d6ce4d6bb 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -886,7 +886,6 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) case RELEASE: case ERASE: case ALLOW_MEDIUM_REMOVAL: - case VERIFY_10: case SEEK_10: case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: @@ -903,6 +902,16 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) case ALLOW_OVERWRITE: cmd->xfer = 0; break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: + if ((buf[1] & 2) == 0) { + cmd->xfer = 0; + } else if ((buf[1] & 4) == 1) { + cmd->xfer = 1; + } + cmd->xfer *= dev->blocksize; + break; case MODE_SENSE: break; case WRITE_SAME_10: @@ -1100,6 +1109,9 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd) case WRITE_VERIFY_12: case WRITE_16: case WRITE_VERIFY_16: + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: case COPY: case COPY_VERIFY: case COMPARE: -- cgit v1.2.1 From d97e7730816094a71cd1f19a56d7a73f77cdbf96 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Nov 2013 11:18:56 +0100 Subject: scsi-disk: fix VERIFY emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VERIFY emulation was completely botched (and remained botched through all the refactorings). The command must be emulated both in check-medium mode (BYTCHK=00, which we implement by doing nothing) and in check-bytes mode (which we do not implement yet). Unlike WRITE AND VERIFY (which we treat simply as WRITE with FUA bit set), VERIFY cannot be handled like READ. In fact the device is _receiving_ data for VERIFY, not _sending_ it like READ. Cc: qemu-stable@nongnu.org Tested-by: Hervé Poussineau Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'hw') diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index efadfc023f..6904ac2440 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1720,10 +1720,19 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req) scsi_disk_emulate_unmap(r, r->iov.iov_base); break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: + if (r->req.status == -1) { + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); + } + break; + case WRITE_SAME_10: case WRITE_SAME_16: scsi_disk_emulate_write_same(r, r->iov.iov_base); break; + default: abort(); } @@ -1964,6 +1973,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) case UNMAP: DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer); break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: + DPRINTF("Verify (bytchk %lu)\n", (r->req.buf[1] >> 1) & 3); + if (req->cmd.buf[1] & 6) { + goto illegal_request; + } + break; case WRITE_SAME_10: case WRITE_SAME_16: DPRINTF("WRITE SAME %d (len %lu)\n", @@ -2044,10 +2061,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; } - /* fallthrough */ - case VERIFY_10: - case VERIFY_12: - case VERIFY_16: DPRINTF("Write %s(sector %" PRId64 ", count %u)\n", (command & 0xe) == 0xe ? "And Verify " : "", r->req.cmd.lba, len); @@ -2315,14 +2328,14 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = { [UNMAP] = &scsi_disk_emulate_reqops, [WRITE_SAME_10] = &scsi_disk_emulate_reqops, [WRITE_SAME_16] = &scsi_disk_emulate_reqops, + [VERIFY_10] = &scsi_disk_emulate_reqops, + [VERIFY_12] = &scsi_disk_emulate_reqops, + [VERIFY_16] = &scsi_disk_emulate_reqops, [READ_6] = &scsi_disk_dma_reqops, [READ_10] = &scsi_disk_dma_reqops, [READ_12] = &scsi_disk_dma_reqops, [READ_16] = &scsi_disk_dma_reqops, - [VERIFY_10] = &scsi_disk_dma_reqops, - [VERIFY_12] = &scsi_disk_dma_reqops, - [VERIFY_16] = &scsi_disk_dma_reqops, [WRITE_6] = &scsi_disk_dma_reqops, [WRITE_10] = &scsi_disk_dma_reqops, [WRITE_12] = &scsi_disk_dma_reqops, -- cgit v1.2.1 From 98e33f1b0eff84d9538cf957dde48c3f67f6f9d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 Dec 2013 13:40:15 +0100 Subject: scsi-disk: fix WRITE SAME with large non-zero payload Due to a thinko in the patch that implemented WRITE SAME. Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 6904ac2440..7653411097 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1626,7 +1626,7 @@ static void scsi_write_same_complete(void *opaque, int ret) bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE); r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector, &data->qiov, data->iov.iov_len / 512, - scsi_write_same_complete, r); + scsi_write_same_complete, data); return; } -- cgit v1.2.1