From: Cong Meng <mc@linux.vnet.ibm.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
stefanha@linux.vnet.ibm.com, zwanp@cn.ibm.com,
linuxram@us.ibm.com, qemu-devel@nongnu.org,
Cong Meng <mc@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH] add support for ATA_PASSTHROUGH_xx scsi command
Date: Fri, 3 Aug 2012 12:02:19 +0800 [thread overview]
Message-ID: <1343966539-955-1-git-send-email-mc@linux.vnet.ibm.com> (raw)
Correct the command names of opcode 0x85 and 0xa1, and calculate
their xfer size from CDB.
ChangeLog:
v2: For opcode 0xa1 on TYPE_ROM device, do not calc the xfer size
v3: Complete xfer calculation of all situations
Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
---
hw/scsi-bus.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
hw/scsi-defs.h | 4 +-
2 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index e4ec19e..553dc8b 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -733,6 +733,74 @@ static int scsi_get_performance_length(int num_desc, int type, int data_type)
}
}
+static size_t ata_passthrough_xfer_unit(SCSIDevice *dev, uint8_t *buf)
+{
+ int byte_block = (buf[2] >> 2) & 0x1;
+ int type = (buf[2] >> 4) & 0x1;
+ size_t xfer_unit;
+
+ if (byte_block) {
+ if (type) {
+ xfer_unit = dev->blocksize;
+ } else {
+ xfer_unit = 512;
+ }
+ } else {
+ xfer_unit = 1;
+ }
+
+ return xfer_unit;
+}
+
+static size_t ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
+{
+ int length = buf[2] & 0x3;
+ size_t xfer;
+ size_t unit = ata_passthrough_xfer_unit(dev, buf);
+
+ switch (length) {
+ case 0:
+ xfer = 0;
+ break;
+ case 1:
+ xfer = buf[3] * unit;
+ break;
+ case 2:
+ xfer = buf[4] * unit;
+ break;
+ case 3:
+ xfer = UINT32_MAX;
+ break;
+ }
+
+ return xfer;
+}
+
+static size_t ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
+{
+ int extend = buf[1] & 0x1;
+ int length = buf[2] & 0x3;
+ size_t xfer;
+ size_t unit = ata_passthrough_xfer_unit(dev, buf);
+
+ switch (length) {
+ case 0:
+ xfer = 0;
+ break;
+ case 1:
+ xfer = ((buf[3] * extend) << 8 | buf[4]) * unit;
+ break;
+ case 2:
+ xfer = ((buf[5] * extend) << 8 | buf[6]) * unit;
+ break;
+ case 3:
+ xfer = UINT32_MAX;
+ break;
+ }
+
+ return xfer;
+}
+
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
{
switch (buf[0] >> 5) {
@@ -867,6 +935,17 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
cmd->xfer = buf[9] | (buf[8] << 8);
}
break;
+ case ATA_PASSTHROUGH_12:
+ if (dev->type == TYPE_ROM) {
+ /* BLANK command of MMC */
+ cmd->xfer = 0;
+ } else {
+ cmd->xfer = ata_passthrough_12_xfer_size(dev, buf);
+ }
+ break;
+ case ATA_PASSTHROUGH_16:
+ cmd->xfer = ata_passthrough_16_xfer_size(dev, buf);
+ break;
}
return 0;
}
@@ -996,9 +1075,14 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case SEND_DVD_STRUCTURE:
case PERSISTENT_RESERVE_OUT:
case MAINTENANCE_OUT:
- case ATA_PASSTHROUGH:
cmd->mode = SCSI_XFER_TO_DEV;
break;
+ case ATA_PASSTHROUGH_12:
+ case ATA_PASSTHROUGH_16:
+ /* T_DIR */
+ cmd->mode = (cmd->buf[2] & 0x8) ?
+ SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV;
+ break;
default:
cmd->mode = SCSI_XFER_FROM_DEV;
break;
@@ -1335,7 +1419,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
[ EXTENDED_COPY ] = "EXTENDED_COPY",
- [ ATA_PASSTHROUGH ] = "ATA_PASSTHROUGH",
+ [ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
[ READ_16 ] = "READ_16",
@@ -1352,7 +1436,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
[ REPORT_LUNS ] = "REPORT_LUNS",
- [ BLANK ] = "BLANK",
+ [ ATA_PASSTHROUGH_12 ] = "ATA_PASSTHROUGH_12",
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index 8a73f74..d7a4019 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -100,7 +100,7 @@
#define READ_REVERSE_16 0x81
#define ALLOW_OVERWRITE 0x82
#define EXTENDED_COPY 0x83
-#define ATA_PASSTHROUGH 0x85
+#define ATA_PASSTHROUGH_16 0x85
#define ACCESS_CONTROL_IN 0x86
#define ACCESS_CONTROL_OUT 0x87
#define READ_16 0x88
@@ -117,7 +117,7 @@
#define SERVICE_ACTION_IN_16 0x9e
#define WRITE_LONG_16 0x9f
#define REPORT_LUNS 0xa0
-#define BLANK 0xa1
+#define ATA_PASSTHROUGH_12 0xa1
#define MAINTENANCE_IN 0xa3
#define MAINTENANCE_OUT 0xa4
#define MOVE_MEDIUM 0xa5
--
1.7.7.6
next reply other threads:[~2012-08-03 4:04 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-03 4:02 Cong Meng [this message]
2012-08-03 6:57 ` [Qemu-devel] [PATCH] add support for ATA_PASSTHROUGH_xx scsi command Paolo Bonzini
2012-08-03 7:01 ` 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=1343966539-955-1-git-send-email-mc@linux.vnet.ibm.com \
--to=mc@linux.vnet.ibm.com \
--cc=linuxram@us.ibm.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
--cc=zwanp@cn.ibm.com \
/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).