diff options
author | Minwoo Im <dn3108@gmail.com> | 2017-06-23 14:41:10 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2017-06-27 11:25:39 -0400 |
commit | b1ffbf854e0887e2b828b9a3343264453662dec6 (patch) | |
tree | 71420dd08a9f22de9fd87fb5a477020657e97ccd /drivers/ata | |
parent | 0ce968f3825153d570f6d765f2c0c79bcb1f0949 (diff) |
libata: Support for an ATA PASS-THROUGH(32) command.
SAT-4(SCSI/ATA Translation) supports for an ata pass-thru(32).
This patch will allow to translate an ata pass-thru(32) SCSI cmd
to an ATA cmd.
Signed-off-by: Minwoo Im <dn3108@gmail.com>
Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 72 |
2 files changed, 68 insertions, 6 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a846c29f3248..d1b2c6b5f680 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -2661,7 +2661,7 @@ int ata_dev_configure(struct ata_device *dev) | |||
2661 | ata_dev_config_sense_reporting(dev); | 2661 | ata_dev_config_sense_reporting(dev); |
2662 | ata_dev_config_zac(dev); | 2662 | ata_dev_config_zac(dev); |
2663 | ata_dev_config_trusted(dev); | 2663 | ata_dev_config_trusted(dev); |
2664 | dev->cdb_len = 16; | 2664 | dev->cdb_len = 32; |
2665 | } | 2665 | } |
2666 | 2666 | ||
2667 | /* ATAPI-specific feature tests */ | 2667 | /* ATAPI-specific feature tests */ |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4c300749aca5..815c6e240aea 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -3126,7 +3126,7 @@ ata_scsi_map_proto(u8 byte1) | |||
3126 | * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile | 3126 | * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile |
3127 | * @qc: command structure to be initialized | 3127 | * @qc: command structure to be initialized |
3128 | * | 3128 | * |
3129 | * Handles either 12 or 16-byte versions of the CDB. | 3129 | * Handles either 12, 16, or 32-byte versions of the CDB. |
3130 | * | 3130 | * |
3131 | * RETURNS: | 3131 | * RETURNS: |
3132 | * Zero on success, non-zero on failure. | 3132 | * Zero on success, non-zero on failure. |
@@ -3138,13 +3138,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
3138 | struct ata_device *dev = qc->dev; | 3138 | struct ata_device *dev = qc->dev; |
3139 | const u8 *cdb = scmd->cmnd; | 3139 | const u8 *cdb = scmd->cmnd; |
3140 | u16 fp; | 3140 | u16 fp; |
3141 | u16 cdb_offset = 0; | ||
3141 | 3142 | ||
3142 | if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { | 3143 | /* 7Fh variable length cmd means a ata pass-thru(32) */ |
3144 | if (cdb[0] == VARIABLE_LENGTH_CMD) | ||
3145 | cdb_offset = 9; | ||
3146 | |||
3147 | tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]); | ||
3148 | if (tf->protocol == ATA_PROT_UNKNOWN) { | ||
3143 | fp = 1; | 3149 | fp = 1; |
3144 | goto invalid_fld; | 3150 | goto invalid_fld; |
3145 | } | 3151 | } |
3146 | 3152 | ||
3147 | if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0) | 3153 | if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0) |
3148 | tf->protocol = ATA_PROT_NCQ_NODATA; | 3154 | tf->protocol = ATA_PROT_NCQ_NODATA; |
3149 | 3155 | ||
3150 | /* enable LBA */ | 3156 | /* enable LBA */ |
@@ -3180,7 +3186,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
3180 | tf->lbah = cdb[12]; | 3186 | tf->lbah = cdb[12]; |
3181 | tf->device = cdb[13]; | 3187 | tf->device = cdb[13]; |
3182 | tf->command = cdb[14]; | 3188 | tf->command = cdb[14]; |
3183 | } else { | 3189 | } else if (cdb[0] == ATA_12) { |
3184 | /* | 3190 | /* |
3185 | * 12-byte CDB - incapable of extended commands. | 3191 | * 12-byte CDB - incapable of extended commands. |
3186 | */ | 3192 | */ |
@@ -3193,6 +3199,30 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
3193 | tf->lbah = cdb[7]; | 3199 | tf->lbah = cdb[7]; |
3194 | tf->device = cdb[8]; | 3200 | tf->device = cdb[8]; |
3195 | tf->command = cdb[9]; | 3201 | tf->command = cdb[9]; |
3202 | } else { | ||
3203 | /* | ||
3204 | * 32-byte CDB - may contain extended command fields. | ||
3205 | * | ||
3206 | * If that is the case, copy the upper byte register values. | ||
3207 | */ | ||
3208 | if (cdb[10] & 0x01) { | ||
3209 | tf->hob_feature = cdb[20]; | ||
3210 | tf->hob_nsect = cdb[22]; | ||
3211 | tf->hob_lbal = cdb[16]; | ||
3212 | tf->hob_lbam = cdb[15]; | ||
3213 | tf->hob_lbah = cdb[14]; | ||
3214 | tf->flags |= ATA_TFLAG_LBA48; | ||
3215 | } else | ||
3216 | tf->flags &= ~ATA_TFLAG_LBA48; | ||
3217 | |||
3218 | tf->feature = cdb[21]; | ||
3219 | tf->nsect = cdb[23]; | ||
3220 | tf->lbal = cdb[19]; | ||
3221 | tf->lbam = cdb[18]; | ||
3222 | tf->lbah = cdb[17]; | ||
3223 | tf->device = cdb[24]; | ||
3224 | tf->command = cdb[25]; | ||
3225 | tf->auxiliary = get_unaligned_be32(&cdb[28]); | ||
3196 | } | 3226 | } |
3197 | 3227 | ||
3198 | /* For NCQ commands copy the tag value */ | 3228 | /* For NCQ commands copy the tag value */ |
@@ -4138,6 +4168,35 @@ static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc) | |||
4138 | } | 4168 | } |
4139 | 4169 | ||
4140 | /** | 4170 | /** |
4171 | * ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler | ||
4172 | * @qc: Command to be translated | ||
4173 | * | ||
4174 | * Translate a SCSI variable length CDB to specified commands. | ||
4175 | * It checks a service action value in CDB to call corresponding handler. | ||
4176 | * | ||
4177 | * RETURNS: | ||
4178 | * Zero on success, non-zero on failure | ||
4179 | * | ||
4180 | */ | ||
4181 | static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc) | ||
4182 | { | ||
4183 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
4184 | const u8 *cdb = scmd->cmnd; | ||
4185 | const u16 sa = get_unaligned_be16(&cdb[8]); | ||
4186 | |||
4187 | /* | ||
4188 | * if service action represents a ata pass-thru(32) command, | ||
4189 | * then pass it to ata_scsi_pass_thru handler. | ||
4190 | */ | ||
4191 | if (sa == ATA_32) | ||
4192 | return ata_scsi_pass_thru(qc); | ||
4193 | |||
4194 | unspprt_sa: | ||
4195 | /* unsupported service action */ | ||
4196 | return 1; | ||
4197 | } | ||
4198 | |||
4199 | /** | ||
4141 | * ata_get_xlat_func - check if SCSI to ATA translation is possible | 4200 | * ata_get_xlat_func - check if SCSI to ATA translation is possible |
4142 | * @dev: ATA device | 4201 | * @dev: ATA device |
4143 | * @cmd: SCSI command opcode to consider | 4202 | * @cmd: SCSI command opcode to consider |
@@ -4177,6 +4236,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) | |||
4177 | case ATA_16: | 4236 | case ATA_16: |
4178 | return ata_scsi_pass_thru; | 4237 | return ata_scsi_pass_thru; |
4179 | 4238 | ||
4239 | case VARIABLE_LENGTH_CMD: | ||
4240 | return ata_scsi_var_len_cdb_xlat; | ||
4241 | |||
4180 | case MODE_SELECT: | 4242 | case MODE_SELECT: |
4181 | case MODE_SELECT_10: | 4243 | case MODE_SELECT_10: |
4182 | return ata_scsi_mode_select_xlat; | 4244 | return ata_scsi_mode_select_xlat; |
@@ -4461,7 +4523,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) | |||
4461 | shost->max_id = 16; | 4523 | shost->max_id = 16; |
4462 | shost->max_lun = 1; | 4524 | shost->max_lun = 1; |
4463 | shost->max_channel = 1; | 4525 | shost->max_channel = 1; |
4464 | shost->max_cmd_len = 16; | 4526 | shost->max_cmd_len = 32; |
4465 | 4527 | ||
4466 | /* Schedule policy is determined by ->qc_defer() | 4528 | /* Schedule policy is determined by ->qc_defer() |
4467 | * callback and it needs to see every deferred qc. | 4529 | * callback and it needs to see every deferred qc. |