xref: /freebsd/sys/dev/isci/scil/sati_write_long.c (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23  * The full GNU General Public License is included in this distribution
24  * in the file called LICENSE.GPL.
25  *
26  * BSD LICENSE
27  *
28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  *   * Redistributions of source code must retain the above copyright
36  *     notice, this list of conditions and the following disclaimer.
37  *   * Redistributions in binary form must reproduce the above copyright
38  *     notice, this list of conditions and the following disclaimer in
39  *     the documentation and/or other materials provided with the
40  *     distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
57 
58 /**
59  * @file
60  * @brief This file contains the implementation to translate
61  *        SCSI Write Long 10 and 16 commands based on the SAT spec.
62  */
63 
64 #if !defined(DISABLE_SATI_WRITE_LONG)
65 
66 #include <dev/isci/scil/sati_write_long.h>
67 #include <dev/isci/scil/sati_device.h>
68 #include <dev/isci/scil/sati_util.h>
69 #include <dev/isci/scil/intel_scsi.h>
70 #include <dev/isci/scil/intel_ata.h>
71 #include <dev/isci/scil/intel_sat.h>
72 #include <dev/isci/scil/sati_callbacks.h>
73 #include <dev/isci/scil/sati_move.h>
74 
75 #define LOGICAL_PER_PHYSICAL_SECTOR 0xF
76 
77 #define WR_UNCOR_BIT          0x02
78 #define WR_UNCOR_PBLOCK_BIT   0x03
79 #define COR_DIS_WR_UNCORR_BIT 0x06
80 
81 
82 /**
83  * @brief This method will translate the write long 10 & 16 SCSI commands into
84  *        ATA write uncorrectable commands. For more information on the
85  *        parameters passed to this method, please reference
86  *        sati_translate_command().
87  *
88  * @return Indicate if the command translation succeeded.
89  * @retval SCI_SUCCESS This is returned if the command translation was
90  *         successful.
91  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
92  *         a problem with the translation of write long.
93  *
94  */
95 SATI_STATUS sati_write_long_translate_command(
96    SATI_TRANSLATOR_SEQUENCE_T * sequence,
97    void                       * scsi_io,
98    void                       * ata_io
99 )
100 {
101    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
102    SATI_STATUS status = SATI_FAILURE;
103    U16 byte_transfer_length;
104    U8 device_head  = 0;
105 
106    if((sequence->device->capabilities &
107        SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE) == 0)
108    {
109       sati_scsi_sense_data_construct(
110          sequence,
111          scsi_io,
112          SCSI_STATUS_CHECK_CONDITION,
113          SCSI_SENSE_ILLEGAL_REQUEST,
114          SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
115          SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
116       );
117       return SATI_FAILURE_CHECK_RESPONSE_DATA;
118    }
119 
120    //Write Long 10
121    if(sati_get_cdb_byte(cdb, 0) == SCSI_WRITE_LONG_10)
122    {
123       byte_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) |
124                              (sati_get_cdb_byte(cdb, 8));
125 
126       sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
127    }
128    else //Write Long 16
129    {
130       byte_transfer_length = (sati_get_cdb_byte(cdb, 12) << 8) |
131                              (sati_get_cdb_byte(cdb, 13));
132 
133       status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
134 
135       if( status == SATI_FAILURE_CHECK_RESPONSE_DATA)
136       {
137          return status;
138       }
139    }
140 
141 
142    sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
143 
144    if( byte_transfer_length != 0 )
145    {
146       sati_scsi_sense_data_construct(
147          sequence,
148          scsi_io,
149          SCSI_STATUS_CHECK_CONDITION,
150          SCSI_SENSE_ILLEGAL_REQUEST,
151          SCSI_ASC_INVALID_FIELD_IN_CDB,
152          SCSI_ASCQ_INVALID_FIELD_IN_CDB
153       );
154       return SATI_FAILURE_CHECK_RESPONSE_DATA;
155    }
156 
157    switch(SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb))
158    {
159       case WR_UNCOR_BIT :
160 
161          if( (sequence->device->capabilities &
162               SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR) != 0 )
163          {
164             sati_scsi_sense_data_construct(
165                sequence,
166                scsi_io,
167                SCSI_STATUS_CHECK_CONDITION,
168                SCSI_SENSE_ILLEGAL_REQUEST,
169                SCSI_ASC_INVALID_FIELD_IN_CDB,
170                SCSI_ASCQ_INVALID_FIELD_IN_CDB
171             );
172             return SATI_FAILURE_CHECK_RESPONSE_DATA;
173          }
174          else
175          {
176             sati_ata_write_uncorrectable_construct(
177                ata_io,
178                sequence,
179                ATA_WRITE_UNCORRECTABLE_PSEUDO
180             );
181             sequence->type = SATI_SEQUENCE_WRITE_LONG;
182             status = SATI_SUCCESS;
183          }
184          break;
185 
186       case WR_UNCOR_PBLOCK_BIT :
187 
188          sati_ata_write_uncorrectable_construct(
189             ata_io,
190             sequence,
191             ATA_WRITE_UNCORRECTABLE_PSEUDO
192          );
193          sequence->type = SATI_SEQUENCE_WRITE_LONG;
194          status = SATI_SUCCESS;
195          break;
196 
197       case COR_DIS_WR_UNCORR_BIT :
198 
199          sati_ata_write_uncorrectable_construct(
200             ata_io,
201             sequence,
202             ATA_WRITE_UNCORRECTABLE_FLAGGED
203          );
204          sequence->type = SATI_SEQUENCE_WRITE_LONG;
205          status = SATI_SUCCESS;
206          break;
207 
208       default :
209 
210          sati_scsi_sense_data_construct(
211             sequence,
212             scsi_io,
213             SCSI_STATUS_CHECK_CONDITION,
214             SCSI_SENSE_ILLEGAL_REQUEST,
215             SCSI_ASC_INVALID_FIELD_IN_CDB,
216             SCSI_ASCQ_INVALID_FIELD_IN_CDB
217          );
218          return SATI_FAILURE_CHECK_RESPONSE_DATA;
219          break;
220    }
221    return status;
222 }
223 
224 /**
225  * @brief This method will translate the response to the SATI Write Long
226  *        translation. This response is only error checking the
227  *        ATA Write Uncorrectable command.
228  *
229  * @return SATI_STATUS Indicates if the response translation succeeded.
230  * @retval SCI_COMPLETE This is returned if the command translation was
231  *         successful.
232  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
233  *         a problem with the translation of write long.
234  */
235 SATI_STATUS sati_write_long_translate_response(
236    SATI_TRANSLATOR_SEQUENCE_T * sequence,
237    void                       * scsi_io,
238    void                       * ata_io
239 )
240 {
241    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
242 
243    if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
244    {
245       sati_scsi_sense_data_construct(
246          sequence,
247          scsi_io,
248          SCSI_STATUS_CHECK_CONDITION,
249          SCSI_SENSE_ABORTED_COMMAND,
250          SCSI_ASC_COMMAND_SEQUENCE_ERROR,
251          SCSI_ASCQ_NO_ADDITIONAL_SENSE
252       );
253       return SATI_FAILURE_CHECK_RESPONSE_DATA;
254    }
255    else
256    {
257       return SATI_COMPLETE;
258    }
259 }
260 
261 #endif // !defined(DISABLE_SATI_WRITE_LONG)
262