1/*-
2 * This file is provided under a dual BSD/GPLv2 license.  When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 *   * Redistributions of source code must retain the above copyright
34 *     notice, this list of conditions and the following disclaimer.
35 *   * Redistributions in binary form must reproduce the above copyright
36 *     notice, this list of conditions and the following disclaimer in
37 *     the documentation and/or other materials provided with the
38 *     distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD$");
55
56/**
57 * @file
58 * @brief This file contains the method implementations for translating
59 *        the SCSI VERIFY (10, 12, 16-byte) commands.
60 */
61
62#if !defined(DISABLE_SATI_VERIFY)
63
64#include <dev/isci/scil/sati_verify.h>
65#include <dev/isci/scil/sati_callbacks.h>
66#include <dev/isci/scil/sati_util.h>
67#include <dev/isci/scil/sati_move.h>
68
69#include <dev/isci/scil/intel_ata.h>
70#include <dev/isci/scil/intel_scsi.h>
71#include <dev/isci/scil/intel_sat.h>
72
73//******************************************************************************
74//* P R I V A T E   M E T H O D S
75//******************************************************************************
76
77/**
78 * @brief This method performs the SCSI VERIFY command translation
79 *        functionality common to all VERIFY command sizes.
80 *        This includes:
81 *        - setting the command register
82 *        - setting the device head register
83 *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
84 *        For more information on the parameters passed to this method,
85 *        please reference sati_translate_command().
86 *
87 * @return Indicate if the method was successfully completed.
88 * @retval SATI_SUCCESS This is returned in all other cases.
89 */
90static
91SATI_STATUS sati_verify_translate_command(
92   SATI_TRANSLATOR_SEQUENCE_T * sequence,
93   void                       * scsi_io,
94   void                       * ata_io
95)
96{
97   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
98   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
99
100   /**
101    * The translator doesn't support performing the byte check operation.
102    * As a result, error the request if the BYTCHK bit is set.
103    */
104   if ((sati_get_cdb_byte(cdb, 1) & SCSI_VERIFY_BYTCHK_ENABLED))
105   {
106      sati_scsi_sense_data_construct(
107         sequence,
108         scsi_io,
109         SCSI_STATUS_CHECK_CONDITION,
110         SCSI_SENSE_ILLEGAL_REQUEST,
111         SCSI_ASC_INVALID_FIELD_IN_CDB,
112         SCSI_ASCQ_INVALID_FIELD_IN_CDB
113      );
114      return SATI_FAILURE_CHECK_RESPONSE_DATA;
115   }
116
117   sequence->protocol       = SAT_PROTOCOL_NON_DATA;
118   sequence->data_direction = SATI_DATA_DIRECTION_NONE;
119
120   sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
121
122   // Ensure the device supports the 48 bit feature set.
123   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
124      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
125   else
126      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
127
128   return SATI_SUCCESS;
129}
130
131//******************************************************************************
132//* P U B L I C   M E T H O D S
133//******************************************************************************
134
135/**
136 * @brief This method performs all of the translation required for a
137 *        SCSI VERIFY 10 byte CDB.
138 *        This includes:
139 *        - logical block address translation
140 *        - transfer length (sector count) translation
141 *        - translation items common to all VERIFY CDB sizes.
142 *        For more information on the parameters passed to this method,
143 *        please reference sati_translate_command().
144 *
145 * @return Indicate if the command translation was successful.
146 *         For more information on return values please reference
147 *         sati_move_set_sector_count(), sati_verify_translate_command()
148 */
149SATI_STATUS sati_verify_10_translate_command(
150   SATI_TRANSLATOR_SEQUENCE_T * sequence,
151   void                       * scsi_io,
152   void                       * ata_io
153)
154{
155   SATI_STATUS   status;
156   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
157   U32           sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
158                                (sati_get_cdb_byte(cdb, 8));
159
160   if(sati_device_state_stopped(sequence, scsi_io))
161   {
162      return SATI_FAILURE_CHECK_RESPONSE_DATA;
163   }
164   else
165   {
166      sequence->type = SATI_SEQUENCE_VERIFY_10;
167
168      // Fill in the Logical Block Address fields and sector count registers.
169      sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
170      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
171      if (status != SATI_SUCCESS)
172         return status;
173
174      return sati_verify_translate_command(sequence, scsi_io, ata_io);
175   }
176}
177
178/**
179 * @brief This method performs all of the translation required for a
180 *        SCSI VERIFY 12 byte CDB.
181 *        This includes:
182 *        - logical block address translation
183 *        - transfer length (sector count) translation
184 *        - translation items common to all VERIFY CDB sizes.
185 *        For more information on the parameters passed to this method,
186 *        please reference sati_translate_command().
187 *
188 * @return Indicate if the command translation was successful.
189 *         For more information on return values please reference
190 *         sati_move_set_sector_count(), sati_verify_translate_command()
191 */
192SATI_STATUS sati_verify_12_translate_command(
193   SATI_TRANSLATOR_SEQUENCE_T * sequence,
194   void                       * scsi_io,
195   void                       * ata_io
196)
197{
198   SATI_STATUS   status;
199   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
200   U32           sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
201                                (sati_get_cdb_byte(cdb, 7) << 16) |
202                                (sati_get_cdb_byte(cdb, 8) << 8)  |
203                                (sati_get_cdb_byte(cdb, 9));
204
205   if(sati_device_state_stopped(sequence, scsi_io))
206   {
207      return SATI_FAILURE_CHECK_RESPONSE_DATA;
208   }
209   else
210   {
211      sequence->type = SATI_SEQUENCE_VERIFY_12;
212
213      // Fill in the Logical Block Address fields and sector count registers.
214      sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
215      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
216      if (status != SATI_SUCCESS)
217         return status;
218
219      return sati_verify_translate_command(sequence, scsi_io, ata_io);
220   }
221}
222
223/**
224 * @brief This method performs all of the translation required for a
225 *        SCSI VERIFY 16 byte CDB.
226 *        This includes:
227 *        - logical block address translation
228 *        - transfer length (sector count) translation
229 *        - translation items common to all VERIFY CDB sizes.
230 *        For more information on the parameters passed to this method,
231 *        please reference sati_translate_command().
232 *
233 * @return Indicate if the command translation was successful.
234 *         For more information on return values please reference
235 *         sati_move_set_sector_count(), sati_verify_translate_command()
236 */
237SATI_STATUS sati_verify_16_translate_command(
238   SATI_TRANSLATOR_SEQUENCE_T * sequence,
239   void                       * scsi_io,
240   void                       * ata_io
241)
242{
243   SATI_STATUS   status;
244   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
245   U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
246                                (sati_get_cdb_byte(cdb, 11) << 16) |
247                                (sati_get_cdb_byte(cdb, 12) << 8)  |
248                                (sati_get_cdb_byte(cdb, 13));
249
250   if(sati_device_state_stopped(sequence, scsi_io))
251   {
252      return SATI_FAILURE_CHECK_RESPONSE_DATA;
253   }
254   else
255   {
256      sequence->type = SATI_SEQUENCE_VERIFY_16;
257
258      // Fill in the Logical Block Address field.
259      status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
260      if (status != SATI_SUCCESS)
261         return status;
262
263      // Fill in the Sector Count fields.
264      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
265      if (status != SATI_SUCCESS)
266         return status;
267
268      return sati_verify_translate_command(sequence, scsi_io, ata_io);
269   }
270}
271
272#endif // !defined(DISABLE_SATI_VERIFY)
273
274