scsi: add support for ATA_PASSTHROUGH_xx scsi command
Correct the command names of opcode 0x85 and 0xa1, and calculate their xfer size from CDB. Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
1f07730896
commit
e4b65262a3
@ -733,6 +733,72 @@ static int scsi_get_performance_length(int num_desc, int type, int data_type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ata_passthrough_xfer_unit(SCSIDevice *dev, uint8_t *buf)
|
||||||
|
{
|
||||||
|
int byte_block = (buf[2] >> 2) & 0x1;
|
||||||
|
int type = (buf[2] >> 4) & 0x1;
|
||||||
|
int xfer_unit;
|
||||||
|
|
||||||
|
if (byte_block) {
|
||||||
|
if (type) {
|
||||||
|
xfer_unit = dev->blocksize;
|
||||||
|
} else {
|
||||||
|
xfer_unit = 512;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xfer_unit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xfer_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||||
|
{
|
||||||
|
int length = buf[2] & 0x3;
|
||||||
|
int xfer;
|
||||||
|
int unit = ata_passthrough_xfer_unit(dev, buf);
|
||||||
|
|
||||||
|
switch (length) {
|
||||||
|
case 0:
|
||||||
|
case 3: /* USB-specific. */
|
||||||
|
xfer = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
xfer = buf[3];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
xfer = buf[4];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xfer * unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||||
|
{
|
||||||
|
int extend = buf[1] & 0x1;
|
||||||
|
int length = buf[2] & 0x3;
|
||||||
|
int xfer;
|
||||||
|
int unit = ata_passthrough_xfer_unit(dev, buf);
|
||||||
|
|
||||||
|
switch (length) {
|
||||||
|
case 0:
|
||||||
|
case 3: /* USB-specific. */
|
||||||
|
xfer = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
xfer = buf[4];
|
||||||
|
xfer |= (extend ? buf[3] << 8 : 0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
xfer = buf[6];
|
||||||
|
xfer |= (extend ? buf[5] << 8 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xfer * unit;
|
||||||
|
}
|
||||||
|
|
||||||
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||||
{
|
{
|
||||||
switch (buf[0] >> 5) {
|
switch (buf[0] >> 5) {
|
||||||
@ -867,6 +933,17 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
|||||||
cmd->xfer = buf[9] | (buf[8] << 8);
|
cmd->xfer = buf[9] | (buf[8] << 8);
|
||||||
}
|
}
|
||||||
break;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -996,9 +1073,14 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
|
|||||||
case SEND_DVD_STRUCTURE:
|
case SEND_DVD_STRUCTURE:
|
||||||
case PERSISTENT_RESERVE_OUT:
|
case PERSISTENT_RESERVE_OUT:
|
||||||
case MAINTENANCE_OUT:
|
case MAINTENANCE_OUT:
|
||||||
case ATA_PASSTHROUGH:
|
|
||||||
cmd->mode = SCSI_XFER_TO_DEV;
|
cmd->mode = SCSI_XFER_TO_DEV;
|
||||||
break;
|
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:
|
default:
|
||||||
cmd->mode = SCSI_XFER_FROM_DEV;
|
cmd->mode = SCSI_XFER_FROM_DEV;
|
||||||
break;
|
break;
|
||||||
@ -1335,7 +1417,7 @@ static const char *scsi_command_name(uint8_t cmd)
|
|||||||
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
|
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
|
||||||
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
|
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
|
||||||
[ EXTENDED_COPY ] = "EXTENDED_COPY",
|
[ EXTENDED_COPY ] = "EXTENDED_COPY",
|
||||||
[ ATA_PASSTHROUGH ] = "ATA_PASSTHROUGH",
|
[ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
|
||||||
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
|
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
|
||||||
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
|
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
|
||||||
[ READ_16 ] = "READ_16",
|
[ READ_16 ] = "READ_16",
|
||||||
@ -1352,7 +1434,7 @@ static const char *scsi_command_name(uint8_t cmd)
|
|||||||
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
|
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
|
||||||
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
|
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
|
||||||
[ REPORT_LUNS ] = "REPORT_LUNS",
|
[ REPORT_LUNS ] = "REPORT_LUNS",
|
||||||
[ BLANK ] = "BLANK",
|
[ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
|
||||||
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
|
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
|
||||||
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
|
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
|
||||||
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
|
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
#define READ_REVERSE_16 0x81
|
#define READ_REVERSE_16 0x81
|
||||||
#define ALLOW_OVERWRITE 0x82
|
#define ALLOW_OVERWRITE 0x82
|
||||||
#define EXTENDED_COPY 0x83
|
#define EXTENDED_COPY 0x83
|
||||||
#define ATA_PASSTHROUGH 0x85
|
#define ATA_PASSTHROUGH_16 0x85
|
||||||
#define ACCESS_CONTROL_IN 0x86
|
#define ACCESS_CONTROL_IN 0x86
|
||||||
#define ACCESS_CONTROL_OUT 0x87
|
#define ACCESS_CONTROL_OUT 0x87
|
||||||
#define READ_16 0x88
|
#define READ_16 0x88
|
||||||
@ -117,7 +117,7 @@
|
|||||||
#define SERVICE_ACTION_IN_16 0x9e
|
#define SERVICE_ACTION_IN_16 0x9e
|
||||||
#define WRITE_LONG_16 0x9f
|
#define WRITE_LONG_16 0x9f
|
||||||
#define REPORT_LUNS 0xa0
|
#define REPORT_LUNS 0xa0
|
||||||
#define BLANK 0xa1
|
#define ATA_PASSTHROUGH_12 0xa1
|
||||||
#define MAINTENANCE_IN 0xa3
|
#define MAINTENANCE_IN 0xa3
|
||||||
#define MAINTENANCE_OUT 0xa4
|
#define MAINTENANCE_OUT 0xa4
|
||||||
#define MOVE_MEDIUM 0xa5
|
#define MOVE_MEDIUM 0xa5
|
||||||
|
Loading…
Reference in New Issue
Block a user