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