1230557Sjimharris/*- 2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license. When using or 3230557Sjimharris * redistributing this file, you may do so under either license. 4230557Sjimharris * 5230557Sjimharris * GPL LICENSE SUMMARY 6230557Sjimharris * 7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8230557Sjimharris * 9230557Sjimharris * This program is free software; you can redistribute it and/or modify 10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as 11230557Sjimharris * published by the Free Software Foundation. 12230557Sjimharris * 13230557Sjimharris * This program is distributed in the hope that it will be useful, but 14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of 15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16230557Sjimharris * General Public License for more details. 17230557Sjimharris * 18230557Sjimharris * You should have received a copy of the GNU General Public License 19230557Sjimharris * along with this program; if not, write to the Free Software 20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21230557Sjimharris * The full GNU General Public License is included in this distribution 22230557Sjimharris * in the file called LICENSE.GPL. 23230557Sjimharris * 24230557Sjimharris * BSD LICENSE 25230557Sjimharris * 26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27230557Sjimharris * All rights reserved. 28230557Sjimharris * 29230557Sjimharris * Redistribution and use in source and binary forms, with or without 30230557Sjimharris * modification, are permitted provided that the following conditions 31230557Sjimharris * are met: 32230557Sjimharris * 33230557Sjimharris * * Redistributions of source code must retain the above copyright 34230557Sjimharris * notice, this list of conditions and the following disclaimer. 35230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 36230557Sjimharris * notice, this list of conditions and the following disclaimer in 37230557Sjimharris * the documentation and/or other materials provided with the 38230557Sjimharris * distribution. 39230557Sjimharris * 40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51230557Sjimharris */ 52230557Sjimharris 53230557Sjimharris#include <sys/cdefs.h> 54230557Sjimharris__FBSDID("$FreeBSD: releng/10.3/sys/dev/isci/scil/sati_util.c 240514 2012-09-14 20:05:38Z jimharris $"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * @brief This file contains all of the method implementations that 59230557Sjimharris * provide generic support for SATI. Some methods can be utilized 60230557Sjimharris * by a user to construct ATA/ATAPI commands, copy ATA device 61230557Sjimharris * structure data, fill in sense data, etc. 62230557Sjimharris */ 63230557Sjimharris 64230557Sjimharris#include <dev/isci/scil/sati_util.h> 65230557Sjimharris#include <dev/isci/scil/sati_callbacks.h> 66230557Sjimharris#include <dev/isci/scil/intel_scsi.h> 67230557Sjimharris#include <dev/isci/scil/intel_ata.h> 68230557Sjimharris#include <dev/isci/scil/intel_sat.h> 69230557Sjimharris#include <dev/isci/scil/intel_sas.h> 70230557Sjimharris 71230557Sjimharris/** 72230557Sjimharris * @brief This method will set the data direction, protocol, and transfer 73230557Sjimharris * kength for an ATA non-data command. 74230557Sjimharris * 75230557Sjimharris * @pre It is expected that the user will use this method for setting these 76230557Sjimharris * values in a non-data ATA command constuct. 77230557Sjimharris * 78230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 79230557Sjimharris * for which to build the IDENTIFY DEVICE command. 80230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 81230557Sjimharris * for which the command is being constructed. 82230557Sjimharris * 83230557Sjimharris * @return none. 84230557Sjimharris */ 85230557Sjimharrisvoid sati_ata_non_data_command( 86230557Sjimharris void * ata_io, 87230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 88230557Sjimharris) 89230557Sjimharris{ 90230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_NONE; 91230557Sjimharris sequence->protocol = SAT_PROTOCOL_NON_DATA; 92230557Sjimharris sequence->ata_transfer_length = 0; 93230557Sjimharris} 94230557Sjimharris 95230557Sjimharris/** 96230557Sjimharris * @brief This method will construct the ATA identify device command. 97230557Sjimharris * 98230557Sjimharris * @pre It is expected that the user has properly set the current contents 99230557Sjimharris * of the register FIS to 0. 100230557Sjimharris * 101230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 102230557Sjimharris * for which to build the IDENTIFY DEVICE command. 103230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 104230557Sjimharris * for which the command is being constructed. 105230557Sjimharris * 106230557Sjimharris * @return none. 107230557Sjimharris */ 108230557Sjimharrisvoid sati_ata_identify_device_construct( 109230557Sjimharris void * ata_io, 110230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 111230557Sjimharris) 112230557Sjimharris{ 113230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 114230557Sjimharris 115230557Sjimharris sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE); 116230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_IN; 117230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 118230557Sjimharris sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T); 119230557Sjimharris} 120230557Sjimharris 121230557Sjimharris/** 122230557Sjimharris* @brief This method will construct the ATA Execute Device Diagnostic command. 123230557Sjimharris* 124230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure 125230557Sjimharris* for which to build the IDENTIFY DEVICE command. 126230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 127230557Sjimharris* for which the command is being constructed. 128230557Sjimharris* 129230557Sjimharris* @return none. 130230557Sjimharris*/ 131230557Sjimharrisvoid sati_ata_execute_device_diagnostic_construct( 132230557Sjimharris void * ata_io, 133230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 134230557Sjimharris) 135230557Sjimharris{ 136230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 137230557Sjimharris 138230557Sjimharris sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG); 139230557Sjimharris 140230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_IN; 141230557Sjimharris sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC; 142230557Sjimharris sequence->ata_transfer_length = 16; 143230557Sjimharris} 144230557Sjimharris 145230557Sjimharris/** 146230557Sjimharris * @brief This method will set data bytes in the user data area. If the 147230557Sjimharris * caller requests it, the data written will be forced to ascii 148230557Sjimharris * printable characters if it isn't already a printable character. 149230557Sjimharris * A printable character is considered to be >= 0x20 and <= 0x70. 150230557Sjimharris * 151230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 152230557Sjimharris * for which to copy and swap the data. 153230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO 154230557Sjimharris * request containing the destination buffer into which to copy. 155230557Sjimharris * @param[in] destination_offset This parameter specifies the offset into 156230557Sjimharris * the data buffer where the information will be copied to. 157230557Sjimharris * @param[in] source_value This parameter specifies the value retrieved 158230557Sjimharris * from the source buffer that is to be copied into the user 159230557Sjimharris * buffer area. 160230557Sjimharris * @param[in] use_printable_chars This parameter indicates if the copy should 161230557Sjimharris * ensure that the value copied is considered an ASCII printable 162230557Sjimharris * character (e.g. A, B, " ", etc.). These characters reside 163230557Sjimharris * in the 0x20 - 0x7E ASCII range. 164230557Sjimharris * 165230557Sjimharris * @return none 166230557Sjimharris */ 167230557Sjimharrisstatic 168230557Sjimharrisvoid sati_set_ascii_data_byte( 169230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 170230557Sjimharris void * destination_scsi_io, 171230557Sjimharris U32 destination_offset, 172230557Sjimharris U8 source_value, 173230557Sjimharris BOOL use_printable_chars 174230557Sjimharris) 175230557Sjimharris{ 176230557Sjimharris // if the user requests that the copied data be ascii printable, then 177230557Sjimharris // default to " " (i.e. 0x20) for all non-ascii printable characters. 178230557Sjimharris if((use_printable_chars == TRUE) 179230557Sjimharris && ((source_value < 0x20) || (source_value > 0x7E))) 180230557Sjimharris { 181230557Sjimharris source_value = 0x20; 182230557Sjimharris } 183230557Sjimharris 184230557Sjimharris sati_set_data_byte( 185230557Sjimharris sequence, destination_scsi_io, destination_offset, source_value 186230557Sjimharris ); 187230557Sjimharris} 188230557Sjimharris 189230557Sjimharris/** 190230557Sjimharris * @brief This method performs a copy operation using an offset into the 191230557Sjimharris * source buffer, an offset into the destination buffer, and a length. 192230557Sjimharris * It will perform the byte swap from the 16-bit identify field 193230557Sjimharris * into the network byte order SCSI location. 194230557Sjimharris * 195230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 196230557Sjimharris * for which to copy and swap the data. 197230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO 198230557Sjimharris * request containing the destination buffer into which to copy. 199230557Sjimharris * @param[in] destination_offset This parameter specifies the offset into 200230557Sjimharris * the data buffer where the information will be copied to. 201230557Sjimharris * @param[in] source_buffer This parameter specifies the source buffer from 202230557Sjimharris * which the data will be copied. 203230557Sjimharris * @param[in] source_offset This parameter specifies the offset into the 204230557Sjimharris * source buffer where the copy shall begin. 205230557Sjimharris * @param[in] length This parameter specifies the number of bytes to copy 206230557Sjimharris * during this operation. 207230557Sjimharris * @param[in] use_printable_chars This parameter indicates if the copy should 208230557Sjimharris * ensure that the value copied is considered an ASCII printable 209230557Sjimharris * character (e.g. A, B, " ", etc.). These characters reside 210230557Sjimharris * in the 0x20 - 0x7E ASCII range. 211230557Sjimharris * 212230557Sjimharris * @return none 213230557Sjimharris */ 214230557Sjimharrisvoid sati_ata_identify_device_copy_data( 215230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 216230557Sjimharris void * destination_scsi_io, 217230557Sjimharris U32 destination_offset, 218230557Sjimharris U8 * source_buffer, 219230557Sjimharris U32 source_offset, 220230557Sjimharris U32 length, 221230557Sjimharris BOOL use_printable_chars 222230557Sjimharris) 223230557Sjimharris{ 224230557Sjimharris source_buffer += source_offset; 225230557Sjimharris while (length > 0) 226230557Sjimharris { 227230557Sjimharris sati_set_ascii_data_byte( 228230557Sjimharris sequence, 229230557Sjimharris destination_scsi_io, 230230557Sjimharris destination_offset, 231230557Sjimharris *(source_buffer+1), 232230557Sjimharris use_printable_chars 233230557Sjimharris ); 234230557Sjimharris 235230557Sjimharris sati_set_ascii_data_byte( 236230557Sjimharris sequence, 237230557Sjimharris destination_scsi_io, 238230557Sjimharris destination_offset+1, 239230557Sjimharris *source_buffer, 240230557Sjimharris use_printable_chars 241230557Sjimharris ); 242230557Sjimharris 243230557Sjimharris destination_offset += 2; 244230557Sjimharris source_buffer += 2; 245230557Sjimharris length -= 2; 246230557Sjimharris } 247230557Sjimharris} 248230557Sjimharris 249230557Sjimharris/** 250230557Sjimharris * @brief This method performs a copy operation using a source buffer, 251230557Sjimharris * an offset into the destination buffer, and a length. 252230557Sjimharris * 253230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 254230557Sjimharris * for which to copy and swap the data. 255230557Sjimharris * @param[out] destination_scsi_io This parameter specifies the SCSI IO 256230557Sjimharris * request containing the destination buffer into which to copy. 257230557Sjimharris * @param[in] destination_offset This parameter specifies the offset into 258230557Sjimharris * the data buffer where the information will be copied to. 259230557Sjimharris * @param[in] source_buffer This parameter specifies the source buffer from 260230557Sjimharris * which the data will be copied. 261230557Sjimharris * @param[in] length This parameter specifies the number of bytes to copy 262230557Sjimharris * during this operation. 263230557Sjimharris * 264230557Sjimharris * @return none 265230557Sjimharris */ 266230557Sjimharrisvoid sati_copy_data( 267230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 268230557Sjimharris void * destination_scsi_io, 269230557Sjimharris U32 destination_offset, 270230557Sjimharris U8 * source_buffer, 271230557Sjimharris U32 length 272230557Sjimharris) 273230557Sjimharris{ 274230557Sjimharris while (length > 0) 275230557Sjimharris { 276230557Sjimharris sati_set_data_byte( 277230557Sjimharris sequence, destination_scsi_io, destination_offset, *source_buffer 278230557Sjimharris ); 279230557Sjimharris 280230557Sjimharris destination_offset++; 281230557Sjimharris source_buffer++; 282230557Sjimharris length--; 283230557Sjimharris } 284230557Sjimharris} 285230557Sjimharris 286230557Sjimharris/** 287230557Sjimharris * @brief This method extracts the Logical Block Address high and low 32-bit 288230557Sjimharris * values and the sector count 32-bit value from the ATA identify 289230557Sjimharris * device data. 290230557Sjimharris * 291230557Sjimharris * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA 292230557Sjimharris * from which to extract the sector information. 293230557Sjimharris * @param[out] lba_high This parameter specifies the upper 32 bits for the 294230557Sjimharris * number of logical block addresses for the device. The upper 295230557Sjimharris * 16-bits should always be 0, since 48-bits of LBA is the most 296230557Sjimharris * supported by an ATA device. 297230557Sjimharris * @param[out] lba_low This parameter specifies the lower 32 bits for the 298230557Sjimharris * number of logical block addresses for the device. 299230557Sjimharris * @param[out] sector_size This parameter specifies the 32-bits of sector 300230557Sjimharris * size. If the ATA device doesn't support reporting it's 301230557Sjimharris * sector size, then 512 bytes is utilized as the default value. 302230557Sjimharris * 303230557Sjimharris * @return none 304230557Sjimharris */ 305230557Sjimharrisvoid sati_ata_identify_device_get_sector_info( 306230557Sjimharris ATA_IDENTIFY_DEVICE_DATA_T * identify, 307230557Sjimharris U32 * lba_high, 308230557Sjimharris U32 * lba_low, 309230557Sjimharris U32 * sector_size 310230557Sjimharris) 311230557Sjimharris{ 312230557Sjimharris // Calculate the values to be returned 313230557Sjimharris // Calculation will be different if the SATA device supports 314230557Sjimharris // 48-bit addressing. Bit 10 of Word 86 of ATA Identify 315230557Sjimharris if (identify->command_set_enabled1 316230557Sjimharris & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE) 317230557Sjimharris { 318230557Sjimharris // This drive supports 48-bit addressing 319230557Sjimharris 320230557Sjimharris *lba_high = identify->max_48bit_lba[7] << 24; 321230557Sjimharris *lba_high |= identify->max_48bit_lba[6] << 16; 322230557Sjimharris *lba_high |= identify->max_48bit_lba[5] << 8; 323230557Sjimharris *lba_high |= identify->max_48bit_lba[4]; 324230557Sjimharris 325230557Sjimharris *lba_low = identify->max_48bit_lba[3] << 24; 326230557Sjimharris *lba_low |= identify->max_48bit_lba[2] << 16; 327230557Sjimharris *lba_low |= identify->max_48bit_lba[1] << 8; 328230557Sjimharris *lba_low |= identify->max_48bit_lba[0]; 329230557Sjimharris } 330230557Sjimharris else 331230557Sjimharris { 332230557Sjimharris // This device doesn't support 48-bit addressing 333230557Sjimharris // Pull out the largest LBA from words 60 and 61. 334230557Sjimharris *lba_high = 0; 335230557Sjimharris *lba_low = identify->total_num_sectors[3] << 24; 336230557Sjimharris *lba_low |= identify->total_num_sectors[2] << 16; 337230557Sjimharris *lba_low |= identify->total_num_sectors[1] << 8; 338230557Sjimharris *lba_low |= identify->total_num_sectors[0]; 339230557Sjimharris } 340230557Sjimharris 341230557Sjimharris // If the ATA device reports its sector size (bit 12 of Word 106), 342230557Sjimharris // then use that instead. 343230557Sjimharris if (identify->physical_logical_sector_info 344230557Sjimharris & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE) 345230557Sjimharris { 346230557Sjimharris *sector_size = identify->words_per_logical_sector[3] << 24; 347230557Sjimharris *sector_size |= identify->words_per_logical_sector[2] << 16; 348230557Sjimharris *sector_size |= identify->words_per_logical_sector[1] << 8; 349230557Sjimharris *sector_size |= identify->words_per_logical_sector[0]; 350230557Sjimharris } 351230557Sjimharris else 352230557Sjimharris { 353230557Sjimharris // Default the sector size to 512 bytes 354230557Sjimharris *sector_size = 512; 355230557Sjimharris } 356230557Sjimharris} 357230557Sjimharris 358230557Sjimharris/** 359230557Sjimharris * @brief This method will construct the ATA check power mode command. 360230557Sjimharris * 361230557Sjimharris * @pre It is expected that the user has properly set the current contents 362230557Sjimharris * of the register FIS to 0. 363230557Sjimharris * 364230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 365230557Sjimharris * for which to build the CHECK POWER MODE command. 366230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 367230557Sjimharris * for which the command is being constructed. 368230557Sjimharris * 369230557Sjimharris * @return none. 370230557Sjimharris */ 371230557Sjimharrisvoid sati_ata_check_power_mode_construct( 372230557Sjimharris void * ata_io, 373230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 374230557Sjimharris) 375230557Sjimharris{ 376230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 377230557Sjimharris 378230557Sjimharris sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE); 379230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 380230557Sjimharris} 381230557Sjimharris 382230557Sjimharris/** 383230557Sjimharris * @brief This method is utilized to set a specific byte in the sense 384230557Sjimharris * data area. It will ensure that the supplied byte offset 385230557Sjimharris * isn't larger then the length of the requested sense data. 386230557Sjimharris * 387230557Sjimharris * @param[in] scsi_io This parameter specifies the user SCSI IO request 388230557Sjimharris * for which to set the sense data byte. 389230557Sjimharris * @param[in] byte_offset This parameter specifies the byte offset into 390230557Sjimharris * the sense data buffer where the data should be written. 391230557Sjimharris * @param[in] value This parameter specifies the 8-bit value to be written 392230557Sjimharris * into the sense data area. 393230557Sjimharris * 394230557Sjimharris * @return none 395230557Sjimharris */ 396230557Sjimharrisvoid sati_set_sense_data_byte( 397230557Sjimharris U8 * sense_data, 398230557Sjimharris U32 max_sense_data_len, 399230557Sjimharris U32 byte_offset, 400230557Sjimharris U8 value 401230557Sjimharris) 402230557Sjimharris{ 403230557Sjimharris // Ensure that we don't attempt to write past the end of the sense 404230557Sjimharris // data buffer. 405230557Sjimharris if (byte_offset < max_sense_data_len) 406230557Sjimharris sense_data[byte_offset] = value; 407230557Sjimharris} 408230557Sjimharris 409230557Sjimharris/** 410230557Sjimharris * @brief This method will construct the common response IU in the user 411230557Sjimharris * request's response IU location. 412230557Sjimharris * 413230557Sjimharris * @param[out] rsp_iu This parameter specifies the user request's 414230557Sjimharris * response IU to be constructed. 415230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 416230557Sjimharris * value for the user's IO request. 417230557Sjimharris * @param[in] sense_data_length This parameter specifies the sense data 418230557Sjimharris * length for response IU. 419230557Sjimharris * @param[in] data_present The parameter specifies the specific 420230557Sjimharris * data present value for response IU. 421230557Sjimharris * 422230557Sjimharris * @return none 423230557Sjimharris */ 424230557Sjimharrisvoid sati_scsi_common_response_iu_construct( 425230557Sjimharris SCI_SSP_RESPONSE_IU_T * rsp_iu, 426230557Sjimharris U8 scsi_status, 427230557Sjimharris U8 sense_data_length, 428230557Sjimharris U8 data_present 429230557Sjimharris) 430230557Sjimharris{ 431230557Sjimharris rsp_iu->sense_data_length[3] = sense_data_length; 432230557Sjimharris rsp_iu->sense_data_length[2] = 0; 433230557Sjimharris rsp_iu->sense_data_length[1] = 0; 434230557Sjimharris rsp_iu->sense_data_length[0] = 0; 435230557Sjimharris rsp_iu->status = scsi_status; 436230557Sjimharris rsp_iu->data_present = data_present; 437230557Sjimharris} 438230557Sjimharris 439230557Sjimharris/** 440230557Sjimharris * @brief This method will construct the buffer for sense data 441230557Sjimharris * sense data buffer location. Additionally, it will set the user's 442230557Sjimharris * SCSI status. 443230557Sjimharris * 444230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 445230557Sjimharris * for which to construct the buffer for sense data. 446230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 447230557Sjimharris * value for the user's IO request. 448230557Sjimharris * @param[out] sense_data This paramater 449230557Sjimharris * 450230557Sjimharris * @return none 451230557Sjimharris */ 452230557Sjimharrisstatic 453230557Sjimharrisvoid sati_scsi_get_sense_data_buffer( 454230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 455230557Sjimharris void * scsi_io, 456230557Sjimharris U8 scsi_status, 457230557Sjimharris U8 ** sense_data, 458230557Sjimharris U32 * sense_len) 459230557Sjimharris{ 460230557Sjimharris#ifdef SATI_TRANSPORT_SUPPORTS_SAS 461230557Sjimharris SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 462230557Sjimharris sati_cb_get_response_iu_address(scsi_io); 463230557Sjimharris 464230557Sjimharris sati_scsi_common_response_iu_construct( 465230557Sjimharris rsp_iu, 466230557Sjimharris scsi_status, 467230557Sjimharris sati_scsi_get_sense_data_length(sequence, scsi_io), 468230557Sjimharris SCSI_RESPONSE_DATA_PRES_SENSE_DATA 469230557Sjimharris ); 470230557Sjimharris 471230557Sjimharris *sense_data = (U8*) rsp_iu->data; 472230557Sjimharris *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes 473230557Sjimharris#else 474230557Sjimharris *sense_data = sati_cb_get_sense_data_address(scsi_io); 475230557Sjimharris *sense_len = sati_cb_get_sense_data_length(scsi_io); 476230557Sjimharris sati_cb_set_scsi_status(scsi_io, scsi_status); 477230557Sjimharris#endif // SATI_TRANSPORT_SUPPORTS_SAS 478230557Sjimharris} 479230557Sjimharris 480230557Sjimharris/** 481230557Sjimharris * @brief This method extract response code based on on device settings. 482230557Sjimharris * 483230557Sjimharris * @return response code 484230557Sjimharris */ 485230557Sjimharrisstatic 486230557SjimharrisU8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence) 487230557Sjimharris{ 488230557Sjimharris if (sequence->device->descriptor_sense_enable) 489230557Sjimharris { 490230557Sjimharris return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE; 491230557Sjimharris } 492230557Sjimharris else 493230557Sjimharris { 494230557Sjimharris return SCSI_FIXED_CURRENT_RESPONSE_CODE; 495230557Sjimharris } 496230557Sjimharris} 497230557Sjimharris 498230557Sjimharris/** 499230557Sjimharris * @brief This method will return length of descriptor sense data for executed command. 500230557Sjimharris * 501230557Sjimharris * @return sense data length 502230557Sjimharris */ 503230557Sjimharrisstatic 504230557SjimharrisU8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, 505230557Sjimharris void * scsi_io) 506230557Sjimharris{ 507230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 508230557Sjimharris //Initial value is descriptor header length 509230557Sjimharris U8 length = 8; 510230557Sjimharris 511230557Sjimharris switch (sati_get_cdb_byte(cdb, 0)) 512230557Sjimharris { 513230557Sjimharris#if !defined(DISABLE_SATI_WRITE_LONG) 514230557Sjimharris case SCSI_WRITE_LONG_10: 515230557Sjimharris case SCSI_WRITE_LONG_16: 516230557Sjimharris length += SCSI_BLOCK_DESCRIPTOR_LENGTH + 517230557Sjimharris SCSI_INFORMATION_DESCRIPTOR_LENGTH; 518230557Sjimharris break; 519230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_LONG) 520230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 521230557Sjimharris case SCSI_REASSIGN_BLOCKS: 522230557Sjimharris length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH + 523230557Sjimharris SCSI_INFORMATION_DESCRIPTOR_LENGTH; 524230557Sjimharris break; 525230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 526230557Sjimharris case SCSI_READ_6: 527230557Sjimharris case SCSI_READ_10: 528230557Sjimharris case SCSI_READ_12: 529230557Sjimharris case SCSI_READ_16: 530230557Sjimharris case SCSI_WRITE_6: 531230557Sjimharris case SCSI_WRITE_10: 532230557Sjimharris case SCSI_WRITE_12: 533230557Sjimharris case SCSI_WRITE_16: 534230557Sjimharris#if !defined(DISABLE_SATI_VERIFY) 535230557Sjimharris case SCSI_VERIFY_10: 536230557Sjimharris case SCSI_VERIFY_12: 537230557Sjimharris case SCSI_VERIFY_16: 538230557Sjimharris#endif // !defined(DISABLE_SATI_VERIFY) 539230557Sjimharris#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 540230557Sjimharris && !defined(DISABLE_SATI_VERIFY) \ 541230557Sjimharris && !defined(DISABLE_SATI_WRITE) 542230557Sjimharris 543230557Sjimharris case SCSI_WRITE_AND_VERIFY_10: 544230557Sjimharris case SCSI_WRITE_AND_VERIFY_12: 545230557Sjimharris case SCSI_WRITE_AND_VERIFY_16: 546230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 547230557Sjimharris // && !defined(DISABLE_SATI_VERIFY) 548230557Sjimharris // && !defined(DISABLE_SATI_WRITE) 549230557Sjimharris length += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 550230557Sjimharris break; 551230557Sjimharris } 552230557Sjimharris 553230557Sjimharris return length; 554230557Sjimharris} 555230557Sjimharris 556230557Sjimharris/** 557230557Sjimharris * @brief This method will return length of sense data. 558230557Sjimharris * 559230557Sjimharris * @return sense data length 560230557Sjimharris */ 561230557SjimharrisU8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io) 562230557Sjimharris{ 563230557Sjimharris U8 response_code; 564230557Sjimharris 565230557Sjimharris response_code = sati_scsi_get_sense_data_response_code(sequence); 566230557Sjimharris 567230557Sjimharris switch (response_code) 568230557Sjimharris { 569230557Sjimharris case SCSI_FIXED_CURRENT_RESPONSE_CODE: 570230557Sjimharris case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 571230557Sjimharris return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 572230557Sjimharris break; 573230557Sjimharris case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 574230557Sjimharris case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 575230557Sjimharris return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io); 576230557Sjimharris break; 577230557Sjimharris } 578230557Sjimharris 579230557Sjimharris return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; 580230557Sjimharris} 581230557Sjimharris 582230557Sjimharris/** 583230557Sjimharris * @brief This method will construct the sense data buffer in the user's 584230557Sjimharris * sense data buffer location. Additionally, it will set the user's 585230557Sjimharris * SCSI status. 586230557Sjimharris * 587230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 588230557Sjimharris * for which to construct the sense data. 589230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 590230557Sjimharris * for which to construct the sense data. 591230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 592230557Sjimharris * value for the user's IO request. 593230557Sjimharris * @param[in] sense_key This parameter specifies the sense key to 594230557Sjimharris * be set for the user's IO request. 595230557Sjimharris * @param[in] additional_sense_code This parameter specifies the 596230557Sjimharris * additional sense code (ASC) key to be set for the user's 597230557Sjimharris * IO request. 598230557Sjimharris * @param[in] additional_sense_code_qualifier This parameter specifies 599230557Sjimharris * the additional sense code qualifier (ASCQ) key to be set 600230557Sjimharris * for the user's IO request. 601230557Sjimharris * 602230557Sjimharris * @return none 603230557Sjimharris */ 604230557Sjimharrisvoid sati_scsi_sense_data_construct( 605230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 606230557Sjimharris void * scsi_io, 607230557Sjimharris U8 scsi_status, 608230557Sjimharris U8 sense_key, 609230557Sjimharris U8 additional_sense_code, 610230557Sjimharris U8 additional_sense_code_qualifier 611230557Sjimharris) 612230557Sjimharris{ 613230557Sjimharris U8 response_code; 614230557Sjimharris 615230557Sjimharris response_code = sati_scsi_get_sense_data_response_code(sequence); 616230557Sjimharris 617230557Sjimharris switch (response_code) 618230557Sjimharris { 619230557Sjimharris case SCSI_FIXED_CURRENT_RESPONSE_CODE: 620230557Sjimharris case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 621230557Sjimharris sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 622230557Sjimharris sense_key, additional_sense_code, additional_sense_code_qualifier); 623230557Sjimharris break; 624230557Sjimharris case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 625230557Sjimharris case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 626230557Sjimharris sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code, 627230557Sjimharris sense_key, additional_sense_code, additional_sense_code_qualifier); 628230557Sjimharris break; 629230557Sjimharris } 630230557Sjimharris 631230557Sjimharris sequence->is_sense_response_set = TRUE; 632230557Sjimharris} 633230557Sjimharris 634230557Sjimharris/** 635230557Sjimharris * @brief This method will construct the block descriptor in the user's descriptor 636230557Sjimharris * sense data buffer location. 637230557Sjimharris * 638230557Sjimharris * @param[in] sense_data This parameter specifies the user SCSI IO request 639230557Sjimharris * for which to set the sense data byte. 640230557Sjimharris * @param[in] sense_len This parameter specifies length of the sense data 641230557Sjimharris * to be returned by SATI. 642230557Sjimharris * @param[out] descriptor_len This parameter returns the length of constructed 643230557Sjimharris * descriptor. 644230557Sjimharris * 645230557Sjimharris * @return none 646230557Sjimharris */ 647230557Sjimharrisstatic 648230557Sjimharrisvoid sati_scsi_block_descriptor_construct( 649230557Sjimharris U8 * sense_data, 650230557Sjimharris U32 sense_len) 651230557Sjimharris{ 652230557Sjimharris U8 ili = 1; 653230557Sjimharris 654230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE); 655230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH); 656230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 657230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5)); 658230557Sjimharris} 659230557Sjimharris 660230557Sjimharris/** 661230557Sjimharris * @brief This method will construct the command-specific descriptor for 662230557Sjimharris * the descriptor sense data buffer in the user's sense data buffer 663230557Sjimharris * location. 664230557Sjimharris * 665230557Sjimharris * @param[in] sense_data This parameter specifies the user SCSI IO request 666230557Sjimharris * for which to set the sense data byte. 667230557Sjimharris * @param[in] sense_len This parameter specifies length of the sense data 668230557Sjimharris * to be returned by SATI. 669230557Sjimharris * @param[out] descriptor_len This parameter returns the length of constructed 670230557Sjimharris * descriptor. 671230557Sjimharris * @param[in] information_buff This parameter specifies the address for which 672230557Sjimharris * to set the command-specific information buffer. 673230557Sjimharris * 674230557Sjimharris * @return none 675230557Sjimharris */ 676230557Sjimharrisstatic 677230557Sjimharrisvoid sati_scsi_command_specific_descriptor_construct( 678230557Sjimharris U8 * sense_data, 679230557Sjimharris U32 sense_len, 680230557Sjimharris U8 * information_buff) 681230557Sjimharris{ 682230557Sjimharris U8 i; 683230557Sjimharris 684230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE); 685230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH); 686230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, 0); 687230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 688230557Sjimharris 689230557Sjimharris // fill information buffer 690230557Sjimharris // SBC 5.20.1 REASSIGN BLOCKS command overview 691230557Sjimharris // If information about the first LBA not reassigned is not available 692230557Sjimharris // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh 693230557Sjimharris for (i=0; i<8; i++) 694230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]); 695230557Sjimharris} 696230557Sjimharris 697230557Sjimharris/** 698230557Sjimharris * @brief This method will construct the information descriptor for 699230557Sjimharris * the descriptor sense data buffer in the user's sense data buffer 700230557Sjimharris * location. 701230557Sjimharris * 702230557Sjimharris * @param[in] sense_data This parameter specifies the user SCSI IO request 703230557Sjimharris * for which to set the sense data byte. 704230557Sjimharris * @param[in] sense_len This parameter specifies length of the sense data 705230557Sjimharris * to be returned by SATI. 706230557Sjimharris * @param[out] descriptor_len This parameter returns the length of constructed 707230557Sjimharris * descriptor. 708230557Sjimharris * @param[in] information_buff This parameter specifies the address for which 709230557Sjimharris * to set the information buffer. 710230557Sjimharris * 711230557Sjimharris * @return none 712230557Sjimharris */ 713230557Sjimharrisstatic 714230557Sjimharrisvoid sati_scsi_information_descriptor_construct( 715230557Sjimharris U8 * sense_data, 716230557Sjimharris U32 sense_len, 717230557Sjimharris U8 * information_buff) 718230557Sjimharris{ 719230557Sjimharris U8 i; 720230557Sjimharris U8 valid = 1; 721230557Sjimharris 722230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE); 723230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH); 724230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7)); 725230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 726230557Sjimharris 727230557Sjimharris // fill information buffer 728230557Sjimharris for (i=0; i<8; i++) 729230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]); 730230557Sjimharris} 731230557Sjimharris 732230557Sjimharris/** 733230557Sjimharris * @brief This method will construct the descriptors in the user's descriptor 734230557Sjimharris * sense data buffer location. 735230557Sjimharris * 736230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 737230557Sjimharris * for which to construct the sense data. 738230557Sjimharris * @param[in] sense_data This parameter specifies the user SCSI IO request 739230557Sjimharris * for which to set the sense data byte. 740230557Sjimharris * @param[in] sense_len This parameter specifies length of the sense data 741230557Sjimharris * to be returned by SATI. 742230557Sjimharris * @param[out] descriptor_len This parameter returns the length of constructed 743230557Sjimharris * descriptor. 744230557Sjimharris * @param[in] information_buff This parameter specifies the address for which 745230557Sjimharris * to set the information buffer. 746230557Sjimharris * 747230557Sjimharris * @return none 748230557Sjimharris */ 749230557Sjimharrisstatic 750230557Sjimharrisvoid sati_scsi_common_descriptors_construct( 751230557Sjimharris void * scsi_io, 752230557Sjimharris U8 * sense_data, 753230557Sjimharris U32 sense_len, 754230557Sjimharris U8 * information_buff) 755230557Sjimharris{ 756230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 757230557Sjimharris U8 offset = 0; 758230557Sjimharris 759230557Sjimharris switch (sati_get_cdb_byte(cdb, 0)) 760230557Sjimharris { 761230557Sjimharris#if !defined(DISABLE_SATI_WRITE_LONG) 762230557Sjimharris case SCSI_WRITE_LONG_10: 763230557Sjimharris case SCSI_WRITE_LONG_16: 764230557Sjimharris sati_scsi_block_descriptor_construct( 765230557Sjimharris sense_data + offset, 766230557Sjimharris sense_len - offset); 767230557Sjimharris 768230557Sjimharris offset += SCSI_BLOCK_DESCRIPTOR_LENGTH; 769230557Sjimharris sati_scsi_information_descriptor_construct( 770230557Sjimharris sense_data + offset, 771230557Sjimharris sense_len - offset, 772230557Sjimharris information_buff); 773230557Sjimharris 774230557Sjimharris offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 775230557Sjimharris break; 776230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_LONG) 777230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 778230557Sjimharris case SCSI_REASSIGN_BLOCKS: 779230557Sjimharris sati_scsi_command_specific_descriptor_construct( 780230557Sjimharris sense_data + offset, 781230557Sjimharris sense_len - offset, 782230557Sjimharris NULL); 783230557Sjimharris 784230557Sjimharris offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH; 785230557Sjimharris sati_scsi_information_descriptor_construct( 786230557Sjimharris sense_data + offset, 787230557Sjimharris sense_len - offset, 788230557Sjimharris information_buff); 789230557Sjimharris 790230557Sjimharris offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 791230557Sjimharris break; 792230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 793230557Sjimharris case SCSI_READ_6: 794230557Sjimharris case SCSI_READ_10: 795230557Sjimharris case SCSI_READ_12: 796230557Sjimharris case SCSI_READ_16: 797230557Sjimharris case SCSI_WRITE_6: 798230557Sjimharris case SCSI_WRITE_10: 799230557Sjimharris case SCSI_WRITE_12: 800230557Sjimharris case SCSI_WRITE_16: 801230557Sjimharris#if !defined(DISABLE_SATI_VERIFY) 802230557Sjimharris case SCSI_VERIFY_10: 803230557Sjimharris case SCSI_VERIFY_12: 804230557Sjimharris case SCSI_VERIFY_16: 805230557Sjimharris#endif // !defined(DISABLE_SATI_VERIFY) 806230557Sjimharris#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ 807230557Sjimharris && !defined(DISABLE_SATI_VERIFY) \ 808230557Sjimharris && !defined(DISABLE_SATI_WRITE) 809230557Sjimharris 810230557Sjimharris case SCSI_WRITE_AND_VERIFY_10: 811230557Sjimharris case SCSI_WRITE_AND_VERIFY_12: 812230557Sjimharris case SCSI_WRITE_AND_VERIFY_16: 813230557Sjimharris#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) 814230557Sjimharris // && !defined(DISABLE_SATI_VERIFY) 815230557Sjimharris // && !defined(DISABLE_SATI_WRITE) 816230557Sjimharris sati_scsi_information_descriptor_construct( 817230557Sjimharris sense_data + offset, 818230557Sjimharris sense_len - offset, 819230557Sjimharris information_buff); 820230557Sjimharris 821230557Sjimharris offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; 822230557Sjimharris break; 823230557Sjimharris } 824230557Sjimharris} 825230557Sjimharris 826230557Sjimharris/** 827230557Sjimharris * @brief This method will construct the descriptor sense data buffer in 828230557Sjimharris * the user's sense data buffer location. Additionally, it will set 829230557Sjimharris * the user's SCSI status. 830230557Sjimharris * 831230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 832230557Sjimharris * for which to construct the sense data. 833230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 834230557Sjimharris * for which to construct the sense data. 835230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 836230557Sjimharris * value for the user's IO request. 837230557Sjimharris * @param[in] sense_key This parameter specifies the sense key to 838230557Sjimharris * be set for the user's IO request. 839230557Sjimharris * @param[in] additional_sense_code This parameter specifies the 840230557Sjimharris * additional sense code (ASC) key to be set for the user's 841230557Sjimharris * IO request. 842230557Sjimharris * @param[in] additional_sense_code_qualifier This parameter specifies 843230557Sjimharris * the additional sense code qualifier (ASCQ) key to be set 844230557Sjimharris * for the user's IO request. 845230557Sjimharris * 846230557Sjimharris * @return none 847230557Sjimharris */ 848230557Sjimharrisvoid sati_scsi_descriptor_sense_data_construct( 849230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 850230557Sjimharris void * scsi_io, 851230557Sjimharris U8 scsi_status, 852230557Sjimharris U8 response_code, 853230557Sjimharris U8 sense_key, 854230557Sjimharris U8 additional_sense_code, 855230557Sjimharris U8 additional_sense_code_qualifier 856230557Sjimharris) 857230557Sjimharris{ 858230557Sjimharris U8 * sense_data; 859230557Sjimharris U32 sense_len; 860230557Sjimharris 861230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 862230557Sjimharris 863230557Sjimharris sati_set_sense_data_byte( 864230557Sjimharris sense_data, 865230557Sjimharris sense_len, 866230557Sjimharris 0, 867230557Sjimharris response_code 868230557Sjimharris ); 869230557Sjimharris 870230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 871230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 872230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 873230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 874230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 875230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 876230557Sjimharris 877230557Sjimharris sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL); 878230557Sjimharris 879230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 880230557Sjimharris} 881230557Sjimharris 882230557Sjimharris/** 883230557Sjimharris * @brief This method will construct the fixed format sense data buffer 884230557Sjimharris * in the user's sense data buffer location. Additionally, it will 885230557Sjimharris * set the user's SCSI status. 886230557Sjimharris * 887230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 888230557Sjimharris * for which to construct the sense data. 889230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 890230557Sjimharris * for which to construct the sense data. 891230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 892230557Sjimharris * value for the user's IO request. 893230557Sjimharris * @param[in] sense_key This parameter specifies the sense key to 894230557Sjimharris * be set for the user's IO request. 895230557Sjimharris * @param[in] additional_sense_code This parameter specifies the 896230557Sjimharris * additional sense code (ASC) key to be set for the user's 897230557Sjimharris * IO request. 898230557Sjimharris * @param[in] additional_sense_code_qualifier This parameter specifies 899230557Sjimharris * the additional sense code qualifier (ASCQ) key to be set 900230557Sjimharris * for the user's IO request. 901230557Sjimharris * 902230557Sjimharris * @return none 903230557Sjimharris */ 904230557Sjimharrisvoid sati_scsi_fixed_sense_data_construct( 905230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 906230557Sjimharris void * scsi_io, 907230557Sjimharris U8 scsi_status, 908230557Sjimharris U8 response_code, 909230557Sjimharris U8 sense_key, 910230557Sjimharris U8 additional_sense_code, 911230557Sjimharris U8 additional_sense_code_qualifier 912230557Sjimharris) 913230557Sjimharris{ 914230557Sjimharris U8 * sense_data; 915230557Sjimharris U32 sense_len; 916230557Sjimharris 917230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 918230557Sjimharris 919230557Sjimharris // Write out the sense data format per SPC-4. 920230557Sjimharris // We utilize the fixed format sense data format. 921230557Sjimharris 922230557Sjimharris sati_set_sense_data_byte( 923230557Sjimharris sense_data, 924230557Sjimharris sense_len, 925230557Sjimharris 0, 926230557Sjimharris response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT 927230557Sjimharris ); 928230557Sjimharris 929230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 930230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 931230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, 0); 932230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 933230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 934230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 935230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 7, 0); 936230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 937230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 938230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 939230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 940230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 941230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 942230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 943230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 15, 0); 944230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 945230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 946230557Sjimharris} 947230557Sjimharris 948230557Sjimharris/** 949230557Sjimharris* @brief This method will construct common sense data that will be identical in 950230557Sjimharris* both read error sense construct functions. 951230557Sjimharris* sati_scsi_read_ncq_error_sense_construct, 952230557Sjimharris* sati_scsi_read_error_sense_construct 953230557Sjimharris* 954230557Sjimharris * @param[in] sense_data This parameter specifies the user SCSI IO request 955230557Sjimharris * for which to set the sense data byte. 956230557Sjimharris* @param[in] sense_len This parameter specifies length of the sense data 957230557Sjimharris* to be returned by SATI. 958230557Sjimharris* @param[in] sense_key This parameter specifies the sense key to 959230557Sjimharris* be set for the user's IO request. 960230557Sjimharris* @param[in] additional_sense_code This parameter specifies the 961230557Sjimharris* additional sense code (ASC) key to be set for the user's 962230557Sjimharris* IO request. 963230557Sjimharris* @param[in] additional_sense_code_qualifier This parameter specifies 964230557Sjimharris* the additional sense code qualifier (ASCQ) key to be set 965230557Sjimharris* for the user's IO request. 966230557Sjimharris* 967230557Sjimharris* @return none 968230557Sjimharris*/ 969230557Sjimharrisstatic 970230557Sjimharrisvoid sati_scsi_common_fixed_sense_construct( 971230557Sjimharris U8 * sense_data, 972230557Sjimharris U32 sense_len, 973230557Sjimharris U8 sense_key, 974230557Sjimharris U8 additional_sense_code, 975230557Sjimharris U8 additional_sense_code_qualifier 976230557Sjimharris) 977230557Sjimharris{ 978230557Sjimharris 979230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, 0); 980230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); 981230557Sjimharris 982230557Sjimharris //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions 983230557Sjimharris 984230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 7, 0); 985230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 8, 0); 986230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 9, 0); 987230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 10, 0); 988230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 11, 0); 989230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); 990230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); 991230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 14, 0); 992230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80); 993230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 16, 0); 994230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 17, 0); 995230557Sjimharris} 996230557Sjimharris 997230557Sjimharris/** 998230557Sjimharris * @brief This method will construct the descriptor sense data buffer in 999230557Sjimharris * the user's sense data buffer location. Additionally, it will set 1000230557Sjimharris * the user's SCSI status. 1001230557Sjimharris * 1002230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 1003230557Sjimharris * for which to construct the sense data. 1004230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 1005230557Sjimharris * for which to construct the sense data. 1006230557Sjimharris * @param[in] scsi_status This parameter specifies the SCSI status 1007230557Sjimharris * value for the user's IO request. 1008230557Sjimharris * @param[in] sense_key This parameter specifies the sense key to 1009230557Sjimharris * be set for the user's IO request. 1010230557Sjimharris * @param[in] additional_sense_code This parameter specifies the 1011230557Sjimharris * additional sense code (ASC) key to be set for the user's 1012230557Sjimharris * IO request. 1013230557Sjimharris * @param[in] additional_sense_code_qualifier This parameter specifies 1014230557Sjimharris * the additional sense code qualifier (ASCQ) key to be set 1015230557Sjimharris * for the user's IO request. 1016230557Sjimharris * 1017230557Sjimharris * @return none 1018230557Sjimharris */ 1019230557Sjimharrisstatic 1020230557Sjimharrisvoid sati_scsi_common_descriptor_sense_construct( 1021230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1022230557Sjimharris void * scsi_io, 1023230557Sjimharris U8 * sense_data, 1024230557Sjimharris U32 sense_len, 1025230557Sjimharris U8 sense_key, 1026230557Sjimharris U8 additional_sense_code, 1027230557Sjimharris U8 additional_sense_code_qualifier, 1028230557Sjimharris U8 * information_buff 1029230557Sjimharris) 1030230557Sjimharris{ 1031230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); 1032230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); 1033230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); 1034230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4, 0); 1035230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 5, 0); 1036230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 6, 0); 1037230557Sjimharris 1038230557Sjimharris sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff); 1039230557Sjimharris 1040230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); 1041230557Sjimharris} 1042230557Sjimharris 1043230557Sjimharris/** 1044230557Sjimharris* @brief This method will construct the sense data buffer in the user's 1045230557Sjimharris* descriptor sense data buffer location. Additionally, it will set 1046230557Sjimharris* the user's SCSI status. This is only used for NCQ uncorrectable 1047230557Sjimharris* read errors 1048230557Sjimharris* 1049230557Sjimharris* @param[in] sequence This parameter specifies the translation sequence 1050230557Sjimharris* for which to construct the sense data. 1051230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request 1052230557Sjimharris* for which to construct the sense data. 1053230557Sjimharris* @param[in] ata_input_data This parameter specifies the user's ATA IO 1054230557Sjimharris* response from a Read Log Ext command. 1055230557Sjimharris* @param[in] scsi_status This parameter specifies the SCSI status 1056230557Sjimharris* value for the user's IO request. 1057230557Sjimharris* @param[in] sense_key This parameter specifies the sense key to 1058230557Sjimharris* be set for the user's IO request. 1059230557Sjimharris* @param[in] additional_sense_code This parameter specifies the 1060230557Sjimharris* additional sense code (ASC) key to be set for the user's 1061230557Sjimharris* IO request. 1062230557Sjimharris* @param[in] additional_sense_code_qualifier This parameter specifies 1063230557Sjimharris* the additional sense code qualifier (ASCQ) key to be set 1064230557Sjimharris* for the user's IO request. 1065230557Sjimharris* 1066230557Sjimharris* @return none 1067230557Sjimharris*/ 1068230557Sjimharrisstatic 1069230557Sjimharrisvoid sati_scsi_read_ncq_error_descriptor_sense_construct( 1070230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1071230557Sjimharris void * scsi_io, 1072230557Sjimharris void * ata_input_data, 1073230557Sjimharris U8 scsi_status, 1074230557Sjimharris U8 response_code, 1075230557Sjimharris U8 sense_key, 1076230557Sjimharris U8 additional_sense_code, 1077230557Sjimharris U8 additional_sense_code_qualifier 1078230557Sjimharris) 1079230557Sjimharris{ 1080230557Sjimharris U8 * sense_data; 1081230557Sjimharris U32 sense_len; 1082230557Sjimharris 1083230557Sjimharris U8 information_buff[8] = {0}; 1084230557Sjimharris 1085230557Sjimharris ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1086230557Sjimharris 1087230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1088230557Sjimharris 1089230557Sjimharris sati_set_sense_data_byte( 1090230557Sjimharris sense_data, 1091230557Sjimharris sense_len, 1092230557Sjimharris 0, 1093230557Sjimharris response_code 1094230557Sjimharris ); 1095230557Sjimharris 1096230557Sjimharris information_buff[2] = ncq_log->lba_47_40; 1097230557Sjimharris information_buff[3] = ncq_log->lba_39_32; 1098230557Sjimharris information_buff[4] = ncq_log->lba_31_24; 1099230557Sjimharris information_buff[5] = ncq_log->lba_23_16; 1100230557Sjimharris information_buff[6] = ncq_log->lba_15_8; 1101230557Sjimharris information_buff[7] = ncq_log->lba_7_0; 1102230557Sjimharris 1103230557Sjimharris sati_scsi_common_descriptor_sense_construct( 1104230557Sjimharris sequence, 1105230557Sjimharris scsi_io, 1106230557Sjimharris sense_data, 1107230557Sjimharris sense_len, 1108230557Sjimharris sense_key, 1109230557Sjimharris additional_sense_code, 1110230557Sjimharris additional_sense_code_qualifier, 1111230557Sjimharris information_buff 1112230557Sjimharris ); 1113230557Sjimharris} 1114230557Sjimharris 1115230557Sjimharris/** 1116230557Sjimharris* @brief This method will construct the sense data buffer in the user's 1117230557Sjimharris* sense data buffer location. Additionally, it will set the user's 1118230557Sjimharris* SCSI status. This is only used for NCQ uncorrectable read errors 1119230557Sjimharris* 1120230557Sjimharris* @param[in] sequence This parameter specifies the translation sequence 1121230557Sjimharris* for which to construct the sense data. 1122230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request 1123230557Sjimharris* for which to construct the sense data. 1124230557Sjimharris* @param[in] ata_input_data This parameter specifies the user's ATA IO 1125230557Sjimharris* response from a Read Log Ext command. 1126230557Sjimharris* @param[in] scsi_status This parameter specifies the SCSI status 1127230557Sjimharris* value for the user's IO request. 1128230557Sjimharris* @param[in] sense_key This parameter specifies the sense key to 1129230557Sjimharris* be set for the user's IO request. 1130230557Sjimharris* @param[in] additional_sense_code This parameter specifies the 1131230557Sjimharris* additional sense code (ASC) key to be set for the user's 1132230557Sjimharris* IO request. 1133230557Sjimharris* @param[in] additional_sense_code_qualifier This parameter specifies 1134230557Sjimharris* the additional sense code qualifier (ASCQ) key to be set 1135230557Sjimharris* for the user's IO request. 1136230557Sjimharris* 1137230557Sjimharris* @return none 1138230557Sjimharris*/ 1139230557Sjimharrisstatic 1140230557Sjimharrisvoid sati_scsi_read_ncq_error_fixed_sense_construct( 1141230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1142230557Sjimharris void * scsi_io, 1143230557Sjimharris void * ata_input_data, 1144230557Sjimharris U8 scsi_status, 1145230557Sjimharris U8 response_code, 1146230557Sjimharris U8 sense_key, 1147230557Sjimharris U8 additional_sense_code, 1148230557Sjimharris U8 additional_sense_code_qualifier 1149230557Sjimharris) 1150230557Sjimharris{ 1151230557Sjimharris U8 * sense_data; 1152230557Sjimharris U32 sense_len; 1153230557Sjimharris U8 valid = TRUE; 1154230557Sjimharris 1155230557Sjimharris ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; 1156230557Sjimharris 1157230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1158230557Sjimharris 1159230557Sjimharris if(ncq_log->lba_39_32 > 0) 1160230557Sjimharris { 1161230557Sjimharris valid = FALSE; 1162230557Sjimharris } 1163230557Sjimharris 1164230557Sjimharris sati_set_sense_data_byte( 1165230557Sjimharris sense_data, 1166230557Sjimharris sense_len, 1167230557Sjimharris 0, 1168230557Sjimharris (valid << 7) | response_code 1169230557Sjimharris ); 1170230557Sjimharris 1171230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24); 1172230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16); 1173230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8); 1174230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0); 1175230557Sjimharris 1176230557Sjimharris sati_scsi_common_fixed_sense_construct( 1177230557Sjimharris sense_data, 1178230557Sjimharris sense_len, 1179230557Sjimharris sense_key, 1180230557Sjimharris additional_sense_code, 1181230557Sjimharris additional_sense_code_qualifier 1182230557Sjimharris ); 1183230557Sjimharris} 1184230557Sjimharris 1185230557Sjimharrisvoid sati_scsi_read_ncq_error_sense_construct( 1186230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1187230557Sjimharris void * scsi_io, 1188230557Sjimharris void * ata_input_data, 1189230557Sjimharris U8 scsi_status, 1190230557Sjimharris U8 sense_key, 1191230557Sjimharris U8 additional_sense_code, 1192230557Sjimharris U8 additional_sense_code_qualifier 1193230557Sjimharris) 1194230557Sjimharris{ 1195230557Sjimharris U8 response_code; 1196230557Sjimharris 1197230557Sjimharris response_code = sati_scsi_get_sense_data_response_code(sequence); 1198230557Sjimharris 1199230557Sjimharris switch (response_code) 1200230557Sjimharris { 1201230557Sjimharris case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1202230557Sjimharris case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1203230557Sjimharris sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1204230557Sjimharris response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1205230557Sjimharris break; 1206230557Sjimharris case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1207230557Sjimharris case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1208230557Sjimharris sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1209230557Sjimharris response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1210230557Sjimharris break; 1211230557Sjimharris } 1212230557Sjimharris 1213230557Sjimharris sequence->is_sense_response_set = TRUE; 1214230557Sjimharris} 1215230557Sjimharris 1216230557Sjimharris/** 1217230557Sjimharris* @brief This method will construct the sense data buffer in the user's 1218230557Sjimharris* sense data buffer location. Additionally, it will set the user's 1219230557Sjimharris* SCSI status. This is used for uncorrectable read errors. 1220230557Sjimharris* 1221230557Sjimharris* @param[in] sequence This parameter specifies the translation sequence 1222230557Sjimharris* for which to construct the sense data. 1223230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request 1224230557Sjimharris* for which to construct the sense data. 1225230557Sjimharris* @param[in] ata_io This parameter is a pointer to the ATA IO data used 1226230557Sjimharris* to get the ATA register fis. 1227230557Sjimharris* @param[in] scsi_status This parameter specifies the SCSI status 1228230557Sjimharris* value for the user's IO request. 1229230557Sjimharris* @param[in] sense_key This parameter specifies the sense key to 1230230557Sjimharris* be set for the user's IO request. 1231230557Sjimharris* @param[in] additional_sense_code This parameter specifies the 1232230557Sjimharris* additional sense code (ASC) key to be set for the user's 1233230557Sjimharris* IO request. 1234230557Sjimharris* @param[in] additional_sense_code_qualifier This parameter specifies 1235230557Sjimharris* the additional sense code qualifier (ASCQ) key to be set 1236230557Sjimharris* for the user's IO request. 1237230557Sjimharris* 1238230557Sjimharris* @return none 1239230557Sjimharris*/ 1240230557Sjimharrisstatic 1241230557Sjimharrisvoid sati_scsi_read_error_descriptor_sense_construct( 1242230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1243230557Sjimharris void * scsi_io, 1244230557Sjimharris void * ata_io, 1245230557Sjimharris U8 scsi_status, 1246230557Sjimharris U8 response_code, 1247230557Sjimharris U8 sense_key, 1248230557Sjimharris U8 additional_sense_code, 1249230557Sjimharris U8 additional_sense_code_qualifier 1250230557Sjimharris) 1251230557Sjimharris{ 1252230557Sjimharris U8 * sense_data; 1253230557Sjimharris U32 sense_len; 1254230557Sjimharris U8 information_buff[8] = {0}; 1255230557Sjimharris 1256230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1257230557Sjimharris 1258230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1259230557Sjimharris 1260230557Sjimharris information_buff[2] = sati_get_ata_lba_high_ext(register_fis); 1261230557Sjimharris information_buff[3] = sati_get_ata_lba_mid_ext(register_fis); 1262230557Sjimharris information_buff[4] = sati_get_ata_lba_low_ext(register_fis); 1263230557Sjimharris information_buff[5] = sati_get_ata_lba_high(register_fis); 1264230557Sjimharris information_buff[6] = sati_get_ata_lba_mid(register_fis); 1265230557Sjimharris information_buff[7] = sati_get_ata_lba_low(register_fis); 1266230557Sjimharris 1267230557Sjimharris sati_set_sense_data_byte( 1268230557Sjimharris sense_data, 1269230557Sjimharris sense_len, 1270230557Sjimharris 0, 1271230557Sjimharris SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE 1272230557Sjimharris ); 1273230557Sjimharris 1274230557Sjimharris sati_scsi_common_descriptor_sense_construct( 1275230557Sjimharris sequence, 1276230557Sjimharris scsi_io, 1277230557Sjimharris sense_data, 1278230557Sjimharris sense_len, 1279230557Sjimharris sense_key, 1280230557Sjimharris additional_sense_code, 1281230557Sjimharris additional_sense_code_qualifier, 1282230557Sjimharris information_buff 1283230557Sjimharris ); 1284230557Sjimharris} 1285230557Sjimharris 1286230557Sjimharris/** 1287230557Sjimharris* @brief This method will construct the sense data buffer in the user's 1288230557Sjimharris* sense data buffer location. Additionally, it will set the user's 1289230557Sjimharris* SCSI status. This is used for uncorrectable read errors. 1290230557Sjimharris* 1291230557Sjimharris* @param[in] sequence This parameter specifies the translation sequence 1292230557Sjimharris* for which to construct the sense data. 1293230557Sjimharris* @param[in,out] scsi_io This parameter specifies the user's IO request 1294230557Sjimharris* for which to construct the sense data. 1295230557Sjimharris* @param[in] ata_io This parameter is a pointer to the ATA IO data used 1296230557Sjimharris* to get the ATA register fis. 1297230557Sjimharris* @param[in] scsi_status This parameter specifies the SCSI status 1298230557Sjimharris* value for the user's IO request. 1299230557Sjimharris* @param[in] sense_key This parameter specifies the sense key to 1300230557Sjimharris* be set for the user's IO request. 1301230557Sjimharris* @param[in] additional_sense_code This parameter specifies the 1302230557Sjimharris* additional sense code (ASC) key to be set for the user's 1303230557Sjimharris* IO request. 1304230557Sjimharris* @param[in] additional_sense_code_qualifier This parameter specifies 1305230557Sjimharris* the additional sense code qualifier (ASCQ) key to be set 1306230557Sjimharris* for the user's IO request. 1307230557Sjimharris* 1308230557Sjimharris* @return none 1309230557Sjimharris*/ 1310230557Sjimharrisstatic 1311230557Sjimharrisvoid sati_scsi_read_error_fixed_sense_construct( 1312230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1313230557Sjimharris void * scsi_io, 1314230557Sjimharris void * ata_io, 1315230557Sjimharris U8 scsi_status, 1316230557Sjimharris U8 response_code, 1317230557Sjimharris U8 sense_key, 1318230557Sjimharris U8 additional_sense_code, 1319230557Sjimharris U8 additional_sense_code_qualifier 1320230557Sjimharris) 1321230557Sjimharris{ 1322230557Sjimharris U8 * sense_data; 1323230557Sjimharris U32 sense_len; 1324230557Sjimharris U8 valid = TRUE; 1325230557Sjimharris 1326230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1327230557Sjimharris 1328230557Sjimharris sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); 1329230557Sjimharris 1330230557Sjimharris if(sati_get_ata_lba_mid_ext(register_fis) > 0) 1331230557Sjimharris { 1332230557Sjimharris valid = FALSE; 1333230557Sjimharris } 1334230557Sjimharris 1335230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis)); 1336230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis)); 1337230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis)); 1338230557Sjimharris sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis)); 1339230557Sjimharris 1340230557Sjimharris 1341230557Sjimharris sati_set_sense_data_byte( 1342230557Sjimharris sense_data, 1343230557Sjimharris sense_len, 1344230557Sjimharris 0, 1345230557Sjimharris (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE 1346230557Sjimharris ); 1347230557Sjimharris 1348230557Sjimharris sati_scsi_common_fixed_sense_construct( 1349230557Sjimharris sense_data, 1350230557Sjimharris sense_len, 1351230557Sjimharris sense_key, 1352230557Sjimharris additional_sense_code, 1353230557Sjimharris additional_sense_code_qualifier 1354230557Sjimharris ); 1355230557Sjimharris} 1356230557Sjimharris 1357230557Sjimharrisvoid sati_scsi_read_error_sense_construct( 1358230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1359230557Sjimharris void * scsi_io, 1360230557Sjimharris void * ata_input_data, 1361230557Sjimharris U8 scsi_status, 1362230557Sjimharris U8 sense_key, 1363230557Sjimharris U8 additional_sense_code, 1364230557Sjimharris U8 additional_sense_code_qualifier 1365230557Sjimharris) 1366230557Sjimharris{ 1367230557Sjimharris U8 response_code; 1368230557Sjimharris 1369230557Sjimharris response_code = sati_scsi_get_sense_data_response_code(sequence); 1370230557Sjimharris 1371230557Sjimharris switch (response_code) 1372230557Sjimharris { 1373230557Sjimharris case SCSI_FIXED_CURRENT_RESPONSE_CODE: 1374230557Sjimharris case SCSI_FIXED_DEFERRED_RESPONSE_CODE: 1375230557Sjimharris sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1376230557Sjimharris response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1377230557Sjimharris break; 1378230557Sjimharris case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: 1379230557Sjimharris case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: 1380230557Sjimharris sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, 1381230557Sjimharris response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); 1382230557Sjimharris break; 1383230557Sjimharris } 1384230557Sjimharris 1385230557Sjimharris sequence->is_sense_response_set = TRUE; 1386230557Sjimharris} 1387230557Sjimharris 1388230557Sjimharris/* 1389230557Sjimharris * @brief This method builds the scsi response data for a sata task management 1390230557Sjimharris * request. 1391230557Sjimharris * 1392230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 1393230557Sjimharris * for which to construct the sense data. 1394230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 1395230557Sjimharris * for which to construct the sense data. 1396230557Sjimharris * @param[in] response_data The response status for the task management 1397230557Sjimharris * request. 1398230557Sjimharris */ 1399230557Sjimharrisvoid sati_scsi_response_data_construct( 1400230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1401230557Sjimharris void * scsi_io, 1402230557Sjimharris U8 response_data 1403230557Sjimharris) 1404230557Sjimharris{ 1405230557Sjimharris#ifdef SATI_TRANSPORT_SUPPORTS_SAS 1406230557Sjimharris SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) 1407230557Sjimharris sati_cb_get_response_iu_address(scsi_io); 1408230557Sjimharris rsp_iu->data_present = 0x01; 1409230557Sjimharris rsp_iu->response_data_length[3] = sizeof(U32); 1410230557Sjimharris rsp_iu->status = 0; 1411230557Sjimharris ((U8 *)rsp_iu->data)[3] = response_data; 1412230557Sjimharris#else 1413230557Sjimharris#endif // SATI_TRANSPORT_SUPPORTS_SAS 1414230557Sjimharris} 1415230557Sjimharris 1416230557Sjimharris/** 1417230557Sjimharris * @brief This method checks to make sure that the translation isn't 1418230557Sjimharris * exceeding the allocation length specified in the CDB prior 1419230557Sjimharris * to retrieving the payload data byte from the user's buffer. 1420230557Sjimharris * 1421230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 1422230557Sjimharris * for which to set the user payload data byte. 1423230557Sjimharris * @param[in] byte_offset This parameter specifies the offset into 1424230557Sjimharris * the user's payload buffer at which to write the supplied 1425230557Sjimharris * value. 1426230557Sjimharris * @param[in] value This parameter specifies the memory location into 1427230557Sjimharris * which to read the value from the user's payload buffer. 1428230557Sjimharris * 1429230557Sjimharris * @return none 1430230557Sjimharris */ 1431230557Sjimharrisvoid sati_get_data_byte( 1432230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1433230557Sjimharris void * scsi_io, 1434230557Sjimharris U32 byte_offset, 1435230557Sjimharris U8 * value 1436230557Sjimharris) 1437230557Sjimharris{ 1438230557Sjimharris if (byte_offset < sequence->allocation_length) 1439230557Sjimharris sati_cb_get_data_byte(scsi_io, byte_offset, value); 1440230557Sjimharris} 1441230557Sjimharris 1442230557Sjimharris/** 1443230557Sjimharris * @brief This method checks to make sure that the translation isn't 1444230557Sjimharris * exceeding the allocation length specified in the CDB while 1445230557Sjimharris * translating payload data into the user's buffer. 1446230557Sjimharris * 1447230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 1448230557Sjimharris * for which to set the user payload data byte. 1449230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 1450230557Sjimharris * for which to set the user payload data byte. 1451230557Sjimharris * @param[in] byte_offset This parameter specifies the offset into 1452230557Sjimharris * the user's payload buffer at which to write the supplied 1453230557Sjimharris * value. 1454230557Sjimharris * @param[in] value This parameter specifies the new value to be 1455230557Sjimharris * written out into the user's payload buffer. 1456230557Sjimharris * 1457230557Sjimharris * @return none 1458230557Sjimharris */ 1459230557Sjimharrisvoid sati_set_data_byte( 1460230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1461230557Sjimharris void * scsi_io, 1462230557Sjimharris U32 byte_offset, 1463230557Sjimharris U8 value 1464230557Sjimharris) 1465230557Sjimharris{ 1466230557Sjimharris if (byte_offset < sequence->allocation_length) 1467230557Sjimharris { 1468230557Sjimharris sequence->number_data_bytes_set++; 1469230557Sjimharris sati_cb_set_data_byte(scsi_io, byte_offset, value); 1470230557Sjimharris } 1471230557Sjimharris} 1472230557Sjimharris 1473230557Sjimharris/** 1474230557Sjimharris * @brief This method checks to make sure that the translation isn't 1475230557Sjimharris * exceeding the allocation length specified in the CDB while 1476230557Sjimharris * translating payload data into the user's buffer. 1477230557Sjimharris * 1478230557Sjimharris * @param[in] sequence This parameter specifies the translation sequence 1479230557Sjimharris * for which to set the user payload data dword. 1480230557Sjimharris * @param[in,out] scsi_io This parameter specifies the user's IO request 1481230557Sjimharris * for which to set the user payload data dword. 1482230557Sjimharris * @param[in] byte_offset This parameter specifies the offset into 1483230557Sjimharris * the user's payload buffer at which to write the supplied 1484230557Sjimharris * value. 1485230557Sjimharris * @param[in] value This parameter specifies the new value to be 1486230557Sjimharris * written out into the user's payload buffer. 1487230557Sjimharris * 1488230557Sjimharris * @return none 1489230557Sjimharris */ 1490230557Sjimharrisvoid sati_set_data_dword( 1491230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1492230557Sjimharris void * scsi_io, 1493230557Sjimharris U32 byte_offset, 1494230557Sjimharris U32 value 1495230557Sjimharris) 1496230557Sjimharris{ 1497230557Sjimharris /// @todo Check to ensure that the bytes appear correctly (SAS Address). 1498230557Sjimharris 1499230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF); 1500230557Sjimharris byte_offset++; 1501230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF); 1502230557Sjimharris byte_offset++; 1503230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF); 1504230557Sjimharris byte_offset++; 1505230557Sjimharris sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF); 1506230557Sjimharris} 1507230557Sjimharris 1508230557Sjimharris/** 1509230557Sjimharris * @brief This method will construct the ATA flush cache command. 1510230557Sjimharris * 1511230557Sjimharris * @pre It is expected that the user has properly set the current contents 1512230557Sjimharris * of the register FIS to 0. 1513230557Sjimharris * 1514230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1515230557Sjimharris * for which to build the FLUSH CACHE command. 1516230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1517230557Sjimharris * for which the command is being constructed. 1518230557Sjimharris * 1519230557Sjimharris * @return none. 1520230557Sjimharris */ 1521230557Sjimharrisvoid sati_ata_flush_cache_construct( 1522230557Sjimharris void * ata_io, 1523230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1524230557Sjimharris) 1525230557Sjimharris{ 1526230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1527230557Sjimharris 1528230557Sjimharris sati_set_ata_command(register_fis, ATA_FLUSH_CACHE); 1529230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1530230557Sjimharris} 1531230557Sjimharris 1532230557Sjimharris/** 1533230557Sjimharris * @brief This method will construct the ATA standby immediate command. 1534230557Sjimharris * 1535230557Sjimharris * @pre It is expected that the user has properly set the current contents 1536230557Sjimharris * of the register FIS to 0. 1537230557Sjimharris * 1538230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1539230557Sjimharris * for which to build the STANDBY IMMEDIATE command. 1540230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1541230557Sjimharris * for which the command is being constructed. 1542230557Sjimharris * 1543230557Sjimharris * @param[in] count This parameter specifies the time period programmed 1544230557Sjimharris * into the Standby Timer. See ATA8 spec for more details 1545230557Sjimharris * @return none. 1546230557Sjimharris */ 1547230557Sjimharrisvoid sati_ata_standby_construct( 1548230557Sjimharris void * ata_io, 1549230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1550230557Sjimharris U16 count 1551230557Sjimharris) 1552230557Sjimharris{ 1553230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1554230557Sjimharris 1555230557Sjimharris sati_set_ata_command(register_fis, ATA_STANDBY); 1556230557Sjimharris sati_set_ata_sector_count(register_fis, count); 1557230557Sjimharris 1558230557Sjimharris sequence->device->ata_standby_timer = (U8) count; 1559230557Sjimharris 1560230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1561230557Sjimharris} 1562230557Sjimharris 1563230557Sjimharris/** 1564230557Sjimharris * @brief This method will construct the ATA standby immediate command. 1565230557Sjimharris * 1566230557Sjimharris * @pre It is expected that the user has properly set the current contents 1567230557Sjimharris * of the register FIS to 0. 1568230557Sjimharris * 1569230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1570230557Sjimharris * for which to build the STANDBY IMMEDIATE command. 1571230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1572230557Sjimharris * for which the command is being constructed. 1573230557Sjimharris * 1574230557Sjimharris * @return none. 1575230557Sjimharris */ 1576230557Sjimharrisvoid sati_ata_standby_immediate_construct( 1577230557Sjimharris void * ata_io, 1578230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1579230557Sjimharris) 1580230557Sjimharris{ 1581230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1582230557Sjimharris 1583230557Sjimharris sati_set_ata_command(register_fis, ATA_STANDBY_IMMED); 1584230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1585230557Sjimharris} 1586230557Sjimharris 1587230557Sjimharris/** 1588230557Sjimharris * @brief This method will construct the ATA idle immediate command. 1589230557Sjimharris * 1590230557Sjimharris * @pre It is expected that the user has properly set the current contents 1591230557Sjimharris * of the register FIS to 0. 1592230557Sjimharris * 1593230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1594230557Sjimharris * for which to build the IDLE IMMEDIATE command. 1595230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1596230557Sjimharris * for which the command is being constructed. 1597230557Sjimharris * 1598230557Sjimharris * @return none. 1599230557Sjimharris */ 1600230557Sjimharrisvoid sati_ata_idle_immediate_construct( 1601230557Sjimharris void * ata_io, 1602230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1603230557Sjimharris) 1604230557Sjimharris{ 1605230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1606230557Sjimharris 1607230557Sjimharris sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1608230557Sjimharris sati_set_ata_features(register_fis, 0x00); 1609230557Sjimharris sati_set_ata_sector_count(register_fis, 0x00); 1610230557Sjimharris sati_set_ata_lba_high(register_fis, 0x00); 1611230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x00); 1612230557Sjimharris sati_set_ata_lba_low(register_fis, 0x00); 1613230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1614230557Sjimharris} 1615230557Sjimharris 1616230557Sjimharris/** 1617230557Sjimharris * @brief This method will construct the ATA idle immediate command 1618230557Sjimharris for Unload Features. 1619230557Sjimharris * 1620230557Sjimharris * @pre It is expected that the user has properly set the current contents 1621230557Sjimharris * of the register FIS to 0. 1622230557Sjimharris * 1623230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1624230557Sjimharris * for which to build the IDLE IMMEDIATE command. 1625230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1626230557Sjimharris * for which the command is being constructed. 1627230557Sjimharris * 1628230557Sjimharris * @return none. 1629230557Sjimharris */ 1630230557Sjimharrisvoid sati_ata_idle_immediate_unload_construct( 1631230557Sjimharris void * ata_io, 1632230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1633230557Sjimharris) 1634230557Sjimharris{ 1635230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1636230557Sjimharris 1637230557Sjimharris sati_set_ata_command(register_fis, ATA_IDLE_IMMED); 1638230557Sjimharris sati_set_ata_features(register_fis, 0x44); 1639230557Sjimharris sati_set_ata_sector_count(register_fis, 0x00); 1640230557Sjimharris sati_set_ata_lba_high(register_fis, 0x55); 1641230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x4E); 1642230557Sjimharris sati_set_ata_lba_low(register_fis, 0x4C); 1643230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1644230557Sjimharris} 1645230557Sjimharris 1646230557Sjimharris/** 1647230557Sjimharris * @brief This method will construct the ATA IDLE command.\ 1648230557Sjimharris * 1649230557Sjimharris * @pre It is expected that the user has properly set the current contents 1650230557Sjimharris * of the register FIS to 0. 1651230557Sjimharris * 1652230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1653230557Sjimharris * for which to build the ATA IDLE command. 1654230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1655230557Sjimharris * for which the command is being constructed. 1656230557Sjimharris * 1657230557Sjimharris * @return none. 1658230557Sjimharris */ 1659230557Sjimharrisvoid sati_ata_idle_construct( 1660230557Sjimharris void * ata_io, 1661230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1662230557Sjimharris) 1663230557Sjimharris{ 1664230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1665230557Sjimharris 1666230557Sjimharris sati_set_ata_command(register_fis, ATA_IDLE); 1667230557Sjimharris sati_set_ata_features(register_fis, 0x00); 1668230557Sjimharris sati_set_ata_sector_count(register_fis, 0x00); 1669230557Sjimharris 1670230557Sjimharris sequence->device->ata_standby_timer = 0x00; 1671230557Sjimharris 1672230557Sjimharris sati_set_ata_lba_high(register_fis, 0x00); 1673230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x00); 1674230557Sjimharris sati_set_ata_lba_low(register_fis, 0x00); 1675230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1676230557Sjimharris} 1677230557Sjimharris 1678230557Sjimharris/** 1679230557Sjimharris * @brief This method will construct the ATA MEDIA EJECT command. 1680230557Sjimharris * 1681230557Sjimharris * @pre It is expected that the user has properly set the current contents 1682230557Sjimharris * of the register FIS to 0. 1683230557Sjimharris * 1684230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1685230557Sjimharris * for which to build the MEDIA EJCT command. 1686230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1687230557Sjimharris * for which the command is being constructed. 1688230557Sjimharris * 1689230557Sjimharris * @return none. 1690230557Sjimharris */ 1691230557Sjimharrisvoid sati_ata_media_eject_construct( 1692230557Sjimharris void * ata_io, 1693230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1694230557Sjimharris) 1695230557Sjimharris{ 1696230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1697230557Sjimharris 1698230557Sjimharris sati_set_ata_command(register_fis, ATA_MEDIA_EJECT); 1699230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1700230557Sjimharris} 1701230557Sjimharris 1702230557Sjimharris 1703230557Sjimharris/** 1704230557Sjimharris * @brief This method will construct the ATA read verify sector(s) command. 1705230557Sjimharris * 1706230557Sjimharris * @pre It is expected that the user has properly set the current contents 1707230557Sjimharris * of the register FIS to 0. 1708230557Sjimharris * 1709230557Sjimharris * @param[out] ata_io This parameter specifies the ATA IO request structure 1710230557Sjimharris * for which to build the ATA READ VERIFY SECTOR(S) command. 1711230557Sjimharris * @param[in] sequence This parameter specifies the translator sequence 1712230557Sjimharris * for which the command is being constructed. 1713230557Sjimharris * 1714230557Sjimharris * @return none. 1715230557Sjimharris */ 1716230557Sjimharrisvoid sati_ata_read_verify_sectors_construct( 1717230557Sjimharris void * ata_io, 1718230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1719230557Sjimharris) 1720230557Sjimharris{ 1721230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1722230557Sjimharris 1723230557Sjimharris sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); 1724230557Sjimharris 1725230557Sjimharris //According to SAT-2 (v7) 9.11.3 1726230557Sjimharris sati_set_ata_sector_count(register_fis, 1); 1727230557Sjimharris 1728230557Sjimharris //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the 1729230557Sjimharris //maximum LBA supported by the ATA device in its current configuration. 1730230557Sjimharris //From the unit test, it seems we have to set LBA to a non-zero value. 1731230557Sjimharris sati_set_ata_lba_low(register_fis, 1); 1732230557Sjimharris 1733230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1734230557Sjimharris} 1735230557Sjimharris 1736230557Sjimharris/** 1737230557Sjimharris * @brief This method will construct a ATA SMART Return Status command so the 1738230557Sjimharris * status of the ATA device can be returned. The status of the SMART 1739230557Sjimharris * threshold will be returned by this command. 1740230557Sjimharris * 1741230557Sjimharris * @return N/A 1742230557Sjimharris * 1743230557Sjimharris */ 1744230557Sjimharrisvoid sati_ata_smart_return_status_construct( 1745230557Sjimharris void * ata_io, 1746230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1747230557Sjimharris U8 feature_value 1748230557Sjimharris) 1749230557Sjimharris{ 1750230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1751230557Sjimharris 1752230557Sjimharris sati_set_ata_command(register_fis, ATA_SMART); 1753230557Sjimharris 1754230557Sjimharris sati_set_ata_features(register_fis, feature_value); 1755230557Sjimharris 1756230557Sjimharris sati_set_ata_lba_high(register_fis, 0xC2); 1757230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x4F); 1758230557Sjimharris 1759230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1760230557Sjimharris} 1761230557Sjimharris 1762230557Sjimharris/** 1763230557Sjimharris * @brief This method will construct a ATA SMART Return Status command so the 1764230557Sjimharris * status of the ATA device can be returned. The status of the SMART 1765230557Sjimharris * threshold will be returned by this command. 1766230557Sjimharris * 1767230557Sjimharris * @return N/A 1768230557Sjimharris * 1769230557Sjimharris */ 1770230557Sjimharrisvoid sati_ata_smart_read_log_construct( 1771230557Sjimharris void * ata_io, 1772230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1773230557Sjimharris U8 log_address, 1774230557Sjimharris U32 transfer_length 1775230557Sjimharris) 1776230557Sjimharris{ 1777230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1778230557Sjimharris 1779230557Sjimharris sati_set_ata_command(register_fis, ATA_SMART); 1780230557Sjimharris sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG); 1781230557Sjimharris 1782230557Sjimharris sati_set_ata_lba_high(register_fis, 0xC2); 1783230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x4F); 1784230557Sjimharris sati_set_ata_lba_low(register_fis, log_address); 1785230557Sjimharris 1786230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_IN; 1787230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1788230557Sjimharris sequence->ata_transfer_length = transfer_length; 1789230557Sjimharris} 1790230557Sjimharris 1791230557Sjimharris/** 1792230557Sjimharris * @brief This method will construct a Write Uncorrectable ATA command that 1793230557Sjimharris * will write one sector with a psuedo or flagged error. The type of 1794230557Sjimharris * error is specified by the feature value. 1795230557Sjimharris * 1796230557Sjimharris * @return N/A 1797230557Sjimharris * 1798230557Sjimharris */ 1799230557Sjimharrisvoid sati_ata_write_uncorrectable_construct( 1800230557Sjimharris void * ata_io, 1801230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1802230557Sjimharris U8 feature_value 1803230557Sjimharris) 1804230557Sjimharris{ 1805230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1806230557Sjimharris 1807230557Sjimharris sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE); 1808230557Sjimharris sati_set_ata_features(register_fis, feature_value); 1809230557Sjimharris sati_set_ata_sector_count(register_fis, 0x0001); 1810230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1811230557Sjimharris} 1812230557Sjimharris 1813230557Sjimharris/** 1814230557Sjimharris * @brief This method will construct a Mode Select ATA SET FEATURES command 1815230557Sjimharris * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead 1816230557Sjimharris * 1817230557Sjimharris * @return N/A 1818230557Sjimharris * 1819230557Sjimharris */ 1820230557Sjimharrisvoid sati_ata_set_features_construct( 1821230557Sjimharris void * ata_io, 1822230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1823230557Sjimharris U8 feature 1824230557Sjimharris) 1825230557Sjimharris{ 1826230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1827230557Sjimharris 1828230557Sjimharris sati_set_ata_command(register_fis, ATA_SET_FEATURES); 1829230557Sjimharris sati_set_ata_features(register_fis, feature); 1830230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 1831230557Sjimharris} 1832230557Sjimharris 1833230557Sjimharris 1834230557Sjimharris 1835230557Sjimharris/** 1836230557Sjimharris * @brief This method will construct a Read Log ext ATA command that 1837230557Sjimharris * will request a log page based on the log_address. 1838230557Sjimharris * 1839230557Sjimharris * @param[in] log_address This parameter specifies the log page 1840230557Sjimharris * to be returned from Read Log Ext. 1841230557Sjimharris * 1842230557Sjimharris * @param[in] transfer_length This parameter specifies the size of the 1843230557Sjimharris * log page response returned by Read Log Ext. 1844230557Sjimharris * 1845230557Sjimharris * @return N/A 1846230557Sjimharris * 1847230557Sjimharris */ 1848230557Sjimharrisvoid sati_ata_read_log_ext_construct( 1849230557Sjimharris void * ata_io, 1850230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1851230557Sjimharris U8 log_address, 1852230557Sjimharris U32 transfer_length 1853230557Sjimharris) 1854230557Sjimharris{ 1855230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1856230557Sjimharris 1857230557Sjimharris sati_set_ata_command(register_fis, ATA_READ_LOG_EXT); 1858230557Sjimharris 1859230557Sjimharris sati_set_ata_lba_low(register_fis, log_address); 1860230557Sjimharris sati_set_ata_lba_mid(register_fis, 0x00); 1861230557Sjimharris sati_set_ata_lba_mid_exp(register_fis, 0x00); 1862230557Sjimharris 1863230557Sjimharris sati_set_ata_sector_count(register_fis, 0x01); 1864230557Sjimharris 1865230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_IN; 1866230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1867230557Sjimharris sequence->ata_transfer_length = transfer_length; 1868230557Sjimharris 1869230557Sjimharris} 1870230557Sjimharris 1871230557Sjimharris/** 1872230557Sjimharris* @brief This method will check if the ATA device is in the stopped power 1873230557Sjimharris* state. This is used for all medium access commands for SAT 1874230557Sjimharris* compliance. See SAT2r07 section 9.11.1 1875230557Sjimharris* 1876230557Sjimharris* @param[in] sequence - SATI sequence data with the device state. 1877230557Sjimharris* 1878230557Sjimharris* @return TRUE If device is stopped 1879230557Sjimharris* 1880230557Sjimharris*/ 1881230557SjimharrisBOOL sati_device_state_stopped( 1882230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1883230557Sjimharris void * scsi_io 1884230557Sjimharris) 1885230557Sjimharris{ 1886230557Sjimharris if(sequence->device->state == SATI_DEVICE_STATE_STOPPED) 1887230557Sjimharris { 1888230557Sjimharris sati_scsi_sense_data_construct( 1889230557Sjimharris sequence, 1890230557Sjimharris scsi_io, 1891230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 1892230557Sjimharris SCSI_SENSE_NOT_READY , 1893230557Sjimharris SCSI_ASC_INITIALIZING_COMMAND_REQUIRED, 1894230557Sjimharris SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 1895230557Sjimharris ); 1896230557Sjimharris return TRUE; 1897230557Sjimharris } 1898230557Sjimharris return FALSE; 1899230557Sjimharris} 1900230557Sjimharris 1901230557Sjimharris/** 1902230557Sjimharris* @brief This method will construct a ATA Read Buffer command that 1903230557Sjimharris* will request PIO in data containing the target device's buffer. 1904230557Sjimharris* 1905230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure 1906230557Sjimharris* for which to build the ATA READ VERIFY SECTOR(S) command. 1907230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 1908230557Sjimharris* for which the command is being constructed. 1909230557Sjimharris* @return N/A 1910230557Sjimharris* 1911230557Sjimharris*/ 1912230557Sjimharrisvoid sati_ata_read_buffer_construct( 1913230557Sjimharris void * ata_io, 1914230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1915230557Sjimharris) 1916230557Sjimharris{ 1917230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1918230557Sjimharris 1919230557Sjimharris sati_set_ata_command(register_fis, ATA_READ_BUFFER); 1920230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_IN; 1921230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; 1922230557Sjimharris sequence->ata_transfer_length = 512; 1923230557Sjimharris} 1924230557Sjimharris 1925230557Sjimharris 1926230557Sjimharris/** 1927230557Sjimharris* @brief This method will construct a ATA Write Buffer command that 1928230557Sjimharris* will send PIO out data to the target device's buffer. 1929230557Sjimharris* 1930230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure 1931230557Sjimharris* for which to build the ATA READ VERIFY SECTOR(S) command. 1932230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 1933230557Sjimharris* for which the command is being constructed. 1934230557Sjimharris* @return N/A 1935230557Sjimharris* 1936230557Sjimharris*/ 1937230557Sjimharrisvoid sati_ata_write_buffer_construct( 1938230557Sjimharris void * ata_io, 1939230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence 1940230557Sjimharris) 1941230557Sjimharris{ 1942230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1943230557Sjimharris 1944230557Sjimharris sati_set_ata_command(register_fis, ATA_WRITE_BUFFER); 1945230557Sjimharris 1946230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_OUT; 1947230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 1948230557Sjimharris sequence->ata_transfer_length = 512; 1949230557Sjimharris} 1950230557Sjimharris 1951230557Sjimharris 1952230557Sjimharris/** 1953230557Sjimharris* @brief This method will construct a ATA Download Microcode command that 1954230557Sjimharris* will send PIO out data containing new firmware for the target drive. 1955230557Sjimharris* 1956230557Sjimharris* @param[out] ata_io This parameter specifies the ATA IO request structure 1957230557Sjimharris* for which to build the ATA READ VERIFY SECTOR(S) command. 1958230557Sjimharris* @param[in] sequence This parameter specifies the translator sequence 1959230557Sjimharris* for which the command is being constructed. 1960230557Sjimharris* @param[in] mode This parameter specifies the download microcode sub-command 1961230557Sjimharris* code. 1962230557Sjimharris* @param[in] allocation_length This parameter specifies the number of bytes 1963230557Sjimharris* being sent to the target device. 1964230557Sjimharris* @param[in] buffer_offset This parameter specifies the buffer offset for the 1965230557Sjimharris* data sent to the target device. 1966230557Sjimharris* 1967230557Sjimharris* @return N/A 1968230557Sjimharris* 1969230557Sjimharris*/ 1970230557Sjimharrisvoid sati_ata_download_microcode_construct( 1971230557Sjimharris void * ata_io, 1972230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1973230557Sjimharris U8 mode, 1974230557Sjimharris U32 allocation_length, 1975230557Sjimharris U32 buffer_offset 1976230557Sjimharris) 1977230557Sjimharris{ 1978230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 1979240514Sjimharris U32 allocation_blocks = allocation_length >> 9; 1980240514Sjimharris U32 buffer_blkoffset = buffer_offset >> 9; 1981230557Sjimharris 1982230557Sjimharris sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE); 1983230557Sjimharris sati_set_ata_features(register_fis, mode); 1984230557Sjimharris 1985230557Sjimharris if(mode == ATA_MICROCODE_DOWNLOAD_SAVE) 1986230557Sjimharris { 1987230557Sjimharris sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9)); 1988230557Sjimharris sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17)); 1989230557Sjimharris } 1990230557Sjimharris else //mode == 0x03 1991230557Sjimharris { 1992240514Sjimharris sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff)); 1993240514Sjimharris sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff)); 1994240514Sjimharris sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff)); 1995240514Sjimharris sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff)); 1996230557Sjimharris } 1997230557Sjimharris 1998230557Sjimharris if((allocation_length == 0) && (buffer_offset == 0)) 1999230557Sjimharris { 2000230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 2001230557Sjimharris } 2002230557Sjimharris else 2003230557Sjimharris { 2004230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_OUT; 2005230557Sjimharris sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; 2006230557Sjimharris sequence->ata_transfer_length = allocation_length; 2007230557Sjimharris } 2008230557Sjimharris} 2009