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 reassign blocks command. 60230557Sjimharris */ 61230557Sjimharris 62230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 63230557Sjimharris 64230557Sjimharris#include <dev/isci/scil/sati_reassign_blocks.h> 65230557Sjimharris#include <dev/isci/scil/sati_callbacks.h> 66230557Sjimharris#include <dev/isci/scil/sati_move.h> 67230557Sjimharris#include <dev/isci/scil/sati_write.h> 68230557Sjimharris#include <dev/isci/scil/sati_translator_sequence.h> 69230557Sjimharris#include <dev/isci/scil/sati_util.h> 70230557Sjimharris#include <dev/isci/scil/intel_scsi.h> 71230557Sjimharris 72230557Sjimharris 73230557Sjimharris//****************************************************************************** 74230557Sjimharris//* P R I V A T E M E T H O D S 75230557Sjimharris//****************************************************************************** 76230557Sjimharris// static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state; 77230557Sjimharris 78230557Sjimharris/** 79230557Sjimharris * @brief This method copies short 24bits LBA bytes to the command register 80230557Sjimharris * @return Indicate if the method was successfully completed. 81230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 82230557Sjimharris */ 83230557Sjimharrisstatic 84230557Sjimharrisvoid set_current_lba(U8 * lba, void * ata_io) 85230557Sjimharris{ 86230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 87230557Sjimharris 88230557Sjimharris sati_set_ata_lba_low(register_fis, lba[0]); 89230557Sjimharris sati_set_ata_lba_mid(register_fis, lba[1]); 90230557Sjimharris sati_set_ata_lba_high(register_fis, lba[2]); 91230557Sjimharris sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F)); 92230557Sjimharris 93230557Sjimharris 94230557Sjimharris} 95230557Sjimharris 96230557Sjimharris/** 97230557Sjimharris * @brief This method copies short 48bits LBA bytes to the command register 98230557Sjimharris * @return Indicate if the method was successfully completed. 99230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 100230557Sjimharris */ 101230557Sjimharrisstatic 102230557Sjimharrisvoid set_current_long_lba(U8 * lba, void * ata_io) 103230557Sjimharris{ 104230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 105230557Sjimharris 106230557Sjimharris sati_set_ata_lba_low(register_fis, lba[0]); 107230557Sjimharris sati_set_ata_lba_mid(register_fis, lba[1]); 108230557Sjimharris sati_set_ata_lba_high(register_fis, lba[2]); 109230557Sjimharris sati_set_ata_lba_low_exp(register_fis, lba[3]); 110230557Sjimharris sati_set_ata_lba_mid_exp(register_fis, lba[4]); 111230557Sjimharris sati_set_ata_lba_high_exp(register_fis, lba[5]); 112230557Sjimharris} 113230557Sjimharris 114230557Sjimharris/** 115230557Sjimharris * @brief This method performs the SCSI VERIFY command translation 116230557Sjimharris * functionality. 117230557Sjimharris * This includes: 118230557Sjimharris * - setting the command register 119230557Sjimharris * - setting the device head register 120230557Sjimharris * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. 121230557Sjimharris * For more information on the parameters passed to this method, 122230557Sjimharris * please reference sati_translate_command(). 123230557Sjimharris * 124230557Sjimharris * @return Indicate if the method was successfully completed. 125230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 126230557Sjimharris */ 127230557Sjimharrisstatic 128230557SjimharrisSATI_STATUS sati_reassign_blocks_verify_command( 129230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 130230557Sjimharris void * scsi_io, 131230557Sjimharris void * ata_io 132230557Sjimharris) 133230557Sjimharris{ 134230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 135230557Sjimharris 136230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 137230557Sjimharris 138230557Sjimharris // Ensure the device supports the 48 bit feature set. 139230557Sjimharris if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) 140230557Sjimharris sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT); 141230557Sjimharris else 142230557Sjimharris sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); 143230557Sjimharris 144230557Sjimharris return SATI_SUCCESS; 145230557Sjimharris} 146230557Sjimharris 147230557Sjimharris/** 148230557Sjimharris * @brief This method performs the SCSI Write sector command translation 149230557Sjimharris * functionality. 150230557Sjimharris * This includes: 151230557Sjimharris * - setting the command register 152230557Sjimharris * - setting the device head register 153230557Sjimharris * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. 154230557Sjimharris * For more information on the parameters passed to this method, 155230557Sjimharris * please reference sati_translate_command(). 156230557Sjimharris * 157230557Sjimharris * @return Indicate if the method was successfully completed. 158230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 159230557Sjimharris */ 160230557Sjimharrisstatic 161230557SjimharrisSATI_STATUS sati_reassign_blocks_write_command( 162230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 163230557Sjimharris void * scsi_io, 164230557Sjimharris void * ata_io 165230557Sjimharris) 166230557Sjimharris{ 167230557Sjimharris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 168230557Sjimharris 169230557Sjimharris sati_ata_non_data_command(ata_io, sequence); 170230557Sjimharris sequence->data_direction = SATI_DATA_DIRECTION_OUT; 171230557Sjimharris 172230557Sjimharris// sati_set_ata_sector_count(register_fis, 1); 173230557Sjimharris// status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0); 174230557Sjimharris 175230557Sjimharris // Ensure the device supports the 48 bit feature set. 176230557Sjimharris if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) 177230557Sjimharris sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT); 178230557Sjimharris else 179230557Sjimharris sati_set_ata_command(register_fis, ATA_WRITE_DMA); 180230557Sjimharris 181230557Sjimharris return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0); 182230557Sjimharris} 183230557Sjimharris 184230557Sjimharris/** 185230557Sjimharris * @brief This method performs the retrieving of parameter LBA praparation and setting 186230557Sjimharris * processing flags before/after calling SCSI Verify sector command. 187230557Sjimharris * @return Indicate if the method was successfully completed. 188230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 189230557Sjimharris */ 190230557Sjimharrisstatic 191230557SjimharrisSATI_STATUS sati_reassign_blocks_verify_condition( 192230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 193230557Sjimharris void * scsi_io, 194230557Sjimharris void * ata_io 195230557Sjimharris) 196230557Sjimharris{ 197230557Sjimharris U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0}; 198230557Sjimharris U32 lba_offset; 199230557Sjimharris U8 page_size; 200230557Sjimharris U32 index; 201230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 202230557Sjimharris 203230557Sjimharris lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset; 204230557Sjimharris page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size; 205230557Sjimharris 206230557Sjimharris for(index = 0; index < page_size; index++) 207230557Sjimharris { 208230557Sjimharris sati_get_data_byte(sequence, scsi_io, lba_offset+index, ¤t_lba_bytes[index]); 209230557Sjimharris } 210230557Sjimharris 211230557Sjimharris if (page_size == 4) 212230557Sjimharris set_current_lba(current_lba_bytes, ata_io); 213230557Sjimharris else 214230557Sjimharris set_current_long_lba(current_lba_bytes, ata_io); 215230557Sjimharris 216230557Sjimharris status = sati_reassign_blocks_verify_command(sequence, scsi_io, ata_io); 217230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++; 218230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND; 219230557Sjimharris return status; 220230557Sjimharris} 221230557Sjimharris 222230557Sjimharris/** 223230557Sjimharris * @brief This method performs the retrieving of parameter LBA praparation and setting 224230557Sjimharris * processing flags before/after calling SCSI Write sector command. 225230557Sjimharris * @return Indicate if the method was successfully completed. 226230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases. 227230557Sjimharris */ 228230557Sjimharrisstatic 229230557SjimharrisSATI_STATUS sati_reassign_blocks_write_condition( 230230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 231230557Sjimharris void * scsi_io, 232230557Sjimharris void * ata_io 233230557Sjimharris) 234230557Sjimharris{ 235230557Sjimharris U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0}; 236230557Sjimharris U32 lba_offset; 237230557Sjimharris U8 page_size; 238230557Sjimharris U32 index; 239230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 240230557Sjimharris 241230557Sjimharris lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset; 242230557Sjimharris page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size; 243230557Sjimharris 244230557Sjimharris for(index = 0; index < page_size; index++) 245230557Sjimharris { 246230557Sjimharris sati_get_data_byte(sequence, scsi_io, lba_offset+index, ¤t_lba_bytes[index]); 247230557Sjimharris } 248230557Sjimharris 249230557Sjimharris if (page_size == 4) 250230557Sjimharris set_current_lba(current_lba_bytes, ata_io); 251230557Sjimharris else 252230557Sjimharris set_current_long_lba(current_lba_bytes, ata_io); 253230557Sjimharris 254230557Sjimharris status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io); 255230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++; 256230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND; 257230557Sjimharris return status ; 258230557Sjimharris} 259230557Sjimharris 260230557Sjimharris 261230557Sjimharris/** 262230557Sjimharris * @brief This method will perform the pre-processing of Reassign Blocks command and parameter. 263230557Sjimharris */ 264230557Sjimharrisstatic 265230557Sjimharrisvoid sati_reassign_blocks_initial_processing( 266230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 267230557Sjimharris void * scsi_io, 268230557Sjimharris void * ata_io 269230557Sjimharris) 270230557Sjimharris{ 271230557Sjimharris U32 index; 272230557Sjimharris U8 long_lba_bit; 273230557Sjimharris U8 long_list_bit; 274230557Sjimharris U8 lba_offset; 275230557Sjimharris U8 page_size; 276230557Sjimharris U32 data_transfer_length; 277230557Sjimharris U8 header_bytes[4]={0,0,0,0}; 278230557Sjimharris 279230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 280230557Sjimharris 281230557Sjimharris //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs. 282230557Sjimharris //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs. 283230557Sjimharris if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0) 284230557Sjimharris { 285230557Sjimharris long_lba_bit=0; 286230557Sjimharris page_size = 4; //beginning of lba list 287230557Sjimharris } 288230557Sjimharris else 289230557Sjimharris { 290230557Sjimharris long_lba_bit=1; 291230557Sjimharris page_size = 8; 292230557Sjimharris } 293230557Sjimharris 294230557Sjimharris //The long list (LONGLIST) bit specifies which parameter list header 295230557Sjimharris if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0) 296230557Sjimharris { 297230557Sjimharris long_list_bit=0; 298230557Sjimharris } 299230557Sjimharris else 300230557Sjimharris { 301230557Sjimharris long_list_bit=1; 302230557Sjimharris } 303230557Sjimharris 304230557Sjimharris sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved 305230557Sjimharris 306230557Sjimharris //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes) 307230557Sjimharris for(index = 0; index < 4; index++) 308230557Sjimharris { 309230557Sjimharris sati_get_data_byte(sequence, scsi_io, index, &header_bytes[index]); 310230557Sjimharris } 311230557Sjimharris 312230557Sjimharris lba_offset = 4; //beginning of lba list 313230557Sjimharris 314230557Sjimharris if (long_list_bit==0) 315230557Sjimharris { 316230557Sjimharris //Header byte 2 and 3 is the parameter list length 317230557Sjimharris data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset; 318230557Sjimharris } 319230557Sjimharris else 320230557Sjimharris { 321230557Sjimharris //Header byte 0, 1, 2 and 3 contain the parameter list length 322230557Sjimharris data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) + 323230557Sjimharris (header_bytes[2]<<8) + header_bytes[3] + lba_offset; 324230557Sjimharris } 325230557Sjimharris 326230557Sjimharris sequence->allocation_length = data_transfer_length; 327230557Sjimharris 328230557Sjimharris //Initialized the global processing state 329230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.lba_size = page_size; 330230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.lba_offset = lba_offset; 331230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0; 332230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.block_lists_size = data_transfer_length - lba_offset; 333230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0; 334230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed = FALSE; 335230557Sjimharris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL; 336230557Sjimharris} 337230557Sjimharris 338230557Sjimharris/** 339230557Sjimharris * @brief This method will get the data size of not yet processed data. 340230557Sjimharris * 341230557Sjimharris * @param[in] lba_process_state This parameter points to the processing state fields 342230557Sjimharris * of current block lba. 343230557Sjimharris * 344230557Sjimharris * @return This method returns the sizeof not yet processed data. 345230557Sjimharris */ 346230557Sjimharrisstatic 347230557SjimharrisU32 sati_reassign_blocks_unprocessed_data_size( 348230557Sjimharris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state 349230557Sjimharris) 350230557Sjimharris{ 351230557Sjimharris U32 unprocessed_data_size; 352230557Sjimharris 353230557Sjimharris if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed) 354230557Sjimharris { 355230557Sjimharris unprocessed_data_size = lba_process_state->block_lists_size - 356230557Sjimharris lba_process_state->size_of_data_processed; 357230557Sjimharris } 358230557Sjimharris else 359230557Sjimharris { 360230557Sjimharris unprocessed_data_size = 0; 361230557Sjimharris } 362230557Sjimharris 363230557Sjimharris return unprocessed_data_size; 364230557Sjimharris} 365230557Sjimharris 366230557Sjimharris 367230557Sjimharris/** 368230557Sjimharris * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation. 369230557Sjimharris * 370230557Sjimharris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields 371230557Sjimharris * of current lba block. 372230557Sjimharris * 373230557Sjimharris * 374230557Sjimharris * @return Indicate if the translation was successful. 375230557Sjimharris * @retval SATI_SUCCESS 376230557Sjimharris * @retval SATI_COMPLETE 377230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 378230557Sjimharris */ 379230557Sjimharrisstatic 380230557SjimharrisSATI_STATUS sati_reassign_blocks_process_each_lba( 381230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 382230557Sjimharris void * scsi_io, 383230557Sjimharris void * ata_io 384230557Sjimharris ) 385230557Sjimharris{ 386230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 387230557Sjimharris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 388230557Sjimharris 389230557Sjimharris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 390230557Sjimharris 391230557Sjimharris if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&& 392230557Sjimharris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL)) 393230557Sjimharris { 394230557Sjimharris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 395230557Sjimharris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 396230557Sjimharris } 397230557Sjimharris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&& 398230557Sjimharris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS)) 399230557Sjimharris { 400230557Sjimharris // point to next lba 401230557Sjimharris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 402230557Sjimharris reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size; 403230557Sjimharris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 404230557Sjimharris } 405230557Sjimharris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&& 406230557Sjimharris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL)) 407230557Sjimharris { 408230557Sjimharris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 409230557Sjimharris status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io); 410230557Sjimharris } 411230557Sjimharris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) && 412230557Sjimharris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS)) 413230557Sjimharris { 414230557Sjimharris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 415230557Sjimharris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 416230557Sjimharris } 417230557Sjimharris else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL 418230557Sjimharris { 419230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 420230557Sjimharris } 421230557Sjimharris 422230557Sjimharris return status; 423230557Sjimharris} 424230557Sjimharris 425230557Sjimharris/** 426230557Sjimharris * @brief This method will process the each lba. 427230557Sjimharris * 428230557Sjimharris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields 429230557Sjimharris * of current lba. 430230557Sjimharris * 431230557Sjimharris * @return Indicate if the translation was successful. 432230557Sjimharris * @retval SATI_SUCCESS 433230557Sjimharris * @retval SATI_COMPLETE 434230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 435230557Sjimharris */ 436230557Sjimharrisstatic 437230557SjimharrisSATI_STATUS sati_reassign_blocks_process( 438230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 439230557Sjimharris void * scsi_io, 440230557Sjimharris void * ata_io 441230557Sjimharris) 442230557Sjimharris{ 443230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 444230557Sjimharris 445230557Sjimharris U32 page_size = 0; // in bytes 446230557Sjimharris U32 size_of_data_to_be_processed; 447230557Sjimharris U32 lba_offset; 448230557Sjimharris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 449230557Sjimharris 450230557Sjimharris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 451230557Sjimharris 452230557Sjimharris lba_offset = reassign_blocks_process_state->lba_offset; 453230557Sjimharris page_size = reassign_blocks_process_state->lba_size; 454230557Sjimharris 455230557Sjimharris 456230557Sjimharris if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size) 457230557Sjimharris { 458230557Sjimharris return status; 459230557Sjimharris } 460230557Sjimharris 461230557Sjimharris // Any more lba blocks? If not, done. 462230557Sjimharris if(reassign_blocks_process_state->block_lists_size == 463230557Sjimharris reassign_blocks_process_state->size_of_data_processed) 464230557Sjimharris { 465230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 466230557Sjimharris status = SATI_COMPLETE; 467230557Sjimharris } 468230557Sjimharris //start processing next lba 469230557Sjimharris else 470230557Sjimharris { 471230557Sjimharris size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size 472230557Sjimharris - reassign_blocks_process_state->size_of_data_processed; 473230557Sjimharris 474230557Sjimharris status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io); 475230557Sjimharris 476230557Sjimharris } 477230557Sjimharris 478230557Sjimharris return status; 479230557Sjimharris} 480230557Sjimharris 481230557Sjimharris//****************************************************************************** 482230557Sjimharris//* P U B L I C M E T H O D S 483230557Sjimharris//****************************************************************************** 484230557Sjimharris 485230557Sjimharris/** 486230557Sjimharris * @brief This method will translate the SCSI Reassign Blocks command 487230557Sjimharris * into corresponding ATA commands. Depending upon the capabilities 488230557Sjimharris * supported by the target different ATA commands can be selected. 489230557Sjimharris * Additionally, in some cases more than a single ATA command may 490230557Sjimharris * be required. 491230557Sjimharris * 492230557Sjimharris * @return Indicate if the command translation succeeded. 493230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was 494230557Sjimharris * successful. 495230557Sjimharris * @retval SCI_COMPLETE This is returned if the command translation was 496230557Sjimharris * successful and no ATA commands need to be set. 497230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 498230557Sjimharris * sense data has been created as a result of something specified 499230557Sjimharris * in the parameter data fields. 500230557Sjimharris */ 501230557SjimharrisSATI_STATUS sati_reassign_blocks_translate_command( 502230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 503230557Sjimharris void * scsi_io, 504230557Sjimharris void * ata_io 505230557Sjimharris) 506230557Sjimharris{ 507230557Sjimharris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 508230557Sjimharris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 509230557Sjimharris 510230557Sjimharris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 511230557Sjimharris 512230557Sjimharris sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS; 513230557Sjimharris 514230557Sjimharris //Initial processing if 515230557Sjimharris if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 516230557Sjimharris { 517230557Sjimharris sati_reassign_blocks_initial_processing( 518230557Sjimharris sequence, 519230557Sjimharris scsi_io, 520230557Sjimharris ata_io 521230557Sjimharris ); 522230557Sjimharris } 523230557Sjimharris 524230557Sjimharris // start processing current lba 525230557Sjimharris if(reassign_blocks_process_state->current_lba_processed) 526230557Sjimharris { 527230557Sjimharris reassign_blocks_process_state->ata_command_sent_for_current_lba = 0; 528230557Sjimharris reassign_blocks_process_state->current_lba_processed = FALSE; 529230557Sjimharris } 530230557Sjimharris 531230557Sjimharris status = sati_reassign_blocks_process(sequence, scsi_io, ata_io); 532230557Sjimharris 533230557Sjimharris if(reassign_blocks_process_state->block_lists_size == 534230557Sjimharris reassign_blocks_process_state->size_of_data_processed) 535230557Sjimharris { 536230557Sjimharris // Done this lba 537230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 538230557Sjimharris } 539230557Sjimharris else 540230557Sjimharris { 541230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 542230557Sjimharris } 543230557Sjimharris 544230557Sjimharris if(status == SATI_FAILURE_CHECK_RESPONSE_DATA) 545230557Sjimharris { 546230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 547230557Sjimharris sati_scsi_sense_data_construct( 548230557Sjimharris sequence, 549230557Sjimharris scsi_io, 550230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 551230557Sjimharris SCSI_SENSE_MEDIUM_ERROR, 552230557Sjimharris SCSI_ASC_UNRECOVERED_READ_ERROR, 553230557Sjimharris SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 554230557Sjimharris ); 555230557Sjimharris } 556230557Sjimharris 557230557Sjimharris return status; 558230557Sjimharris} 559230557Sjimharris 560230557Sjimharris/** 561230557Sjimharris * @brief This method will translate the ATA command register FIS 562230557Sjimharris * response into an appropriate SCSI response for Reassign Blocks 563230557Sjimharris * For more information on the parameters passed to this method, 564230557Sjimharris * please reference sati_translate_response(). 565230557Sjimharris * 566230557Sjimharris * @return Indicate if the response translation succeeded. 567230557Sjimharris * @retval SCI_SUCCESS This is returned if the data translation was 568230557Sjimharris * successful. 569230557Sjimharris */ 570230557SjimharrisSATI_STATUS sati_reassign_blocks_translate_response( 571230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 572230557Sjimharris void * scsi_io, 573230557Sjimharris void * ata_io 574230557Sjimharris) 575230557Sjimharris{ 576230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 577230557Sjimharris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 578230557Sjimharris 579230557Sjimharris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 580230557Sjimharris 581230557Sjimharris if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 582230557Sjimharris { 583230557Sjimharris reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL; 584230557Sjimharris 585230557Sjimharris //Checking for the number of ATA commands attempted on current LBA, stop 586230557Sjimharris //the seaquence after 2 commands have returned errors. 587230557Sjimharris if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2) 588230557Sjimharris { 589230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 590230557Sjimharris reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size; 591230557Sjimharris return SATI_SEQUENCE_INCOMPLETE; 592230557Sjimharris } 593230557Sjimharris else 594230557Sjimharris { 595230557Sjimharris sati_scsi_sense_data_construct( 596230557Sjimharris sequence, 597230557Sjimharris scsi_io, 598230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 599230557Sjimharris SCSI_SENSE_MEDIUM_ERROR, 600230557Sjimharris SCSI_ASC_UNRECOVERED_READ_ERROR, 601230557Sjimharris SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 602230557Sjimharris ); 603230557Sjimharris } 604230557Sjimharris 605230557Sjimharris return SATI_FAILURE_CHECK_RESPONSE_DATA; 606230557Sjimharris } 607230557Sjimharris else 608230557Sjimharris { 609230557Sjimharris reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS; 610230557Sjimharris if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2) 611230557Sjimharris reassign_blocks_process_state->current_lba_processed = TRUE; 612230557Sjimharris 613230557Sjimharris if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 614230557Sjimharris { 615230557Sjimharris return SATI_SEQUENCE_INCOMPLETE; 616230557Sjimharris } 617230557Sjimharris } 618230557Sjimharris return SATI_COMPLETE; 619230557Sjimharris} 620230557Sjimharris 621230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 622230557Sjimharris 623