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 method implementations required to
61 *        translate the SCSI write (6, 10, 12, or 16-byte) commands.
62 */
63
64#include <dev/isci/scil/sati_move.h>
65#include <dev/isci/scil/sati_write.h>
66#include <dev/isci/scil/sati_callbacks.h>
67#include <dev/isci/scil/sati_util.h>
68
69#include <dev/isci/scil/intel_ata.h>
70#include <dev/isci/scil/intel_scsi.h>
71
72//******************************************************************************
73//* P R I V A T E   M E T H O D S
74//******************************************************************************
75
76/**
77 * @brief This method performs the common translation functionality for
78 *        all SCSI write operations that are 10 bytes in size or larger.
79 *        Translated/Written items include:
80 *        - Force Unit Access (FUA)
81 *        - Sector Count/Transfer Length
82 *        - Command register
83 *
84 * @param[in] sector_count This parameter specifies the number of sectors
85 *            to be transferred by this request.
86 * @param[in] device_head This parameter points to device head register
87 *            that is to be written into the ATA task file (register FIS).
88 *
89 * @return Indicate if the command translation succeeded.
90 * @see sati_move_set_sector_count() for additional return values.
91 */
92static
93SATI_STATUS sati_write_large_translate_command(
94   SATI_TRANSLATOR_SEQUENCE_T * sequence,
95   void                       * scsi_io,
96   void                       * ata_io,
97   U32                          sector_count,
98   U8                         * device_head
99)
100{
101   sequence->data_direction = SATI_DATA_DIRECTION_OUT;
102
103   return sati_move_large_translate_command(
104             sequence,
105             scsi_io,
106             ata_io,
107             sector_count,
108             device_head
109          );
110}
111
112/**
113 * @brief This method performs the common translation functionality for
114 *        all SCSI write operations containing a 32-bit logical block
115 *        address.
116 *        Translated/Written items include:
117 *        - Logical Block Address (LBA)
118 *        - Force Unit Access (FUA)
119 *        - Sector Count/Transfer Length
120 *        - Command register
121 *        For more information on the parameters passed to this method,
122 *        please reference sati_translate_command().
123 *
124 * @param[in] sector_count This parameter specifies the number of sectors
125 *            to be transferred by this request.
126 * @param[in] control_byte_offset This parameter specifies the byte offset
127 *            into the command descriptor block at which the control byte
128 *            is located.
129 *
130 * @return Indicate if the command translation succeeded.
131 * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
132 *      for additional return values.
133 */
134static
135SATI_STATUS sati_write_32_bit_lba_translate_command(
136   SATI_TRANSLATOR_SEQUENCE_T * sequence,
137   void                       * scsi_io,
138   void                       * ata_io,
139   U32                          sector_count,
140   U8                           control_byte_offset
141)
142{
143   U8           device_head = 0;
144   SATI_STATUS  status;
145
146   status = sati_write_large_translate_command(
147               sequence, scsi_io, ata_io, sector_count, &device_head
148            );
149
150   if (status == SATI_SUCCESS)
151   {
152      status = sati_move_32_bit_lba_translate_command(
153                  sequence, scsi_io, ata_io, device_head
154               );
155   }
156
157   return status;
158}
159
160//******************************************************************************
161//* P U B L I C   M E T H O D S
162//******************************************************************************
163
164/**
165 * @brief This method will translate the SCSI write command into a
166 *        corresponding ATA write 6 command.  Depending upon the capabilities
167 *        supported by the target different ATA commands can be selected.
168 *        For more information on the parameters passed to this method,
169 *        please reference sati_translate_command().
170 *
171 * @return Indicate if the command translation succeeded.
172 * @retval SCI_SUCCESS This is returned if the command translation was
173 *         successful.
174 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
175 *         sense data has been created as a result of something specified
176 *         in the CDB.
177 */
178SATI_STATUS sati_write_6_translate_command(
179   SATI_TRANSLATOR_SEQUENCE_T * sequence,
180   void                       * scsi_io,
181   void                       * ata_io
182)
183{
184   if(sati_device_state_stopped(sequence, scsi_io))
185   {
186      return SATI_FAILURE_CHECK_RESPONSE_DATA;
187   }
188   else
189   {
190      sequence->data_direction = SATI_DATA_DIRECTION_OUT;
191      sequence->type           = SATI_SEQUENCE_WRITE_6;
192
193      return sati_move_small_translate_command(sequence, scsi_io, ata_io);
194   }
195}
196
197/**
198 * @brief This method will translate the SCSI write 10 command into a
199 *        corresponding ATA write command.  Depending upon the capabilities
200 *        supported by the target different ATA commands can be selected.
201 *        It ensures that all translation required for this command is
202 *        performed successfully.
203 *        For more information on the parameters passed to this method,
204 *        please reference sati_translate_command().
205 *
206 * @return Indicate if the command translation succeeded.
207 * @see sati_write_32_bit_lba_translate_command() for return values.
208 */
209SATI_STATUS sati_write_10_translate_command(
210   SATI_TRANSLATOR_SEQUENCE_T * sequence,
211   void                       * scsi_io,
212   void                       * ata_io
213)
214{
215   U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
216   U32   sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
217                        (sati_get_cdb_byte(cdb, 8));
218
219   if(sati_device_state_stopped(sequence, scsi_io))
220   {
221      return SATI_FAILURE_CHECK_RESPONSE_DATA;
222   }
223   else
224   {
225      sequence->type     = SATI_SEQUENCE_WRITE_10;
226
227      return sati_write_32_bit_lba_translate_command(
228                sequence, scsi_io, ata_io, sector_count, 9
229             );
230   }
231}
232
233/**
234 * @brief This method will translate the SCSI write 12 command into a
235 *        corresponding ATA write command.  Depending upon the capabilities
236 *        supported by the target different ATA commands can be selected.
237 *        It ensures that all translation required for this command is
238 *        performed successfully.
239 *        For more information on the parameters passed to this method,
240 *        please reference sati_translate_command().
241 *
242 * @return Indicate if the command translation succeeded.
243 * @see sati_write_32_bit_lba_translate_command() for return values.
244 */
245SATI_STATUS sati_write_12_translate_command(
246   SATI_TRANSLATOR_SEQUENCE_T * sequence,
247   void                       * scsi_io,
248   void                       * ata_io
249)
250{
251   U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
252   U32   sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
253                        (sati_get_cdb_byte(cdb, 7) << 16) |
254                        (sati_get_cdb_byte(cdb, 8) << 8)  |
255                        (sati_get_cdb_byte(cdb, 9));
256
257   if(sati_device_state_stopped(sequence, scsi_io))
258   {
259      return SATI_FAILURE_CHECK_RESPONSE_DATA;
260   }
261   else
262   {
263      sequence->type = SATI_SEQUENCE_WRITE_12;
264
265      return sati_write_32_bit_lba_translate_command(
266                sequence, scsi_io, ata_io, sector_count, 11
267             );
268   }
269}
270
271/**
272 * @brief This method will translate the SCSI write 16 command into a
273 *        corresponding ATA write command.  Depending upon the capabilities
274 *        supported by the target different ATA commands can be selected.
275 *        It ensures that all translation required for this command is
276 *        performed successfully.
277 *        For more information on the parameters passed to this method,
278 *        please reference sati_translate_command().
279 *
280 * @return Indicate if the command translation succeeded.
281 * @see sati_write_large_translate_command(), sati_move_translate_64_bit_lba()
282 *      for additional return values.
283 */
284SATI_STATUS sati_write_16_translate_command(
285   SATI_TRANSLATOR_SEQUENCE_T * sequence,
286   void                       * scsi_io,
287   void                       * ata_io
288)
289{
290   SATI_STATUS   status;
291   U8            device_head  = 0;
292   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
293   U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
294                                (sati_get_cdb_byte(cdb, 11) << 16) |
295                                (sati_get_cdb_byte(cdb, 12) << 8)  |
296                                (sati_get_cdb_byte(cdb, 13));
297
298   if(sati_device_state_stopped(sequence, scsi_io))
299   {
300      return SATI_FAILURE_CHECK_RESPONSE_DATA;
301   }
302   else
303   {
304      sequence->type   = SATI_SEQUENCE_WRITE_16;
305
306      // Translate the sector count, write command register, and check various
307      // other parts of the CDB.
308      status = sati_write_large_translate_command(
309                  sequence, scsi_io, ata_io, sector_count, &device_head
310               );
311
312      // Attempt to translate the 64-bit LBA field from the SCSI request
313      // into the 48-bits of LBA in the ATA register FIS.
314      if (status == SATI_SUCCESS)
315      {
316         sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
317         status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
318      }
319
320      return status;
321   }
322}
323
324