From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 11/32] scsi-disk: split scsi-disk reqops
Date: Fri, 27 Jul 2012 17:02:38 +0200 [thread overview]
Message-ID: <1343401379-19495-12-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1343401379-19495-1-git-send-email-pbonzini@redhat.com>
Only checks for present medium were still done in scsi_send_command
for emulated commands. So move those to scsi_disk_emulate_command
and return different SCSIReqOps depending on the kind of command.
Checks for present medium can be done unconditionally for the
scsi_disk_dma_reqops case.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi-disk.c | 191 ++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 123 insertions(+), 68 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 9f7258d..ea0b05e 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1262,14 +1262,39 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
return 0;
}
-static int scsi_disk_emulate_command(SCSIDiskReq *r)
+static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
{
- SCSIRequest *req = &r->req;
+ SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
uint64_t nb_sectors;
uint8_t *outbuf;
int buflen = 0;
+ switch (req->cmd.buf[0]) {
+ case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ case RESERVE:
+ case RESERVE_10:
+ case RELEASE:
+ case RELEASE_10:
+ case START_STOP:
+ case ALLOW_MEDIUM_REMOVAL:
+ case GET_CONFIGURATION:
+ case GET_EVENT_STATUS_NOTIFICATION:
+ case MECHANISM_STATUS:
+ case REQUEST_SENSE:
+ break;
+
+ default:
+ if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+ scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+ return 0;
+ }
+ break;
+ }
+
+ assert(req->cmd.mode != SCSI_XFER_TO_DEV);
if (!r->iov.iov_base) {
/*
* FIXME: we shouldn't return anything bigger than 4k, but the code
@@ -1332,7 +1357,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
break;
case START_STOP:
if (scsi_disk_emulate_start_stop(r) < 0) {
- return -1;
+ return 0;
}
break;
case ALLOW_MEDIUM_REMOVAL:
@@ -1503,18 +1528,23 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
scsi_aio_complete, r);
return 0;
default:
+ DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
- return -1;
+ return 0;
}
- assert(r->sector_count == 0);
- buflen = MIN(buflen, req->cmd.xfer);
- return buflen;
+ assert(!r->req.aiocb && r->sector_count == 0);
+ r->iov.iov_len = MIN(buflen, req->cmd.xfer);
+ r->sector_count = -1;
+ if (r->iov.iov_len == 0) {
+ scsi_req_complete(&r->req, GOOD);
+ }
+ return r->iov.iov_len;
illegal_request:
if (r->req.status == -1) {
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
}
- return -1;
+ return 0;
illegal_lba:
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
@@ -1526,49 +1556,18 @@ illegal_lba:
(eg. disk reads), negative for transfers to the device (eg. disk writes),
and zero if the command does not transfer any data. */
-static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
+static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
int32_t len;
uint8_t command;
- int rc;
command = buf[0];
- DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
-
-#ifdef DEBUG_SCSI
- {
- int i;
- for (i = 1; i < r->req.cmd.len; i++) {
- printf(" 0x%02x", buf[i]);
- }
- printf("\n");
- }
-#endif
- switch (command) {
- case INQUIRY:
- case MODE_SENSE:
- case MODE_SENSE_10:
- case RESERVE:
- case RESERVE_10:
- case RELEASE:
- case RELEASE_10:
- case START_STOP:
- case ALLOW_MEDIUM_REMOVAL:
- case GET_CONFIGURATION:
- case GET_EVENT_STATUS_NOTIFICATION:
- case MECHANISM_STATUS:
- case REQUEST_SENSE:
- break;
-
- default:
- if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
- scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
- return 0;
- }
- break;
+ if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+ scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+ return 0;
}
switch (command) {
@@ -1605,30 +1604,19 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
r->sector_count = len * (s->qdev.blocksize / 512);
break;
default:
- rc = scsi_disk_emulate_command(r);
- if (rc < 0) {
- return 0;
- }
- if (r->req.aiocb) {
- return 0;
- }
- r->iov.iov_len = rc;
- break;
+ abort();
illegal_lba:
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
return 0;
}
- if (r->sector_count == 0 && r->iov.iov_len == 0) {
+ if (r->sector_count == 0) {
scsi_req_complete(&r->req, GOOD);
}
- len = r->sector_count * 512 + r->iov.iov_len;
+ assert(r->iov.iov_len == 0);
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
- return -len;
+ return -r->sector_count * 512;
} else {
- if (!r->sector_count) {
- r->sector_count = -1;
- }
- return len;
+ return r->sector_count * 512;
}
}
@@ -1793,10 +1781,19 @@ static int scsi_disk_initfn(SCSIDevice *dev)
}
}
-static const SCSIReqOps scsi_disk_reqops = {
+static const SCSIReqOps scsi_disk_emulate_reqops = {
.size = sizeof(SCSIDiskReq),
.free_req = scsi_free_request,
- .send_command = scsi_send_command,
+ .send_command = scsi_disk_emulate_command,
+ .read_data = scsi_read_data,
+ .write_data = scsi_write_data,
+ .get_buf = scsi_get_buf,
+};
+
+static const SCSIReqOps scsi_disk_dma_reqops = {
+ .size = sizeof(SCSIDiskReq),
+ .free_req = scsi_free_request,
+ .send_command = scsi_disk_dma_command,
.read_data = scsi_read_data,
.write_data = scsi_write_data,
.cancel_io = scsi_cancel_io,
@@ -1805,13 +1802,72 @@ static const SCSIReqOps scsi_disk_reqops = {
.save_request = scsi_disk_save_request,
};
+static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
+ [TEST_UNIT_READY] = &scsi_disk_emulate_reqops,
+ [INQUIRY] = &scsi_disk_emulate_reqops,
+ [MODE_SENSE] = &scsi_disk_emulate_reqops,
+ [MODE_SENSE_10] = &scsi_disk_emulate_reqops,
+ [START_STOP] = &scsi_disk_emulate_reqops,
+ [ALLOW_MEDIUM_REMOVAL] = &scsi_disk_emulate_reqops,
+ [READ_CAPACITY_10] = &scsi_disk_emulate_reqops,
+ [READ_TOC] = &scsi_disk_emulate_reqops,
+ [READ_DVD_STRUCTURE] = &scsi_disk_emulate_reqops,
+ [READ_DISC_INFORMATION] = &scsi_disk_emulate_reqops,
+ [GET_CONFIGURATION] = &scsi_disk_emulate_reqops,
+ [GET_EVENT_STATUS_NOTIFICATION] = &scsi_disk_emulate_reqops,
+ [MECHANISM_STATUS] = &scsi_disk_emulate_reqops,
+ [SERVICE_ACTION_IN_16] = &scsi_disk_emulate_reqops,
+ [REQUEST_SENSE] = &scsi_disk_emulate_reqops,
+ [SYNCHRONIZE_CACHE] = &scsi_disk_emulate_reqops,
+ [SEEK_10] = &scsi_disk_emulate_reqops,
+#if 0
+ [MODE_SELECT] = &scsi_disk_emulate_reqops,
+ [MODE_SELECT_10] = &scsi_disk_emulate_reqops,
+#endif
+ [WRITE_SAME_10] = &scsi_disk_emulate_reqops,
+ [WRITE_SAME_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,
+ [WRITE_16] = &scsi_disk_dma_reqops,
+ [WRITE_VERIFY_10] = &scsi_disk_dma_reqops,
+ [WRITE_VERIFY_12] = &scsi_disk_dma_reqops,
+ [WRITE_VERIFY_16] = &scsi_disk_dma_reqops,
+};
+
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
uint8_t *buf, void *hba_private)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIRequest *req;
+ const SCSIReqOps *ops;
+ uint8_t command;
- req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
+#ifdef DEBUG_SCSI
+ DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, buf[0]);
+ {
+ int i;
+ for (i = 1; i < r->req.cmd.len; i++) {
+ printf(" 0x%02x", buf[i]);
+ }
+ printf("\n");
+ }
+#endif
+
+ command = buf[0];
+ ops = scsi_disk_reqops_dispatch[command];
+ if (!ops) {
+ ops = &scsi_disk_emulate_reqops;
+ }
+ req = scsi_req_alloc(ops, &s->qdev, tag, lun, hba_private);
return req;
}
@@ -1925,15 +1981,14 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
* unreliable, too. It is even possible that reads deliver random data
* from the host page cache (this is probably a Linux bug).
*
- * We might use scsi_disk_reqops as long as no writing commands are
+ * We might use scsi_disk_dma_reqops as long as no writing commands are
* seen, but performance usually isn't paramount on optical media. So,
* just make scsi-block operate the same as scsi-generic for them.
*/
- if (s->qdev.type == TYPE_ROM) {
- break;
- }
- return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
- hba_private);
+ if (s->qdev.type != TYPE_ROM) {
+ return scsi_req_alloc(&scsi_disk_dma_reqops, &s->qdev, tag, lun,
+ hba_private);
+ }
}
return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
--
1.7.10.4
next prev parent reply other threads:[~2012-07-27 15:03 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-27 15:02 [Qemu-devel] [PULL 00/32] SCSI patches for 2012-08-27 Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 01/32] megasas: Replace trace_megasas_dcmd_dump_frame() Paolo Bonzini
2012-07-30 9:40 ` Stefan Hajnoczi
2012-07-27 15:02 ` [Qemu-devel] [PATCH 02/32] megasas: fix misuse of scsi_req_abort Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 03/32] lsi: use qdev_reset_all Paolo Bonzini
2013-04-23 8:47 ` Jan Kiszka
2013-04-23 16:13 ` Paolo Bonzini
2013-04-23 16:43 ` Paolo Bonzini
2013-04-23 16:54 ` Jan Kiszka
2012-07-27 15:02 ` [Qemu-devel] [PATCH 04/32] lsi: introduce lsi_request_free Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 05/32] lsi: avoid redundant tests of s->current != NULL Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 06/32] scsi-block: remove properties that are not relevant for passthrough Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 07/32] cutils: add strpadcpy() Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 08/32] scsi-disk: let the user customize vendor and product name Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 09/32] scsi-disk: make discard asynchronous Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 10/32] scsi-disk: move all non-DMA commands to scsi_disk_emulate_command Paolo Bonzini
2012-07-27 15:02 ` Paolo Bonzini [this message]
2012-07-27 15:02 ` [Qemu-devel] [PATCH 12/32] scsi-disk: separate read_data/write_data implementation for emulate_reqops Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 13/32] scsi-disk: support emulated TO_DEV requests Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 14/32] scsi-disk: adjust offsets in MODE SENSE by 2 Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 15/32] scsi-disk: fix changeable values for MODE_PAGE_R_W_ERROR Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 16/32] scsi-disk: parse MODE SELECT commands and parameters Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 17/32] scsi-disk: support toggling the write cache Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 18/32] scsi-disk: rd/wr/vr-protect !=0 is an error Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 19/32] scsi-disk: improve the lba-out-of-range tests for read/write/verify Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 20/32] scsi-disk: Fail medium writes with proper sense for readonly LUNs Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 21/32] scsi-disk: removable hard disks support load/eject Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 22/32] scsi: add tracepoint for scsi_req_cancel Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 23/32] scsi: introduce hotplug() and hot_unplug() interfaces for SCSI bus Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 24/32] scsi: establish precedence levels for unit attention Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 25/32] scsi-disk: report resized disk via sense codes Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 26/32] scsi: report parameter changes to HBA drivers Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 27/32] virtio-scsi: Implement hotplug support for virtio-scsi Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 28/32] virtio-scsi: Report missed events Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 29/32] virtio-scsi: do not report dropped events after reset Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 30/32] virtio-scsi: report parameter change events Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 31/32] virtio-scsi: add ioeventfd support Paolo Bonzini
2012-07-27 15:02 ` [Qemu-devel] [PATCH 32/32] virtio-scsi: enable MSI-X support Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1343401379-19495-12-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).