sati_util.c revision 302380
1275970Scy/*- 2275970Scy * This file is provided under a dual BSD/GPLv2 license. When using or 3275970Scy * redistributing this file, you may do so under either license. 4275970Scy * 5275970Scy * GPL LICENSE SUMMARY 6275970Scy * 7275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8275970Scy * 9275970Scy * This program is free software; you can redistribute it and/or modify 10275970Scy * it under the terms of version 2 of the GNU General Public License as 11285612Sdelphij * published by the Free Software Foundation. 12275970Scy * 13275970Scy * This program is distributed in the hope that it will be useful, but 14275970Scy * WITHOUT ANY WARRANTY; without even the implied warranty of 15275970Scy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16275970Scy * General Public License for more details. 17275970Scy * 18275970Scy * You should have received a copy of the GNU General Public License 19275970Scy * along with this program; if not, write to the Free Software 20275970Scy * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21275970Scy * The full GNU General Public License is included in this distribution 22275970Scy * in the file called LICENSE.GPL. 23275970Scy * 24275970Scy * BSD LICENSE 25275970Scy * 26275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27275970Scy * All rights reserved. 28275970Scy * 29275970Scy * Redistribution and use in source and binary forms, with or without 30275970Scy * modification, are permitted provided that the following conditions 31275970Scy * are met: 32275970Scy * 33275970Scy * * Redistributions of source code must retain the above copyright 34275970Scy * notice, this list of conditions and the following disclaimer. 35275970Scy * * Redistributions in binary form must reproduce the above copyright 36275970Scy * notice, this list of conditions and the following disclaimer in 37275970Scy * the documentation and/or other materials provided with the 38275970Scy * distribution. 39275970Scy * 40275970Scy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41275970Scy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42275970Scy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43275970Scy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44275970Scy * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45275970Scy * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46275970Scy * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50275970Scy * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51275970Scy */ 52275970Scy 53275970Scy#include <sys/cdefs.h> 54275970Scy__FBSDID("$FreeBSD: head/sys/dev/isci/scil/sati_util.c 302380 2016-07-06 20:48:42Z jimharris $"); 55275970Scy 56275970Scy/** 57275970Scy * @file 58275970Scy * @brief This file contains all of the method implementations that 59275970Scy * provide generic support for SATI. Some methods can be utilized 60275970Scy * by a user to construct ATA/ATAPI commands, copy ATA device 61275970Scy * structure data, fill in sense data, etc. 62275970Scy */ 63275970Scy 64275970Scy#include <dev/isci/scil/sati_util.h> 65275970Scy#include <dev/isci/scil/sati_callbacks.h> 66275970Scy#include <dev/isci/scil/intel_scsi.h> 67275970Scy#include <dev/isci/scil/intel_ata.h> 68275970Scy#include <dev/isci/scil/intel_sat.h> 69275970Scy#include <dev/isci/scil/intel_sas.h> 70275970Scy 71275970Scy/** 72275970Scy * @brief This method will set the data direction, protocol, and transfer 73275970Scy * kength for an ATA non-data command. 74275970Scy * 75275970Scy * @pre It is expected that the user will use this method for setting these 76275970Scy * values in a non-data ATA command constuct. 77275970Scy * 78275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure 79275970Scy * for which to build the IDENTIFY DEVICE command. 80275970Scy * @param[in] sequence This parameter specifies the translator sequence 81275970Scy * for which the command is being constructed. 82275970Scy * 83275970Scy * @return none. 84275970Scy */ 85275970Scyvoid sati_ata_non_data_command( 86275970Scy void * ata_io, 87275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence 88275970Scy) 89275970Scy{ 90275970Scy sequence->data_direction = SATI_DATA_DIRECTION_NONE; 91275970Scy sequence->protocol = SAT_PROTOCOL_NON_DATA; 92275970Scy sequence->ata_transfer_length = 0; 93275970Scy} 94275970Scy 95275970Scy/** 96275970Scy * @brief This method will construct the ATA identify device command. 97275970Scy * 98275970Scy * @pre It is expected that the user has properly set the current contents 99275970Scy * of the register FIS to 0. 100275970Scy * 101275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure 102275970Scy * for which to build the IDENTIFY DEVICE command. 103275970Scy * @param[in] sequence This parameter specifies the translator sequence 104275970Scy * for which the command is being constructed. 105275970Scy * 106275970Scy * @return none. 107275970Scy */ 108275970Scyvoid sati_ata_identify_device_construct( 109275970Scy void * ata_io, 110275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence 111275970Scy) 112275970Scy{ 113275970Scy U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 114275970Scy 115275970Scy sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE); 116285612Sdelphij sequence->data_direction = SATI_DATA_DIRECTION_IN; 117285612Sdelphij sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 118285612Sdelphij sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T); 119285612Sdelphij} 120285612Sdelphij 121285612Sdelphij/** 122285612Sdelphij* @brief This method will construct the ATA Execute Device Diagnostic command. 123285612Sdelphij* 124285612Sdelphij* @param[out] ata_io This parameter specifies the ATA IO request structure 125285612Sdelphij* for which to build the IDENTIFY DEVICE command. 126285612Sdelphij* @param[in] sequence This parameter specifies the translator sequence 127285612Sdelphij* for which the command is being constructed. 128285612Sdelphij* 129285612Sdelphij* @return none. 130285612Sdelphij*/ 131285612Sdelphijvoid sati_ata_execute_device_diagnostic_construct( 132285612Sdelphij void * ata_io, 133275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence 134275970Scy) 135275970Scy{ 136275970Scy U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 137275970Scy 138275970Scy sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG); 139275970Scy 140275970Scy sequence->data_direction = SATI_DATA_DIRECTION_IN; 141275970Scy sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC; 142275970Scy sequence->ata_transfer_length = 16; 143275970Scy} 144275970Scy 145285612Sdelphij/** 146285612Sdelphij * @brief This method will set data bytes in the user data area. If the 147275970Scy * caller requests it, the data written will be forced to ascii 148275970Scy * printable characters if it isn't already a printable character. 149275970Scy * A printable character is considered to be >= 0x20 and <= 0x70. 150275970Scy * 151275970Scy * @param[in] sequence This parameter specifies the translation sequence 152275970Scy * for which to copy and swap the data. 153275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO 154275970Scy * request containing the destination buffer into which to copy. 155275970Scy * @param[in] destination_offset This parameter specifies the offset into 156275970Scy * the data buffer where the information will be copied to. 157275970Scy * @param[in] source_value This parameter specifies the value retrieved 158275970Scy * from the source buffer that is to be copied into the user 159285612Sdelphij * buffer area. 160275970Scy * @param[in] use_printable_chars This parameter indicates if the copy should 161275970Scy * ensure that the value copied is considered an ASCII printable 162275970Scy * character (e.g. A, B, " ", etc.). These characters reside 163275970Scy * in the 0x20 - 0x7E ASCII range. 164275970Scy * 165275970Scy * @return none 166275970Scy */ 167275970Scystatic 168275970Scyvoid sati_set_ascii_data_byte( 169275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence, 170275970Scy void * destination_scsi_io, 171275970Scy U32 destination_offset, 172275970Scy U8 source_value, 173275970Scy BOOL use_printable_chars 174275970Scy) 175275970Scy{ 176275970Scy // if the user requests that the copied data be ascii printable, then 177275970Scy // default to " " (i.e. 0x20) for all non-ascii printable characters. 178275970Scy if((use_printable_chars == TRUE) 179275970Scy && ((source_value < 0x20) || (source_value > 0x7E))) 180275970Scy { 181275970Scy source_value = 0x20; 182275970Scy } 183275970Scy 184275970Scy sati_set_data_byte( 185275970Scy sequence, destination_scsi_io, destination_offset, source_value 186275970Scy ); 187275970Scy} 188275970Scy 189275970Scy/** 190275970Scy * @brief This method performs a copy operation using an offset into the 191275970Scy * source buffer, an offset into the destination buffer, and a length. 192275970Scy * It will perform the byte swap from the 16-bit identify field 193275970Scy * into the network byte order SCSI location. 194275970Scy * 195275970Scy * @param[in] sequence This parameter specifies the translation sequence 196275970Scy * for which to copy and swap the data. 197275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO 198275970Scy * request containing the destination buffer into which to copy. 199275970Scy * @param[in] destination_offset This parameter specifies the offset into 200275970Scy * the data buffer where the information will be copied to. 201275970Scy * @param[in] source_buffer This parameter specifies the source buffer from 202275970Scy * which the data will be copied. 203275970Scy * @param[in] source_offset This parameter specifies the offset into the 204275970Scy * source buffer where the copy shall begin. 205275970Scy * @param[in] length This parameter specifies the number of bytes to copy 206275970Scy * during this operation. 207275970Scy * @param[in] use_printable_chars This parameter indicates if the copy should 208275970Scy * ensure that the value copied is considered an ASCII printable 209275970Scy * character (e.g. A, B, " ", etc.). These characters reside 210275970Scy * in the 0x20 - 0x7E ASCII range. 211275970Scy * 212275970Scy * @return none 213275970Scy */ 214275970Scyvoid sati_ata_identify_device_copy_data( 215275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence, 216275970Scy void * destination_scsi_io, 217275970Scy U32 destination_offset, 218275970Scy U8 * source_buffer, 219275970Scy U32 source_offset, 220275970Scy U32 length, 221275970Scy BOOL use_printable_chars 222275970Scy) 223275970Scy{ 224275970Scy source_buffer += source_offset; 225275970Scy while (length > 0) 226275970Scy { 227275970Scy sati_set_ascii_data_byte( 228275970Scy sequence, 229285612Sdelphij destination_scsi_io, 230285612Sdelphij destination_offset, 231275970Scy *(source_buffer+1), 232275970Scy use_printable_chars 233275970Scy ); 234275970Scy 235275970Scy sati_set_ascii_data_byte( 236275970Scy sequence, 237275970Scy destination_scsi_io, 238275970Scy destination_offset+1, 239275970Scy *source_buffer, 240275970Scy use_printable_chars 241275970Scy ); 242275970Scy 243275970Scy destination_offset += 2; 244275970Scy source_buffer += 2; 245275970Scy length -= 2; 246275970Scy } 247275970Scy} 248275970Scy 249275970Scy/** 250275970Scy * @brief This method performs a copy operation using a source buffer, 251275970Scy * an offset into the destination buffer, and a length. 252275970Scy * 253275970Scy * @param[in] sequence This parameter specifies the translation sequence 254275970Scy * for which to copy and swap the data. 255275970Scy * @param[out] destination_scsi_io This parameter specifies the SCSI IO 256275970Scy * request containing the destination buffer into which to copy. 257275970Scy * @param[in] destination_offset This parameter specifies the offset into 258275970Scy * the data buffer where the information will be copied to. 259275970Scy * @param[in] source_buffer This parameter specifies the source buffer from 260275970Scy * which the data will be copied. 261275970Scy * @param[in] length This parameter specifies the number of bytes to copy 262275970Scy * during this operation. 263275970Scy * 264275970Scy * @return none 265275970Scy */ 266275970Scyvoid sati_copy_data( 267275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence, 268275970Scy void * destination_scsi_io, 269275970Scy U32 destination_offset, 270275970Scy U8 * source_buffer, 271275970Scy U32 length 272275970Scy) 273275970Scy{ 274275970Scy while (length > 0) 275275970Scy { 276275970Scy sati_set_data_byte( 277275970Scy sequence, destination_scsi_io, destination_offset, *source_buffer 278275970Scy ); 279275970Scy 280275970Scy destination_offset++; 281275970Scy source_buffer++; 282275970Scy length--; 283275970Scy } 284275970Scy} 285275970Scy 286275970Scy/** 287275970Scy * @brief This method extracts the Logical Block Address high and low 32-bit 288275970Scy * values and the sector count 32-bit value from the ATA identify 289275970Scy * device data. 290275970Scy * 291275970Scy * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA 292275970Scy * from which to extract the sector information. 293275970Scy * @param[out] lba_high This parameter specifies the upper 32 bits for the 294275970Scy * number of logical block addresses for the device. The upper 295275970Scy * 16-bits should always be 0, since 48-bits of LBA is the most 296275970Scy * supported by an ATA device. 297275970Scy * @param[out] lba_low This parameter specifies the lower 32 bits for the 298275970Scy * number of logical block addresses for the device. 299275970Scy * @param[out] sector_size This parameter specifies the 32-bits of sector 300275970Scy * size. If the ATA device doesn't support reporting it's 301275970Scy * sector size, then 512 bytes is utilized as the default value. 302275970Scy * 303275970Scy * @return none 304275970Scy */ 305275970Scyvoid sati_ata_identify_device_get_sector_info( 306275970Scy ATA_IDENTIFY_DEVICE_DATA_T * identify, 307275970Scy U32 * lba_high, 308275970Scy U32 * lba_low, 309275970Scy U32 * sector_size 310275970Scy) 311275970Scy{ 312275970Scy // Calculate the values to be returned 313275970Scy // Calculation will be different if the SATA device supports 314275970Scy // 48-bit addressing. Bit 10 of Word 86 of ATA Identify 315275970Scy if (identify->command_set_enabled1 316275970Scy & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE) 317275970Scy { 318275970Scy // This drive supports 48-bit addressing 319275970Scy 320275970Scy *lba_high = identify->max_48bit_lba[7] << 24; 321275970Scy *lba_high |= identify->max_48bit_lba[6] << 16; 322275970Scy *lba_high |= identify->max_48bit_lba[5] << 8; 323275970Scy *lba_high |= identify->max_48bit_lba[4]; 324275970Scy 325275970Scy *lba_low = identify->max_48bit_lba[3] << 24; 326275970Scy *lba_low |= identify->max_48bit_lba[2] << 16; 327275970Scy *lba_low |= identify->max_48bit_lba[1] << 8; 328275970Scy *lba_low |= identify->max_48bit_lba[0]; 329275970Scy } 330275970Scy else 331275970Scy { 332275970Scy // This device doesn't support 48-bit addressing 333275970Scy // Pull out the largest LBA from words 60 and 61. 334275970Scy *lba_high = 0; 335275970Scy *lba_low = identify->total_num_sectors[3] << 24; 336275970Scy *lba_low |= identify->total_num_sectors[2] << 16; 337275970Scy *lba_low |= identify->total_num_sectors[1] << 8; 338275970Scy *lba_low |= identify->total_num_sectors[0]; 339275970Scy } 340275970Scy 341275970Scy // If the ATA device reports its sector size (bit 12 of Word 106), 342275970Scy // then use that instead. 343275970Scy if (identify->physical_logical_sector_info 344275970Scy & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE) 345275970Scy { 346275970Scy *sector_size = identify->words_per_logical_sector[3] << 24; 347275970Scy *sector_size |= identify->words_per_logical_sector[2] << 16; 348275970Scy *sector_size |= identify->words_per_logical_sector[1] << 8; 349275970Scy *sector_size |= identify->words_per_logical_sector[0]; 350275970Scy } 351275970Scy else 352275970Scy { 353275970Scy // Default the sector size to 512 bytes 354275970Scy *sector_size = 512; 355275970Scy } 356275970Scy} 357275970Scy 358275970Scy/** 359275970Scy * @brief This method will construct the ATA check power mode command. 360275970Scy * 361275970Scy * @pre It is expected that the user has properly set the current contents 362275970Scy * of the register FIS to 0. 363275970Scy * 364275970Scy * @param[out] ata_io This parameter specifies the ATA IO request structure 365275970Scy * for which to build the CHECK POWER MODE command. 366275970Scy * @param[in] sequence This parameter specifies the translator sequence 367275970Scy * for which the command is being constructed. 368275970Scy * 369275970Scy * @return none. 370275970Scy */ 371275970Scyvoid sati_ata_check_power_mode_construct( 372275970Scy void * ata_io, 373275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence 374275970Scy) 375275970Scy{ 376275970Scy U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 377275970Scy 378275970Scy sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE); 379275970Scy sati_ata_non_data_command(ata_io, sequence); 380275970Scy} 381275970Scy 382275970Scy/** 383275970Scy * @brief This method is utilized to set a specific byte in the sense 384275970Scy * data area. It will ensure that the supplied byte offset 385275970Scy * isn't larger then the length of the requested sense data. 386275970Scy * 387275970Scy * @param[in] scsi_io This parameter specifies the user SCSI IO request 388275970Scy * for which to set the sense data byte. 389275970Scy * @param[in] byte_offset This parameter specifies the byte offset into 390275970Scy * the sense data buffer where the data should be written. 391275970Scy * @param[in] value This parameter specifies the 8-bit value to be written 392275970Scy * into the sense data area. 393275970Scy * 394275970Scy * @return none 395275970Scy */ 396275970Scyvoid sati_set_sense_data_byte( 397275970Scy U8 * sense_data, 398275970Scy U32 max_sense_data_len, 399275970Scy U32 byte_offset, 400275970Scy U8 value 401275970Scy) 402275970Scy{ 403275970Scy // Ensure that we don't attempt to write past the end of the sense 404285612Sdelphij // data buffer. 405275970Scy if (byte_offset < max_sense_data_len) 406275970Scy sense_data[byte_offset] = value; 407275970Scy} 408275970Scy 409275970Scy/** 410275970Scy * @brief This method will construct the common response IU in the user 411275970Scy * request's response IU location. 412275970Scy * 413275970Scy * @param[out] rsp_iu This parameter specifies the user request's 414275970Scy * response IU to be constructed. 415275970Scy * @param[in] scsi_status This parameter specifies the SCSI status 416275970Scy * value for the user's IO request. 417275970Scy * @param[in] sense_data_length This parameter specifies the sense data 418275970Scy * length for response IU. 419275970Scy * @param[in] data_present The parameter specifies the specific 420275970Scy * data present value for response IU. 421275970Scy * 422275970Scy * @return none 423275970Scy */ 424275970Scyvoid sati_scsi_common_response_iu_construct( 425275970Scy SCI_SSP_RESPONSE_IU_T * rsp_iu, 426275970Scy U8 scsi_status, 427275970Scy U8 sense_data_length, 428275970Scy U8 data_present 429275970Scy) 430275970Scy{ 431275970Scy rsp_iu->sense_data_length[3] = sense_data_length; 432275970Scy rsp_iu->sense_data_length[2] = 0; 433275970Scy rsp_iu->sense_data_length[1] = 0; 434275970Scy rsp_iu->sense_data_length[0] = 0; 435275970Scy rsp_iu->status = scsi_status; 436275970Scy rsp_iu->data_present = data_present; 437275970Scy} 438275970Scy 439275970Scy/** 440275970Scy * @brief This method will construct the buffer for sense data 441275970Scy * sense data buffer location. Additionally, it will set the user's 442275970Scy * SCSI status. 443275970Scy * 444275970Scy * @param[in,out] scsi_io This parameter specifies the user's IO request 445275970Scy * for which to construct the buffer for sense data. 446275970Scy * @param[in] scsi_status This parameter specifies the SCSI status 447275970Scy * value for the user's IO request. 448275970Scy * @param[out] sense_data This paramater 449275970Scy * 450275970Scy * @return none 451275970Scy */ 452275970Scystatic 453275970Scyvoid sati_scsi_get_sense_data_buffer( 454275970Scy SATI_TRANSLATOR_SEQUENCE_T * sequence, 455275970Scy void * scsi_io, 456275970Scy U8 scsi_status, 457275970Scy U8 ** sense_data, 458275970Scy U32 * sense_len) 459275970Scy{ 460275970Scy#ifdef SATI_TRANSPORT_SUPPORTS_SAS 461275970Scy SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 462275970Scy sati_cb_get_response_iu_address(scsi_io); 463275970Scy 464275970Scy sati_scsi_common_response_iu_construct( 465275970Scy rsp_iu, 466275970Scy scsi_status, 467275970Scy sati_scsi_get_sense_data_length(sequence, scsi_io), 468275970Scy SCSI_RESPONSE_DATA_PRES_SENSE_DATA 469275970Scy ); 470275970Scy 471275970Scy *sense_data = (U8*) rsp_iu->data; 472275970Scy *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes 473275970Scy#else 474275970Scy *sense_data = sati_cb_get_sense_data_address(scsi_io); 475275970Scy *sense_len = sati_cb_get_sense_data_length(scsi_io); 476275970Scy sati_cb_set_scsi_status(scsi_io, scsi_status); 477275970Scy#endif // SATI_TRANSPORT_SUPPORTS_SAS 478275970Scy} 479275970Scy 480275970Scy/** 481275970Scy * @brief This method extract response code based on on device settings. 482275970Scy * 483275970Scy * @return response code 484275970Scy */ 485275970Scystatic 486275970ScyU8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence) 487275970Scy{ 488275970Scy if (sequence->device->descriptor_sense_enable) 489275970Scy { 490275970Scy return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE; 491275970Scy } 492275970Scy else 493275970Scy { 494275970Scy return SCSI_FIXED_CURRENT_RESPONSE_CODE; 495275970Scy } 496275970Scy} 497275970Scy 498275970Scy/** 499275970Scy * @brief This method will return length of descriptor sense data for executed command. 500275970Scy * 501275970Scy * @return sense data length 502275970Scy */ 503275970Scystatic 504275970ScyU8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, 505275970Scy void * scsi_io) 506275970Scy{ 507275970Scy U8 * cdb = sati_cb_get_cdb_address(scsi_io); 508275970Scy //Initial value is descriptor header length 509275970Scy U8 length = 8; 510275970Scy 511275970Scy switch (sati_get_cdb_byte(cdb, 0)) 512275970Scy { 513275970Scy#if !defined(DISABLE_SATI_WRITE_LONG) 514275970Scy case SCSI_WRITE_LONG_10: 515275970Scy case SCSI_WRITE_LONG_16: 516275970Scy length += SCSI_BLOCK_DESCRIPTOR_LENGTH + 517275970Scy SCSI_INFORMATION_DESCRIPTOR_LENGTH; 518275970Scy break; 519275970Scy#endif // !defined(DISABLE_SATI_WRITE_LONG) 520275970Scy#if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 521275970Scy case SCSI_REASSIGN_BLOCKS: 522275970Scy length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH + 523275970Scy SCSI_INFORMATION_DESCRIPTOR_LENGTH; 524275970Scy break; 525275970Scy#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 526275970Scy case SCSI_READ_6: 527275970Scy case SCSI_READ_10: 528275970Scy case SCSI_READ_12: 529275970Scy case SCSI_READ_16: 530275970Scy case SCSI_WRITE_6: 531275970Scy case SCSI_WRITE_10: 532275970Scy case SCSI_WRITE_12: 533275970Scy case SCSI_WRITE_16: 534275970Scy#if !defined(DISABLE_SATI_VERIFY) 535275970Scy case SCSI_VERIFY_10: 536275970Scy case SCSI_VERIFY_12: 537275970Scy case SCSI_VERIFY_16: 538275970Scy#endif // !defined(DISABLE_SATI_VERIFY) 539275970Scy#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 540275970Scy && !defined(DISABLE_SATI_VERIFY) \ 541275970Scy && !defined(DISABLE_SATI_WRITE) 542275970Scy 543275970Scy case SCSI_WRITE_AND_VERIFY_10: 544275970Scy case SCSI_WRITE_AND_VERIFY_12: 545275970Scy case SCSI_WRITE_AND_VERIFY_16: 546#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 547 // && !defined(DISABLE_SATI_VERIFY) 548 // && !defined(DISABLE_SATI_WRITE) 549 length += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 550 break; 551 } 552 553 return length; 554} 555 556/** 557 * @brief This method will return length of sense data. 558 * 559 * @return sense data length 560 */ 561U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io) 562{ 563 U8 response_code; 564 565 response_code = sati_scsi_get_sense_data_response_code(sequence); 566 567 switch (response_code) 568 { 569 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 570 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 571 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 572 break; 573 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 574 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 575 return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io); 576 break; 577 } 578 579 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 580} 581 582/** 583 * @brief This method will construct the sense data buffer in the user's 584 * sense data buffer location. Additionally, it will set the user's 585 * SCSI status. 586 * 587 * @param[in] sequence This parameter specifies the translation sequence 588 * for which to construct the sense data. 589 * @param[in,out] scsi_io This parameter specifies the user's IO request 590 * for which to construct the sense data. 591 * @param[in] scsi_status This parameter specifies the SCSI status 592 * value for the user's IO request. 593 * @param[in] sense_key This parameter specifies the sense key to 594 * be set for the user's IO request. 595 * @param[in] additional_sense_code This parameter specifies the 596 * additional sense code (ASC) key to be set for the user's 597 * IO request. 598 * @param[in] additional_sense_code_qualifier This parameter specifies 599 * the additional sense code qualifier (ASCQ) key to be set 600 * for the user's IO request. 601 * 602 * @return none 603 */ 604void sati_scsi_sense_data_construct( 605 SATI_TRANSLATOR_SEQUENCE_T * sequence, 606 void * scsi_io, 607 U8 scsi_status, 608 U8 sense_key, 609 U8 additional_sense_code, 610 U8 additional_sense_code_qualifier 611) 612{ 613 U8 response_code; 614 615 response_code = sati_scsi_get_sense_data_response_code(sequence); 616 617 switch (response_code) 618 { 619 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 620 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 621 sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 622 sense_key, additional_sense_code, additional_sense_code_qualifier); 623 break; 624 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 625 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 626 sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 627 sense_key, additional_sense_code, additional_sense_code_qualifier); 628 break; 629 } 630 631 sequence->is_sense_response_set = TRUE; 632} 633 634/** 635 * @brief This method will construct the block descriptor in the user's descriptor 636 * sense data buffer location. 637 * 638 * @param[in] sense_data This parameter specifies the user SCSI IO request 639 * for which to set the sense data byte. 640 * @param[in] sense_len This parameter specifies length of the sense data 641 * to be returned by SATI. 642 * @param[out] descriptor_len This parameter returns the length of constructed 643 * descriptor. 644 * 645 * @return none 646 */ 647static 648void sati_scsi_block_descriptor_construct( 649 U8 * sense_data, 650 U32 sense_len) 651{ 652 U8 ili = 1; 653 654 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE); 655 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH); 656 sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 657 sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5)); 658} 659 660/** 661 * @brief This method will construct the command-specific descriptor for 662 * the descriptor sense data buffer in the user's sense data buffer 663 * location. 664 * 665 * @param[in] sense_data This parameter specifies the user SCSI IO request 666 * for which to set the sense data byte. 667 * @param[in] sense_len This parameter specifies length of the sense data 668 * to be returned by SATI. 669 * @param[out] descriptor_len This parameter returns the length of constructed 670 * descriptor. 671 * @param[in] information_buff This parameter specifies the address for which 672 * to set the command-specific information buffer. 673 * 674 * @return none 675 */ 676static 677void sati_scsi_command_specific_descriptor_construct( 678 U8 * sense_data, 679 U32 sense_len, 680 U8 * information_buff) 681{ 682 U8 i; 683 684 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE); 685 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH); 686 sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 687 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 688 689 // fill information buffer 690 // SBC 5.20.1 REASSIGN BLOCKS command overview 691 // If information about the first LBA not reassigned is not available 692 // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh 693 for (i=0; i<8; i++) 694 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]); 695} 696 697/** 698 * @brief This method will construct the information descriptor for 699 * the descriptor sense data buffer in the user's sense data buffer 700 * location. 701 * 702 * @param[in] sense_data This parameter specifies the user SCSI IO request 703 * for which to set the sense data byte. 704 * @param[in] sense_len This parameter specifies length of the sense data 705 * to be returned by SATI. 706 * @param[out] descriptor_len This parameter returns the length of constructed 707 * descriptor. 708 * @param[in] information_buff This parameter specifies the address for which 709 * to set the information buffer. 710 * 711 * @return none 712 */ 713static 714void sati_scsi_information_descriptor_construct( 715 U8 * sense_data, 716 U32 sense_len, 717 U8 * information_buff) 718{ 719 U8 i; 720 U8 valid = 1; 721 722 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE); 723 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH); 724 sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7)); 725 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 726 727 // fill information buffer 728 for (i=0; i<8; i++) 729 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]); 730} 731 732/** 733 * @brief This method will construct the descriptors in the user's descriptor 734 * sense data buffer location. 735 * 736 * @param[in,out] scsi_io This parameter specifies the user's IO request 737 * for which to construct the sense data. 738 * @param[in] sense_data This parameter specifies the user SCSI IO request 739 * for which to set the sense data byte. 740 * @param[in] sense_len This parameter specifies length of the sense data 741 * to be returned by SATI. 742 * @param[out] descriptor_len This parameter returns the length of constructed 743 * descriptor. 744 * @param[in] information_buff This parameter specifies the address for which 745 * to set the information buffer. 746 * 747 * @return none 748 */ 749static 750void sati_scsi_common_descriptors_construct( 751 void * scsi_io, 752 U8 * sense_data, 753 U32 sense_len, 754 U8 * information_buff) 755{ 756 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 757 U8 offset = 0; 758 759 switch (sati_get_cdb_byte(cdb, 0)) 760 { 761#if !defined(DISABLE_SATI_WRITE_LONG) 762 case SCSI_WRITE_LONG_10: 763 case SCSI_WRITE_LONG_16: 764 sati_scsi_block_descriptor_construct( 765 sense_data + offset, 766 sense_len - offset); 767 768 offset += SCSI_BLOCK_DESCRIPTOR_LENGTH; 769 sati_scsi_information_descriptor_construct( 770 sense_data + offset, 771 sense_len - offset, 772 information_buff); 773 774 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 775 break; 776#endif // !defined(DISABLE_SATI_WRITE_LONG) 777#if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 778 case SCSI_REASSIGN_BLOCKS: 779 sati_scsi_command_specific_descriptor_construct( 780 sense_data + offset, 781 sense_len - offset, 782 NULL); 783 784 offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH; 785 sati_scsi_information_descriptor_construct( 786 sense_data + offset, 787 sense_len - offset, 788 information_buff); 789 790 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 791 break; 792#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 793 case SCSI_READ_6: 794 case SCSI_READ_10: 795 case SCSI_READ_12: 796 case SCSI_READ_16: 797 case SCSI_WRITE_6: 798 case SCSI_WRITE_10: 799 case SCSI_WRITE_12: 800 case SCSI_WRITE_16: 801#if !defined(DISABLE_SATI_VERIFY) 802 case SCSI_VERIFY_10: 803 case SCSI_VERIFY_12: 804 case SCSI_VERIFY_16: 805#endif // !defined(DISABLE_SATI_VERIFY) 806#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 807 && !defined(DISABLE_SATI_VERIFY) \ 808 && !defined(DISABLE_SATI_WRITE) 809 810 case SCSI_WRITE_AND_VERIFY_10: 811 case SCSI_WRITE_AND_VERIFY_12: 812 case SCSI_WRITE_AND_VERIFY_16: 813#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 814 // && !defined(DISABLE_SATI_VERIFY) 815 // && !defined(DISABLE_SATI_WRITE) 816 sati_scsi_information_descriptor_construct( 817 sense_data + offset, 818 sense_len - offset, 819 information_buff); 820 821 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 822 break; 823 } 824} 825 826/** 827 * @brief This method will construct the descriptor sense data buffer in 828 * the user's sense data buffer location. Additionally, it will set 829 * the user's SCSI status. 830 * 831 * @param[in] sequence This parameter specifies the translation sequence 832 * for which to construct the sense data. 833 * @param[in,out] scsi_io This parameter specifies the user's IO request 834 * for which to construct the sense data. 835 * @param[in] scsi_status This parameter specifies the SCSI status 836 * value for the user's IO request. 837 * @param[in] sense_key This parameter specifies the sense key to 838 * be set for the user's IO request. 839 * @param[in] additional_sense_code This parameter specifies the 840 * additional sense code (ASC) key to be set for the user's 841 * IO request. 842 * @param[in] additional_sense_code_qualifier This parameter specifies 843 * the additional sense code qualifier (ASCQ) key to be set 844 * for the user's IO request. 845 * 846 * @return none 847 */ 848void sati_scsi_descriptor_sense_data_construct( 849 SATI_TRANSLATOR_SEQUENCE_T * sequence, 850 void * scsi_io, 851 U8 scsi_status, 852 U8 response_code, 853 U8 sense_key, 854 U8 additional_sense_code, 855 U8 additional_sense_code_qualifier 856) 857{ 858 U8 * sense_data; 859 U32 sense_len; 860 861 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 862 863 sati_set_sense_data_byte( 864 sense_data, 865 sense_len, 866 0, 867 response_code 868 ); 869 870 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 871 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 872 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 873 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 874 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 875 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 876 877 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL); 878 879 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 880} 881 882/** 883 * @brief This method will construct the fixed format sense data buffer 884 * in the user's sense data buffer location. Additionally, it will 885 * set the user's SCSI status. 886 * 887 * @param[in] sequence This parameter specifies the translation sequence 888 * for which to construct the sense data. 889 * @param[in,out] scsi_io This parameter specifies the user's IO request 890 * for which to construct the sense data. 891 * @param[in] scsi_status This parameter specifies the SCSI status 892 * value for the user's IO request. 893 * @param[in] sense_key This parameter specifies the sense key to 894 * be set for the user's IO request. 895 * @param[in] additional_sense_code This parameter specifies the 896 * additional sense code (ASC) key to be set for the user's 897 * IO request. 898 * @param[in] additional_sense_code_qualifier This parameter specifies 899 * the additional sense code qualifier (ASCQ) key to be set 900 * for the user's IO request. 901 * 902 * @return none 903 */ 904void sati_scsi_fixed_sense_data_construct( 905 SATI_TRANSLATOR_SEQUENCE_T * sequence, 906 void * scsi_io, 907 U8 scsi_status, 908 U8 response_code, 909 U8 sense_key, 910 U8 additional_sense_code, 911 U8 additional_sense_code_qualifier 912) 913{ 914 U8 * sense_data; 915 U32 sense_len; 916 917 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 918 919 // Write out the sense data format per SPC-4. 920 // We utilize the fixed format sense data format. 921 922 sati_set_sense_data_byte( 923 sense_data, 924 sense_len, 925 0, 926 response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT 927 ); 928 929 sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 930 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 931 sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 932 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 933 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 934 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 935 sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7); 936 sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 937 sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 938 sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 939 sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 940 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 941 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 942 sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 943 sati_set_sense_data_byte(sense_data, sense_len, 15, 0); 944 sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 945 sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 946} 947 948/** 949* @brief This method will construct common sense data that will be identical in 950* both read error sense construct functions. 951* sati_scsi_read_ncq_error_sense_construct, 952* sati_scsi_read_error_sense_construct 953* 954 * @param[in] sense_data This parameter specifies the user SCSI IO request 955 * for which to set the sense data byte. 956* @param[in] sense_len This parameter specifies length of the sense data 957* to be returned by SATI. 958* @param[in] sense_key This parameter specifies the sense key to 959* be set for the user's IO request. 960* @param[in] additional_sense_code This parameter specifies the 961* additional sense code (ASC) key to be set for the user's 962* IO request. 963* @param[in] additional_sense_code_qualifier This parameter specifies 964* the additional sense code qualifier (ASCQ) key to be set 965* for the user's IO request. 966* 967* @return none 968*/ 969static 970void sati_scsi_common_fixed_sense_construct( 971 U8 * sense_data, 972 U32 sense_len, 973 U8 sense_key, 974 U8 additional_sense_code, 975 U8 additional_sense_code_qualifier 976) 977{ 978 979 sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 980 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 981 982 //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions 983 984 sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7); 985 sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 986 sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 987 sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 988 sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 989 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 990 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 991 sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 992 sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80); 993 sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 994 sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 995} 996 997/** 998 * @brief This method will construct the descriptor sense data buffer in 999 * the user's sense data buffer location. Additionally, it will set 1000 * the user's SCSI status. 1001 * 1002 * @param[in] sequence This parameter specifies the translation sequence 1003 * for which to construct the sense data. 1004 * @param[in,out] scsi_io This parameter specifies the user's IO request 1005 * for which to construct the sense data. 1006 * @param[in] scsi_status This parameter specifies the SCSI status 1007 * value for the user's IO request. 1008 * @param[in] sense_key This parameter specifies the sense key to 1009 * be set for the user's IO request. 1010 * @param[in] additional_sense_code This parameter specifies the 1011 * additional sense code (ASC) key to be set for the user's 1012 * IO request. 1013 * @param[in] additional_sense_code_qualifier This parameter specifies 1014 * the additional sense code qualifier (ASCQ) key to be set 1015 * for the user's IO request. 1016 * 1017 * @return none 1018 */ 1019static 1020void sati_scsi_common_descriptor_sense_construct( 1021 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1022 void * scsi_io, 1023 U8 * sense_data, 1024 U32 sense_len, 1025 U8 sense_key, 1026 U8 additional_sense_code, 1027 U8 additional_sense_code_qualifier, 1028 U8 * information_buff 1029) 1030{ 1031 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 1032 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 1033 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 1034 sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 1035 sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 1036 sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 1037 1038 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff); 1039 1040 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 1041} 1042 1043/** 1044* @brief This method will construct the sense data buffer in the user's 1045* descriptor sense data buffer location. Additionally, it will set 1046* the user's SCSI status. This is only used for NCQ uncorrectable 1047* read errors 1048* 1049* @param[in] sequence This parameter specifies the translation sequence 1050* for which to construct the sense data. 1051* @param[in,out] scsi_io This parameter specifies the user's IO request 1052* for which to construct the sense data. 1053* @param[in] ata_input_data This parameter specifies the user's ATA IO 1054* response from a Read Log Ext command. 1055* @param[in] scsi_status This parameter specifies the SCSI status 1056* value for the user's IO request. 1057* @param[in] sense_key This parameter specifies the sense key to 1058* be set for the user's IO request. 1059* @param[in] additional_sense_code This parameter specifies the 1060* additional sense code (ASC) key to be set for the user's 1061* IO request. 1062* @param[in] additional_sense_code_qualifier This parameter specifies 1063* the additional sense code qualifier (ASCQ) key to be set 1064* for the user's IO request. 1065* 1066* @return none 1067*/ 1068static 1069void sati_scsi_read_ncq_error_descriptor_sense_construct( 1070 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1071 void * scsi_io, 1072 void * ata_input_data, 1073 U8 scsi_status, 1074 U8 response_code, 1075 U8 sense_key, 1076 U8 additional_sense_code, 1077 U8 additional_sense_code_qualifier 1078) 1079{ 1080 U8 * sense_data; 1081 U32 sense_len; 1082 1083 U8 information_buff[8] = {0}; 1084 1085 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1086 1087 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1088 1089 sati_set_sense_data_byte( 1090 sense_data, 1091 sense_len, 1092 0, 1093 response_code 1094 ); 1095 1096 information_buff[2] = ncq_log->lba_47_40; 1097 information_buff[3] = ncq_log->lba_39_32; 1098 information_buff[4] = ncq_log->lba_31_24; 1099 information_buff[5] = ncq_log->lba_23_16; 1100 information_buff[6] = ncq_log->lba_15_8; 1101 information_buff[7] = ncq_log->lba_7_0; 1102 1103 sati_scsi_common_descriptor_sense_construct( 1104 sequence, 1105 scsi_io, 1106 sense_data, 1107 sense_len, 1108 sense_key, 1109 additional_sense_code, 1110 additional_sense_code_qualifier, 1111 information_buff 1112 ); 1113} 1114 1115/** 1116* @brief This method will construct the sense data buffer in the user's 1117* sense data buffer location. Additionally, it will set the user's 1118* SCSI status. This is only used for NCQ uncorrectable read errors 1119* 1120* @param[in] sequence This parameter specifies the translation sequence 1121* for which to construct the sense data. 1122* @param[in,out] scsi_io This parameter specifies the user's IO request 1123* for which to construct the sense data. 1124* @param[in] ata_input_data This parameter specifies the user's ATA IO 1125* response from a Read Log Ext command. 1126* @param[in] scsi_status This parameter specifies the SCSI status 1127* value for the user's IO request. 1128* @param[in] sense_key This parameter specifies the sense key to 1129* be set for the user's IO request. 1130* @param[in] additional_sense_code This parameter specifies the 1131* additional sense code (ASC) key to be set for the user's 1132* IO request. 1133* @param[in] additional_sense_code_qualifier This parameter specifies 1134* the additional sense code qualifier (ASCQ) key to be set 1135* for the user's IO request. 1136* 1137* @return none 1138*/ 1139static 1140void sati_scsi_read_ncq_error_fixed_sense_construct( 1141 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1142 void * scsi_io, 1143 void * ata_input_data, 1144 U8 scsi_status, 1145 U8 response_code, 1146 U8 sense_key, 1147 U8 additional_sense_code, 1148 U8 additional_sense_code_qualifier 1149) 1150{ 1151 U8 * sense_data; 1152 U32 sense_len; 1153 U8 valid = TRUE; 1154 1155 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1156 1157 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1158 1159 if(ncq_log->lba_39_32 > 0) 1160 { 1161 valid = FALSE; 1162 } 1163 1164 sati_set_sense_data_byte( 1165 sense_data, 1166 sense_len, 1167 0, 1168 (valid << 7) | response_code 1169 ); 1170 1171 sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24); 1172 sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16); 1173 sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8); 1174 sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0); 1175 1176 sati_scsi_common_fixed_sense_construct( 1177 sense_data, 1178 sense_len, 1179 sense_key, 1180 additional_sense_code, 1181 additional_sense_code_qualifier 1182 ); 1183} 1184 1185void sati_scsi_read_ncq_error_sense_construct( 1186 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1187 void * scsi_io, 1188 void * ata_input_data, 1189 U8 scsi_status, 1190 U8 sense_key, 1191 U8 additional_sense_code, 1192 U8 additional_sense_code_qualifier 1193) 1194{ 1195 U8 response_code; 1196 1197 response_code = sati_scsi_get_sense_data_response_code(sequence); 1198 1199 switch (response_code) 1200 { 1201 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1202 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1203 sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1204 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1205 break; 1206 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1207 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1208 sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1209 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1210 break; 1211 } 1212 1213 sequence->is_sense_response_set = TRUE; 1214} 1215 1216/** 1217* @brief This method will construct the sense data buffer in the user's 1218* sense data buffer location. Additionally, it will set the user's 1219* SCSI status. This is used for uncorrectable read errors. 1220* 1221* @param[in] sequence This parameter specifies the translation sequence 1222* for which to construct the sense data. 1223* @param[in,out] scsi_io This parameter specifies the user's IO request 1224* for which to construct the sense data. 1225* @param[in] ata_io This parameter is a pointer to the ATA IO data used 1226* to get the ATA register fis. 1227* @param[in] scsi_status This parameter specifies the SCSI status 1228* value for the user's IO request. 1229* @param[in] sense_key This parameter specifies the sense key to 1230* be set for the user's IO request. 1231* @param[in] additional_sense_code This parameter specifies the 1232* additional sense code (ASC) key to be set for the user's 1233* IO request. 1234* @param[in] additional_sense_code_qualifier This parameter specifies 1235* the additional sense code qualifier (ASCQ) key to be set 1236* for the user's IO request. 1237* 1238* @return none 1239*/ 1240static 1241void sati_scsi_read_error_descriptor_sense_construct( 1242 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1243 void * scsi_io, 1244 void * ata_io, 1245 U8 scsi_status, 1246 U8 response_code, 1247 U8 sense_key, 1248 U8 additional_sense_code, 1249 U8 additional_sense_code_qualifier 1250) 1251{ 1252 U8 * sense_data; 1253 U32 sense_len; 1254 U8 information_buff[8] = {0}; 1255 1256 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1257 1258 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1259 1260 information_buff[2] = sati_get_ata_lba_high_ext(register_fis); 1261 information_buff[3] = sati_get_ata_lba_mid_ext(register_fis); 1262 information_buff[4] = sati_get_ata_lba_low_ext(register_fis); 1263 information_buff[5] = sati_get_ata_lba_high(register_fis); 1264 information_buff[6] = sati_get_ata_lba_mid(register_fis); 1265 information_buff[7] = sati_get_ata_lba_low(register_fis); 1266 1267 sati_set_sense_data_byte( 1268 sense_data, 1269 sense_len, 1270 0, 1271 SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE 1272 ); 1273 1274 sati_scsi_common_descriptor_sense_construct( 1275 sequence, 1276 scsi_io, 1277 sense_data, 1278 sense_len, 1279 sense_key, 1280 additional_sense_code, 1281 additional_sense_code_qualifier, 1282 information_buff 1283 ); 1284} 1285 1286/** 1287* @brief This method will construct the sense data buffer in the user's 1288* sense data buffer location. Additionally, it will set the user's 1289* SCSI status. This is used for uncorrectable read errors. 1290* 1291* @param[in] sequence This parameter specifies the translation sequence 1292* for which to construct the sense data. 1293* @param[in,out] scsi_io This parameter specifies the user's IO request 1294* for which to construct the sense data. 1295* @param[in] ata_io This parameter is a pointer to the ATA IO data used 1296* to get the ATA register fis. 1297* @param[in] scsi_status This parameter specifies the SCSI status 1298* value for the user's IO request. 1299* @param[in] sense_key This parameter specifies the sense key to 1300* be set for the user's IO request. 1301* @param[in] additional_sense_code This parameter specifies the 1302* additional sense code (ASC) key to be set for the user's 1303* IO request. 1304* @param[in] additional_sense_code_qualifier This parameter specifies 1305* the additional sense code qualifier (ASCQ) key to be set 1306* for the user's IO request. 1307* 1308* @return none 1309*/ 1310static 1311void sati_scsi_read_error_fixed_sense_construct( 1312 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1313 void * scsi_io, 1314 void * ata_io, 1315 U8 scsi_status, 1316 U8 response_code, 1317 U8 sense_key, 1318 U8 additional_sense_code, 1319 U8 additional_sense_code_qualifier 1320) 1321{ 1322 U8 * sense_data; 1323 U32 sense_len; 1324 U8 valid = TRUE; 1325 1326 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1327 1328 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1329 1330 if(sati_get_ata_lba_mid_ext(register_fis) > 0) 1331 { 1332 valid = FALSE; 1333 } 1334 1335 sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis)); 1336 sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis)); 1337 sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis)); 1338 sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis)); 1339 1340 1341 sati_set_sense_data_byte( 1342 sense_data, 1343 sense_len, 1344 0, 1345 (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE 1346 ); 1347 1348 sati_scsi_common_fixed_sense_construct( 1349 sense_data, 1350 sense_len, 1351 sense_key, 1352 additional_sense_code, 1353 additional_sense_code_qualifier 1354 ); 1355} 1356 1357void sati_scsi_read_error_sense_construct( 1358 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1359 void * scsi_io, 1360 void * ata_input_data, 1361 U8 scsi_status, 1362 U8 sense_key, 1363 U8 additional_sense_code, 1364 U8 additional_sense_code_qualifier 1365) 1366{ 1367 U8 response_code; 1368 1369 response_code = sati_scsi_get_sense_data_response_code(sequence); 1370 1371 switch (response_code) 1372 { 1373 case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1374 case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1375 sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1376 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1377 break; 1378 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1379 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1380 sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1381 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1382 break; 1383 } 1384 1385 sequence->is_sense_response_set = TRUE; 1386} 1387 1388/* 1389 * @brief This method builds the scsi response data for a sata task management 1390 * request. 1391 * 1392 * @param[in] sequence This parameter specifies the translation sequence 1393 * for which to construct the sense data. 1394 * @param[in,out] scsi_io This parameter specifies the user's IO request 1395 * for which to construct the sense data. 1396 * @param[in] response_data The response status for the task management 1397 * request. 1398 */ 1399void sati_scsi_response_data_construct( 1400 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1401 void * scsi_io, 1402 U8 response_data 1403) 1404{ 1405#ifdef SATI_TRANSPORT_SUPPORTS_SAS 1406 SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 1407 sati_cb_get_response_iu_address(scsi_io); 1408 rsp_iu->data_present = 0x01; 1409 rsp_iu->response_data_length[3] = sizeof(U32); 1410 rsp_iu->status = 0; 1411 ((U8 *)rsp_iu->data)[3] = response_data; 1412#else 1413#endif // SATI_TRANSPORT_SUPPORTS_SAS 1414} 1415 1416/** 1417 * @brief This method checks to make sure that the translation isn't 1418 * exceeding the allocation length specified in the CDB prior 1419 * to retrieving the payload data byte from the user's buffer. 1420 * 1421 * @param[in,out] scsi_io This parameter specifies the user's IO request 1422 * for which to set the user payload data byte. 1423 * @param[in] byte_offset This parameter specifies the offset into 1424 * the user's payload buffer at which to write the supplied 1425 * value. 1426 * @param[in] value This parameter specifies the memory location into 1427 * which to read the value from the user's payload buffer. 1428 * 1429 * @return none 1430 */ 1431void sati_get_data_byte( 1432 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1433 void * scsi_io, 1434 U32 byte_offset, 1435 U8 * value 1436) 1437{ 1438 if (byte_offset < sequence->allocation_length) 1439 sati_cb_get_data_byte(scsi_io, byte_offset, value); 1440} 1441 1442/** 1443 * @brief This method checks to make sure that the translation isn't 1444 * exceeding the allocation length specified in the CDB while 1445 * translating payload data into the user's buffer. 1446 * 1447 * @param[in] sequence This parameter specifies the translation sequence 1448 * for which to set the user payload data byte. 1449 * @param[in,out] scsi_io This parameter specifies the user's IO request 1450 * for which to set the user payload data byte. 1451 * @param[in] byte_offset This parameter specifies the offset into 1452 * the user's payload buffer at which to write the supplied 1453 * value. 1454 * @param[in] value This parameter specifies the new value to be 1455 * written out into the user's payload buffer. 1456 * 1457 * @return none 1458 */ 1459void sati_set_data_byte( 1460 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1461 void * scsi_io, 1462 U32 byte_offset, 1463 U8 value 1464) 1465{ 1466 if (byte_offset < sequence->allocation_length) 1467 { 1468 sequence->number_data_bytes_set++; 1469 sati_cb_set_data_byte(scsi_io, byte_offset, value); 1470 } 1471} 1472 1473/** 1474 * @brief This method checks to make sure that the translation isn't 1475 * exceeding the allocation length specified in the CDB while 1476 * translating payload data into the user's buffer. 1477 * 1478 * @param[in] sequence This parameter specifies the translation sequence 1479 * for which to set the user payload data dword. 1480 * @param[in,out] scsi_io This parameter specifies the user's IO request 1481 * for which to set the user payload data dword. 1482 * @param[in] byte_offset This parameter specifies the offset into 1483 * the user's payload buffer at which to write the supplied 1484 * value. 1485 * @param[in] value This parameter specifies the new value to be 1486 * written out into the user's payload buffer. 1487 * 1488 * @return none 1489 */ 1490void sati_set_data_dword( 1491 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1492 void * scsi_io, 1493 U32 byte_offset, 1494 U32 value 1495) 1496{ 1497 /// @todo Check to ensure that the bytes appear correctly (SAS Address). 1498 1499 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF); 1500 byte_offset++; 1501 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF); 1502 byte_offset++; 1503 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF); 1504 byte_offset++; 1505 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF); 1506} 1507 1508/** 1509 * @brief This method will construct the ATA flush cache command. 1510 * 1511 * @pre It is expected that the user has properly set the current contents 1512 * of the register FIS to 0. 1513 * 1514 * @param[out] ata_io This parameter specifies the ATA IO request structure 1515 * for which to build the FLUSH CACHE command. 1516 * @param[in] sequence This parameter specifies the translator sequence 1517 * for which the command is being constructed. 1518 * 1519 * @return none. 1520 */ 1521void sati_ata_flush_cache_construct( 1522 void * ata_io, 1523 SATI_TRANSLATOR_SEQUENCE_T * sequence 1524) 1525{ 1526 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1527 1528 sati_set_ata_command(register_fis, ATA_FLUSH_CACHE); 1529 sati_ata_non_data_command(ata_io, sequence); 1530} 1531 1532/** 1533 * @brief This method will construct the ATA standby immediate command. 1534 * 1535 * @pre It is expected that the user has properly set the current contents 1536 * of the register FIS to 0. 1537 * 1538 * @param[out] ata_io This parameter specifies the ATA IO request structure 1539 * for which to build the STANDBY IMMEDIATE command. 1540 * @param[in] sequence This parameter specifies the translator sequence 1541 * for which the command is being constructed. 1542 * 1543 * @param[in] count This parameter specifies the time period programmed 1544 * into the Standby Timer. See ATA8 spec for more details 1545 * @return none. 1546 */ 1547void sati_ata_standby_construct( 1548 void * ata_io, 1549 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1550 U16 count 1551) 1552{ 1553 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1554 1555 sati_set_ata_command(register_fis, ATA_STANDBY); 1556 sati_set_ata_sector_count(register_fis, count); 1557 1558 sequence->device->ata_standby_timer = (U8) count; 1559 1560 sati_ata_non_data_command(ata_io, sequence); 1561} 1562 1563/** 1564 * @brief This method will construct the ATA standby immediate command. 1565 * 1566 * @pre It is expected that the user has properly set the current contents 1567 * of the register FIS to 0. 1568 * 1569 * @param[out] ata_io This parameter specifies the ATA IO request structure 1570 * for which to build the STANDBY IMMEDIATE command. 1571 * @param[in] sequence This parameter specifies the translator sequence 1572 * for which the command is being constructed. 1573 * 1574 * @return none. 1575 */ 1576void sati_ata_standby_immediate_construct( 1577 void * ata_io, 1578 SATI_TRANSLATOR_SEQUENCE_T * sequence 1579) 1580{ 1581 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1582 1583 sati_set_ata_command(register_fis, ATA_STANDBY_IMMED); 1584 sati_ata_non_data_command(ata_io, sequence); 1585} 1586 1587/** 1588 * @brief This method will construct the ATA idle immediate command. 1589 * 1590 * @pre It is expected that the user has properly set the current contents 1591 * of the register FIS to 0. 1592 * 1593 * @param[out] ata_io This parameter specifies the ATA IO request structure 1594 * for which to build the IDLE IMMEDIATE command. 1595 * @param[in] sequence This parameter specifies the translator sequence 1596 * for which the command is being constructed. 1597 * 1598 * @return none. 1599 */ 1600void sati_ata_idle_immediate_construct( 1601 void * ata_io, 1602 SATI_TRANSLATOR_SEQUENCE_T * sequence 1603) 1604{ 1605 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1606 1607 sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1608 sati_set_ata_features(register_fis, 0x00); 1609 sati_set_ata_sector_count(register_fis, 0x00); 1610 sati_set_ata_lba_high(register_fis, 0x00); 1611 sati_set_ata_lba_mid(register_fis, 0x00); 1612 sati_set_ata_lba_low(register_fis, 0x00); 1613 sati_ata_non_data_command(ata_io, sequence); 1614} 1615 1616/** 1617 * @brief This method will construct the ATA idle immediate command 1618 for Unload Features. 1619 * 1620 * @pre It is expected that the user has properly set the current contents 1621 * of the register FIS to 0. 1622 * 1623 * @param[out] ata_io This parameter specifies the ATA IO request structure 1624 * for which to build the IDLE IMMEDIATE command. 1625 * @param[in] sequence This parameter specifies the translator sequence 1626 * for which the command is being constructed. 1627 * 1628 * @return none. 1629 */ 1630void sati_ata_idle_immediate_unload_construct( 1631 void * ata_io, 1632 SATI_TRANSLATOR_SEQUENCE_T * sequence 1633) 1634{ 1635 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1636 1637 sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1638 sati_set_ata_features(register_fis, 0x44); 1639 sati_set_ata_sector_count(register_fis, 0x00); 1640 sati_set_ata_lba_high(register_fis, 0x55); 1641 sati_set_ata_lba_mid(register_fis, 0x4E); 1642 sati_set_ata_lba_low(register_fis, 0x4C); 1643 sati_ata_non_data_command(ata_io, sequence); 1644} 1645 1646/** 1647 * @brief This method will construct the ATA IDLE command.\ 1648 * 1649 * @pre It is expected that the user has properly set the current contents 1650 * of the register FIS to 0. 1651 * 1652 * @param[out] ata_io This parameter specifies the ATA IO request structure 1653 * for which to build the ATA IDLE command. 1654 * @param[in] sequence This parameter specifies the translator sequence 1655 * for which the command is being constructed. 1656 * 1657 * @return none. 1658 */ 1659void sati_ata_idle_construct( 1660 void * ata_io, 1661 SATI_TRANSLATOR_SEQUENCE_T * sequence 1662) 1663{ 1664 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1665 1666 sati_set_ata_command(register_fis, ATA_IDLE); 1667 sati_set_ata_features(register_fis, 0x00); 1668 sati_set_ata_sector_count(register_fis, 0x00); 1669 1670 sequence->device->ata_standby_timer = 0x00; 1671 1672 sati_set_ata_lba_high(register_fis, 0x00); 1673 sati_set_ata_lba_mid(register_fis, 0x00); 1674 sati_set_ata_lba_low(register_fis, 0x00); 1675 sati_ata_non_data_command(ata_io, sequence); 1676} 1677 1678/** 1679 * @brief This method will construct the ATA MEDIA EJECT command. 1680 * 1681 * @pre It is expected that the user has properly set the current contents 1682 * of the register FIS to 0. 1683 * 1684 * @param[out] ata_io This parameter specifies the ATA IO request structure 1685 * for which to build the MEDIA EJCT command. 1686 * @param[in] sequence This parameter specifies the translator sequence 1687 * for which the command is being constructed. 1688 * 1689 * @return none. 1690 */ 1691void sati_ata_media_eject_construct( 1692 void * ata_io, 1693 SATI_TRANSLATOR_SEQUENCE_T * sequence 1694) 1695{ 1696 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1697 1698 sati_set_ata_command(register_fis, ATA_MEDIA_EJECT); 1699 sati_ata_non_data_command(ata_io, sequence); 1700} 1701 1702 1703/** 1704 * @brief This method will construct the ATA read verify sector(s) command. 1705 * 1706 * @pre It is expected that the user has properly set the current contents 1707 * of the register FIS to 0. 1708 * 1709 * @param[out] ata_io This parameter specifies the ATA IO request structure 1710 * for which to build the ATA READ VERIFY SECTOR(S) command. 1711 * @param[in] sequence This parameter specifies the translator sequence 1712 * for which the command is being constructed. 1713 * 1714 * @return none. 1715 */ 1716void sati_ata_read_verify_sectors_construct( 1717 void * ata_io, 1718 SATI_TRANSLATOR_SEQUENCE_T * sequence 1719) 1720{ 1721 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1722 1723 sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); 1724 1725 //According to SAT-2 (v7) 9.11.3 1726 sati_set_ata_sector_count(register_fis, 1); 1727 1728 //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the 1729 //maximum LBA supported by the ATA device in its current configuration. 1730 //From the unit test, it seems we have to set LBA to a non-zero value. 1731 sati_set_ata_lba_low(register_fis, 1); 1732 1733 sati_ata_non_data_command(ata_io, sequence); 1734} 1735 1736/** 1737 * @brief This method will construct a ATA SMART Return Status command so the 1738 * status of the ATA device can be returned. The status of the SMART 1739 * threshold will be returned by this command. 1740 * 1741 * @return N/A 1742 * 1743 */ 1744void sati_ata_smart_return_status_construct( 1745 void * ata_io, 1746 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1747 U8 feature_value 1748) 1749{ 1750 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1751 1752 sati_set_ata_command(register_fis, ATA_SMART); 1753 1754 sati_set_ata_features(register_fis, feature_value); 1755 1756 sati_set_ata_lba_high(register_fis, 0xC2); 1757 sati_set_ata_lba_mid(register_fis, 0x4F); 1758 1759 sati_ata_non_data_command(ata_io, sequence); 1760} 1761 1762/** 1763 * @brief This method will construct a ATA SMART Return Status command so the 1764 * status of the ATA device can be returned. The status of the SMART 1765 * threshold will be returned by this command. 1766 * 1767 * @return N/A 1768 * 1769 */ 1770void sati_ata_smart_read_log_construct( 1771 void * ata_io, 1772 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1773 U8 log_address, 1774 U32 transfer_length 1775) 1776{ 1777 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1778 1779 sati_set_ata_command(register_fis, ATA_SMART); 1780 sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG); 1781 1782 sati_set_ata_lba_high(register_fis, 0xC2); 1783 sati_set_ata_lba_mid(register_fis, 0x4F); 1784 sati_set_ata_lba_low(register_fis, log_address); 1785 1786 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1787 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1788 sequence->ata_transfer_length = transfer_length; 1789} 1790 1791/** 1792 * @brief This method will construct a Write Uncorrectable ATA command that 1793 * will write one sector with a pseudo or flagged error. The type of 1794 * error is specified by the feature value. 1795 * 1796 * @return N/A 1797 * 1798 */ 1799void sati_ata_write_uncorrectable_construct( 1800 void * ata_io, 1801 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1802 U8 feature_value 1803) 1804{ 1805 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1806 1807 sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE); 1808 sati_set_ata_features(register_fis, feature_value); 1809 sati_set_ata_sector_count(register_fis, 0x0001); 1810 sati_ata_non_data_command(ata_io, sequence); 1811} 1812 1813/** 1814 * @brief This method will construct a Mode Select ATA SET FEATURES command 1815 * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead 1816 * 1817 * @return N/A 1818 * 1819 */ 1820void sati_ata_set_features_construct( 1821 void * ata_io, 1822 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1823 U8 feature 1824) 1825{ 1826 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1827 1828 sati_set_ata_command(register_fis, ATA_SET_FEATURES); 1829 sati_set_ata_features(register_fis, feature); 1830 sati_ata_non_data_command(ata_io, sequence); 1831} 1832 1833 1834 1835/** 1836 * @brief This method will construct a Read Log ext ATA command that 1837 * will request a log page based on the log_address. 1838 * 1839 * @param[in] log_address This parameter specifies the log page 1840 * to be returned from Read Log Ext. 1841 * 1842 * @param[in] transfer_length This parameter specifies the size of the 1843 * log page response returned by Read Log Ext. 1844 * 1845 * @return N/A 1846 * 1847 */ 1848void sati_ata_read_log_ext_construct( 1849 void * ata_io, 1850 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1851 U8 log_address, 1852 U32 transfer_length 1853) 1854{ 1855 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1856 1857 sati_set_ata_command(register_fis, ATA_READ_LOG_EXT); 1858 1859 sati_set_ata_lba_low(register_fis, log_address); 1860 sati_set_ata_lba_mid(register_fis, 0x00); 1861 sati_set_ata_lba_mid_exp(register_fis, 0x00); 1862 1863 sati_set_ata_sector_count(register_fis, 0x01); 1864 1865 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1866 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1867 sequence->ata_transfer_length = transfer_length; 1868 1869} 1870 1871/** 1872* @brief This method will check if the ATA device is in the stopped power 1873* state. This is used for all medium access commands for SAT 1874* compliance. See SAT2r07 section 9.11.1 1875* 1876* @param[in] sequence - SATI sequence data with the device state. 1877* 1878* @return TRUE If device is stopped 1879* 1880*/ 1881BOOL sati_device_state_stopped( 1882 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1883 void * scsi_io 1884) 1885{ 1886 if(sequence->device->state == SATI_DEVICE_STATE_STOPPED) 1887 { 1888 sati_scsi_sense_data_construct( 1889 sequence, 1890 scsi_io, 1891 SCSI_STATUS_CHECK_CONDITION, 1892 SCSI_SENSE_NOT_READY , 1893 SCSI_ASC_INITIALIZING_COMMAND_REQUIRED, 1894 SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 1895 ); 1896 return TRUE; 1897 } 1898 return FALSE; 1899} 1900 1901/** 1902* @brief This method will construct a ATA Read Buffer command that 1903* will request PIO in data containing the target device's buffer. 1904* 1905* @param[out] ata_io This parameter specifies the ATA IO request structure 1906* for which to build the ATA READ VERIFY SECTOR(S) command. 1907* @param[in] sequence This parameter specifies the translator sequence 1908* for which the command is being constructed. 1909* @return N/A 1910* 1911*/ 1912void sati_ata_read_buffer_construct( 1913 void * ata_io, 1914 SATI_TRANSLATOR_SEQUENCE_T * sequence 1915) 1916{ 1917 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1918 1919 sati_set_ata_command(register_fis, ATA_READ_BUFFER); 1920 sequence->data_direction = SATI_DATA_DIRECTION_IN; 1921 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1922 sequence->ata_transfer_length = 512; 1923} 1924 1925 1926/** 1927* @brief This method will construct a ATA Write Buffer command that 1928* will send PIO out data to the target device's buffer. 1929* 1930* @param[out] ata_io This parameter specifies the ATA IO request structure 1931* for which to build the ATA READ VERIFY SECTOR(S) command. 1932* @param[in] sequence This parameter specifies the translator sequence 1933* for which the command is being constructed. 1934* @return N/A 1935* 1936*/ 1937void sati_ata_write_buffer_construct( 1938 void * ata_io, 1939 SATI_TRANSLATOR_SEQUENCE_T * sequence 1940) 1941{ 1942 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1943 1944 sati_set_ata_command(register_fis, ATA_WRITE_BUFFER); 1945 1946 sequence->data_direction = SATI_DATA_DIRECTION_OUT; 1947 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 1948 sequence->ata_transfer_length = 512; 1949} 1950 1951 1952/** 1953* @brief This method will construct a ATA Download Microcode command that 1954* will send PIO out data containing new firmware for the target drive. 1955* 1956* @param[out] ata_io This parameter specifies the ATA IO request structure 1957* for which to build the ATA READ VERIFY SECTOR(S) command. 1958* @param[in] sequence This parameter specifies the translator sequence 1959* for which the command is being constructed. 1960* @param[in] mode This parameter specifies the download microcode sub-command 1961* code. 1962* @param[in] allocation_length This parameter specifies the number of bytes 1963* being sent to the target device. 1964* @param[in] buffer_offset This parameter specifies the buffer offset for the 1965* data sent to the target device. 1966* 1967* @return N/A 1968* 1969*/ 1970void sati_ata_download_microcode_construct( 1971 void * ata_io, 1972 SATI_TRANSLATOR_SEQUENCE_T * sequence, 1973 U8 mode, 1974 U32 allocation_length, 1975 U32 buffer_offset 1976) 1977{ 1978 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1979 U32 allocation_blocks = allocation_length >> 9; 1980 U32 buffer_blkoffset = buffer_offset >> 9; 1981 1982 sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE); 1983 sati_set_ata_features(register_fis, mode); 1984 1985 if(mode == ATA_MICROCODE_DOWNLOAD_SAVE) 1986 { 1987 sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9)); 1988 sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17)); 1989 } 1990 else //mode == 0x03 1991 { 1992 sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff)); 1993 sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff)); 1994 sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff)); 1995 sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff)); 1996 } 1997 1998 if((allocation_length == 0) && (buffer_offset == 0)) 1999 { 2000 sati_ata_non_data_command(ata_io, sequence); 2001 } 2002 else 2003 { 2004 sequence->data_direction = SATI_DATA_DIRECTION_OUT; 2005 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 2006 sequence->ata_transfer_length = allocation_length; 2007 } 2008} 2009