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 method implementations required to 61 * translate the SCSI start stop unit command. 62 */ 63 64 #if !defined(DISABLE_SATI_START_STOP_UNIT) 65 66 #include <dev/isci/scil/sati_start_stop_unit.h> 67 #include <dev/isci/scil/sati_util.h> 68 #include <dev/isci/scil/sati_callbacks.h> 69 #include <dev/isci/scil/intel_ata.h> 70 #include <dev/isci/scil/intel_scsi.h> 71 72 /** 73 * @brief This method will translate the start stop unit SCSI command into 74 * various ATA commands depends on the value in POWER CONTIDTION, LOEJ 75 * and START fields. 76 * For more information on the parameters passed to this method, 77 * please reference sati_translate_command(). 78 * 79 * @return Indicate if the command translation succeeded. 80 * @retval SCI_SUCCESS This is returned if the command translation was 81 * successful. 82 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA Please refer to spec. 83 * 84 */ 85 SATI_STATUS sati_start_stop_unit_translate_command( 86 SATI_TRANSLATOR_SEQUENCE_T * sequence, 87 void * scsi_io, 88 void * ata_io 89 ) 90 { 91 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 92 93 switch ( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) ) 94 { 95 case SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID: 96 if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0 97 && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 ) 98 { 99 if ( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 1 ) 100 { 101 //directly send ATA STANDBY_IMMEDIATE 102 sati_ata_standby_immediate_construct(ata_io, sequence); 103 sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED; 104 } 105 else 106 { 107 if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 108 { 109 //First, send ATA flush command. 110 sati_ata_flush_cache_construct(ata_io, sequence); 111 sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE; 112 113 //remember there is next step. 114 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 115 } 116 else 117 { 118 //the first step, flush cache command, has completed. 119 //Send standby immediate now. 120 sati_ata_standby_immediate_construct(ata_io, sequence); 121 sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED; 122 123 } 124 } 125 } 126 else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0 127 && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 ) 128 { 129 //need to know whether the device supports removable medial feature set. 130 if (sequence->device->capabilities & SATI_DEVICE_CAP_REMOVABLE_MEDIA) 131 { 132 //send ATA MEDIA EJECT command. 133 sati_ata_media_eject_construct(ata_io, sequence); 134 sequence->command_specific_data.translated_command = ATA_MEDIA_EJECT; 135 } 136 else 137 { 138 sati_scsi_sense_data_construct( 139 sequence, 140 scsi_io, 141 SCSI_STATUS_CHECK_CONDITION, 142 SCSI_SENSE_ILLEGAL_REQUEST, 143 SCSI_ASC_INVALID_FIELD_IN_CDB, 144 SCSI_ASCQ_INVALID_FIELD_IN_CDB 145 ); 146 return SATI_FAILURE_CHECK_RESPONSE_DATA; 147 } 148 } 149 else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1 150 && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 ) 151 { 152 //send an ATA verify command 153 sati_ata_read_verify_sectors_construct(ata_io, sequence); 154 sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS; 155 } 156 else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1 157 && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 ) 158 { 159 sati_scsi_sense_data_construct( 160 sequence, 161 scsi_io, 162 SCSI_STATUS_CHECK_CONDITION, 163 SCSI_SENSE_ILLEGAL_REQUEST, 164 SCSI_ASC_INVALID_FIELD_IN_CDB, 165 SCSI_ASCQ_INVALID_FIELD_IN_CDB 166 ); 167 return SATI_FAILURE_CHECK_RESPONSE_DATA; 168 } 169 170 break; 171 //Power Condition Field is set to 0x01(Device to transition to Active state) 172 case SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE: 173 174 if( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 175 { 176 sati_ata_idle_construct(ata_io, sequence); 177 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 178 sequence->command_specific_data.translated_command = ATA_IDLE; 179 } 180 else 181 { 182 sati_ata_read_verify_sectors_construct(ata_io, sequence); 183 sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS; 184 } 185 break; 186 187 //Power Condition Field is set to 0x02(Device to transition to Idle state) 188 case SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE: 189 190 if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 && 191 sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 192 { 193 sati_ata_flush_cache_construct(ata_io, sequence); 194 sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE; 195 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 196 } 197 else 198 { 199 if( SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) == 0 ) 200 { 201 sati_ata_idle_immediate_construct(ata_io, sequence); 202 } 203 else 204 { 205 sati_ata_idle_immediate_unload_construct(ata_io, sequence); 206 } 207 sequence->command_specific_data.translated_command = ATA_IDLE_IMMED; 208 } 209 break; 210 211 //Power Condition Field is set to 0x03(Device to transition to Standby state) 212 case SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY: 213 if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 && 214 sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 215 { 216 sati_ata_flush_cache_construct(ata_io, sequence); 217 sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE; 218 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 219 } 220 else 221 { 222 sati_ata_standby_immediate_construct(ata_io, sequence); 223 sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED; 224 } 225 break; 226 227 //Power Condition Field is set to 0xB(force Standby state) 228 case SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL: 229 230 if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 && 231 sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 232 { 233 sati_ata_flush_cache_construct(ata_io, sequence); 234 sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE; 235 sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 236 } 237 else 238 { 239 sati_ata_standby_construct(ata_io, sequence, 0); 240 sequence->command_specific_data.translated_command = ATA_STANDBY; 241 } 242 break; 243 244 case SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL: 245 default: //TBD. 246 sati_scsi_sense_data_construct( 247 sequence, 248 scsi_io, 249 SCSI_STATUS_CHECK_CONDITION, 250 SCSI_SENSE_ILLEGAL_REQUEST, 251 SCSI_ASC_INVALID_FIELD_IN_CDB, 252 SCSI_ASCQ_INVALID_FIELD_IN_CDB 253 ); 254 return SATI_FAILURE_CHECK_RESPONSE_DATA; 255 break; 256 } 257 258 if ( SATI_START_STOP_UNIT_IMMED_BIT(cdb) == 1 ) 259 { 260 //@todo: return good status now. 261 ; 262 } 263 sequence->type = SATI_SEQUENCE_START_STOP_UNIT; 264 return SATI_SUCCESS; 265 } 266 267 268 /** 269 * @brief This method will translate the ATA command register FIS 270 * response into an appropriate SCSI response for START STOP UNIT. 271 * For more information on the parameters passed to this method, 272 * please reference sati_translate_response(). 273 * 274 * @return Indicate if the response translation succeeded. 275 * @retval SCI_SUCCESS This is returned if the data translation was 276 * successful. 277 */ 278 SATI_STATUS sati_start_stop_unit_translate_response( 279 SATI_TRANSLATOR_SEQUENCE_T * sequence, 280 void * scsi_io, 281 void * ata_io 282 ) 283 { 284 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 285 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 286 287 if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 288 { 289 switch ( sequence->command_specific_data.translated_command ) 290 { 291 case ATA_FLUSH_CACHE: 292 case ATA_STANDBY_IMMED: 293 case ATA_IDLE_IMMED: 294 case ATA_IDLE: 295 case ATA_STANDBY: 296 //Note: There is lack of reference in spec of the error handling for 297 //READ_VERIFY command. 298 case ATA_READ_VERIFY_SECTORS: 299 sati_scsi_sense_data_construct( 300 sequence, 301 scsi_io, 302 SCSI_STATUS_CHECK_CONDITION, 303 SCSI_SENSE_ABORTED_COMMAND, 304 SCSI_ASC_COMMAND_SEQUENCE_ERROR, 305 SCSI_ASCQ_NO_ADDITIONAL_SENSE 306 ); 307 break; 308 309 case ATA_MEDIA_EJECT: 310 sati_scsi_sense_data_construct( 311 sequence, 312 scsi_io, 313 SCSI_STATUS_CHECK_CONDITION, 314 SCSI_SENSE_ABORTED_COMMAND, 315 SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED, 316 SCSI_ASCQ_NO_ADDITIONAL_SENSE 317 ); 318 break; 319 320 default: 321 sati_scsi_sense_data_construct( 322 sequence, 323 scsi_io, 324 SCSI_STATUS_CHECK_CONDITION, 325 SCSI_SENSE_ILLEGAL_REQUEST, 326 SCSI_ASC_INVALID_FIELD_IN_CDB, 327 SCSI_ASCQ_INVALID_FIELD_IN_CDB 328 ); 329 break; 330 } 331 sequence->state = SATI_SEQUENCE_STATE_FINAL; 332 return SATI_FAILURE_CHECK_RESPONSE_DATA; 333 } 334 else 335 { 336 switch ( sequence->command_specific_data.translated_command ) 337 { 338 case ATA_READ_VERIFY_SECTORS: 339 340 sati_scsi_sense_data_construct( 341 sequence, 342 scsi_io, 343 SCSI_STATUS_GOOD, 344 SCSI_SENSE_NO_SENSE, 345 SCSI_ASC_NO_ADDITIONAL_SENSE, 346 SCSI_ASCQ_NO_ADDITIONAL_SENSE 347 ); 348 //device state is now operational(active) 349 sequence->device->state = SATI_DEVICE_STATE_OPERATIONAL; 350 sequence->state = SATI_SEQUENCE_STATE_FINAL; 351 break; 352 353 case ATA_IDLE_IMMED: 354 355 sati_scsi_sense_data_construct( 356 sequence, 357 scsi_io, 358 SCSI_STATUS_GOOD, 359 SCSI_SENSE_NO_SENSE, 360 SCSI_ASC_NO_ADDITIONAL_SENSE, 361 SCSI_ASCQ_NO_ADDITIONAL_SENSE 362 ); 363 sequence->device->state = SATI_DEVICE_STATE_IDLE; 364 sequence->state = SATI_SEQUENCE_STATE_FINAL; 365 break; 366 367 //These three commands will be issued when the power condition is 0x00 or 0x03 368 case ATA_MEDIA_EJECT: 369 case ATA_STANDBY: 370 case ATA_STANDBY_IMMED: 371 372 sati_scsi_sense_data_construct( 373 sequence, 374 scsi_io, 375 SCSI_STATUS_GOOD, 376 SCSI_SENSE_NO_SENSE, 377 SCSI_ASC_NO_ADDITIONAL_SENSE, 378 SCSI_ASCQ_NO_ADDITIONAL_SENSE 379 ); 380 381 if( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) == 0 ) 382 { 383 sequence->device->state = SATI_DEVICE_STATE_STOPPED; 384 } 385 else 386 { 387 sequence->device->state = SATI_DEVICE_STATE_STANDBY; 388 } 389 sequence->state = SATI_SEQUENCE_STATE_FINAL; 390 break; 391 392 default: 393 //FLUSH Cache command does not require any success handling 394 break; 395 } 396 397 if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 398 { 399 return SATI_SEQUENCE_INCOMPLETE; 400 } 401 } 402 return SATI_COMPLETE; 403 } 404 405 #endif // !defined(DISABLE_SATI_START_STOP_UNIT) 406 407