sati_mode_sense_6.c revision 331722
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: stable/11/sys/dev/isci/scil/sati_mode_sense_6.c 331722 2018-03-29 02:50:57Z eadler $"); 55 56/** 57 * @file 58 * @brief This file contains the method implementations required to 59 * translate the SCSI mode sense 6-byte commands. 60 */ 61 62#if !defined(DISABLE_SATI_MODE_SENSE) 63 64#include <dev/isci/scil/sati_mode_sense.h> 65#include <dev/isci/scil/sati_mode_sense_6.h> 66#include <dev/isci/scil/sati_mode_pages.h> 67#include <dev/isci/scil/sati_callbacks.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 72//****************************************************************************** 73//* P R I V A T E M E T H O D S 74//****************************************************************************** 75 76/** 77 * @brief This method builds the mode parameter header for a 6-byte SCSI 78 * mode sense data response. The parameter header is 4 bytes in 79 * size. 80 * For more information on the parameters passed to this method, 81 * please reference sati_translate_command(). 82 * 83 * @param[in] identify This parameter specifies the ATA remote device's 84 * received IDENTIFY DEVICE data. 85 * @param[in] mode_data_length This parameter specifies the amount of data 86 * to be returned as part of this mode sense request. 87 * 88 * @return This method returns the number of bytes written into the 89 * data buffer. 90 */ 91static 92U32 sati_mode_sense_6_build_header( 93 SATI_TRANSLATOR_SEQUENCE_T * sequence, 94 void * scsi_io, 95 ATA_IDENTIFY_DEVICE_DATA_T * identify, 96 U8 mode_data_length 97) 98{ 99 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 100 101 // Fill in the length of the mode parameter data returned (do not include 102 // the size of the mode data length field in the total). 103 sati_set_data_byte(sequence, scsi_io, 0, (U8)mode_data_length-1); 104 105 // Medium Type is 0 for SBC devices 106 sati_set_data_byte(sequence, scsi_io, 1, SCSI_MODE_HEADER_MEDIUM_TYPE_SBC); 107 108 // Write Protect (WP), Rsvd, DPOFUA, Rsvd 109 if (sequence->device->capabilities & SATI_DEVICE_CAP_DMA_FUA_ENABLE) 110 sati_set_data_byte(sequence,scsi_io,2,SCSI_MODE_SENSE_HEADER_FUA_ENABLE); 111 else 112 sati_set_data_byte(sequence, scsi_io, 2, 0); 113 114 // Set the block descriptor length if block descriptors are utilized. 115 if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) 116 sati_set_data_byte(sequence, scsi_io, 3, 0); 117 else 118 sati_set_data_byte( 119 sequence, scsi_io, 3, SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 120 ); 121 122 return SCSI_MODE_SENSE_6_HEADER_LENGTH; 123} 124 125/** 126 * @brief This method perform the data translation common to all SCSI MODE 127 * SENSE 6 byte commands. This includes building the mode page 128 * header and block descriptor (if requested). 129 * For more information on the parameters passed to this method, 130 * please reference sati_translate_command(). 131 * 132 * @param[in] identify This parameter specifies the remote device's IDENTIFY 133 * DEVICE data to be used during translation. 134 * @param[in] transfer_length This parameter specifies the size of the 135 * mode page (including header & block descriptor). 136 * 137 * @return This method returns the number of bytes written into the user's 138 * mode page data buffer. 139 */ 140static 141U32 sati_mode_sense_6_translate_data( 142 SATI_TRANSLATOR_SEQUENCE_T * sequence, 143 ATA_IDENTIFY_DEVICE_DATA_T * identify, 144 void * scsi_io, 145 U8 transfer_length 146) 147{ 148 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 149 U32 offset; 150 151 offset = sati_mode_sense_6_build_header( 152 sequence, scsi_io, identify, transfer_length 153 ); 154 155 // Determine if the caller disabled block descriptors (DBD). If not, 156 // then generate a block descriptor. 157 if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0) 158 offset += sati_mode_sense_build_std_block_descriptor( 159 sequence, scsi_io, identify, offset 160 ); 161 162 return offset; 163} 164 165//****************************************************************************** 166//* P R O T E C T E D M E T H O D S 167//****************************************************************************** 168 169/** 170 * @brief This method will translate the SCSI mode sense 6 byte command 171 * into corresponding ATA commands. If the command is well-formed, 172 * then the translation will result in an ATA IDENTIFY DEVICE 173 * command. 174 * For more information on the parameters passed to this method, 175 * please reference sati_translate_command(). 176 * 177 * @return Indicate if the command translation succeeded. 178 * @retval SCI_SUCCESS This is returned if the command translation was 179 * successful. 180 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 181 * sense data has been created as a result of something specified 182 * in the CDB. 183 */ 184SATI_STATUS sati_mode_sense_6_translate_command( 185 SATI_TRANSLATOR_SEQUENCE_T * sequence, 186 void * scsi_io, 187 void * ata_io 188) 189{ 190 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 191 192 // Set the data length based on the allocation length field in the CDB. 193 sequence->allocation_length = sati_get_cdb_byte(cdb, 4); 194 195 return sati_mode_sense_translate_command(sequence, scsi_io, ata_io, 6); 196} 197 198/** 199 * @brief This method will perform data translation from the supplied ATA 200 * input data (i.e. an ATA IDENTIFY DEVICE block) into a CACHING 201 * mode page format. The data will be written into the user's mode 202 * page data buffer. This function operates specifically for MODE 203 * SENSE 6 commands. 204 * For more information on the parameters passed to this method, 205 * please reference sati_translate_data(). 206 * 207 * @return none. 208 */ 209void sati_mode_sense_6_caching_translate_data( 210 SATI_TRANSLATOR_SEQUENCE_T * sequence, 211 void * ata_input_data, 212 void * scsi_io 213) 214{ 215 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 216 ata_input_data; 217 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 218 + SCSI_MODE_PAGE_08_LENGTH; 219 U32 page_offset = sati_mode_sense_6_translate_data( 220 sequence, identify, scsi_io, data_length 221 ); 222 223 sati_mode_sense_caching_translate_data( 224 sequence, scsi_io, identify, page_offset 225 ); 226} 227 228/** 229 * @brief This method will perform data translation from the supplied ATA 230 * input data (i.e. an ATA IDENTIFY DEVICE block) into a INFORMATIONAL 231 * EXCEPTIONS CONTROL mode page format. The data will be written 232 * into the user's mode page data buffer. This function operates 233 * specifically for MODE SENSE 6 commands. 234 * For more information on the parameters passed to this method, 235 * please reference sati_translate_data(). 236 * 237 * @return none. 238 */ 239void sati_mode_sense_6_informational_excp_control_translate_data( 240 SATI_TRANSLATOR_SEQUENCE_T * sequence, 241 void * ata_input_data, 242 void * scsi_io 243) 244{ 245 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 246 ata_input_data; 247 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 248 + SCSI_MODE_PAGE_1C_LENGTH; 249 U32 page_offset = sati_mode_sense_6_translate_data( 250 sequence, identify, scsi_io, data_length 251 ); 252 253 sati_mode_sense_informational_excp_control_translate_data( 254 sequence, scsi_io, identify, page_offset 255 ); 256} 257 258/** 259* @brief This method will perform data translation from the supplied ATA 260* input data (i.e. an ATA IDENTIFY DEVICE block) into a DISCONNECT 261* RECONNECT mode page format. The data will be written 262* into the user's mode page data buffer. This function operates 263* specifically for MODE SENSE 6 commands. 264* For more information on the parameters passed to this method, 265* please reference sati_translate_data(). 266* 267* @return none. 268*/ 269void sati_mode_sense_6_disconnect_reconnect_translate_data( 270 SATI_TRANSLATOR_SEQUENCE_T * sequence, 271 void * ata_input_data, 272 void * scsi_io 273) 274{ 275 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 276 ata_input_data; 277 278 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 279 + SCSI_MODE_PAGE_02_LENGTH ; 280 281 U32 page_offset = sati_mode_sense_6_translate_data( 282 sequence, identify, scsi_io, data_length 283 ); 284 285 sati_mode_sense_disconnect_reconnect_translate_data( 286 sequence, scsi_io, identify, page_offset 287 ); 288} 289 290/** 291* @brief This method will perform data translation from the supplied ATA 292* input data (i.e. an ATA IDENTIFY DEVICE block) into a READ WRITE ERROR 293* mode page format. The data will be written 294* into the user's mode page data buffer. This function operates 295* specifically for MODE SENSE 6 commands. 296* For more information on the parameters passed to this method, 297* please reference sati_translate_data(). 298* 299* @return none. 300*/ 301void sati_mode_sense_6_read_write_error_translate_data( 302 SATI_TRANSLATOR_SEQUENCE_T * sequence, 303 void * ata_input_data, 304 void * scsi_io 305) 306{ 307 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 308 ata_input_data; 309 310 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 311 + SCSI_MODE_PAGE_01_LENGTH; 312 313 U32 page_offset = sati_mode_sense_6_translate_data( 314 sequence, identify, scsi_io, data_length 315 ); 316 317 sati_mode_sense_read_write_error_translate_data( 318 sequence, scsi_io, identify, page_offset 319 ); 320} 321 322/** 323* @brief This method will perform data translation from the supplied ATA 324* input data (i.e. an ATA IDENTIFY DEVICE block) into a CONTROL 325* mode page format. The data will be written 326* into the user's mode page data buffer. This function operates 327* specifically for MODE SENSE 6 commands. 328* For more information on the parameters passed to this method, 329* please reference sati_translate_data(). 330* 331* @return none. 332*/ 333void sati_mode_sense_6_control_translate_data( 334 SATI_TRANSLATOR_SEQUENCE_T * sequence, 335 void * ata_input_data, 336 void * scsi_io 337) 338{ 339 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 340 ata_input_data; 341 342 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 343 + SCSI_MODE_PAGE_0A_LENGTH; 344 345 U32 page_offset = sati_mode_sense_6_translate_data( 346 sequence, identify, scsi_io, data_length 347 ); 348 349 sati_mode_sense_control_translate_data( 350 sequence, scsi_io, identify, page_offset 351 ); 352} 353 354/** 355* @brief This method will perform data translation from the supplied ATA 356* input data (i.e. an ATA IDENTIFY DEVICE block) into a Power 357* Condition mode page format. The data will be written 358* into the user's mode page data buffer. This function operates 359* specifically for MODE SENSE 6 commands. 360* For more information on the parameters passed to this method, 361* please reference sati_translate_data(). 362* 363* @return none. 364*/ 365void sati_mode_sense_6_power_condition_translate_data( 366 SATI_TRANSLATOR_SEQUENCE_T * sequence, 367 void * ata_input_data, 368 void * scsi_io 369) 370{ 371 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 372 ata_input_data; 373 374 U8 data_length; 375 U32 page_offset; 376 377 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 378 + SCSI_MODE_PAGE_1A_LENGTH; 379 380 page_offset = sati_mode_sense_6_translate_data( 381 sequence, identify, scsi_io, data_length 382 ); 383 384 sati_mode_sense_power_condition_translate_data( 385 sequence, scsi_io, identify, page_offset 386 ); 387} 388 389 390 391/** 392 * @brief This method will perform data translation from the supplied ATA 393 * input data (i.e. an ATA IDENTIFY DEVICE block) into an ALL 394 * PAGES mode page format. The ALL PAGES mode page is basically a 395 * conglomeration of all mode pages and sub-pages into a single 396 * page. The data will be written into the user's mode page 397 * data buffer. This function operates specifically for MODE 398 * SENSE 6 commands. 399 * For more information on the parameters passed to this method, 400 * please reference sati_translate_data(). 401 * 402 * @return none. 403 */ 404void sati_mode_sense_6_all_pages_translate_data( 405 SATI_TRANSLATOR_SEQUENCE_T * sequence, 406 void * ata_input_data, 407 void * scsi_io 408) 409{ 410 ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*) 411 ata_input_data; 412 U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6) 413 + SCSI_MODE_PAGE_01_LENGTH 414 + SCSI_MODE_PAGE_02_LENGTH 415 + SCSI_MODE_PAGE_08_LENGTH 416 + SCSI_MODE_PAGE_0A_LENGTH 417 + SCSI_MODE_PAGE_1C_LENGTH; 418 419 U32 page_offset = sati_mode_sense_6_translate_data( 420 sequence, identify, scsi_io, data_length 421 ); 422 423 sati_mode_sense_all_pages_translate_data( 424 sequence, scsi_io, identify, page_offset 425 ); 426} 427 428#endif // !defined(DISABLE_SATI_MODE_SENSE) 429 430