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, ¤t_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, ¤t_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