1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris * @brief This file contains the method implementations required to
59230557Sjimharris *        translate the SCSI reassign blocks command.
60230557Sjimharris */
61230557Sjimharris
62230557Sjimharris#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/sati_reassign_blocks.h>
65230557Sjimharris#include <dev/isci/scil/sati_callbacks.h>
66230557Sjimharris#include <dev/isci/scil/sati_move.h>
67230557Sjimharris#include <dev/isci/scil/sati_write.h>
68230557Sjimharris#include <dev/isci/scil/sati_translator_sequence.h>
69230557Sjimharris#include <dev/isci/scil/sati_util.h>
70230557Sjimharris#include <dev/isci/scil/intel_scsi.h>
71230557Sjimharris
72230557Sjimharris
73230557Sjimharris//******************************************************************************
74230557Sjimharris//* P R I V A T E   M E T H O D S
75230557Sjimharris//******************************************************************************
76230557Sjimharris// static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state;
77230557Sjimharris
78230557Sjimharris/**
79230557Sjimharris * @brief This method copies short 24bits LBA bytes to the command register
80230557Sjimharris * @return Indicate if the method was successfully completed.
81230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
82230557Sjimharris */
83230557Sjimharrisstatic
84230557Sjimharrisvoid set_current_lba(U8 * lba, void  * ata_io)
85230557Sjimharris{
86230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
87230557Sjimharris
88230557Sjimharris   sati_set_ata_lba_low(register_fis, lba[0]);
89230557Sjimharris   sati_set_ata_lba_mid(register_fis, lba[1]);
90230557Sjimharris   sati_set_ata_lba_high(register_fis, lba[2]);
91230557Sjimharris   sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F));
92230557Sjimharris
93230557Sjimharris
94230557Sjimharris}
95230557Sjimharris
96230557Sjimharris/**
97230557Sjimharris * @brief This method copies short 48bits LBA bytes to the command register
98230557Sjimharris * @return Indicate if the method was successfully completed.
99230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
100230557Sjimharris */
101230557Sjimharrisstatic
102230557Sjimharrisvoid set_current_long_lba(U8 * lba, void  * ata_io)
103230557Sjimharris{
104230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
105230557Sjimharris
106230557Sjimharris   sati_set_ata_lba_low(register_fis, lba[0]);
107230557Sjimharris   sati_set_ata_lba_mid(register_fis, lba[1]);
108230557Sjimharris   sati_set_ata_lba_high(register_fis, lba[2]);
109230557Sjimharris   sati_set_ata_lba_low_exp(register_fis, lba[3]);
110230557Sjimharris   sati_set_ata_lba_mid_exp(register_fis, lba[4]);
111230557Sjimharris   sati_set_ata_lba_high_exp(register_fis, lba[5]);
112230557Sjimharris}
113230557Sjimharris
114230557Sjimharris/**
115230557Sjimharris * @brief This method performs the SCSI VERIFY command translation
116230557Sjimharris *        functionality.
117230557Sjimharris *        This includes:
118230557Sjimharris *        - setting the command register
119230557Sjimharris *        - setting the device head register
120230557Sjimharris *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
121230557Sjimharris *        For more information on the parameters passed to this method,
122230557Sjimharris *        please reference sati_translate_command().
123230557Sjimharris *
124230557Sjimharris * @return Indicate if the method was successfully completed.
125230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
126230557Sjimharris */
127230557Sjimharrisstatic
128230557SjimharrisSATI_STATUS sati_reassign_blocks_verify_command(
129230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
130230557Sjimharris   void                       * scsi_io,
131230557Sjimharris   void                       * ata_io
132230557Sjimharris)
133230557Sjimharris{
134230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
135230557Sjimharris
136230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
137230557Sjimharris
138230557Sjimharris   // Ensure the device supports the 48 bit feature set.
139230557Sjimharris   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
140230557Sjimharris      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
141230557Sjimharris   else
142230557Sjimharris      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
143230557Sjimharris
144230557Sjimharris   return SATI_SUCCESS;
145230557Sjimharris}
146230557Sjimharris
147230557Sjimharris/**
148230557Sjimharris * @brief This method performs the SCSI Write sector command translation
149230557Sjimharris *        functionality.
150230557Sjimharris *        This includes:
151230557Sjimharris *        - setting the command register
152230557Sjimharris *        - setting the device head register
153230557Sjimharris *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
154230557Sjimharris *        For more information on the parameters passed to this method,
155230557Sjimharris *        please reference sati_translate_command().
156230557Sjimharris *
157230557Sjimharris * @return Indicate if the method was successfully completed.
158230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
159230557Sjimharris */
160230557Sjimharrisstatic
161230557SjimharrisSATI_STATUS sati_reassign_blocks_write_command(
162230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
163230557Sjimharris   void                       * scsi_io,
164230557Sjimharris   void                       * ata_io
165230557Sjimharris)
166230557Sjimharris{
167230557Sjimharris   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
168230557Sjimharris
169230557Sjimharris   sati_ata_non_data_command(ata_io, sequence);
170230557Sjimharris   sequence->data_direction = SATI_DATA_DIRECTION_OUT;
171230557Sjimharris
172230557Sjimharris//   sati_set_ata_sector_count(register_fis, 1);
173230557Sjimharris//   status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
174230557Sjimharris
175230557Sjimharris   // Ensure the device supports the 48 bit feature set.
176230557Sjimharris   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
177230557Sjimharris      sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT);
178230557Sjimharris   else
179230557Sjimharris      sati_set_ata_command(register_fis, ATA_WRITE_DMA);
180230557Sjimharris
181230557Sjimharris   return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
182230557Sjimharris}
183230557Sjimharris
184230557Sjimharris/**
185230557Sjimharris * @brief This method performs the retrieving of parameter LBA praparation and setting
186230557Sjimharris *        processing flags before/after calling SCSI Verify sector command.
187230557Sjimharris * @return Indicate if the method was successfully completed.
188230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
189230557Sjimharris */
190230557Sjimharrisstatic
191230557SjimharrisSATI_STATUS sati_reassign_blocks_verify_condition(
192230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
193230557Sjimharris   void     * scsi_io,
194230557Sjimharris   void     * ata_io
195230557Sjimharris)
196230557Sjimharris{
197230557Sjimharris   U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
198230557Sjimharris   U32 lba_offset;
199230557Sjimharris   U8 page_size;
200230557Sjimharris   U32 index;
201230557Sjimharris   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
202230557Sjimharris
203230557Sjimharris   lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
204230557Sjimharris   page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
205230557Sjimharris
206230557Sjimharris   for(index = 0; index < page_size; index++)
207230557Sjimharris   {
208230557Sjimharris      sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
209230557Sjimharris   }
210230557Sjimharris
211230557Sjimharris   if (page_size == 4)
212230557Sjimharris      set_current_lba(current_lba_bytes, ata_io);
213230557Sjimharris   else
214230557Sjimharris      set_current_long_lba(current_lba_bytes, ata_io);
215230557Sjimharris
216230557Sjimharris   status = sati_reassign_blocks_verify_command(sequence, scsi_io, ata_io);
217230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
218230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
219230557Sjimharris   return  status;
220230557Sjimharris}
221230557Sjimharris
222230557Sjimharris/**
223230557Sjimharris * @brief This method performs the retrieving of parameter LBA praparation and setting
224230557Sjimharris *        processing flags before/after calling SCSI Write sector command.
225230557Sjimharris * @return Indicate if the method was successfully completed.
226230557Sjimharris * @retval SATI_SUCCESS This is returned in all other cases.
227230557Sjimharris */
228230557Sjimharrisstatic
229230557SjimharrisSATI_STATUS sati_reassign_blocks_write_condition(
230230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
231230557Sjimharris   void     * scsi_io,
232230557Sjimharris   void     * ata_io
233230557Sjimharris)
234230557Sjimharris{
235230557Sjimharris   U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
236230557Sjimharris   U32 lba_offset;
237230557Sjimharris   U8 page_size;
238230557Sjimharris   U32 index;
239230557Sjimharris   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
240230557Sjimharris
241230557Sjimharris   lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
242230557Sjimharris   page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
243230557Sjimharris
244230557Sjimharris   for(index = 0; index < page_size; index++)
245230557Sjimharris   {
246230557Sjimharris      sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
247230557Sjimharris   }
248230557Sjimharris
249230557Sjimharris   if (page_size == 4)
250230557Sjimharris      set_current_lba(current_lba_bytes, ata_io);
251230557Sjimharris   else
252230557Sjimharris      set_current_long_lba(current_lba_bytes, ata_io);
253230557Sjimharris
254230557Sjimharris   status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io);
255230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
256230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
257230557Sjimharris   return  status ;
258230557Sjimharris}
259230557Sjimharris
260230557Sjimharris
261230557Sjimharris/**
262230557Sjimharris * @brief This method will perform the pre-processing of Reassign Blocks command and parameter.
263230557Sjimharris */
264230557Sjimharrisstatic
265230557Sjimharrisvoid  sati_reassign_blocks_initial_processing(
266230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
267230557Sjimharris   void                       * scsi_io,
268230557Sjimharris   void                       * ata_io
269230557Sjimharris)
270230557Sjimharris{
271230557Sjimharris   U32 index;
272230557Sjimharris   U8 long_lba_bit;
273230557Sjimharris   U8 long_list_bit;
274230557Sjimharris   U8 lba_offset;
275230557Sjimharris   U8  page_size;
276230557Sjimharris   U32 data_transfer_length;
277230557Sjimharris   U8 header_bytes[4]={0,0,0,0};
278230557Sjimharris
279230557Sjimharris   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
280230557Sjimharris
281230557Sjimharris   //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs.
282230557Sjimharris   //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs.
283230557Sjimharris   if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0)
284230557Sjimharris   {
285230557Sjimharris      long_lba_bit=0;
286230557Sjimharris      page_size = 4; //beginning of lba list
287230557Sjimharris   }
288230557Sjimharris   else
289230557Sjimharris   {
290230557Sjimharris      long_lba_bit=1;
291230557Sjimharris      page_size = 8;
292230557Sjimharris   }
293230557Sjimharris
294230557Sjimharris   //The long list (LONGLIST) bit specifies which parameter list header
295230557Sjimharris   if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0)
296230557Sjimharris   {
297230557Sjimharris      long_list_bit=0;
298230557Sjimharris   }
299230557Sjimharris   else
300230557Sjimharris   {
301230557Sjimharris      long_list_bit=1;
302230557Sjimharris   }
303230557Sjimharris
304230557Sjimharris   sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved
305230557Sjimharris
306230557Sjimharris   //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes)
307230557Sjimharris   for(index = 0; index < 4; index++)
308230557Sjimharris   {
309230557Sjimharris      sati_get_data_byte(sequence, scsi_io, index,   &header_bytes[index]);
310230557Sjimharris   }
311230557Sjimharris
312230557Sjimharris   lba_offset = 4; //beginning of lba list
313230557Sjimharris
314230557Sjimharris   if (long_list_bit==0)
315230557Sjimharris   {
316230557Sjimharris      //Header byte 2 and 3 is the parameter list length
317230557Sjimharris      data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
318230557Sjimharris   }
319230557Sjimharris   else
320230557Sjimharris   {
321230557Sjimharris      //Header byte 0, 1, 2 and 3 contain the parameter list length
322230557Sjimharris      data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) +
323230557Sjimharris         (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
324230557Sjimharris   }
325230557Sjimharris
326230557Sjimharris   sequence->allocation_length = data_transfer_length;
327230557Sjimharris
328230557Sjimharris   //Initialized the global processing state
329230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.lba_size   =     page_size;
330230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.lba_offset =     lba_offset;
331230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0;
332230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.block_lists_size       = data_transfer_length  -  lba_offset;
333230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0;
334230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed  = FALSE;
335230557Sjimharris   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status     = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
336230557Sjimharris}
337230557Sjimharris
338230557Sjimharris/**
339230557Sjimharris * @brief This method will get the data size of not yet processed data.
340230557Sjimharris *
341230557Sjimharris * @param[in] lba_process_state This parameter points to the processing state fields
342230557Sjimharris *            of current block lba.
343230557Sjimharris *
344230557Sjimharris * @return This method returns the sizeof not yet processed data.
345230557Sjimharris */
346230557Sjimharrisstatic
347230557SjimharrisU32 sati_reassign_blocks_unprocessed_data_size(
348230557Sjimharris   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state
349230557Sjimharris)
350230557Sjimharris{
351230557Sjimharris   U32 unprocessed_data_size;
352230557Sjimharris
353230557Sjimharris   if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed)
354230557Sjimharris   {
355230557Sjimharris      unprocessed_data_size = lba_process_state->block_lists_size -
356230557Sjimharris         lba_process_state->size_of_data_processed;
357230557Sjimharris   }
358230557Sjimharris   else
359230557Sjimharris   {
360230557Sjimharris      unprocessed_data_size = 0;
361230557Sjimharris   }
362230557Sjimharris
363230557Sjimharris   return unprocessed_data_size;
364230557Sjimharris}
365230557Sjimharris
366230557Sjimharris
367230557Sjimharris/**
368230557Sjimharris * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation.
369230557Sjimharris *
370230557Sjimharris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
371230557Sjimharris *            of current lba block.
372230557Sjimharris *
373230557Sjimharris *
374230557Sjimharris * @return Indicate if the translation was successful.
375230557Sjimharris * @retval SATI_SUCCESS
376230557Sjimharris * @retval SATI_COMPLETE
377230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
378230557Sjimharris */
379230557Sjimharrisstatic
380230557SjimharrisSATI_STATUS sati_reassign_blocks_process_each_lba(
381230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
382230557Sjimharris   void                       * scsi_io,
383230557Sjimharris   void                       * ata_io
384230557Sjimharris   )
385230557Sjimharris{
386230557Sjimharris   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
387230557Sjimharris   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
388230557Sjimharris
389230557Sjimharris   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
390230557Sjimharris
391230557Sjimharris   if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
392230557Sjimharris      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
393230557Sjimharris   {
394230557Sjimharris      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
395230557Sjimharris      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
396230557Sjimharris   }
397230557Sjimharris   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
398230557Sjimharris      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
399230557Sjimharris   {
400230557Sjimharris      // point to next lba
401230557Sjimharris      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
402230557Sjimharris      reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size;
403230557Sjimharris      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
404230557Sjimharris   }
405230557Sjimharris   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&&
406230557Sjimharris      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
407230557Sjimharris   {
408230557Sjimharris      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
409230557Sjimharris      status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io);
410230557Sjimharris   }
411230557Sjimharris   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) &&
412230557Sjimharris      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
413230557Sjimharris   {
414230557Sjimharris      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
415230557Sjimharris      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
416230557Sjimharris   }
417230557Sjimharris   else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL
418230557Sjimharris   {
419230557Sjimharris      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
420230557Sjimharris   }
421230557Sjimharris
422230557Sjimharris   return status;
423230557Sjimharris}
424230557Sjimharris
425230557Sjimharris/**
426230557Sjimharris * @brief This method will process the each lba.
427230557Sjimharris *
428230557Sjimharris * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
429230557Sjimharris *            of current lba.
430230557Sjimharris *
431230557Sjimharris * @return Indicate if the translation was successful.
432230557Sjimharris * @retval SATI_SUCCESS
433230557Sjimharris * @retval SATI_COMPLETE
434230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
435230557Sjimharris */
436230557Sjimharrisstatic
437230557SjimharrisSATI_STATUS sati_reassign_blocks_process(
438230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
439230557Sjimharris   void                       * scsi_io,
440230557Sjimharris   void                       * ata_io
441230557Sjimharris)
442230557Sjimharris{
443230557Sjimharris   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
444230557Sjimharris
445230557Sjimharris   U32 page_size = 0; // in bytes
446230557Sjimharris   U32 size_of_data_to_be_processed;
447230557Sjimharris   U32 lba_offset;
448230557Sjimharris   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
449230557Sjimharris
450230557Sjimharris   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
451230557Sjimharris
452230557Sjimharris   lba_offset = reassign_blocks_process_state->lba_offset;
453230557Sjimharris   page_size  = reassign_blocks_process_state->lba_size;
454230557Sjimharris
455230557Sjimharris
456230557Sjimharris   if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size)
457230557Sjimharris   {
458230557Sjimharris      return status;
459230557Sjimharris   }
460230557Sjimharris
461230557Sjimharris   // Any more lba blocks? If not, done.
462230557Sjimharris   if(reassign_blocks_process_state->block_lists_size ==
463230557Sjimharris      reassign_blocks_process_state->size_of_data_processed)
464230557Sjimharris   {
465230557Sjimharris      sequence->state = SATI_SEQUENCE_STATE_FINAL;
466230557Sjimharris      status = SATI_COMPLETE;
467230557Sjimharris   }
468230557Sjimharris   //start processing next lba
469230557Sjimharris   else
470230557Sjimharris   {
471230557Sjimharris      size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size
472230557Sjimharris         - reassign_blocks_process_state->size_of_data_processed;
473230557Sjimharris
474230557Sjimharris      status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io);
475230557Sjimharris
476230557Sjimharris   }
477230557Sjimharris
478230557Sjimharris   return status;
479230557Sjimharris}
480230557Sjimharris
481230557Sjimharris//******************************************************************************
482230557Sjimharris//* P U B L I C   M E T H O D S
483230557Sjimharris//******************************************************************************
484230557Sjimharris
485230557Sjimharris/**
486230557Sjimharris * @brief This method will translate the SCSI Reassign Blocks command
487230557Sjimharris *        into corresponding ATA commands.  Depending upon the capabilities
488230557Sjimharris *        supported by the target different ATA commands can be selected.
489230557Sjimharris *        Additionally, in some cases more than a single ATA command may
490230557Sjimharris *        be required.
491230557Sjimharris *
492230557Sjimharris * @return Indicate if the command translation succeeded.
493230557Sjimharris * @retval SCI_SUCCESS This is returned if the command translation was
494230557Sjimharris *         successful.
495230557Sjimharris * @retval SCI_COMPLETE This is returned if the command translation was
496230557Sjimharris *         successful and no ATA commands need to be set.
497230557Sjimharris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
498230557Sjimharris *         sense data has been created as a result of something specified
499230557Sjimharris *         in the parameter data fields.
500230557Sjimharris */
501230557SjimharrisSATI_STATUS sati_reassign_blocks_translate_command(
502230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
503230557Sjimharris   void                       * scsi_io,
504230557Sjimharris   void                       * ata_io
505230557Sjimharris)
506230557Sjimharris{
507230557Sjimharris   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
508230557Sjimharris   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
509230557Sjimharris
510230557Sjimharris   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
511230557Sjimharris
512230557Sjimharris   sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS;
513230557Sjimharris
514230557Sjimharris   //Initial processing if
515230557Sjimharris   if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
516230557Sjimharris   {
517230557Sjimharris      sati_reassign_blocks_initial_processing(
518230557Sjimharris         sequence,
519230557Sjimharris         scsi_io,
520230557Sjimharris         ata_io
521230557Sjimharris      );
522230557Sjimharris   }
523230557Sjimharris
524230557Sjimharris   // start processing current lba
525230557Sjimharris   if(reassign_blocks_process_state->current_lba_processed)
526230557Sjimharris   {
527230557Sjimharris      reassign_blocks_process_state->ata_command_sent_for_current_lba = 0;
528230557Sjimharris      reassign_blocks_process_state->current_lba_processed = FALSE;
529230557Sjimharris   }
530230557Sjimharris
531230557Sjimharris   status = sati_reassign_blocks_process(sequence, scsi_io, ata_io);
532230557Sjimharris
533230557Sjimharris   if(reassign_blocks_process_state->block_lists_size ==
534230557Sjimharris      reassign_blocks_process_state->size_of_data_processed)
535230557Sjimharris   {
536230557Sjimharris      // Done this lba
537230557Sjimharris      sequence->state = SATI_SEQUENCE_STATE_FINAL;
538230557Sjimharris   }
539230557Sjimharris   else
540230557Sjimharris   {
541230557Sjimharris      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
542230557Sjimharris   }
543230557Sjimharris
544230557Sjimharris   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
545230557Sjimharris   {
546230557Sjimharris      sequence->state = SATI_SEQUENCE_STATE_FINAL;
547230557Sjimharris      sati_scsi_sense_data_construct(
548230557Sjimharris         sequence,
549230557Sjimharris         scsi_io,
550230557Sjimharris         SCSI_STATUS_CHECK_CONDITION,
551230557Sjimharris         SCSI_SENSE_MEDIUM_ERROR,
552230557Sjimharris         SCSI_ASC_UNRECOVERED_READ_ERROR,
553230557Sjimharris         SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
554230557Sjimharris      );
555230557Sjimharris   }
556230557Sjimharris
557230557Sjimharris   return status;
558230557Sjimharris}
559230557Sjimharris
560230557Sjimharris/**
561230557Sjimharris * @brief This method will translate the ATA command register FIS
562230557Sjimharris *        response into an appropriate SCSI response for Reassign Blocks
563230557Sjimharris *        For more information on the parameters passed to this method,
564230557Sjimharris *        please reference sati_translate_response().
565230557Sjimharris *
566230557Sjimharris * @return Indicate if the response translation succeeded.
567230557Sjimharris * @retval SCI_SUCCESS This is returned if the data translation was
568230557Sjimharris *         successful.
569230557Sjimharris */
570230557SjimharrisSATI_STATUS sati_reassign_blocks_translate_response(
571230557Sjimharris   SATI_TRANSLATOR_SEQUENCE_T * sequence,
572230557Sjimharris   void                       * scsi_io,
573230557Sjimharris   void                       * ata_io
574230557Sjimharris)
575230557Sjimharris{
576230557Sjimharris   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
577230557Sjimharris   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
578230557Sjimharris
579230557Sjimharris   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
580230557Sjimharris
581230557Sjimharris   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
582230557Sjimharris   {
583230557Sjimharris      reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
584230557Sjimharris
585230557Sjimharris      //Checking for the number of ATA commands attempted on current LBA, stop
586230557Sjimharris      //the seaquence after 2 commands have returned errors.
587230557Sjimharris      if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2)
588230557Sjimharris      {
589230557Sjimharris         sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
590230557Sjimharris         reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size;
591230557Sjimharris         return SATI_SEQUENCE_INCOMPLETE;
592230557Sjimharris      }
593230557Sjimharris      else
594230557Sjimharris      {
595230557Sjimharris         sati_scsi_sense_data_construct(
596230557Sjimharris            sequence,
597230557Sjimharris            scsi_io,
598230557Sjimharris            SCSI_STATUS_CHECK_CONDITION,
599230557Sjimharris            SCSI_SENSE_MEDIUM_ERROR,
600230557Sjimharris            SCSI_ASC_UNRECOVERED_READ_ERROR,
601230557Sjimharris            SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
602230557Sjimharris         );
603230557Sjimharris      }
604230557Sjimharris
605230557Sjimharris      return SATI_FAILURE_CHECK_RESPONSE_DATA;
606230557Sjimharris   }
607230557Sjimharris   else
608230557Sjimharris   {
609230557Sjimharris      reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS;
610230557Sjimharris      if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2)
611230557Sjimharris         reassign_blocks_process_state->current_lba_processed = TRUE;
612230557Sjimharris
613230557Sjimharris      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
614230557Sjimharris      {
615230557Sjimharris         return SATI_SEQUENCE_INCOMPLETE;
616230557Sjimharris      }
617230557Sjimharris   }
618230557Sjimharris   return SATI_COMPLETE;
619230557Sjimharris}
620230557Sjimharris
621230557Sjimharris#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
622230557Sjimharris
623