sati_write_long.c revision 330897
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: stable/11/sys/dev/isci/scil/sati_write_long.c 330897 2018-03-14 03:19:51Z eadler $");
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 */
95SATI_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_PSUEDO
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_PSUEDO
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 */
235SATI_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