xref: /freebsd/sys/dev/isci/scil/sati_reassign_blocks.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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 /**
57f11c7f63SJim Harris  * @file
58f11c7f63SJim Harris  * @brief This file contains the method implementations required to
59f11c7f63SJim Harris  *        translate the SCSI reassign blocks command.
60f11c7f63SJim Harris  */
61f11c7f63SJim Harris 
62f11c7f63SJim Harris #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
63f11c7f63SJim Harris 
64f11c7f63SJim Harris #include <dev/isci/scil/sati_reassign_blocks.h>
65f11c7f63SJim Harris #include <dev/isci/scil/sati_callbacks.h>
66f11c7f63SJim Harris #include <dev/isci/scil/sati_move.h>
67f11c7f63SJim Harris #include <dev/isci/scil/sati_write.h>
68f11c7f63SJim Harris #include <dev/isci/scil/sati_translator_sequence.h>
69f11c7f63SJim Harris #include <dev/isci/scil/sati_util.h>
70f11c7f63SJim Harris #include <dev/isci/scil/intel_scsi.h>
71f11c7f63SJim Harris 
72f11c7f63SJim Harris 
73f11c7f63SJim Harris //******************************************************************************
74f11c7f63SJim Harris //* P R I V A T E   M E T H O D S
75f11c7f63SJim Harris //******************************************************************************
76f11c7f63SJim Harris // static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state;
77f11c7f63SJim Harris 
78f11c7f63SJim Harris /**
79f11c7f63SJim Harris  * @brief This method copies short 24bits LBA bytes to the command register
80f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
81f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
82f11c7f63SJim Harris  */
83f11c7f63SJim Harris static
set_current_lba(U8 * lba,void * ata_io)84f11c7f63SJim Harris void set_current_lba(U8 * lba, void  * ata_io)
85f11c7f63SJim Harris {
86f11c7f63SJim Harris    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
87f11c7f63SJim Harris 
88f11c7f63SJim Harris    sati_set_ata_lba_low(register_fis, lba[0]);
89f11c7f63SJim Harris    sati_set_ata_lba_mid(register_fis, lba[1]);
90f11c7f63SJim Harris    sati_set_ata_lba_high(register_fis, lba[2]);
91f11c7f63SJim Harris    sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F));
92f11c7f63SJim Harris 
93f11c7f63SJim Harris 
94f11c7f63SJim Harris }
95f11c7f63SJim Harris 
96f11c7f63SJim Harris /**
97f11c7f63SJim Harris  * @brief This method copies short 48bits LBA bytes to the command register
98f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
99f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
100f11c7f63SJim Harris  */
101f11c7f63SJim Harris static
set_current_long_lba(U8 * lba,void * ata_io)102f11c7f63SJim Harris void set_current_long_lba(U8 * lba, void  * ata_io)
103f11c7f63SJim Harris {
104f11c7f63SJim Harris    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
105f11c7f63SJim Harris 
106f11c7f63SJim Harris    sati_set_ata_lba_low(register_fis, lba[0]);
107f11c7f63SJim Harris    sati_set_ata_lba_mid(register_fis, lba[1]);
108f11c7f63SJim Harris    sati_set_ata_lba_high(register_fis, lba[2]);
109f11c7f63SJim Harris    sati_set_ata_lba_low_exp(register_fis, lba[3]);
110f11c7f63SJim Harris    sati_set_ata_lba_mid_exp(register_fis, lba[4]);
111f11c7f63SJim Harris    sati_set_ata_lba_high_exp(register_fis, lba[5]);
112f11c7f63SJim Harris }
113f11c7f63SJim Harris 
114f11c7f63SJim Harris /**
115f11c7f63SJim Harris  * @brief This method performs the SCSI VERIFY command translation
116f11c7f63SJim Harris  *        functionality.
117f11c7f63SJim Harris  *        This includes:
118f11c7f63SJim Harris  *        - setting the command register
119f11c7f63SJim Harris  *        - setting the device head register
120f11c7f63SJim Harris  *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
121f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
122f11c7f63SJim Harris  *        please reference sati_translate_command().
123f11c7f63SJim Harris  *
124f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
125f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
126f11c7f63SJim Harris  */
127f11c7f63SJim Harris static
sati_reassign_blocks_verify_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)128f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_verify_command(
129f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
130f11c7f63SJim Harris    void                       * scsi_io,
131f11c7f63SJim Harris    void                       * ata_io
132f11c7f63SJim Harris )
133f11c7f63SJim Harris {
134f11c7f63SJim Harris    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
135f11c7f63SJim Harris 
136f11c7f63SJim Harris    sati_ata_non_data_command(ata_io, sequence);
137f11c7f63SJim Harris 
138f11c7f63SJim Harris    // Ensure the device supports the 48 bit feature set.
139f11c7f63SJim Harris    if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
140f11c7f63SJim Harris       sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
141f11c7f63SJim Harris    else
142f11c7f63SJim Harris       sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
143f11c7f63SJim Harris 
144f11c7f63SJim Harris    return SATI_SUCCESS;
145f11c7f63SJim Harris }
146f11c7f63SJim Harris 
147f11c7f63SJim Harris /**
148f11c7f63SJim Harris  * @brief This method performs the SCSI Write sector command translation
149f11c7f63SJim Harris  *        functionality.
150f11c7f63SJim Harris  *        This includes:
151f11c7f63SJim Harris  *        - setting the command register
152f11c7f63SJim Harris  *        - setting the device head register
153f11c7f63SJim Harris  *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
154f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
155f11c7f63SJim Harris  *        please reference sati_translate_command().
156f11c7f63SJim Harris  *
157f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
158f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
159f11c7f63SJim Harris  */
160f11c7f63SJim Harris static
sati_reassign_blocks_write_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)161f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_write_command(
162f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
163f11c7f63SJim Harris    void                       * scsi_io,
164f11c7f63SJim Harris    void                       * ata_io
165f11c7f63SJim Harris )
166f11c7f63SJim Harris {
167f11c7f63SJim Harris    U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
168f11c7f63SJim Harris 
169f11c7f63SJim Harris    sati_ata_non_data_command(ata_io, sequence);
170f11c7f63SJim Harris    sequence->data_direction = SATI_DATA_DIRECTION_OUT;
171f11c7f63SJim Harris 
172f11c7f63SJim Harris //   sati_set_ata_sector_count(register_fis, 1);
173f11c7f63SJim Harris //   status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
174f11c7f63SJim Harris 
175f11c7f63SJim Harris    // Ensure the device supports the 48 bit feature set.
176f11c7f63SJim Harris    if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
177f11c7f63SJim Harris       sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT);
178f11c7f63SJim Harris    else
179f11c7f63SJim Harris       sati_set_ata_command(register_fis, ATA_WRITE_DMA);
180f11c7f63SJim Harris 
181f11c7f63SJim Harris    return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
182f11c7f63SJim Harris }
183f11c7f63SJim Harris 
184f11c7f63SJim Harris /**
185f11c7f63SJim Harris  * @brief This method performs the retrieving of parameter LBA praparation and setting
186f11c7f63SJim Harris  *        processing flags before/after calling SCSI Verify sector command.
187f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
188f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
189f11c7f63SJim Harris  */
190f11c7f63SJim Harris static
sati_reassign_blocks_verify_condition(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)191f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_verify_condition(
192f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
193f11c7f63SJim Harris    void     * scsi_io,
194f11c7f63SJim Harris    void     * ata_io
195f11c7f63SJim Harris )
196f11c7f63SJim Harris {
197f11c7f63SJim Harris    U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
198f11c7f63SJim Harris    U32 lba_offset;
199f11c7f63SJim Harris    U8 page_size;
200f11c7f63SJim Harris    U32 index;
201f11c7f63SJim Harris    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
202f11c7f63SJim Harris 
203f11c7f63SJim Harris    lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
204f11c7f63SJim Harris    page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
205f11c7f63SJim Harris 
206f11c7f63SJim Harris    for(index = 0; index < page_size; index++)
207f11c7f63SJim Harris    {
208f11c7f63SJim Harris       sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
209f11c7f63SJim Harris    }
210f11c7f63SJim Harris 
211f11c7f63SJim Harris    if (page_size == 4)
212f11c7f63SJim Harris       set_current_lba(current_lba_bytes, ata_io);
213f11c7f63SJim Harris    else
214f11c7f63SJim Harris       set_current_long_lba(current_lba_bytes, ata_io);
215f11c7f63SJim Harris 
216f11c7f63SJim Harris    status = sati_reassign_blocks_verify_command(sequence, scsi_io, ata_io);
217f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
218f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
219f11c7f63SJim Harris    return  status;
220f11c7f63SJim Harris }
221f11c7f63SJim Harris 
222f11c7f63SJim Harris /**
223f11c7f63SJim Harris  * @brief This method performs the retrieving of parameter LBA praparation and setting
224f11c7f63SJim Harris  *        processing flags before/after calling SCSI Write sector command.
225f11c7f63SJim Harris  * @return Indicate if the method was successfully completed.
226f11c7f63SJim Harris  * @retval SATI_SUCCESS This is returned in all other cases.
227f11c7f63SJim Harris  */
228f11c7f63SJim Harris static
sati_reassign_blocks_write_condition(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)229f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_write_condition(
230f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
231f11c7f63SJim Harris    void     * scsi_io,
232f11c7f63SJim Harris    void     * ata_io
233f11c7f63SJim Harris )
234f11c7f63SJim Harris {
235f11c7f63SJim Harris    U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
236f11c7f63SJim Harris    U32 lba_offset;
237f11c7f63SJim Harris    U8 page_size;
238f11c7f63SJim Harris    U32 index;
239f11c7f63SJim Harris    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
240f11c7f63SJim Harris 
241f11c7f63SJim Harris    lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
242f11c7f63SJim Harris    page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
243f11c7f63SJim Harris 
244f11c7f63SJim Harris    for(index = 0; index < page_size; index++)
245f11c7f63SJim Harris    {
246f11c7f63SJim Harris       sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
247f11c7f63SJim Harris    }
248f11c7f63SJim Harris 
249f11c7f63SJim Harris    if (page_size == 4)
250f11c7f63SJim Harris       set_current_lba(current_lba_bytes, ata_io);
251f11c7f63SJim Harris    else
252f11c7f63SJim Harris       set_current_long_lba(current_lba_bytes, ata_io);
253f11c7f63SJim Harris 
254f11c7f63SJim Harris    status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io);
255f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
256f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
257f11c7f63SJim Harris    return  status ;
258f11c7f63SJim Harris }
259f11c7f63SJim Harris 
260f11c7f63SJim Harris 
261f11c7f63SJim Harris /**
262f11c7f63SJim Harris  * @brief This method will perform the pre-processing of Reassign Blocks command and parameter.
263f11c7f63SJim Harris  */
264f11c7f63SJim Harris static
sati_reassign_blocks_initial_processing(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)265f11c7f63SJim Harris void  sati_reassign_blocks_initial_processing(
266f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
267f11c7f63SJim Harris    void                       * scsi_io,
268f11c7f63SJim Harris    void                       * ata_io
269f11c7f63SJim Harris )
270f11c7f63SJim Harris {
271f11c7f63SJim Harris    U32 index;
272f11c7f63SJim Harris    U8 long_lba_bit;
273f11c7f63SJim Harris    U8 long_list_bit;
274f11c7f63SJim Harris    U8 lba_offset;
275f11c7f63SJim Harris    U8  page_size;
276f11c7f63SJim Harris    U32 data_transfer_length;
277f11c7f63SJim Harris    U8 header_bytes[4]={0,0,0,0};
278f11c7f63SJim Harris 
279f11c7f63SJim Harris    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
280f11c7f63SJim Harris 
281f11c7f63SJim Harris    //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs.
282f11c7f63SJim Harris    //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs.
283f11c7f63SJim Harris    if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0)
284f11c7f63SJim Harris    {
285f11c7f63SJim Harris       long_lba_bit=0;
286f11c7f63SJim Harris       page_size = 4; //beginning of lba list
287f11c7f63SJim Harris    }
288f11c7f63SJim Harris    else
289f11c7f63SJim Harris    {
290f11c7f63SJim Harris       long_lba_bit=1;
291f11c7f63SJim Harris       page_size = 8;
292f11c7f63SJim Harris    }
293f11c7f63SJim Harris 
294f11c7f63SJim Harris    //The long list (LONGLIST) bit specifies which parameter list header
295f11c7f63SJim Harris    if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0)
296f11c7f63SJim Harris    {
297f11c7f63SJim Harris       long_list_bit=0;
298f11c7f63SJim Harris    }
299f11c7f63SJim Harris    else
300f11c7f63SJim Harris    {
301f11c7f63SJim Harris       long_list_bit=1;
302f11c7f63SJim Harris    }
303f11c7f63SJim Harris 
304f11c7f63SJim Harris    sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved
305f11c7f63SJim Harris 
306f11c7f63SJim Harris    //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes)
307f11c7f63SJim Harris    for(index = 0; index < 4; index++)
308f11c7f63SJim Harris    {
309f11c7f63SJim Harris       sati_get_data_byte(sequence, scsi_io, index,   &header_bytes[index]);
310f11c7f63SJim Harris    }
311f11c7f63SJim Harris 
312f11c7f63SJim Harris    lba_offset = 4; //beginning of lba list
313f11c7f63SJim Harris 
314f11c7f63SJim Harris    if (long_list_bit==0)
315f11c7f63SJim Harris    {
316f11c7f63SJim Harris       //Header byte 2 and 3 is the parameter list length
317f11c7f63SJim Harris       data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
318f11c7f63SJim Harris    }
319f11c7f63SJim Harris    else
320f11c7f63SJim Harris    {
321f11c7f63SJim Harris       //Header byte 0, 1, 2 and 3 contain the parameter list length
322f11c7f63SJim Harris       data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) +
323f11c7f63SJim Harris          (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
324f11c7f63SJim Harris    }
325f11c7f63SJim Harris 
326f11c7f63SJim Harris    sequence->allocation_length = data_transfer_length;
327f11c7f63SJim Harris 
328f11c7f63SJim Harris    //Initialized the global processing state
329f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.lba_size   =     page_size;
330f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.lba_offset =     lba_offset;
331f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0;
332f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.block_lists_size       = data_transfer_length  -  lba_offset;
333f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0;
334f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed  = FALSE;
335f11c7f63SJim Harris    sequence->command_specific_data.reassign_blocks_process_state.ata_command_status     = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
336f11c7f63SJim Harris }
337f11c7f63SJim Harris 
338f11c7f63SJim Harris /**
339f11c7f63SJim Harris  * @brief This method will get the data size of not yet processed data.
340f11c7f63SJim Harris  *
341f11c7f63SJim Harris  * @param[in] lba_process_state This parameter points to the processing state fields
342f11c7f63SJim Harris  *            of current block lba.
343f11c7f63SJim Harris  *
344f11c7f63SJim Harris  * @return This method returns the sizeof not yet processed data.
345f11c7f63SJim Harris  */
346f11c7f63SJim Harris static
sati_reassign_blocks_unprocessed_data_size(SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state)347f11c7f63SJim Harris U32 sati_reassign_blocks_unprocessed_data_size(
348f11c7f63SJim Harris    SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state
349f11c7f63SJim Harris )
350f11c7f63SJim Harris {
351f11c7f63SJim Harris    U32 unprocessed_data_size;
352f11c7f63SJim Harris 
353f11c7f63SJim Harris    if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed)
354f11c7f63SJim Harris    {
355f11c7f63SJim Harris       unprocessed_data_size = lba_process_state->block_lists_size -
356f11c7f63SJim Harris          lba_process_state->size_of_data_processed;
357f11c7f63SJim Harris    }
358f11c7f63SJim Harris    else
359f11c7f63SJim Harris    {
360f11c7f63SJim Harris       unprocessed_data_size = 0;
361f11c7f63SJim Harris    }
362f11c7f63SJim Harris 
363f11c7f63SJim Harris    return unprocessed_data_size;
364f11c7f63SJim Harris }
365f11c7f63SJim Harris 
366f11c7f63SJim Harris 
367f11c7f63SJim Harris /**
368f11c7f63SJim Harris  * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation.
369f11c7f63SJim Harris  *
370f11c7f63SJim Harris  * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
371f11c7f63SJim Harris  *            of current lba block.
372f11c7f63SJim Harris  *
373f11c7f63SJim Harris  *
374f11c7f63SJim Harris  * @return Indicate if the translation was successful.
375f11c7f63SJim Harris  * @retval SATI_SUCCESS
376f11c7f63SJim Harris  * @retval SATI_COMPLETE
377f11c7f63SJim Harris  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
378f11c7f63SJim Harris  */
379f11c7f63SJim Harris static
sati_reassign_blocks_process_each_lba(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)380f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_process_each_lba(
381f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
382f11c7f63SJim Harris    void                       * scsi_io,
383f11c7f63SJim Harris    void                       * ata_io
384f11c7f63SJim Harris    )
385f11c7f63SJim Harris {
386f11c7f63SJim Harris    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
387f11c7f63SJim Harris    SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
388f11c7f63SJim Harris 
389f11c7f63SJim Harris    reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
390f11c7f63SJim Harris 
391f11c7f63SJim Harris    if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
392f11c7f63SJim Harris       (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
393f11c7f63SJim Harris    {
394f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
395f11c7f63SJim Harris       status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
396f11c7f63SJim Harris    }
397f11c7f63SJim Harris    else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
398f11c7f63SJim Harris       (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
399f11c7f63SJim Harris    {
400f11c7f63SJim Harris       // point to next lba
401f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
402f11c7f63SJim Harris       reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size;
403f11c7f63SJim Harris       status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
404f11c7f63SJim Harris    }
405f11c7f63SJim Harris    else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&&
406f11c7f63SJim Harris       (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
407f11c7f63SJim Harris    {
408f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
409f11c7f63SJim Harris       status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io);
410f11c7f63SJim Harris    }
411f11c7f63SJim Harris    else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) &&
412f11c7f63SJim Harris       (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
413f11c7f63SJim Harris    {
414f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
415f11c7f63SJim Harris       status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
416f11c7f63SJim Harris    }
417f11c7f63SJim Harris    else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL
418f11c7f63SJim Harris    {
419f11c7f63SJim Harris       status = SATI_FAILURE_CHECK_RESPONSE_DATA;
420f11c7f63SJim Harris    }
421f11c7f63SJim Harris 
422f11c7f63SJim Harris    return status;
423f11c7f63SJim Harris }
424f11c7f63SJim Harris 
425f11c7f63SJim Harris /**
426f11c7f63SJim Harris  * @brief This method will process the each lba.
427f11c7f63SJim Harris  *
428f11c7f63SJim Harris  * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
429f11c7f63SJim Harris  *            of current lba.
430f11c7f63SJim Harris  *
431f11c7f63SJim Harris  * @return Indicate if the translation was successful.
432f11c7f63SJim Harris  * @retval SATI_SUCCESS
433f11c7f63SJim Harris  * @retval SATI_COMPLETE
434f11c7f63SJim Harris  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
435f11c7f63SJim Harris  */
436f11c7f63SJim Harris static
sati_reassign_blocks_process(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)437f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_process(
438f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
439f11c7f63SJim Harris    void                       * scsi_io,
440f11c7f63SJim Harris    void                       * ata_io
441f11c7f63SJim Harris )
442f11c7f63SJim Harris {
443f11c7f63SJim Harris    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
444f11c7f63SJim Harris 
445f11c7f63SJim Harris    U32 page_size = 0; // in bytes
446f11c7f63SJim Harris    U32 size_of_data_to_be_processed;
447f11c7f63SJim Harris    U32 lba_offset;
448f11c7f63SJim Harris    SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
449f11c7f63SJim Harris 
450f11c7f63SJim Harris    reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
451f11c7f63SJim Harris 
452f11c7f63SJim Harris    lba_offset = reassign_blocks_process_state->lba_offset;
453f11c7f63SJim Harris    page_size  = reassign_blocks_process_state->lba_size;
454f11c7f63SJim Harris 
455f11c7f63SJim Harris 
456f11c7f63SJim Harris    if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size)
457f11c7f63SJim Harris    {
458f11c7f63SJim Harris       return status;
459f11c7f63SJim Harris    }
460f11c7f63SJim Harris 
461f11c7f63SJim Harris    // Any more lba blocks? If not, done.
462f11c7f63SJim Harris    if(reassign_blocks_process_state->block_lists_size ==
463f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed)
464f11c7f63SJim Harris    {
465f11c7f63SJim Harris       sequence->state = SATI_SEQUENCE_STATE_FINAL;
466f11c7f63SJim Harris       status = SATI_COMPLETE;
467f11c7f63SJim Harris    }
468f11c7f63SJim Harris    //start processing next lba
469f11c7f63SJim Harris    else
470f11c7f63SJim Harris    {
471f11c7f63SJim Harris       size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size
472f11c7f63SJim Harris          - reassign_blocks_process_state->size_of_data_processed;
473f11c7f63SJim Harris 
474f11c7f63SJim Harris       status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io);
475f11c7f63SJim Harris 
476f11c7f63SJim Harris    }
477f11c7f63SJim Harris 
478f11c7f63SJim Harris    return status;
479f11c7f63SJim Harris }
480f11c7f63SJim Harris 
481f11c7f63SJim Harris //******************************************************************************
482f11c7f63SJim Harris //* P U B L I C   M E T H O D S
483f11c7f63SJim Harris //******************************************************************************
484f11c7f63SJim Harris 
485f11c7f63SJim Harris /**
486f11c7f63SJim Harris  * @brief This method will translate the SCSI Reassign Blocks command
487f11c7f63SJim Harris  *        into corresponding ATA commands.  Depending upon the capabilities
488f11c7f63SJim Harris  *        supported by the target different ATA commands can be selected.
489f11c7f63SJim Harris  *        Additionally, in some cases more than a single ATA command may
490f11c7f63SJim Harris  *        be required.
491f11c7f63SJim Harris  *
492f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
493f11c7f63SJim Harris  * @retval SCI_SUCCESS This is returned if the command translation was
494f11c7f63SJim Harris  *         successful.
495f11c7f63SJim Harris  * @retval SCI_COMPLETE This is returned if the command translation was
496f11c7f63SJim Harris  *         successful and no ATA commands need to be set.
497f11c7f63SJim Harris  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
498f11c7f63SJim Harris  *         sense data has been created as a result of something specified
499f11c7f63SJim Harris  *         in the parameter data fields.
500f11c7f63SJim Harris  */
sati_reassign_blocks_translate_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)501f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_translate_command(
502f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
503f11c7f63SJim Harris    void                       * scsi_io,
504f11c7f63SJim Harris    void                       * ata_io
505f11c7f63SJim Harris )
506f11c7f63SJim Harris {
507f11c7f63SJim Harris    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
508f11c7f63SJim Harris    SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
509f11c7f63SJim Harris 
510f11c7f63SJim Harris    reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
511f11c7f63SJim Harris 
512f11c7f63SJim Harris    sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS;
513f11c7f63SJim Harris 
514f11c7f63SJim Harris    //Initial processing if
515f11c7f63SJim Harris    if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
516f11c7f63SJim Harris    {
517f11c7f63SJim Harris       sati_reassign_blocks_initial_processing(
518f11c7f63SJim Harris          sequence,
519f11c7f63SJim Harris          scsi_io,
520f11c7f63SJim Harris          ata_io
521f11c7f63SJim Harris       );
522f11c7f63SJim Harris    }
523f11c7f63SJim Harris 
524f11c7f63SJim Harris    // start processing current lba
525f11c7f63SJim Harris    if(reassign_blocks_process_state->current_lba_processed)
526f11c7f63SJim Harris    {
527f11c7f63SJim Harris       reassign_blocks_process_state->ata_command_sent_for_current_lba = 0;
528f11c7f63SJim Harris       reassign_blocks_process_state->current_lba_processed = FALSE;
529f11c7f63SJim Harris    }
530f11c7f63SJim Harris 
531f11c7f63SJim Harris    status = sati_reassign_blocks_process(sequence, scsi_io, ata_io);
532f11c7f63SJim Harris 
533f11c7f63SJim Harris    if(reassign_blocks_process_state->block_lists_size ==
534f11c7f63SJim Harris       reassign_blocks_process_state->size_of_data_processed)
535f11c7f63SJim Harris    {
536f11c7f63SJim Harris       // Done this lba
537f11c7f63SJim Harris       sequence->state = SATI_SEQUENCE_STATE_FINAL;
538f11c7f63SJim Harris    }
539f11c7f63SJim Harris    else
540f11c7f63SJim Harris    {
541f11c7f63SJim Harris       sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
542f11c7f63SJim Harris    }
543f11c7f63SJim Harris 
544f11c7f63SJim Harris    if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
545f11c7f63SJim Harris    {
546f11c7f63SJim Harris       sequence->state = SATI_SEQUENCE_STATE_FINAL;
547f11c7f63SJim Harris       sati_scsi_sense_data_construct(
548f11c7f63SJim Harris          sequence,
549f11c7f63SJim Harris          scsi_io,
550f11c7f63SJim Harris          SCSI_STATUS_CHECK_CONDITION,
551f11c7f63SJim Harris          SCSI_SENSE_MEDIUM_ERROR,
552f11c7f63SJim Harris          SCSI_ASC_UNRECOVERED_READ_ERROR,
553f11c7f63SJim Harris          SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
554f11c7f63SJim Harris       );
555f11c7f63SJim Harris    }
556f11c7f63SJim Harris 
557f11c7f63SJim Harris    return status;
558f11c7f63SJim Harris }
559f11c7f63SJim Harris 
560f11c7f63SJim Harris /**
561f11c7f63SJim Harris  * @brief This method will translate the ATA command register FIS
562f11c7f63SJim Harris  *        response into an appropriate SCSI response for Reassign Blocks
563f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
564f11c7f63SJim Harris  *        please reference sati_translate_response().
565f11c7f63SJim Harris  *
566f11c7f63SJim Harris  * @return Indicate if the response translation succeeded.
567f11c7f63SJim Harris  * @retval SCI_SUCCESS This is returned if the data translation was
568f11c7f63SJim Harris  *         successful.
569f11c7f63SJim Harris  */
sati_reassign_blocks_translate_response(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)570f11c7f63SJim Harris SATI_STATUS sati_reassign_blocks_translate_response(
571f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
572f11c7f63SJim Harris    void                       * scsi_io,
573f11c7f63SJim Harris    void                       * ata_io
574f11c7f63SJim Harris )
575f11c7f63SJim Harris {
576f11c7f63SJim Harris    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
577f11c7f63SJim Harris    SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
578f11c7f63SJim Harris 
579f11c7f63SJim Harris    reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
580f11c7f63SJim Harris 
581f11c7f63SJim Harris    if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
582f11c7f63SJim Harris    {
583f11c7f63SJim Harris       reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
584f11c7f63SJim Harris 
585f11c7f63SJim Harris       //Checking for the number of ATA commands attempted on current LBA, stop
586f11c7f63SJim Harris       //the seaquence after 2 commands have returned errors.
587f11c7f63SJim Harris       if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2)
588f11c7f63SJim Harris       {
589f11c7f63SJim Harris          sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
590f11c7f63SJim Harris          reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size;
591f11c7f63SJim Harris          return SATI_SEQUENCE_INCOMPLETE;
592f11c7f63SJim Harris       }
593f11c7f63SJim Harris       else
594f11c7f63SJim Harris       {
595f11c7f63SJim Harris          sati_scsi_sense_data_construct(
596f11c7f63SJim Harris             sequence,
597f11c7f63SJim Harris             scsi_io,
598f11c7f63SJim Harris             SCSI_STATUS_CHECK_CONDITION,
599f11c7f63SJim Harris             SCSI_SENSE_MEDIUM_ERROR,
600f11c7f63SJim Harris             SCSI_ASC_UNRECOVERED_READ_ERROR,
601f11c7f63SJim Harris             SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
602f11c7f63SJim Harris          );
603f11c7f63SJim Harris       }
604f11c7f63SJim Harris 
605f11c7f63SJim Harris       return SATI_FAILURE_CHECK_RESPONSE_DATA;
606f11c7f63SJim Harris    }
607f11c7f63SJim Harris    else
608f11c7f63SJim Harris    {
609f11c7f63SJim Harris       reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS;
610f11c7f63SJim Harris       if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2)
611f11c7f63SJim Harris          reassign_blocks_process_state->current_lba_processed = TRUE;
612f11c7f63SJim Harris 
613f11c7f63SJim Harris       if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
614f11c7f63SJim Harris       {
615f11c7f63SJim Harris          return SATI_SEQUENCE_INCOMPLETE;
616f11c7f63SJim Harris       }
617f11c7f63SJim Harris    }
618f11c7f63SJim Harris    return SATI_COMPLETE;
619f11c7f63SJim Harris }
620f11c7f63SJim Harris 
621f11c7f63SJim Harris #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
622f11c7f63SJim Harris 
623