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$"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * @brief This file contains the method implementations required to 59230557Sjimharris * translate the SCSI mode select (6 and 10-byte) commands with 5 60230557Sjimharris * supported mode parameter pages (0x01, 0x02, 0x08, 0x0A, 0x1C). 61230557Sjimharris */ 62230557Sjimharris 63230557Sjimharris#if !defined(DISABLE_SATI_MODE_SELECT) 64230557Sjimharris 65230557Sjimharris#include <dev/isci/scil/sati_mode_select.h> 66230557Sjimharris#include <dev/isci/scil/sati_mode_pages.h> 67230557Sjimharris#include <dev/isci/scil/sati_callbacks.h> 68230557Sjimharris#include <dev/isci/scil/sci_object.h> 69230557Sjimharris#include <dev/isci/scil/sati_translator_sequence.h> 70230557Sjimharris#include <dev/isci/scil/sati_util.h> 71230557Sjimharris 72230557Sjimharris//****************************************************************************** 73230557Sjimharris//* P R I V A T E M E T H O D S 74230557Sjimharris//****************************************************************************** 75230557Sjimharris 76230557Sjimharris/** 77230557Sjimharris * @brief This method will get medium type parameter field per CDB size. 78230557Sjimharris * 79230557Sjimharris * @param[in] scsi_io This parameter specifies the user's SCSI IO object 80230557Sjimharris * for which to calculate the mode page header. 81230557Sjimharris * @param[in] cdb_size This parameter specifies the number of bytes 82230557Sjimharris * associated with the CDB for which to calculate the header. 83230557Sjimharris * 84230557Sjimharris * @return This method returns the medium type for the mode page header. 85230557Sjimharris */ 86230557Sjimharrisstatic 87230557SjimharrisU8 sati_mode_select_get_medium_type( 88230557Sjimharris U8 * mode_parameters, 89230557Sjimharris U32 cdb_size 90230557Sjimharris) 91230557Sjimharris{ 92230557Sjimharris U8 medium_type =0xFF; 93230557Sjimharris SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6; 94230557Sjimharris SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10; 95230557Sjimharris 96230557Sjimharris if(cdb_size == 6) 97230557Sjimharris { 98230557Sjimharris mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters; 99230557Sjimharris medium_type = mode_parameters_6->medium_type; 100230557Sjimharris } 101230557Sjimharris else if(cdb_size == 10) 102230557Sjimharris { 103230557Sjimharris mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters; 104230557Sjimharris medium_type = mode_parameters_10->medium_type; 105230557Sjimharris } 106230557Sjimharris 107230557Sjimharris return medium_type; 108230557Sjimharris} 109230557Sjimharris 110230557Sjimharris/** 111230557Sjimharris * @brief This method will retrieve Block Descriptor Length. 112230557Sjimharris * 113230557Sjimharris * @param[in] mode_parameters This parameter contains the address to the mode parameters. 114230557Sjimharris * @param[in] cdb_size This parameter specifies the number of bytes 115230557Sjimharris * associated with the CDB for which to process the block descriptor. 116230557Sjimharris * 117230557Sjimharris * @return This method returns the size, in bytes, for the mode parameter block descriptor. 118230557Sjimharris */ 119230557Sjimharrisstatic 120230557SjimharrisU32 sati_mode_select_get_mode_block_descriptor_length( 121230557Sjimharris U8 * mode_parameters, 122230557Sjimharris U32 cdb_size 123230557Sjimharris) 124230557Sjimharris{ 125230557Sjimharris U32 mode_block_descriptor_length = 0; 126230557Sjimharris SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6; 127230557Sjimharris SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10; 128230557Sjimharris 129230557Sjimharris if(cdb_size == 6) 130230557Sjimharris { 131230557Sjimharris mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters; 132230557Sjimharris mode_block_descriptor_length = mode_parameters_6->block_descriptor_length; 133230557Sjimharris } 134230557Sjimharris else if(cdb_size == 10) 135230557Sjimharris { 136230557Sjimharris mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters; 137230557Sjimharris //Long LBA bit is the bit0 of the byte 138230557Sjimharris //Spec says another way to get the block descriptor length to multiply the block number 139230557Sjimharris // with block length (8 or 16), but we can get it directly. 140230557Sjimharris mode_block_descriptor_length =(((U16)mode_parameters_10->block_descriptor_length[0]) << 8) + 141230557Sjimharris mode_parameters_10->block_descriptor_length[1]; 142230557Sjimharris 143230557Sjimharris } 144230557Sjimharris 145230557Sjimharris return mode_block_descriptor_length; 146230557Sjimharris 147230557Sjimharris} 148230557Sjimharris 149230557Sjimharris/** 150230557Sjimharris * @brief This method will find the starting byte location for a page. 151230557Sjimharris * 152230557Sjimharris * @param[in] block_descriptor_length This parameter passes in the length of 153230557Sjimharris * block descriptor. 154230557Sjimharris * @param[in] cdb_size This parameter specifies the number of bytes 155230557Sjimharris * associated with the CDB for which to calculate the header. 156230557Sjimharris * 157230557Sjimharris * @return This method returns the offset, for the mode page. 158230557Sjimharris */ 159230557Sjimharrisstatic 160230557SjimharrisU32 sati_mode_select_get_mode_page_offset( 161230557Sjimharris U32 block_descriptor_length, 162230557Sjimharris U32 cdb_size 163230557Sjimharris ) 164230557Sjimharris{ 165230557Sjimharris U32 mode_page_offset; 166230557Sjimharris 167230557Sjimharris if(cdb_size == 6) 168230557Sjimharris { 169230557Sjimharris mode_page_offset = sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T) + block_descriptor_length; 170230557Sjimharris } 171230557Sjimharris else if(cdb_size == 10) 172230557Sjimharris { 173230557Sjimharris mode_page_offset = sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T) + block_descriptor_length; 174230557Sjimharris } 175230557Sjimharris else 176230557Sjimharris { 177230557Sjimharris mode_page_offset = 0; 178230557Sjimharris } 179230557Sjimharris 180230557Sjimharris return mode_page_offset; 181230557Sjimharris} 182230557Sjimharris 183230557Sjimharris/** 184230557Sjimharris * @brief This method will set the initial Mode Select processing state. 185230557Sjimharris */ 186230557Sjimharrisstatic 187230557Sjimharrisvoid sati_mode_select_initialize_mode_sel_processing_state( 188230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 189230557Sjimharris void * scsi_io, 190230557Sjimharris void * ata_io, 191230557Sjimharris U32 data_transfer_length, 192230557Sjimharris U32 mode_page_offset 193230557Sjimharris ) 194230557Sjimharris{ 195230557Sjimharris sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0; 196230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset=mode_page_offset; 197230557Sjimharris sequence->command_specific_data.process_state.mode_pages_size = data_transfer_length - mode_page_offset; 198230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed = 0; 199230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = FALSE; 200230557Sjimharris} 201230557Sjimharris 202230557Sjimharris/** 203230557Sjimharris * @brief This method will get mode page size. 204230557Sjimharris * 205230557Sjimharris * @param[in] page_code This parameter contains page code for the current mode page. 206230557Sjimharris * 207230557Sjimharris * @return This method returns the size of current mode page. 208230557Sjimharris */ 209230557Sjimharrisstatic 210230557SjimharrisU32 sati_mode_select_get_mode_page_size( 211230557Sjimharris U8 page_code 212230557Sjimharris) 213230557Sjimharris{ 214230557Sjimharris U32 page_size=0; 215230557Sjimharris 216230557Sjimharris switch (page_code) 217230557Sjimharris { 218230557Sjimharris case SCSI_MODE_PAGE_READ_WRITE_ERROR: 219230557Sjimharris page_size=SCSI_MODE_PAGE_01_LENGTH; 220230557Sjimharris break; 221230557Sjimharris 222230557Sjimharris case SCSI_MODE_PAGE_DISCONNECT_RECONNECT: 223230557Sjimharris page_size=SCSI_MODE_PAGE_02_LENGTH; 224230557Sjimharris break; 225230557Sjimharris 226230557Sjimharris case SCSI_MODE_PAGE_CACHING: 227230557Sjimharris page_size=SCSI_MODE_PAGE_08_LENGTH; 228230557Sjimharris break; 229230557Sjimharris 230230557Sjimharris case SCSI_MODE_PAGE_CONTROL: 231230557Sjimharris page_size=SCSI_MODE_PAGE_0A_LENGTH; 232230557Sjimharris break; 233230557Sjimharris 234230557Sjimharris case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL: 235230557Sjimharris page_size=SCSI_MODE_PAGE_1C_LENGTH; 236230557Sjimharris break; 237230557Sjimharris 238230557Sjimharris case SCSI_MODE_PAGE_POWER_CONDITION: 239230557Sjimharris page_size=SCSI_MODE_PAGE_1A_LENGTH; 240230557Sjimharris break; 241230557Sjimharris default: 242230557Sjimharris page_size=0; 243230557Sjimharris break; 244230557Sjimharris } 245230557Sjimharris 246230557Sjimharris return page_size; 247230557Sjimharris} 248230557Sjimharris 249230557Sjimharris/** 250230557Sjimharris * @brief This method will check the validity of parameter data of Read Write Error Recovery 251230557Sjimharris * page and further processing the page data if necessary. 252230557Sjimharris * 253230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 254230557Sjimharris * 255230557Sjimharris * @return Indicate if the translation was successful. 256230557Sjimharris * @retval SATI_SUCCESS 257230557Sjimharris * @retval SATI_COMPLETE 258230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 259230557Sjimharris */ 260230557Sjimharrisstatic 261230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_read_write_error_recovery( 262230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T* sequence, 263230557Sjimharris void * scsi_io, 264230557Sjimharris U32 page_size 265230557Sjimharris ) 266230557Sjimharris{ 267230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 268230557Sjimharris 269230557Sjimharris U8 current_mode_page[SCSI_MODE_PAGE_01_LENGTH]={0,0,0,0,0,0,0,0,0,0,0,0}; 270230557Sjimharris U32 mode_page_offset; 271230557Sjimharris 272230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 273230557Sjimharris 274230557Sjimharris //Check all the defined bits for this page 275230557Sjimharris //SPF(0b); Page length 0x0A;AWRE 1; ARRE 0; Error recovery bits 0; RC 0; 276230557Sjimharris //Recovery time limit last two bytes 0 277230557Sjimharris 278230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset, ¤t_mode_page[0]); 279230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+1, ¤t_mode_page[1]); 280230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+2, ¤t_mode_page[2]); 281230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+10, ¤t_mode_page[10]); 282230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+11, ¤t_mode_page[11]); 283230557Sjimharris 284230557Sjimharris if ( ((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) || 285230557Sjimharris (current_mode_page[1] != (SCSI_MODE_PAGE_01_LENGTH - 2)) || 286230557Sjimharris ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK) == 0) || 287230557Sjimharris ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK) != 0) || 288230557Sjimharris ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK) != 0) || 289230557Sjimharris (current_mode_page[10] != 0 ) || 290230557Sjimharris (current_mode_page[11] != 0 ) ) 291230557Sjimharris { 292230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 293230557Sjimharris return status; 294230557Sjimharris } 295230557Sjimharris 296230557Sjimharris //no need to send any command 297230557Sjimharris { 298230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed += page_size; 299230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset += page_size; 300230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = TRUE; 301230557Sjimharris } 302230557Sjimharris 303230557Sjimharris status = SATI_COMPLETE; 304230557Sjimharris 305230557Sjimharris return status; 306230557Sjimharris} 307230557Sjimharris 308230557Sjimharris/** 309230557Sjimharris * @brief This method will check the validity of parameter data of Disconnect Reconnect mode 310230557Sjimharris * page and further processing the page data if necessary. 311230557Sjimharris * 312230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 313230557Sjimharris * 314230557Sjimharris * @return Indicate if the translation was successful. 315230557Sjimharris * @retval SATI_SUCCESS 316230557Sjimharris * @retval SATI_COMPLETE 317230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 318230557Sjimharris */ 319230557Sjimharrisstatic 320230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_disconnect_reconnect( 321230557Sjimharris SATI_MODE_SELECT_PROCESSING_STATE_T * mode_select_process_state, 322230557Sjimharris U32 page_size 323230557Sjimharris ) 324230557Sjimharris{ 325230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 326230557Sjimharris 327230557Sjimharris // No need to check data for valid or invalid this page (undefined) 328230557Sjimharris // No ata command to send 329230557Sjimharris { 330230557Sjimharris mode_select_process_state->size_of_data_processed += page_size; 331230557Sjimharris mode_select_process_state->mode_page_offset += page_size; 332230557Sjimharris mode_select_process_state->current_mode_page_processed = TRUE; 333230557Sjimharris } 334230557Sjimharris 335230557Sjimharris // No further interaction with remote devices 336230557Sjimharris status = SATI_COMPLETE; 337230557Sjimharris 338230557Sjimharris return status; 339230557Sjimharris} 340230557Sjimharris 341230557Sjimharris/** 342230557Sjimharris * @brief This method will check the validity of parameter data of Caching mode 343230557Sjimharris * page and issue multiple ATA set feature commands to complete the translation. 344230557Sjimharris * 345230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 346230557Sjimharris * 347230557Sjimharris * @return Indicate if the translation was successful. 348230557Sjimharris * @retval SATI_SUCCESS 349230557Sjimharris * @retval SATI_COMPLETE 350230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 351230557Sjimharris */ 352230557Sjimharrisstatic 353230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_caching( 354230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 355230557Sjimharris void * scsi_io, 356230557Sjimharris void * ata_io, 357230557Sjimharris U32 page_size 358230557Sjimharris ) 359230557Sjimharris{ 360230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 361230557Sjimharris 362230557Sjimharris //SCSI_MODE_PAGE_08_LENGTH 0x14= 20 363230557Sjimharris U8 current_mode_page[SCSI_MODE_PAGE_08_LENGTH] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 364230557Sjimharris U32 mode_page_offset; 365230557Sjimharris U32 index; 366230557Sjimharris 367230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 368230557Sjimharris sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING; 369230557Sjimharris 370230557Sjimharris for(index = 0; index < SCSI_MODE_PAGE_08_LENGTH; index++) 371230557Sjimharris { 372230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, ¤t_mode_page[index]); 373230557Sjimharris } 374230557Sjimharris 375230557Sjimharris //Check for data validity 376230557Sjimharris //SPF(0b); Page length 0x12;Byte2 to Byte15 all 0 with exception DRA and WCE changeable 377230557Sjimharris 378230557Sjimharris if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) || 379230557Sjimharris (current_mode_page[1] != (SCSI_MODE_PAGE_08_LENGTH-2)) || 380230557Sjimharris ((current_mode_page[2] | SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT)!=SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT) || 381230557Sjimharris (current_mode_page[3] != 0 ) || 382230557Sjimharris (current_mode_page[4] != 0 ) || 383230557Sjimharris (current_mode_page[5] != 0 ) || 384230557Sjimharris (current_mode_page[6] != 0 ) || 385230557Sjimharris (current_mode_page[7] != 0 ) || 386230557Sjimharris (current_mode_page[8] != 0 ) || 387230557Sjimharris (current_mode_page[9] != 0 ) || 388230557Sjimharris (current_mode_page[10] != 0 ) || 389230557Sjimharris (current_mode_page[11] != 0 ) || 390230557Sjimharris ((current_mode_page[12] & SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS) != 0) || 391230557Sjimharris (current_mode_page[13] != 0 ) || 392230557Sjimharris (current_mode_page[14] != 0 ) || 393230557Sjimharris (current_mode_page[15] != 0 )) 394230557Sjimharris { 395230557Sjimharris //parameter data passed in containing data that doesn't meet the SAT-2 requirement 396230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 397230557Sjimharris } 398230557Sjimharris 399230557Sjimharris if(sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 0) 400230557Sjimharris { 401230557Sjimharris //byte2 bit2 WCE==0 disable write cache WCE==1 enable write cache 402230557Sjimharris //SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT ==0x4, 403230557Sjimharris 404230557Sjimharris if ( (current_mode_page[2] & SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT) == 0) 405230557Sjimharris sati_ata_set_features_construct(ata_io, sequence, ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE); 406230557Sjimharris else 407230557Sjimharris sati_ata_set_features_construct(ata_io, sequence, ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE); 408230557Sjimharris 409230557Sjimharris } 410230557Sjimharris else if(sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 1) 411230557Sjimharris { 412230557Sjimharris // DRA bit is set to 0, enable Read look ahead AAh; 413230557Sjimharris // DRA bit is set to 1, disable with set feature command 55h 414230557Sjimharris // SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT== 0x20 415230557Sjimharris 416230557Sjimharris if ( (current_mode_page[12] & SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT) == 0) 417230557Sjimharris sati_ata_set_features_construct(ata_io, sequence,ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD); 418230557Sjimharris else 419230557Sjimharris sati_ata_set_features_construct(ata_io, sequence,ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD); 420230557Sjimharris 421230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed += page_size; 422230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset += page_size; 423230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = TRUE; 424230557Sjimharris 425230557Sjimharris 426230557Sjimharris } 427230557Sjimharris // No more ata commands to send 428230557Sjimharris 429230557Sjimharris sequence->command_specific_data.process_state.ata_command_sent_for_cmp++; 430230557Sjimharris 431230557Sjimharris status = SATI_SUCCESS; 432230557Sjimharris 433230557Sjimharris return status; 434230557Sjimharris} 435230557Sjimharris 436230557Sjimharris/** 437230557Sjimharris * @brief This method will check the validity of parameter data of Control mode 438230557Sjimharris * page and further processing the page data if necessary. 439230557Sjimharris * 440230557Sjimharris * @param[in] mode_select_process_state This parameter points to the processing state fields 441230557Sjimharris * of current mode page. 442230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 443230557Sjimharris * 444230557Sjimharris * @return Indicate if the translation was successful. 445230557Sjimharris * @retval SATI_SUCCESS 446230557Sjimharris * @retval SATI_COMPLETE 447230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 448230557Sjimharris */ 449230557Sjimharrisstatic 450230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_control( 451230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T* sequence, 452230557Sjimharris void * scsi_io, 453230557Sjimharris void * ata_io, 454230557Sjimharris U32 page_size 455230557Sjimharris ) 456230557Sjimharris{ 457230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 458230557Sjimharris 459230557Sjimharris //SCSI_MODE_PAGE_0A_LENGTH 12 460230557Sjimharris U8 current_mode_page[SCSI_MODE_PAGE_0A_LENGTH]={0,0,0,0,0,0,0,0,0,0}; 461230557Sjimharris U32 mode_page_offset; 462230557Sjimharris U32 index; 463230557Sjimharris 464230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 465230557Sjimharris 466230557Sjimharris for(index = 0; index < SCSI_MODE_PAGE_0A_LENGTH; index++) 467230557Sjimharris { 468230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, ¤t_mode_page[index]); 469230557Sjimharris } 470230557Sjimharris 471230557Sjimharris //bit 1 and 2 of byte3 Qerr full task management model etc. then both bits 0 472230557Sjimharris //byte 8 and 9 busy time out period variable if not ffff setable? 473230557Sjimharris //check for page data validity 474230557Sjimharris //Byte2: 0000???0b Byte3: Queued Algorithm Modifier should be set to 1 QErr? 475230557Sjimharris //Byte4: ??000??? Byte5: ?0???000 476230557Sjimharris 477230557Sjimharris if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) || 478230557Sjimharris (current_mode_page[1] != (SCSI_MODE_PAGE_0A_LENGTH - 2)) || 479230557Sjimharris ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC) != 0) || 480230557Sjimharris ((current_mode_page[3] & SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER) != 0) || 481230557Sjimharris ((current_mode_page[4] & SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP ) != 0) || 482230557Sjimharris ((current_mode_page[5] & SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO ) != 0 ) ) 483230557Sjimharris { 484230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 485230557Sjimharris } 486230557Sjimharris 487230557Sjimharris if ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_D_SENSE) != 0) 488230557Sjimharris sequence->device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_ENABLE; 489230557Sjimharris else 490230557Sjimharris sequence->device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE; 491230557Sjimharris 492230557Sjimharris // no ata command need to be comfirmed 493230557Sjimharris { 494230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed += page_size; 495230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset += page_size; 496230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = TRUE; 497230557Sjimharris } 498230557Sjimharris 499230557Sjimharris status = SATI_COMPLETE; 500230557Sjimharris 501230557Sjimharris return status; 502230557Sjimharris} 503230557Sjimharris 504230557Sjimharris/** 505230557Sjimharris * @brief This method will check the validity of parameter data of Information Exception Control 506230557Sjimharris * mode page and further processing the page data if necessary. 507230557Sjimharris * 508230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 509230557Sjimharris * 510230557Sjimharris * @return Indicate if the translation was successful. 511230557Sjimharris * @retval SATI_SUCCESS 512230557Sjimharris * @retval SATI_COMPLETE 513230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 514230557Sjimharris */ 515230557Sjimharrisstatic 516230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_informational_exception_control( 517230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 518230557Sjimharris void * scsi_io, 519230557Sjimharris void * ata_io, 520230557Sjimharris U32 page_size 521230557Sjimharris ) 522230557Sjimharris{ 523230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 524230557Sjimharris 525230557Sjimharris //SCSI_MODE_PAGE_1C_LENGTH 12 526230557Sjimharris U8 current_mode_page[SCSI_MODE_PAGE_1C_LENGTH]={0,0,0,0,0,0,0,0,0,0,0,0}; 527230557Sjimharris U32 mode_page_offset; 528230557Sjimharris U32 index; 529230557Sjimharris 530230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 531230557Sjimharris sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL; 532230557Sjimharris 533230557Sjimharris for(index = 0; index < 4; index++) 534230557Sjimharris { 535230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, ¤t_mode_page[index]); 536230557Sjimharris } 537230557Sjimharris 538230557Sjimharris //Check for data validity 539230557Sjimharris //SPF(0b); Page length 0x0A; Byte2 0????0?? Byte3: ????1100 540230557Sjimharris //SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE same as REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6 541230557Sjimharris //SCSI_MODE_PAGE_DEXCPT_ENABLE 542230557Sjimharris 543230557Sjimharris if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) || 544230557Sjimharris (current_mode_page[1] != (SCSI_MODE_PAGE_1C_LENGTH - 2)) || 545230557Sjimharris ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST)!= 0 ) || 546230557Sjimharris ((current_mode_page[3] & SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK) != 547230557Sjimharris SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE )) 548230557Sjimharris { 549230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 550230557Sjimharris } 551230557Sjimharris 552230557Sjimharris // DEXCPT bit is set to 0, enable SMART reporting D8h; 553230557Sjimharris // DEXCPT bit is set to 1, disable SMART reporting D9h 554230557Sjimharris // SCSI_MODE_PAGE_DEXCPT_ENABLE== 0x08 555230557Sjimharris 556230557Sjimharris if ( (current_mode_page[2] & SCSI_MODE_PAGE_DEXCPT_ENABLE) == 0) 557230557Sjimharris sati_ata_smart_return_status_construct(ata_io, sequence, ATA_SMART_SUB_CMD_ENABLE); 558230557Sjimharris else 559230557Sjimharris sati_ata_smart_return_status_construct(ata_io, sequence, ATA_SMART_SUB_CMD_DISABLE); 560230557Sjimharris 561230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed += page_size; 562230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset += page_size; 563230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = TRUE; 564230557Sjimharris // No more ata commands to send 565230557Sjimharris 566230557Sjimharris status = SATI_SUCCESS; 567230557Sjimharris 568230557Sjimharris return status; 569230557Sjimharris} 570230557Sjimharris 571230557Sjimharris/** 572230557Sjimharris * @brief This method will check the validity of parameter data of Power Condition mode 573230557Sjimharris * page and issue multiple ATA set feature commands to complete the translation. 574230557Sjimharris * 575230557Sjimharris * @param[in] mode_select_process_state This parameter points to the processing state fields 576230557Sjimharris * of current mode page. 577230557Sjimharris * @param[in] page_size This parameter specifies page size of current mode page. 578230557Sjimharris * 579230557Sjimharris * @return Indicate if the translation was successful. 580230557Sjimharris * @retval SATI_SUCCESS 581230557Sjimharris * @retval SATI_COMPLETE 582230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 583230557Sjimharris */ 584230557Sjimharrisstatic 585230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page_power_condition( 586230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 587230557Sjimharris void * scsi_io, 588230557Sjimharris void * ata_io, 589230557Sjimharris U32 page_size 590230557Sjimharris ) 591230557Sjimharris{ 592230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 593230557Sjimharris 594230557Sjimharris //SCSI_MODE_PAGE_1A_LENGTH 10 595230557Sjimharris U8 current_mode_page[SCSI_MODE_PAGE_1A_LENGTH] = {0,0,0,0,0,0,0,0,0,0}; 596230557Sjimharris U32 mode_page_offset; 597230557Sjimharris U32 index; 598230557Sjimharris 599230557Sjimharris U32 timer = 0; 600230557Sjimharris U16 count = 0; 601230557Sjimharris 602230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 603230557Sjimharris 604230557Sjimharris sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION; 605230557Sjimharris 606230557Sjimharris for(index = 0; index < SCSI_MODE_PAGE_1A_LENGTH; index++) 607230557Sjimharris { 608230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, ¤t_mode_page[index]); 609230557Sjimharris } 610230557Sjimharris 611230557Sjimharris //Check for data validity 612230557Sjimharris //SPF(0b); Page length 0x0A; 613230557Sjimharris 614230557Sjimharris if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) || 615230557Sjimharris (current_mode_page[1] != (SCSI_MODE_PAGE_1A_LENGTH - 2) ) || 616230557Sjimharris ((current_mode_page[3] & SCSI_MODE_PAGE_POWER_CONDITION_IDLE)!= 0) 617230557Sjimharris ) 618230557Sjimharris { 619230557Sjimharris //parameter data passed in containing data that doesn't meet the SAT-2 requirement 620230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 621230557Sjimharris } 622230557Sjimharris 623230557Sjimharris // STANDBY bit is set to 0, do nothing since the standby timer can't be set; 624230557Sjimharris // STANDBY bit is set to 1, translate the standby timer 625230557Sjimharris // SCSI_MODE_PAGE_POWER_CONDITION_STANDBY== 0x01 626230557Sjimharris if (current_mode_page[3] & SCSI_MODE_PAGE_POWER_CONDITION_STANDBY) 627230557Sjimharris { 628230557Sjimharris timer = (current_mode_page[8]<<24) + (current_mode_page[9]<<16) + (current_mode_page[10]<<8) + current_mode_page[11]; 629230557Sjimharris 630230557Sjimharris //If the ATA IDENTIFY DEVICE data word 49, bit 13 is set to one, 631230557Sjimharris if (sequence->device->capabilities & SATI_DEVICE_CAP_STANDBY_ENABLE) 632230557Sjimharris { 633230557Sjimharris if (timer == 0) 634230557Sjimharris { 635230557Sjimharris //TPV=0 send ATA STANDBY_IMMEDIATE 636230557Sjimharris sati_ata_standby_immediate_construct(ata_io, sequence); 637230557Sjimharris sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED; 638230557Sjimharris } 639230557Sjimharris else if ((timer > 0) && (timer <= 12000)) 640230557Sjimharris { 641230557Sjimharris //1 to 12 000 INT((z - 1) / 50) + 1 642230557Sjimharris count = (U16)((timer -1) / 50) + 1; 643230557Sjimharris sati_ata_standby_construct(ata_io, sequence, count); 644230557Sjimharris } 645230557Sjimharris else if ((timer > 12000) && (timer <= 12600)) 646230557Sjimharris { 647230557Sjimharris //12 001 to 12 600 FCh 648230557Sjimharris sati_ata_standby_construct(ata_io, sequence, 0xFC); 649230557Sjimharris } 650230557Sjimharris else if ((timer > 12600) && (timer <= 12750)) 651230557Sjimharris { 652230557Sjimharris //12 601 to 12 750 FFh 653230557Sjimharris sati_ata_standby_construct(ata_io, sequence, 0xFF); 654230557Sjimharris } 655230557Sjimharris else if ((timer > 12750) && (timer < 18000)) 656230557Sjimharris { 657230557Sjimharris //12 751 to 17 999 F1h 658230557Sjimharris sati_ata_standby_construct(ata_io, sequence, 0xF1); 659230557Sjimharris } 660230557Sjimharris else if ((timer >= 18000) && (timer <= 198000)) 661230557Sjimharris { 662230557Sjimharris //18 000 to 198 000 INT(z / 18 000) + 240 663230557Sjimharris count = (U16)(timer / 18000) + 240; 664230557Sjimharris sati_ata_standby_construct(ata_io, sequence, count); 665230557Sjimharris } 666230557Sjimharris else 667230557Sjimharris { 668230557Sjimharris //All other values FDh 669230557Sjimharris sati_ata_standby_construct(ata_io, sequence, 0xFD); 670230557Sjimharris } 671230557Sjimharris status = SATI_SUCCESS ; 672230557Sjimharris } 673230557Sjimharris else 674230557Sjimharris { 675230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 676230557Sjimharris //If the ATA IDENTIFY DEVICE data word 49, bit 13 is set to 0 677230557Sjimharris } 678230557Sjimharris } 679230557Sjimharris else 680230557Sjimharris { 681230557Sjimharris status = SATI_COMPLETE; 682230557Sjimharris } 683230557Sjimharris 684230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed += page_size; 685230557Sjimharris sequence->command_specific_data.process_state.mode_page_offset += page_size; 686230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = TRUE; 687230557Sjimharris 688230557Sjimharris return status; 689230557Sjimharris} 690230557Sjimharris 691230557Sjimharris/** 692230557Sjimharris * @brief This method will process the mode page. 693230557Sjimharris * 694230557Sjimharris * 695230557Sjimharris * @return Indicate if the translation was successful. 696230557Sjimharris * @retval SATI_SUCCESS 697230557Sjimharris * @retval SATI_COMPLETE 698230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 699230557Sjimharris */ 700230557Sjimharrisstatic 701230557SjimharrisSATI_STATUS sati_mode_select_process_mode_page( 702230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T* sequence, 703230557Sjimharris void * scsi_io, 704230557Sjimharris void * ata_io 705230557Sjimharris) 706230557Sjimharris{ 707230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 708230557Sjimharris 709230557Sjimharris U8 page_code; 710230557Sjimharris U32 page_size = 0; // in bytes 711230557Sjimharris U32 size_of_data_to_be_processed; 712230557Sjimharris 713230557Sjimharris U8 page_code_byte; 714230557Sjimharris U32 mode_page_offset; 715230557Sjimharris 716230557Sjimharris mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset; 717230557Sjimharris 718230557Sjimharris sati_get_data_byte(sequence, scsi_io, mode_page_offset, &page_code_byte); 719230557Sjimharris 720230557Sjimharris // No more pages. 721230557Sjimharris if(sequence->command_specific_data.process_state.mode_pages_size > 722230557Sjimharris sequence->command_specific_data.process_state.size_of_data_processed) 723230557Sjimharris { 724230557Sjimharris //SCSI_MODE_SENSE_PAGE_CODE_ENABLE==0x3f same for Mode Select 725230557Sjimharris page_code = page_code_byte & SCSI_MODE_SENSE_PAGE_CODE_ENABLE; 726230557Sjimharris page_size = sati_mode_select_get_mode_page_size(page_code); 727230557Sjimharris size_of_data_to_be_processed = sequence->command_specific_data.process_state.mode_pages_size 728230557Sjimharris - sequence->command_specific_data.process_state.size_of_data_processed; 729230557Sjimharris 730230557Sjimharris if( page_size == 0 ) 731230557Sjimharris { 732230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 733230557Sjimharris } 734230557Sjimharris else 735230557Sjimharris { 736230557Sjimharris // process mode page 737230557Sjimharris switch(page_code) 738230557Sjimharris { 739230557Sjimharris case SCSI_MODE_PAGE_READ_WRITE_ERROR: 740230557Sjimharris status = sati_mode_select_process_mode_page_read_write_error_recovery( 741230557Sjimharris sequence, 742230557Sjimharris scsi_io, 743230557Sjimharris page_size 744230557Sjimharris ); 745230557Sjimharris break; 746230557Sjimharris 747230557Sjimharris case SCSI_MODE_PAGE_DISCONNECT_RECONNECT: 748230557Sjimharris status = sati_mode_select_process_mode_page_disconnect_reconnect( 749230557Sjimharris &sequence->command_specific_data.process_state, 750230557Sjimharris page_size 751230557Sjimharris ); 752230557Sjimharris break; 753230557Sjimharris 754230557Sjimharris case SCSI_MODE_PAGE_CACHING: 755230557Sjimharris status = sati_mode_select_process_mode_page_caching( 756230557Sjimharris sequence, 757230557Sjimharris scsi_io, 758230557Sjimharris ata_io, 759230557Sjimharris page_size 760230557Sjimharris ); 761230557Sjimharris break; 762230557Sjimharris 763230557Sjimharris case SCSI_MODE_PAGE_CONTROL: 764230557Sjimharris status = sati_mode_select_process_mode_page_control( 765230557Sjimharris sequence, 766230557Sjimharris scsi_io, 767230557Sjimharris ata_io, 768230557Sjimharris page_size 769230557Sjimharris ); 770230557Sjimharris break; 771230557Sjimharris 772230557Sjimharris case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL: 773230557Sjimharris status = sati_mode_select_process_mode_page_informational_exception_control( 774230557Sjimharris sequence, 775230557Sjimharris scsi_io, 776230557Sjimharris ata_io, 777230557Sjimharris page_size 778230557Sjimharris ); 779230557Sjimharris break; 780230557Sjimharris 781230557Sjimharris case SCSI_MODE_PAGE_POWER_CONDITION: 782230557Sjimharris status = sati_mode_select_process_mode_page_power_condition( 783230557Sjimharris sequence, 784230557Sjimharris scsi_io, 785230557Sjimharris ata_io, 786230557Sjimharris page_size 787230557Sjimharris ); 788230557Sjimharris 789230557Sjimharris break; 790230557Sjimharris 791230557Sjimharris default: 792230557Sjimharris break; 793230557Sjimharris } 794230557Sjimharris 795230557Sjimharris } 796230557Sjimharris } 797230557Sjimharris 798230557Sjimharris return status; 799230557Sjimharris} 800230557Sjimharris 801230557Sjimharris//****************************************************************************** 802230557Sjimharris//* P U B L I C M E T H O D S 803230557Sjimharris//****************************************************************************** 804230557Sjimharris 805230557Sjimharris/** 806230557Sjimharris * @brief This method will translate the SCSI Mode Select 6 byte or 10 byte command 807230557Sjimharris * into corresponding ATA commands. Depending upon the capabilities 808230557Sjimharris * supported by the target different ATA commands can be selected. 809230557Sjimharris * Additionally, in some cases more than a single ATA command may 810230557Sjimharris * be required. 811230557Sjimharris * 812230557Sjimharris * @return Indicate if the command translation succeeded. 813230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was 814230557Sjimharris * successful. 815230557Sjimharris * @retval SCI_COMPLETE This is returned if the command translation was 816230557Sjimharris * successful and no ATA commands need to be set. 817230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 818230557Sjimharris * sense data has been created as a result of something specified 819230557Sjimharris * in the parameter data fields. 820230557Sjimharris */ 821230557Sjimharrisstatic 822230557SjimharrisSATI_STATUS sati_mode_select_translate_command( 823230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 824230557Sjimharris void * scsi_io, 825230557Sjimharris void * ata_io, 826230557Sjimharris U32 cdb_size 827230557Sjimharris) 828230557Sjimharris{ 829230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 830230557Sjimharris U32 mode_page_offset; 831230557Sjimharris U32 block_descriptor_length; 832230557Sjimharris U32 index; 833230557Sjimharris U16 data_transfer_length; 834230557Sjimharris U8 current_mode_parameters[8]={0,0,0,0,0,0,0,0}; 835230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 836230557Sjimharris 837230557Sjimharris // cdb_size must be 6 or 10 838230557Sjimharris if(FALSE == (cdb_size == 6 || cdb_size == 10)) 839230557Sjimharris { 840230557Sjimharris return status; 841230557Sjimharris } 842230557Sjimharris 843230557Sjimharris if(sequence->state == SATI_SEQUENCE_STATE_INITIAL) 844230557Sjimharris { 845230557Sjimharris sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0; 846230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA; 847230557Sjimharris } 848230557Sjimharris 849230557Sjimharris //First, initializes mode_sel_processing_state 850230557Sjimharris if ( sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 0 ) 851230557Sjimharris { 852230557Sjimharris if (cdb_size == 6) 853230557Sjimharris { 854230557Sjimharris //CDB byte 4 is the parameter length 855230557Sjimharris data_transfer_length = sati_get_cdb_byte(cdb, 4); 856230557Sjimharris } 857230557Sjimharris else 858230557Sjimharris { 859230557Sjimharris //CDB byte 7 and 8 for Mode Select 10 860230557Sjimharris data_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) + sati_get_cdb_byte(cdb, 8); 861230557Sjimharris } 862230557Sjimharris 863230557Sjimharris sequence->allocation_length = data_transfer_length; 864230557Sjimharris 865230557Sjimharris //Get 8 bytes for headers (4 bytes for Mode Select 6 and 8 bytes for Mode Select 10) 866230557Sjimharris for( index = 0; index < 8; index++ ) 867230557Sjimharris { 868230557Sjimharris sati_get_data_byte(sequence, scsi_io, index, ¤t_mode_parameters[index]); 869230557Sjimharris } 870230557Sjimharris 871230557Sjimharris //medium type should be 0 872230557Sjimharris if ( sati_mode_select_get_medium_type(current_mode_parameters, cdb_size) != 0 ) 873230557Sjimharris { 874230557Sjimharris sati_scsi_sense_data_construct( 875230557Sjimharris sequence, 876230557Sjimharris scsi_io, 877230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 878230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 879230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_PARM_LIST, 880230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 881230557Sjimharris ); 882230557Sjimharris return status; 883230557Sjimharris } 884230557Sjimharris 885230557Sjimharris block_descriptor_length = sati_mode_select_get_mode_block_descriptor_length( 886230557Sjimharris current_mode_parameters, 887230557Sjimharris cdb_size 888230557Sjimharris ); 889230557Sjimharris 890230557Sjimharris mode_page_offset = sati_mode_select_get_mode_page_offset( 891230557Sjimharris block_descriptor_length, 892230557Sjimharris cdb_size 893230557Sjimharris ); 894230557Sjimharris 895230557Sjimharris if(mode_page_offset > data_transfer_length) 896230557Sjimharris { 897230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 898230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 899230557Sjimharris } 900230557Sjimharris else 901230557Sjimharris { 902230557Sjimharris sati_mode_select_initialize_mode_sel_processing_state( 903230557Sjimharris sequence, 904230557Sjimharris scsi_io, 905230557Sjimharris ata_io, 906230557Sjimharris data_transfer_length, 907230557Sjimharris mode_page_offset 908230557Sjimharris ); 909230557Sjimharris 910230557Sjimharris } 911230557Sjimharris } 912230557Sjimharris 913230557Sjimharris // move to next mode page 914230557Sjimharris if(sequence->command_specific_data.process_state.current_mode_page_processed) 915230557Sjimharris { 916230557Sjimharris sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0; 917230557Sjimharris sequence->command_specific_data.process_state.current_mode_page_processed = FALSE; 918230557Sjimharris } 919230557Sjimharris 920230557Sjimharris status = sati_mode_select_process_mode_page(sequence, scsi_io, ata_io); 921230557Sjimharris 922230557Sjimharris if(sequence->command_specific_data.process_state.current_mode_page_processed != FALSE) 923230557Sjimharris { 924230557Sjimharris // Done this page 925230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 926230557Sjimharris } 927230557Sjimharris else 928230557Sjimharris { 929230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 930230557Sjimharris } 931230557Sjimharris 932230557Sjimharris if(status == SATI_FAILURE_CHECK_RESPONSE_DATA) 933230557Sjimharris { 934230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 935230557Sjimharris sati_scsi_sense_data_construct( 936230557Sjimharris sequence, 937230557Sjimharris scsi_io, 938230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 939230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 940230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_PARM_LIST, 941230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 942230557Sjimharris ); 943230557Sjimharris } 944230557Sjimharris 945230557Sjimharris return status; 946230557Sjimharris} 947230557Sjimharris 948230557Sjimharris/** 949230557Sjimharris * @brief This method will call Mode Select 6 Translation command 950230557Sjimharris * For more information on the parameters passed to this method, 951230557Sjimharris * please reference sati_translate_command(). 952230557Sjimharris * 953230557Sjimharris * @return Indicate if the command translation succeeded. 954230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was 955230557Sjimharris * successful. 956230557Sjimharris * @retval SCI_COMPLETE This is returned if the command translation was 957230557Sjimharris * successful and no ATA commands need to be set. 958230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 959230557Sjimharris * sense data has been created as a result of something specified 960230557Sjimharris * in the parameter data fields. 961230557Sjimharris */ 962230557SjimharrisSATI_STATUS sati_mode_select_6_translate_command( 963230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 964230557Sjimharris void * scsi_io, 965230557Sjimharris void * ata_io 966230557Sjimharris) 967230557Sjimharris{ 968230557Sjimharris SATI_STATUS status=SATI_FAILURE; 969230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 970230557Sjimharris 971230557Sjimharris //PF bit needs to be 1 byte1 bit ???1???? 972230557Sjimharris if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT) 973230557Sjimharris { 974230557Sjimharris sati_scsi_sense_data_construct( 975230557Sjimharris sequence, 976230557Sjimharris scsi_io, 977230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 978230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 979230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 980230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 981230557Sjimharris ); 982230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 983230557Sjimharris return status; 984230557Sjimharris } 985230557Sjimharris 986230557Sjimharris status=sati_mode_select_translate_command( 987230557Sjimharris sequence, 988230557Sjimharris scsi_io, 989230557Sjimharris ata_io, 990230557Sjimharris 6 991230557Sjimharris ); 992230557Sjimharris 993230557Sjimharris if(status == SATI_FAILURE_CHECK_RESPONSE_DATA) 994230557Sjimharris { 995230557Sjimharris sati_scsi_sense_data_construct( 996230557Sjimharris sequence, 997230557Sjimharris scsi_io, 998230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 999230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 1000230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_PARM_LIST, 1001230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 1002230557Sjimharris ); 1003230557Sjimharris } 1004230557Sjimharris return status; 1005230557Sjimharris 1006230557Sjimharris} 1007230557Sjimharris 1008230557Sjimharris/** 1009230557Sjimharris * @brief This method will call Mode Select 10 translation command 1010230557Sjimharris * For more information on the parameters passed to this method, 1011230557Sjimharris * please reference sati_translate_command(). 1012230557Sjimharris * 1013230557Sjimharris * @return Indicate if the command translation succeeded. 1014230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was 1015230557Sjimharris * successful. 1016230557Sjimharris * @retval SCI_COMPLETE This is returned if the command translation was 1017230557Sjimharris * successful and no ATA commands need to be set. 1018230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 1019230557Sjimharris * sense data has been created as a result of something specified 1020230557Sjimharris * in the parameter data fields. 1021230557Sjimharris */ 1022230557SjimharrisSATI_STATUS sati_mode_select_10_translate_command( 1023230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 1024230557Sjimharris void * scsi_io, 1025230557Sjimharris void * ata_io 1026230557Sjimharris) 1027230557Sjimharris{ 1028230557Sjimharris SATI_STATUS status=SATI_FAILURE; 1029230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 1030230557Sjimharris 1031230557Sjimharris //PF bit needs to be 1 byte1 bit ???1???? 1032230557Sjimharris if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT) 1033230557Sjimharris { 1034230557Sjimharris sati_scsi_sense_data_construct( 1035230557Sjimharris sequence, 1036230557Sjimharris scsi_io, 1037230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 1038230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 1039230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 1040230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 1041230557Sjimharris ); 1042230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 1043230557Sjimharris return status; 1044230557Sjimharris } 1045230557Sjimharris 1046230557Sjimharris status=sati_mode_select_translate_command( 1047230557Sjimharris sequence, 1048230557Sjimharris scsi_io, 1049230557Sjimharris ata_io, 1050230557Sjimharris 10 1051230557Sjimharris ); 1052230557Sjimharris 1053230557Sjimharris if(status == SATI_FAILURE_CHECK_RESPONSE_DATA) 1054230557Sjimharris { 1055230557Sjimharris sati_scsi_sense_data_construct( 1056230557Sjimharris sequence, 1057230557Sjimharris scsi_io, 1058230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 1059230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 1060230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_PARM_LIST, 1061230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 1062230557Sjimharris ); 1063230557Sjimharris } 1064230557Sjimharris return status; 1065230557Sjimharris} 1066230557Sjimharris 1067230557Sjimharris/** 1068230557Sjimharris* @brief This method will conduct error handling for the ATA Set Features command 1069230557Sjimharris* that is issued during a Mode Select translation for the Caching Mode 1070230557Sjimharris* page. 1071230557Sjimharris* 1072230557Sjimharris* 1073230557Sjimharris* @return Indicate if the command translation succeeded. 1074230557Sjimharris* 1075230557Sjimharris* @retval SCI_COMPLETE This is returned if the command translation was 1076230557Sjimharris* successful and no additional ATA commands need to be set. 1077230557Sjimharris* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 1078230557Sjimharris* sense data has been created as a result of an error returned 1079230557Sjimharris*/ 1080230557SjimharrisSATI_STATUS sati_mode_select_translate_response( 1081230557SjimharrisSATI_TRANSLATOR_SEQUENCE_T * sequence, 1082230557Sjimharrisvoid * scsi_io, 1083230557Sjimharrisvoid * ata_io 1084230557Sjimharris) 1085230557Sjimharris{ 1086230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 1087230557Sjimharris SATI_STATUS status = SATI_FAILURE; 1088230557Sjimharris 1089230557Sjimharris if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 1090230557Sjimharris { 1091230557Sjimharris sati_scsi_sense_data_construct( 1092230557Sjimharris sequence, 1093230557Sjimharris scsi_io, 1094230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 1095230557Sjimharris SCSI_SENSE_ABORTED_COMMAND, 1096230557Sjimharris SCSI_ASC_NO_ADDITIONAL_SENSE, 1097230557Sjimharris SCSI_ASCQ_NO_ADDITIONAL_SENSE 1098230557Sjimharris ); 1099230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 1100230557Sjimharris } 1101230557Sjimharris else 1102230557Sjimharris { 1103230557Sjimharris if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 1104230557Sjimharris { 1105230557Sjimharris status = SATI_SEQUENCE_INCOMPLETE; 1106230557Sjimharris } 1107230557Sjimharris else 1108230557Sjimharris { 1109230557Sjimharris status = SATI_COMPLETE; 1110230557Sjimharris } 1111230557Sjimharris } 1112230557Sjimharris return status; 1113230557Sjimharris} 1114230557Sjimharris 1115230557Sjimharris#endif // !defined(DISABLE_SATI_MODE_SELECT) 1116