From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:58885) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sx97V-0000Ji-En for qemu-devel@nongnu.org; Fri, 03 Aug 2012 00:04:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Sx97U-00041K-38 for qemu-devel@nongnu.org; Fri, 03 Aug 2012 00:04:13 -0400 Received: from e06smtp11.uk.ibm.com ([195.75.94.107]:41042) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sx97T-000418-Ny for qemu-devel@nongnu.org; Fri, 03 Aug 2012 00:04:12 -0400 Received: from /spool/local by e06smtp11.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 3 Aug 2012 05:04:09 +0100 Received: from d06av12.portsmouth.uk.ibm.com (d06av12.portsmouth.uk.ibm.com [9.149.37.247]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q73447SU2072714 for ; Fri, 3 Aug 2012 05:04:07 +0100 Received: from d06av12.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av12.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q73447rM028411 for ; Thu, 2 Aug 2012 22:04:07 -0600 From: Cong Meng Date: Fri, 3 Aug 2012 12:02:19 +0800 Message-Id: <1343966539-955-1-git-send-email-mc@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH] add support for ATA_PASSTHROUGH_xx scsi command List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini Cc: Peter Maydell , stefanha@linux.vnet.ibm.com, zwanp@cn.ibm.com, linuxram@us.ibm.com, qemu-devel@nongnu.org, Cong Meng 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 --- 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