1f11c7f63SJim Harris /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3*718cf2ccSPedro F. Giffuni * 4f11c7f63SJim Harris * This file is provided under a dual BSD/GPLv2 license. When using or 5f11c7f63SJim Harris * redistributing this file, you may do so under either license. 6f11c7f63SJim Harris * 7f11c7f63SJim Harris * GPL LICENSE SUMMARY 8f11c7f63SJim Harris * 9f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10f11c7f63SJim Harris * 11f11c7f63SJim Harris * This program is free software; you can redistribute it and/or modify 12f11c7f63SJim Harris * it under the terms of version 2 of the GNU General Public License as 13f11c7f63SJim Harris * published by the Free Software Foundation. 14f11c7f63SJim Harris * 15f11c7f63SJim Harris * This program is distributed in the hope that it will be useful, but 16f11c7f63SJim Harris * WITHOUT ANY WARRANTY; without even the implied warranty of 17f11c7f63SJim Harris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18f11c7f63SJim Harris * General Public License for more details. 19f11c7f63SJim Harris * 20f11c7f63SJim Harris * You should have received a copy of the GNU General Public License 21f11c7f63SJim Harris * along with this program; if not, write to the Free Software 22f11c7f63SJim Harris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23f11c7f63SJim Harris * The full GNU General Public License is included in this distribution 24f11c7f63SJim Harris * in the file called LICENSE.GPL. 25f11c7f63SJim Harris * 26f11c7f63SJim Harris * BSD LICENSE 27f11c7f63SJim Harris * 28f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29f11c7f63SJim Harris * All rights reserved. 30f11c7f63SJim Harris * 31f11c7f63SJim Harris * Redistribution and use in source and binary forms, with or without 32f11c7f63SJim Harris * modification, are permitted provided that the following conditions 33f11c7f63SJim Harris * are met: 34f11c7f63SJim Harris * 35f11c7f63SJim Harris * * Redistributions of source code must retain the above copyright 36f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer. 37f11c7f63SJim Harris * * Redistributions in binary form must reproduce the above copyright 38f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer in 39f11c7f63SJim Harris * the documentation and/or other materials provided with the 40f11c7f63SJim Harris * distribution. 41f11c7f63SJim Harris * 42f11c7f63SJim Harris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43f11c7f63SJim Harris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44f11c7f63SJim Harris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45f11c7f63SJim Harris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46f11c7f63SJim Harris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47f11c7f63SJim Harris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48f11c7f63SJim Harris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49f11c7f63SJim Harris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50f11c7f63SJim Harris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51f11c7f63SJim Harris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52f11c7f63SJim Harris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53f11c7f63SJim Harris */ 54f11c7f63SJim Harris 55f11c7f63SJim Harris #include <sys/cdefs.h> 56f11c7f63SJim Harris __FBSDID("$FreeBSD$"); 57f11c7f63SJim Harris 58f11c7f63SJim Harris /** 59f11c7f63SJim Harris * @file 60f11c7f63SJim Harris * @brief This file contains the method implementations required to 61f11c7f63SJim Harris * translate the SCSI reassign blocks command. 62f11c7f63SJim Harris */ 63f11c7f63SJim Harris 64f11c7f63SJim Harris #if !defined(DISABLE_SATI_REASSIGN_BLOCKS) 65f11c7f63SJim Harris 66f11c7f63SJim Harris #include <dev/isci/scil/sati_reassign_blocks.h> 67f11c7f63SJim Harris #include <dev/isci/scil/sati_callbacks.h> 68f11c7f63SJim Harris #include <dev/isci/scil/sati_move.h> 69f11c7f63SJim Harris #include <dev/isci/scil/sati_write.h> 70f11c7f63SJim Harris #include <dev/isci/scil/sati_translator_sequence.h> 71f11c7f63SJim Harris #include <dev/isci/scil/sati_util.h> 72f11c7f63SJim Harris #include <dev/isci/scil/intel_scsi.h> 73f11c7f63SJim Harris 74f11c7f63SJim Harris 75f11c7f63SJim Harris //****************************************************************************** 76f11c7f63SJim Harris //* P R I V A T E M E T H O D S 77f11c7f63SJim Harris //****************************************************************************** 78f11c7f63SJim Harris // static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state; 79f11c7f63SJim Harris 80f11c7f63SJim Harris /** 81f11c7f63SJim Harris * @brief This method copies short 24bits LBA bytes to the command register 82f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 83f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 84f11c7f63SJim Harris */ 85f11c7f63SJim Harris static 86f11c7f63SJim Harris void set_current_lba(U8 * lba, void * ata_io) 87f11c7f63SJim Harris { 88f11c7f63SJim Harris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 89f11c7f63SJim Harris 90f11c7f63SJim Harris sati_set_ata_lba_low(register_fis, lba[0]); 91f11c7f63SJim Harris sati_set_ata_lba_mid(register_fis, lba[1]); 92f11c7f63SJim Harris sati_set_ata_lba_high(register_fis, lba[2]); 93f11c7f63SJim Harris sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F)); 94f11c7f63SJim Harris 95f11c7f63SJim Harris 96f11c7f63SJim Harris } 97f11c7f63SJim Harris 98f11c7f63SJim Harris /** 99f11c7f63SJim Harris * @brief This method copies short 48bits LBA bytes to the command register 100f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 101f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 102f11c7f63SJim Harris */ 103f11c7f63SJim Harris static 104f11c7f63SJim Harris void set_current_long_lba(U8 * lba, void * ata_io) 105f11c7f63SJim Harris { 106f11c7f63SJim Harris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 107f11c7f63SJim Harris 108f11c7f63SJim Harris sati_set_ata_lba_low(register_fis, lba[0]); 109f11c7f63SJim Harris sati_set_ata_lba_mid(register_fis, lba[1]); 110f11c7f63SJim Harris sati_set_ata_lba_high(register_fis, lba[2]); 111f11c7f63SJim Harris sati_set_ata_lba_low_exp(register_fis, lba[3]); 112f11c7f63SJim Harris sati_set_ata_lba_mid_exp(register_fis, lba[4]); 113f11c7f63SJim Harris sati_set_ata_lba_high_exp(register_fis, lba[5]); 114f11c7f63SJim Harris } 115f11c7f63SJim Harris 116f11c7f63SJim Harris /** 117f11c7f63SJim Harris * @brief This method performs the SCSI VERIFY command translation 118f11c7f63SJim Harris * functionality. 119f11c7f63SJim Harris * This includes: 120f11c7f63SJim Harris * - setting the command register 121f11c7f63SJim Harris * - setting the device head register 122f11c7f63SJim Harris * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. 123f11c7f63SJim Harris * For more information on the parameters passed to this method, 124f11c7f63SJim Harris * please reference sati_translate_command(). 125f11c7f63SJim Harris * 126f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 127f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 128f11c7f63SJim Harris */ 129f11c7f63SJim Harris static 130f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_verify_command( 131f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 132f11c7f63SJim Harris void * scsi_io, 133f11c7f63SJim Harris void * ata_io 134f11c7f63SJim Harris ) 135f11c7f63SJim Harris { 136f11c7f63SJim Harris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 137f11c7f63SJim Harris 138f11c7f63SJim Harris sati_ata_non_data_command(ata_io, sequence); 139f11c7f63SJim Harris 140f11c7f63SJim Harris // Ensure the device supports the 48 bit feature set. 141f11c7f63SJim Harris if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) 142f11c7f63SJim Harris sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT); 143f11c7f63SJim Harris else 144f11c7f63SJim Harris sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); 145f11c7f63SJim Harris 146f11c7f63SJim Harris return SATI_SUCCESS; 147f11c7f63SJim Harris } 148f11c7f63SJim Harris 149f11c7f63SJim Harris /** 150f11c7f63SJim Harris * @brief This method performs the SCSI Write sector command translation 151f11c7f63SJim Harris * functionality. 152f11c7f63SJim Harris * This includes: 153f11c7f63SJim Harris * - setting the command register 154f11c7f63SJim Harris * - setting the device head register 155f11c7f63SJim Harris * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. 156f11c7f63SJim Harris * For more information on the parameters passed to this method, 157f11c7f63SJim Harris * please reference sati_translate_command(). 158f11c7f63SJim Harris * 159f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 160f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 161f11c7f63SJim Harris */ 162f11c7f63SJim Harris static 163f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_write_command( 164f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 165f11c7f63SJim Harris void * scsi_io, 166f11c7f63SJim Harris void * ata_io 167f11c7f63SJim Harris ) 168f11c7f63SJim Harris { 169f11c7f63SJim Harris U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 170f11c7f63SJim Harris 171f11c7f63SJim Harris sati_ata_non_data_command(ata_io, sequence); 172f11c7f63SJim Harris sequence->data_direction = SATI_DATA_DIRECTION_OUT; 173f11c7f63SJim Harris 174f11c7f63SJim Harris // sati_set_ata_sector_count(register_fis, 1); 175f11c7f63SJim Harris // status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0); 176f11c7f63SJim Harris 177f11c7f63SJim Harris // Ensure the device supports the 48 bit feature set. 178f11c7f63SJim Harris if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE) 179f11c7f63SJim Harris sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT); 180f11c7f63SJim Harris else 181f11c7f63SJim Harris sati_set_ata_command(register_fis, ATA_WRITE_DMA); 182f11c7f63SJim Harris 183f11c7f63SJim Harris return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0); 184f11c7f63SJim Harris } 185f11c7f63SJim Harris 186f11c7f63SJim Harris /** 187f11c7f63SJim Harris * @brief This method performs the retrieving of parameter LBA praparation and setting 188f11c7f63SJim Harris * processing flags before/after calling SCSI Verify sector command. 189f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 190f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 191f11c7f63SJim Harris */ 192f11c7f63SJim Harris static 193f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_verify_condition( 194f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 195f11c7f63SJim Harris void * scsi_io, 196f11c7f63SJim Harris void * ata_io 197f11c7f63SJim Harris ) 198f11c7f63SJim Harris { 199f11c7f63SJim Harris U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0}; 200f11c7f63SJim Harris U32 lba_offset; 201f11c7f63SJim Harris U8 page_size; 202f11c7f63SJim Harris U32 index; 203f11c7f63SJim Harris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 204f11c7f63SJim Harris 205f11c7f63SJim Harris lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset; 206f11c7f63SJim Harris page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size; 207f11c7f63SJim Harris 208f11c7f63SJim Harris for(index = 0; index < page_size; index++) 209f11c7f63SJim Harris { 210f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, lba_offset+index, ¤t_lba_bytes[index]); 211f11c7f63SJim Harris } 212f11c7f63SJim Harris 213f11c7f63SJim Harris if (page_size == 4) 214f11c7f63SJim Harris set_current_lba(current_lba_bytes, ata_io); 215f11c7f63SJim Harris else 216f11c7f63SJim Harris set_current_long_lba(current_lba_bytes, ata_io); 217f11c7f63SJim Harris 218f11c7f63SJim Harris status = sati_reassign_blocks_verify_command(sequence, scsi_io, ata_io); 219f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++; 220f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND; 221f11c7f63SJim Harris return status; 222f11c7f63SJim Harris } 223f11c7f63SJim Harris 224f11c7f63SJim Harris /** 225f11c7f63SJim Harris * @brief This method performs the retrieving of parameter LBA praparation and setting 226f11c7f63SJim Harris * processing flags before/after calling SCSI Write sector command. 227f11c7f63SJim Harris * @return Indicate if the method was successfully completed. 228f11c7f63SJim Harris * @retval SATI_SUCCESS This is returned in all other cases. 229f11c7f63SJim Harris */ 230f11c7f63SJim Harris static 231f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_write_condition( 232f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 233f11c7f63SJim Harris void * scsi_io, 234f11c7f63SJim Harris void * ata_io 235f11c7f63SJim Harris ) 236f11c7f63SJim Harris { 237f11c7f63SJim Harris U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0}; 238f11c7f63SJim Harris U32 lba_offset; 239f11c7f63SJim Harris U8 page_size; 240f11c7f63SJim Harris U32 index; 241f11c7f63SJim Harris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 242f11c7f63SJim Harris 243f11c7f63SJim Harris lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset; 244f11c7f63SJim Harris page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size; 245f11c7f63SJim Harris 246f11c7f63SJim Harris for(index = 0; index < page_size; index++) 247f11c7f63SJim Harris { 248f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, lba_offset+index, ¤t_lba_bytes[index]); 249f11c7f63SJim Harris } 250f11c7f63SJim Harris 251f11c7f63SJim Harris if (page_size == 4) 252f11c7f63SJim Harris set_current_lba(current_lba_bytes, ata_io); 253f11c7f63SJim Harris else 254f11c7f63SJim Harris set_current_long_lba(current_lba_bytes, ata_io); 255f11c7f63SJim Harris 256f11c7f63SJim Harris status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io); 257f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++; 258f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND; 259f11c7f63SJim Harris return status ; 260f11c7f63SJim Harris } 261f11c7f63SJim Harris 262f11c7f63SJim Harris 263f11c7f63SJim Harris /** 264f11c7f63SJim Harris * @brief This method will perform the pre-processing of Reassign Blocks command and parameter. 265f11c7f63SJim Harris */ 266f11c7f63SJim Harris static 267f11c7f63SJim Harris void sati_reassign_blocks_initial_processing( 268f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 269f11c7f63SJim Harris void * scsi_io, 270f11c7f63SJim Harris void * ata_io 271f11c7f63SJim Harris ) 272f11c7f63SJim Harris { 273f11c7f63SJim Harris U32 index; 274f11c7f63SJim Harris U8 long_lba_bit; 275f11c7f63SJim Harris U8 long_list_bit; 276f11c7f63SJim Harris U8 lba_offset; 277f11c7f63SJim Harris U8 page_size; 278f11c7f63SJim Harris U32 data_transfer_length; 279f11c7f63SJim Harris U8 header_bytes[4]={0,0,0,0}; 280f11c7f63SJim Harris 281f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 282f11c7f63SJim Harris 283f11c7f63SJim Harris //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs. 284f11c7f63SJim Harris //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs. 285f11c7f63SJim Harris if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0) 286f11c7f63SJim Harris { 287f11c7f63SJim Harris long_lba_bit=0; 288f11c7f63SJim Harris page_size = 4; //beginning of lba list 289f11c7f63SJim Harris } 290f11c7f63SJim Harris else 291f11c7f63SJim Harris { 292f11c7f63SJim Harris long_lba_bit=1; 293f11c7f63SJim Harris page_size = 8; 294f11c7f63SJim Harris } 295f11c7f63SJim Harris 296f11c7f63SJim Harris //The long list (LONGLIST) bit specifies which parameter list header 297f11c7f63SJim Harris if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0) 298f11c7f63SJim Harris { 299f11c7f63SJim Harris long_list_bit=0; 300f11c7f63SJim Harris } 301f11c7f63SJim Harris else 302f11c7f63SJim Harris { 303f11c7f63SJim Harris long_list_bit=1; 304f11c7f63SJim Harris } 305f11c7f63SJim Harris 306f11c7f63SJim Harris sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved 307f11c7f63SJim Harris 308f11c7f63SJim Harris //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes) 309f11c7f63SJim Harris for(index = 0; index < 4; index++) 310f11c7f63SJim Harris { 311f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, index, &header_bytes[index]); 312f11c7f63SJim Harris } 313f11c7f63SJim Harris 314f11c7f63SJim Harris lba_offset = 4; //beginning of lba list 315f11c7f63SJim Harris 316f11c7f63SJim Harris if (long_list_bit==0) 317f11c7f63SJim Harris { 318f11c7f63SJim Harris //Header byte 2 and 3 is the parameter list length 319f11c7f63SJim Harris data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset; 320f11c7f63SJim Harris } 321f11c7f63SJim Harris else 322f11c7f63SJim Harris { 323f11c7f63SJim Harris //Header byte 0, 1, 2 and 3 contain the parameter list length 324f11c7f63SJim Harris data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) + 325f11c7f63SJim Harris (header_bytes[2]<<8) + header_bytes[3] + lba_offset; 326f11c7f63SJim Harris } 327f11c7f63SJim Harris 328f11c7f63SJim Harris sequence->allocation_length = data_transfer_length; 329f11c7f63SJim Harris 330f11c7f63SJim Harris //Initialized the global processing state 331f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.lba_size = page_size; 332f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.lba_offset = lba_offset; 333f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0; 334f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.block_lists_size = data_transfer_length - lba_offset; 335f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0; 336f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed = FALSE; 337f11c7f63SJim Harris sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL; 338f11c7f63SJim Harris } 339f11c7f63SJim Harris 340f11c7f63SJim Harris /** 341f11c7f63SJim Harris * @brief This method will get the data size of not yet processed data. 342f11c7f63SJim Harris * 343f11c7f63SJim Harris * @param[in] lba_process_state This parameter points to the processing state fields 344f11c7f63SJim Harris * of current block lba. 345f11c7f63SJim Harris * 346f11c7f63SJim Harris * @return This method returns the sizeof not yet processed data. 347f11c7f63SJim Harris */ 348f11c7f63SJim Harris static 349f11c7f63SJim Harris U32 sati_reassign_blocks_unprocessed_data_size( 350f11c7f63SJim Harris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state 351f11c7f63SJim Harris ) 352f11c7f63SJim Harris { 353f11c7f63SJim Harris U32 unprocessed_data_size; 354f11c7f63SJim Harris 355f11c7f63SJim Harris if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed) 356f11c7f63SJim Harris { 357f11c7f63SJim Harris unprocessed_data_size = lba_process_state->block_lists_size - 358f11c7f63SJim Harris lba_process_state->size_of_data_processed; 359f11c7f63SJim Harris } 360f11c7f63SJim Harris else 361f11c7f63SJim Harris { 362f11c7f63SJim Harris unprocessed_data_size = 0; 363f11c7f63SJim Harris } 364f11c7f63SJim Harris 365f11c7f63SJim Harris return unprocessed_data_size; 366f11c7f63SJim Harris } 367f11c7f63SJim Harris 368f11c7f63SJim Harris 369f11c7f63SJim Harris /** 370f11c7f63SJim Harris * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation. 371f11c7f63SJim Harris * 372f11c7f63SJim Harris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields 373f11c7f63SJim Harris * of current lba block. 374f11c7f63SJim Harris * 375f11c7f63SJim Harris * 376f11c7f63SJim Harris * @return Indicate if the translation was successful. 377f11c7f63SJim Harris * @retval SATI_SUCCESS 378f11c7f63SJim Harris * @retval SATI_COMPLETE 379f11c7f63SJim Harris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 380f11c7f63SJim Harris */ 381f11c7f63SJim Harris static 382f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_process_each_lba( 383f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 384f11c7f63SJim Harris void * scsi_io, 385f11c7f63SJim Harris void * ata_io 386f11c7f63SJim Harris ) 387f11c7f63SJim Harris { 388f11c7f63SJim Harris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 389f11c7f63SJim Harris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 390f11c7f63SJim Harris 391f11c7f63SJim Harris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 392f11c7f63SJim Harris 393f11c7f63SJim Harris if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&& 394f11c7f63SJim Harris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL)) 395f11c7f63SJim Harris { 396f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 397f11c7f63SJim Harris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 398f11c7f63SJim Harris } 399f11c7f63SJim Harris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&& 400f11c7f63SJim Harris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS)) 401f11c7f63SJim Harris { 402f11c7f63SJim Harris // point to next lba 403f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 404f11c7f63SJim Harris reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size; 405f11c7f63SJim Harris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 406f11c7f63SJim Harris } 407f11c7f63SJim Harris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&& 408f11c7f63SJim Harris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL)) 409f11c7f63SJim Harris { 410f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 411f11c7f63SJim Harris status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io); 412f11c7f63SJim Harris } 413f11c7f63SJim Harris else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) && 414f11c7f63SJim Harris (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS)) 415f11c7f63SJim Harris { 416f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size; 417f11c7f63SJim Harris status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io); 418f11c7f63SJim Harris } 419f11c7f63SJim Harris else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL 420f11c7f63SJim Harris { 421f11c7f63SJim Harris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 422f11c7f63SJim Harris } 423f11c7f63SJim Harris 424f11c7f63SJim Harris return status; 425f11c7f63SJim Harris } 426f11c7f63SJim Harris 427f11c7f63SJim Harris /** 428f11c7f63SJim Harris * @brief This method will process the each lba. 429f11c7f63SJim Harris * 430f11c7f63SJim Harris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields 431f11c7f63SJim Harris * of current lba. 432f11c7f63SJim Harris * 433f11c7f63SJim Harris * @return Indicate if the translation was successful. 434f11c7f63SJim Harris * @retval SATI_SUCCESS 435f11c7f63SJim Harris * @retval SATI_COMPLETE 436f11c7f63SJim Harris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA 437f11c7f63SJim Harris */ 438f11c7f63SJim Harris static 439f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_process( 440f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 441f11c7f63SJim Harris void * scsi_io, 442f11c7f63SJim Harris void * ata_io 443f11c7f63SJim Harris ) 444f11c7f63SJim Harris { 445f11c7f63SJim Harris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 446f11c7f63SJim Harris 447f11c7f63SJim Harris U32 page_size = 0; // in bytes 448f11c7f63SJim Harris U32 size_of_data_to_be_processed; 449f11c7f63SJim Harris U32 lba_offset; 450f11c7f63SJim Harris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 451f11c7f63SJim Harris 452f11c7f63SJim Harris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 453f11c7f63SJim Harris 454f11c7f63SJim Harris lba_offset = reassign_blocks_process_state->lba_offset; 455f11c7f63SJim Harris page_size = reassign_blocks_process_state->lba_size; 456f11c7f63SJim Harris 457f11c7f63SJim Harris 458f11c7f63SJim Harris if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size) 459f11c7f63SJim Harris { 460f11c7f63SJim Harris return status; 461f11c7f63SJim Harris } 462f11c7f63SJim Harris 463f11c7f63SJim Harris // Any more lba blocks? If not, done. 464f11c7f63SJim Harris if(reassign_blocks_process_state->block_lists_size == 465f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed) 466f11c7f63SJim Harris { 467f11c7f63SJim Harris sequence->state = SATI_SEQUENCE_STATE_FINAL; 468f11c7f63SJim Harris status = SATI_COMPLETE; 469f11c7f63SJim Harris } 470f11c7f63SJim Harris //start processing next lba 471f11c7f63SJim Harris else 472f11c7f63SJim Harris { 473f11c7f63SJim Harris size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size 474f11c7f63SJim Harris - reassign_blocks_process_state->size_of_data_processed; 475f11c7f63SJim Harris 476f11c7f63SJim Harris status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io); 477f11c7f63SJim Harris 478f11c7f63SJim Harris } 479f11c7f63SJim Harris 480f11c7f63SJim Harris return status; 481f11c7f63SJim Harris } 482f11c7f63SJim Harris 483f11c7f63SJim Harris //****************************************************************************** 484f11c7f63SJim Harris //* P U B L I C M E T H O D S 485f11c7f63SJim Harris //****************************************************************************** 486f11c7f63SJim Harris 487f11c7f63SJim Harris /** 488f11c7f63SJim Harris * @brief This method will translate the SCSI Reassign Blocks command 489f11c7f63SJim Harris * into corresponding ATA commands. Depending upon the capabilities 490f11c7f63SJim Harris * supported by the target different ATA commands can be selected. 491f11c7f63SJim Harris * Additionally, in some cases more than a single ATA command may 492f11c7f63SJim Harris * be required. 493f11c7f63SJim Harris * 494f11c7f63SJim Harris * @return Indicate if the command translation succeeded. 495f11c7f63SJim Harris * @retval SCI_SUCCESS This is returned if the command translation was 496f11c7f63SJim Harris * successful. 497f11c7f63SJim Harris * @retval SCI_COMPLETE This is returned if the command translation was 498f11c7f63SJim Harris * successful and no ATA commands need to be set. 499f11c7f63SJim Harris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 500f11c7f63SJim Harris * sense data has been created as a result of something specified 501f11c7f63SJim Harris * in the parameter data fields. 502f11c7f63SJim Harris */ 503f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_translate_command( 504f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 505f11c7f63SJim Harris void * scsi_io, 506f11c7f63SJim Harris void * ata_io 507f11c7f63SJim Harris ) 508f11c7f63SJim Harris { 509f11c7f63SJim Harris SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 510f11c7f63SJim Harris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 511f11c7f63SJim Harris 512f11c7f63SJim Harris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 513f11c7f63SJim Harris 514f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS; 515f11c7f63SJim Harris 516f11c7f63SJim Harris //Initial processing if 517f11c7f63SJim Harris if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE ) 518f11c7f63SJim Harris { 519f11c7f63SJim Harris sati_reassign_blocks_initial_processing( 520f11c7f63SJim Harris sequence, 521f11c7f63SJim Harris scsi_io, 522f11c7f63SJim Harris ata_io 523f11c7f63SJim Harris ); 524f11c7f63SJim Harris } 525f11c7f63SJim Harris 526f11c7f63SJim Harris // start processing current lba 527f11c7f63SJim Harris if(reassign_blocks_process_state->current_lba_processed) 528f11c7f63SJim Harris { 529f11c7f63SJim Harris reassign_blocks_process_state->ata_command_sent_for_current_lba = 0; 530f11c7f63SJim Harris reassign_blocks_process_state->current_lba_processed = FALSE; 531f11c7f63SJim Harris } 532f11c7f63SJim Harris 533f11c7f63SJim Harris status = sati_reassign_blocks_process(sequence, scsi_io, ata_io); 534f11c7f63SJim Harris 535f11c7f63SJim Harris if(reassign_blocks_process_state->block_lists_size == 536f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed) 537f11c7f63SJim Harris { 538f11c7f63SJim Harris // Done this lba 539f11c7f63SJim Harris sequence->state = SATI_SEQUENCE_STATE_FINAL; 540f11c7f63SJim Harris } 541f11c7f63SJim Harris else 542f11c7f63SJim Harris { 543f11c7f63SJim Harris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 544f11c7f63SJim Harris } 545f11c7f63SJim Harris 546f11c7f63SJim Harris if(status == SATI_FAILURE_CHECK_RESPONSE_DATA) 547f11c7f63SJim Harris { 548f11c7f63SJim Harris sequence->state = SATI_SEQUENCE_STATE_FINAL; 549f11c7f63SJim Harris sati_scsi_sense_data_construct( 550f11c7f63SJim Harris sequence, 551f11c7f63SJim Harris scsi_io, 552f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION, 553f11c7f63SJim Harris SCSI_SENSE_MEDIUM_ERROR, 554f11c7f63SJim Harris SCSI_ASC_UNRECOVERED_READ_ERROR, 555f11c7f63SJim Harris SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 556f11c7f63SJim Harris ); 557f11c7f63SJim Harris } 558f11c7f63SJim Harris 559f11c7f63SJim Harris return status; 560f11c7f63SJim Harris } 561f11c7f63SJim Harris 562f11c7f63SJim Harris /** 563f11c7f63SJim Harris * @brief This method will translate the ATA command register FIS 564f11c7f63SJim Harris * response into an appropriate SCSI response for Reassign Blocks 565f11c7f63SJim Harris * For more information on the parameters passed to this method, 566f11c7f63SJim Harris * please reference sati_translate_response(). 567f11c7f63SJim Harris * 568f11c7f63SJim Harris * @return Indicate if the response translation succeeded. 569f11c7f63SJim Harris * @retval SCI_SUCCESS This is returned if the data translation was 570f11c7f63SJim Harris * successful. 571f11c7f63SJim Harris */ 572f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_translate_response( 573f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence, 574f11c7f63SJim Harris void * scsi_io, 575f11c7f63SJim Harris void * ata_io 576f11c7f63SJim Harris ) 577f11c7f63SJim Harris { 578f11c7f63SJim Harris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 579f11c7f63SJim Harris SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state; 580f11c7f63SJim Harris 581f11c7f63SJim Harris reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state; 582f11c7f63SJim Harris 583f11c7f63SJim Harris if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 584f11c7f63SJim Harris { 585f11c7f63SJim Harris reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL; 586f11c7f63SJim Harris 587f11c7f63SJim Harris //Checking for the number of ATA commands attempted on current LBA, stop 588f11c7f63SJim Harris //the seaquence after 2 commands have returned errors. 589f11c7f63SJim Harris if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2) 590f11c7f63SJim Harris { 591f11c7f63SJim Harris sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 592f11c7f63SJim Harris reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size; 593f11c7f63SJim Harris return SATI_SEQUENCE_INCOMPLETE; 594f11c7f63SJim Harris } 595f11c7f63SJim Harris else 596f11c7f63SJim Harris { 597f11c7f63SJim Harris sati_scsi_sense_data_construct( 598f11c7f63SJim Harris sequence, 599f11c7f63SJim Harris scsi_io, 600f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION, 601f11c7f63SJim Harris SCSI_SENSE_MEDIUM_ERROR, 602f11c7f63SJim Harris SCSI_ASC_UNRECOVERED_READ_ERROR, 603f11c7f63SJim Harris SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 604f11c7f63SJim Harris ); 605f11c7f63SJim Harris } 606f11c7f63SJim Harris 607f11c7f63SJim Harris return SATI_FAILURE_CHECK_RESPONSE_DATA; 608f11c7f63SJim Harris } 609f11c7f63SJim Harris else 610f11c7f63SJim Harris { 611f11c7f63SJim Harris reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS; 612f11c7f63SJim Harris if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2) 613f11c7f63SJim Harris reassign_blocks_process_state->current_lba_processed = TRUE; 614f11c7f63SJim Harris 615f11c7f63SJim Harris if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE) 616f11c7f63SJim Harris { 617f11c7f63SJim Harris return SATI_SEQUENCE_INCOMPLETE; 618f11c7f63SJim Harris } 619f11c7f63SJim Harris } 620f11c7f63SJim Harris return SATI_COMPLETE; 621f11c7f63SJim Harris } 622f11c7f63SJim Harris 623f11c7f63SJim Harris #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) 624f11c7f63SJim Harris 625