xref: /freebsd/sys/dev/isci/scil/sati_reassign_blocks.c (revision 718cf2ccb9956613756ab15d7a0e28f2c8e91cab)
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,   &current_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,   &current_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