1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 __FBSDID("$FreeBSD$"); 57 58 /** 59 * @file 60 * @brief This file contains the implementation to translate 61 * SCSI Request Sense command based of the SAT spec. 62 */ 63 64 #if !defined(DISABLE_SATI_REQUEST_SENSE) 65 66 #include <dev/isci/scil/sati_request_sense.h> 67 #include <dev/isci/scil/sati_device.h> 68 #include <dev/isci/scil/sati_util.h> 69 #include <dev/isci/scil/intel_scsi.h> 70 #include <dev/isci/scil/intel_ata.h> 71 #include <dev/isci/scil/intel_sat.h> 72 #include <dev/isci/scil/sati_callbacks.h> 73 #include <dev/isci/scil/sati_mode_pages.h> 74 75 #define MRIE_BYTE 3 76 #define DEXCPT_BYTE 2 77 78 /** 79 * @brief This method will translate the SCSI request sense command 80 * into corresponding ATA commands. Depending on supported and enabled 81 * capabilities like SMART, different ATA commands can be selected. 82 * For more information on the parameters passed to this method, 83 * please reference sati_translate_command(). 84 * 85 * @return Indicates if the command translation succeeded. 86 * @retval SATI_SUCCESS indicates that the translation was supported and occurred 87 * without error. 88 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 89 * the SATII is processing a format unit commmand. 90 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without 91 * error, and no additional translation is necessary. 92 */ 93 SATI_STATUS sati_request_sense_translate_command( 94 SATI_TRANSLATOR_SEQUENCE_T * sequence, 95 void * scsi_io, 96 void * ata_io 97 ) 98 { 99 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 100 101 //check if SATI is processing format unit command 102 switch(sequence->device->state) 103 { 104 case SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS: 105 sati_scsi_sense_data_construct( 106 sequence, 107 scsi_io, 108 SCSI_STATUS_GOOD, 109 SCSI_SENSE_NOT_READY, 110 SCSI_ASC_LUN_FORMAT_IN_PROGRESS, 111 SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 112 ); 113 return SATI_COMPLETE; 114 break; 115 116 case SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION: 117 sati_scsi_sense_data_construct( 118 sequence, 119 scsi_io, 120 SCSI_STATUS_GOOD, 121 SCSI_SENSE_UNIT_ATTENTION, 122 sequence->device->unit_attention_asc, 123 sequence->device->unit_attention_ascq 124 ); 125 return SATI_COMPLETE; 126 break; 127 //sending sense data status Idle, this is set by start_stop_unit 128 case SATI_DEVICE_STATE_IDLE: 129 sati_scsi_sense_data_construct( 130 sequence, 131 scsi_io, 132 SCSI_STATUS_GOOD, 133 SCSI_SENSE_NO_SENSE, 134 SCSI_ASC_POWER_STATE_CHANGE, 135 SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 136 ); 137 return SATI_COMPLETE; 138 break; 139 //sending sense data status Standby, this is set by start_stop_unit 140 case SATI_DEVICE_STATE_STANDBY: 141 sati_scsi_sense_data_construct( 142 sequence, 143 scsi_io, 144 SCSI_STATUS_GOOD, 145 SCSI_SENSE_NO_SENSE, 146 SCSI_ASC_POWER_STATE_CHANGE, 147 SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 148 ); 149 return SATI_COMPLETE; 150 break; 151 152 case SATI_DEVICE_STATE_STOPPED: 153 sati_scsi_sense_data_construct( 154 sequence, 155 scsi_io, 156 SCSI_STATUS_GOOD, 157 SCSI_SENSE_NO_SENSE, 158 SCSI_ASC_NO_ADDITIONAL_SENSE, 159 SCSI_ASCQ_NO_ADDITIONAL_SENSE 160 ); 161 return SATI_COMPLETE; 162 break; 163 164 default: 165 break; 166 } 167 168 sequence->allocation_length = sati_get_cdb_byte(cdb, 4); 169 170 //Check if the device has SMART support & SMART enabled 171 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT) 172 { 173 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE) 174 { 175 sati_ata_smart_return_status_construct( 176 ata_io, 177 sequence, 178 ATA_SMART_SUB_CMD_RETURN_STATUS 179 ); 180 181 sequence->type = SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS; 182 return SATI_SUCCESS; 183 } 184 } 185 sati_ata_check_power_mode_construct(ata_io, sequence); 186 sequence->type = SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE; 187 return SATI_SUCCESS; 188 } 189 190 /** 191 * @brief This method will translate the response to the SATI Request Sense 192 * translation. ATA_Check_Power_Mode and ATA_SMART_Return_Status will 193 * be translated into a SCSI sense data response. 194 * 195 * @return SATI_STATUS Indicates if the response translation succeeded. 196 * 197 */ 198 SATI_STATUS sati_request_sense_translate_response( 199 SATI_TRANSLATOR_SEQUENCE_T * sequence, 200 void * scsi_io, 201 void * ata_io 202 ) 203 { 204 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 205 U32 mid_register; 206 U32 high_register; 207 U32 sector_count; 208 SATI_STATUS status = SATI_FAILURE; 209 210 if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 211 { 212 sati_scsi_sense_data_construct( 213 sequence, 214 scsi_io, 215 SCSI_STATUS_CHECK_CONDITION, 216 SCSI_SENSE_ABORTED_COMMAND, 217 SCSI_ASC_NO_ADDITIONAL_SENSE , 218 SCSI_ASCQ_NO_ADDITIONAL_SENSE 219 ); 220 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 221 } 222 else 223 { 224 switch(sequence->type) 225 { 226 case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS: 227 228 mid_register = sati_get_ata_lba_mid(register_fis); 229 high_register = sati_get_ata_lba_high(register_fis); 230 if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED 231 && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED) 232 { 233 sati_request_sense_data_response_construct( 234 sequence, 235 scsi_io, 236 SCSI_SENSE_NO_SENSE, 237 SCSI_ASC_HARDWARE_IMPENDING_FAILURE, 238 SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 239 ); 240 status = SATI_COMPLETE; 241 } 242 else 243 { 244 sati_request_sense_data_response_construct( 245 sequence, 246 scsi_io, 247 SCSI_SENSE_NO_SENSE, 248 SCSI_ASC_NO_ADDITIONAL_SENSE, 249 SCSI_ASCQ_NO_ADDITIONAL_SENSE 250 ); 251 status = SATI_COMPLETE; 252 } 253 break; 254 255 case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE: 256 257 sector_count = sati_get_ata_sector_count(register_fis); 258 259 switch(sector_count) 260 { 261 case ATA_STANDBY_POWER_MODE: 262 sati_request_sense_data_response_construct( 263 sequence, 264 scsi_io, 265 SCSI_SENSE_NO_SENSE, 266 SCSI_ASC_POWER_STATE_CHANGE, 267 SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 268 ); 269 status = SATI_COMPLETE; 270 break; 271 272 case ATA_IDLE_POWER_MODE: 273 sati_request_sense_data_response_construct( 274 sequence, 275 scsi_io, 276 SCSI_SENSE_NO_SENSE, 277 SCSI_ASC_POWER_STATE_CHANGE, 278 SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 279 ); 280 status = SATI_COMPLETE; 281 break; 282 283 case ATA_ACTIVE_POWER_MODE: 284 sati_request_sense_data_response_construct( 285 sequence, 286 scsi_io, 287 SCSI_SENSE_NO_SENSE, 288 SCSI_ASC_NO_ADDITIONAL_SENSE, 289 SCSI_ASCQ_NO_ADDITIONAL_SENSE 290 ); 291 status = SATI_COMPLETE; 292 break; 293 294 default: 295 break; 296 } 297 break; 298 299 default: 300 sati_request_sense_data_response_construct( 301 sequence, 302 scsi_io, 303 SCSI_SENSE_NO_SENSE, 304 SCSI_ASC_NO_ADDITIONAL_SENSE, 305 SCSI_ASCQ_NO_ADDITIONAL_SENSE 306 ); 307 status = SATI_COMPLETE; 308 } 309 } 310 311 return status; 312 } 313 314 /** 315 * @brief This method will construct a response for the sati_request_sense 316 * translation. The response will be returned in the data buffer instead 317 * of the response buffer, using sense data format described in SPC-4. 318 * 319 */ 320 void sati_request_sense_data_response_construct( 321 SATI_TRANSLATOR_SEQUENCE_T * sequence, 322 void * scsi_io, 323 U8 sense_key, 324 U8 additional_sense_code, 325 U8 additional_sense_code_qualifier 326 ) 327 { 328 sati_set_data_byte( 329 sequence, 330 scsi_io, 331 0, 332 SCSI_FIXED_CURRENT_RESPONSE_CODE | SCSI_FIXED_SENSE_DATA_VALID_BIT 333 ); 334 335 sati_set_data_byte(sequence, scsi_io, 1, 0); 336 sati_set_data_byte(sequence, scsi_io, 2, sense_key); 337 sati_set_data_byte(sequence, scsi_io, 3, 0); 338 sati_set_data_byte(sequence, scsi_io, 4, 0); 339 sati_set_data_byte(sequence, scsi_io, 5, 0); 340 sati_set_data_byte(sequence, scsi_io, 6, 0); 341 sati_set_data_byte(sequence, scsi_io, 7, 0); 342 sati_set_data_byte(sequence, scsi_io, 8, 0); 343 sati_set_data_byte(sequence, scsi_io, 9, 0); 344 sati_set_data_byte(sequence, scsi_io, 10, 0); 345 sati_set_data_byte(sequence, scsi_io, 11, 0); 346 sati_set_data_byte(sequence, scsi_io, 12, additional_sense_code); 347 sati_set_data_byte(sequence, scsi_io, 13, additional_sense_code_qualifier); 348 sati_set_data_byte(sequence, scsi_io, 14, 0); 349 sati_set_data_byte(sequence, scsi_io, 15, 0); 350 sati_set_data_byte(sequence, scsi_io, 16, 0); 351 sati_set_data_byte(sequence, scsi_io, 17, 0); 352 } 353 354 #endif // !defined(DISABLE_SATI_REQUEST_SENSE) 355 356