xref: /freebsd/sys/dev/isci/scil/sati_read_buffer.c (revision 148a8da8)
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 Read Buffer command based on the SAT spec.
62 */
63 
64 #if !defined(DISABLE_SATI_READ_BUFFER)
65 
66 #include <dev/isci/scil/sati_read_buffer.h>
67 #include <dev/isci/scil/sati_callbacks.h>
68 #include <dev/isci/scil/sati_util.h>
69 
70 
71 /**
72 * @brief This method will translate the SCSI Read Buffer command
73 *        into a corresponding ATA Read Buffer command.
74 *        For more information on the parameters passed to this method,
75 *        please reference sati_translate_command().
76 *
77 * @return Indicates if the command translation succeeded.
78 * @retval SATI_SUCCESS indicates that the translation was supported and occurred
79 *         without error.
80 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
81 *         there is a translation failure.
82 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
83 *         error, and no additional translation is necessary.
84 */
85 SATI_STATUS sati_read_buffer_translate_command(
86    SATI_TRANSLATOR_SEQUENCE_T * sequence,
87    void                       * scsi_io,
88    void                       * ata_io
89 )
90 {
91    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
92    SATI_STATUS status = SATI_FAILURE;
93    U32 allocation_length;
94    U32 buffer_offset;
95 
96    allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
97                         (sati_get_cdb_byte(cdb, 7) << 8)  |
98                         (sati_get_cdb_byte(cdb, 8)));
99 
100    buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
101                     (sati_get_cdb_byte(cdb, 4) << 8)  |
102                     (sati_get_cdb_byte(cdb, 5)));
103 
104    sequence->allocation_length = allocation_length;
105 
106    switch(sati_get_cdb_byte(cdb, 1))
107    {
108       case SATI_READ_BUFFER_MODE_DATA:
109          if((allocation_length == 512) && (buffer_offset == 0) &&
110             (sati_get_cdb_byte(cdb, 2) == 0))
111          {
112             sati_ata_read_buffer_construct(ata_io, sequence);
113             sequence->type = SATI_SEQUENCE_READ_BUFFER;
114             sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
115             status = SATI_SUCCESS;
116          }
117          else
118          {
119             sati_scsi_sense_data_construct(
120                sequence,
121                scsi_io,
122                SCSI_STATUS_CHECK_CONDITION,
123                SCSI_SENSE_ILLEGAL_REQUEST,
124                SCSI_ASC_INVALID_FIELD_IN_CDB,
125                SCSI_ASCQ_INVALID_FIELD_IN_CDB
126             );
127             sequence->state = SATI_SEQUENCE_STATE_FINAL;
128             status = SATI_FAILURE_CHECK_RESPONSE_DATA;
129          }
130       break;
131 
132       case SATI_READ_BUFFER_MODE_DESCRIPTOR:
133 
134          //allocation legnth must be at least four to return translated data
135          if(allocation_length < 4)
136          {
137             sati_scsi_sense_data_construct(
138                sequence,
139                scsi_io,
140                SCSI_STATUS_CHECK_CONDITION,
141                SCSI_SENSE_ILLEGAL_REQUEST,
142                SCSI_ASC_INVALID_FIELD_IN_CDB,
143                SCSI_ASCQ_INVALID_FIELD_IN_CDB
144             );
145             sequence->state = SATI_SEQUENCE_STATE_FINAL;
146             status = SATI_FAILURE_CHECK_RESPONSE_DATA;
147          }
148          else
149          {
150             //figure out if we support other buffer id's
151             sati_set_data_byte(sequence, scsi_io, 0, 0x09); //offset boundary
152             sati_set_data_byte(sequence, scsi_io, 1, 0x00);
153             sati_set_data_byte(sequence, scsi_io, 2, 0x02); //buffer capacity 0x200
154             sati_set_data_byte(sequence, scsi_io, 3, 0x00);
155             sequence->state = SATI_SEQUENCE_STATE_FINAL;
156             status = SATI_COMPLETE;
157          }
158       break;
159 
160       default:
161          //Unspecified sat2v7, returning invalid cdb
162          sati_scsi_sense_data_construct(
163             sequence,
164             scsi_io,
165             SCSI_STATUS_CHECK_CONDITION,
166             SCSI_SENSE_ILLEGAL_REQUEST,
167             SCSI_ASC_INVALID_FIELD_IN_CDB,
168             SCSI_ASCQ_INVALID_FIELD_IN_CDB
169          );
170          sequence->state = SATI_SEQUENCE_STATE_FINAL;
171          status = SATI_FAILURE_CHECK_RESPONSE_DATA;
172    }
173    return status;
174 }
175 
176 /**
177 * @brief This method will complete the Read Buffer Translation by copying the
178          ATA response data into the SCSI request DATA buffer.
179 *        For more information on the parameters passed to this method,
180 *        please reference sati_translate_command().
181 *
182 * @return Indicates if the command translation succeeded.
183 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
184 *         there is a translation failure.
185 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
186 *         error, and no additional translation is necessary.
187 */
188 SATI_STATUS sati_read_buffer_translate_response(
189    SATI_TRANSLATOR_SEQUENCE_T * sequence,
190    void                       * scsi_io,
191    void                       * ata_io
192 )
193 {
194    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
195    U8   ata_status = (U8) sati_get_ata_status(register_fis);
196    SATI_STATUS status = SATI_COMPLETE;
197 
198    if (ata_status & ATA_STATUS_REG_ERROR_BIT)
199    {
200       sati_scsi_sense_data_construct(
201          sequence,
202          scsi_io,
203          SCSI_STATUS_CHECK_CONDITION,
204          SCSI_SENSE_ABORTED_COMMAND,
205          SCSI_ASC_NO_ADDITIONAL_SENSE,
206          SCSI_ASCQ_NO_ADDITIONAL_SENSE
207       );
208 
209       status = SATI_FAILURE_CHECK_RESPONSE_DATA;
210    }
211    else
212    {
213       void * ata_data = sati_cb_get_ata_data_address(ata_io);
214 
215       if(ata_data == NULL)
216       {
217          status = SATI_FAILURE;
218       }
219       else
220       {
221          //copy ATA data into SCSI data buffer
222          sati_copy_data(
223             sequence,
224             scsi_io,
225             0,
226             ata_data,
227             512
228          );
229       }
230    }
231 
232    sequence->state = SATI_SEQUENCE_STATE_FINAL;
233    return status;
234 }
235 
236 
237 #endif //!defined(DISABLE_SATI_READ_BUFFER)
238