xref: /freebsd/sys/dev/isci/scil/sati_request_sense.c (revision 10ff414c)
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 Request Sense command based of the SAT spec.
62  */
63 
64 #if !defined(DISABLE_SATI_REQUEST_SENSE)
65 
66 #include <dev/isci/scil/sati_request_sense.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_mode_pages.h>
74 
75 #define MRIE_BYTE 3
76 #define DEXCPT_BYTE 2
77 
78 /**
79  * @brief This method will translate the SCSI request sense command
80  *        into corresponding ATA commands.  Depending on supported and enabled
81  *        capabilities like SMART, different ATA commands can be selected.
82  *        For more information on the parameters passed to this method,
83  *        please reference sati_translate_command().
84  *
85  * @return Indicates if the command translation succeeded.
86  * @retval SATI_SUCCESS indicates that the translation was supported and occurred
87  *         without error.
88  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
89  *         the SATII is processing a format unit commmand.
90  * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
91  *         error, and no additional translation is necessary.
92  */
93 SATI_STATUS sati_request_sense_translate_command(
94    SATI_TRANSLATOR_SEQUENCE_T * sequence,
95    void                       * scsi_io,
96    void                       * ata_io
97 )
98 {
99    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
100 
101    //check if SATI is processing format unit command
102    switch(sequence->device->state)
103    {
104       case SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS:
105          sati_scsi_sense_data_construct(
106             sequence,
107             scsi_io,
108             SCSI_STATUS_GOOD,
109             SCSI_SENSE_NOT_READY,
110             SCSI_ASC_LUN_FORMAT_IN_PROGRESS,
111             SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS
112          );
113          return SATI_COMPLETE;
114       break;
115 
116       case SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION:
117          sati_scsi_sense_data_construct(
118             sequence,
119             scsi_io,
120             SCSI_STATUS_GOOD,
121             SCSI_SENSE_UNIT_ATTENTION,
122             sequence->device->unit_attention_asc,
123             sequence->device->unit_attention_ascq
124          );
125          return SATI_COMPLETE;
126       break;
127       //sending sense data status Idle, this is set by start_stop_unit
128       case SATI_DEVICE_STATE_IDLE:
129          sati_scsi_sense_data_construct(
130             sequence,
131             scsi_io,
132             SCSI_STATUS_GOOD,
133             SCSI_SENSE_NO_SENSE,
134             SCSI_ASC_POWER_STATE_CHANGE,
135             SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND
136          );
137          return SATI_COMPLETE;
138       break;
139       //sending sense data status Standby, this is set by start_stop_unit
140       case SATI_DEVICE_STATE_STANDBY:
141          sati_scsi_sense_data_construct(
142             sequence,
143             scsi_io,
144             SCSI_STATUS_GOOD,
145             SCSI_SENSE_NO_SENSE,
146             SCSI_ASC_POWER_STATE_CHANGE,
147             SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND
148          );
149          return SATI_COMPLETE;
150       break;
151 
152       case SATI_DEVICE_STATE_STOPPED:
153          sati_scsi_sense_data_construct(
154             sequence,
155             scsi_io,
156             SCSI_STATUS_GOOD,
157             SCSI_SENSE_NO_SENSE,
158             SCSI_ASC_NO_ADDITIONAL_SENSE,
159             SCSI_ASCQ_NO_ADDITIONAL_SENSE
160          );
161          return SATI_COMPLETE;
162       break;
163 
164       default:
165       break;
166    }
167 
168    sequence->allocation_length = sati_get_cdb_byte(cdb, 4);
169 
170    //Check if the device has SMART support & SMART enabled
171    if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
172    {
173        if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
174        {
175             sati_ata_smart_return_status_construct(
176                            ata_io,
177                            sequence,
178                            ATA_SMART_SUB_CMD_RETURN_STATUS
179             );
180 
181             sequence->type = SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS;
182             return SATI_SUCCESS;
183         }
184    }
185    sati_ata_check_power_mode_construct(ata_io, sequence);
186    sequence->type = SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE;
187    return SATI_SUCCESS;
188 }
189 
190 /**
191  * @brief This method will translate the response to the SATI Request Sense
192  *        translation. ATA_Check_Power_Mode and ATA_SMART_Return_Status will
193  *        be translated into a SCSI sense data response.
194  *
195  * @return SATI_STATUS Indicates if the response translation succeeded.
196  *
197  */
198 SATI_STATUS sati_request_sense_translate_response(
199    SATI_TRANSLATOR_SEQUENCE_T * sequence,
200    void                       * scsi_io,
201    void                       * ata_io
202 )
203 {
204    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
205    U32 mid_register;
206    U32 high_register;
207    U32 sector_count;
208    SATI_STATUS status = SATI_FAILURE;
209 
210    if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
211    {
212       sati_scsi_sense_data_construct(
213          sequence,
214          scsi_io,
215          SCSI_STATUS_CHECK_CONDITION,
216          SCSI_SENSE_ABORTED_COMMAND,
217          SCSI_ASC_NO_ADDITIONAL_SENSE ,
218          SCSI_ASCQ_NO_ADDITIONAL_SENSE
219       );
220       status = SATI_FAILURE_CHECK_RESPONSE_DATA;
221    }
222    else
223    {
224       switch(sequence->type)
225       {
226          case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
227 
228             mid_register = sati_get_ata_lba_mid(register_fis);
229             high_register = sati_get_ata_lba_high(register_fis);
230             if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
231                && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
232             {
233                sati_request_sense_data_response_construct(
234                   sequence,
235                   scsi_io,
236                   SCSI_SENSE_NO_SENSE,
237                   SCSI_ASC_HARDWARE_IMPENDING_FAILURE,
238                   SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
239                );
240                status = SATI_COMPLETE;
241             }
242             else
243             {
244                sati_request_sense_data_response_construct(
245                   sequence,
246                   scsi_io,
247                   SCSI_SENSE_NO_SENSE,
248                   SCSI_ASC_NO_ADDITIONAL_SENSE,
249                   SCSI_ASCQ_NO_ADDITIONAL_SENSE
250                );
251                status = SATI_COMPLETE;
252             }
253          break;
254 
255          case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
256 
257             sector_count = sati_get_ata_sector_count(register_fis);
258 
259             switch(sector_count)
260             {
261                 case ATA_STANDBY_POWER_MODE:
262                    sati_request_sense_data_response_construct(
263                       sequence,
264                       scsi_io,
265                       SCSI_SENSE_NO_SENSE,
266                       SCSI_ASC_POWER_STATE_CHANGE,
267                       SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY
268                    );
269                    status = SATI_COMPLETE;
270                 break;
271 
272                 case ATA_IDLE_POWER_MODE:
273                    sati_request_sense_data_response_construct(
274                       sequence,
275                       scsi_io,
276                       SCSI_SENSE_NO_SENSE,
277                       SCSI_ASC_POWER_STATE_CHANGE,
278                       SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE
279                    );
280                    status = SATI_COMPLETE;
281                 break;
282 
283                 case ATA_ACTIVE_POWER_MODE:
284                    sati_request_sense_data_response_construct(
285                       sequence,
286                       scsi_io,
287                       SCSI_SENSE_NO_SENSE,
288                       SCSI_ASC_NO_ADDITIONAL_SENSE,
289                       SCSI_ASCQ_NO_ADDITIONAL_SENSE
290                    );
291                    status = SATI_COMPLETE;
292                 break;
293 
294                 default:
295                 break;
296              }
297          break;
298 
299          default:
300             sati_request_sense_data_response_construct(
301                sequence,
302                scsi_io,
303                SCSI_SENSE_NO_SENSE,
304                SCSI_ASC_NO_ADDITIONAL_SENSE,
305                SCSI_ASCQ_NO_ADDITIONAL_SENSE
306             );
307             status = SATI_COMPLETE;
308       }
309    }
310 
311    return status;
312 }
313 
314 /**
315  * @brief This method will construct a response for the sati_request_sense
316  *        translation. The response will be returned in the data buffer instead
317  *        of the response buffer, using sense data format described in SPC-4.
318  *
319  */
320 void sati_request_sense_data_response_construct(
321    SATI_TRANSLATOR_SEQUENCE_T * sequence,
322    void                       * scsi_io,
323    U8                           sense_key,
324    U8                           additional_sense_code,
325    U8                           additional_sense_code_qualifier
326 )
327 {
328    sati_set_data_byte(
329       sequence,
330       scsi_io,
331       0,
332       SCSI_FIXED_CURRENT_RESPONSE_CODE | SCSI_FIXED_SENSE_DATA_VALID_BIT
333    );
334 
335    sati_set_data_byte(sequence, scsi_io, 1, 0);
336    sati_set_data_byte(sequence, scsi_io, 2, sense_key);
337    sati_set_data_byte(sequence, scsi_io, 3, 0);
338    sati_set_data_byte(sequence, scsi_io, 4, 0);
339    sati_set_data_byte(sequence, scsi_io, 5, 0);
340    sati_set_data_byte(sequence, scsi_io, 6, 0);
341    sati_set_data_byte(sequence, scsi_io, 7, 0);
342    sati_set_data_byte(sequence, scsi_io, 8, 0);
343    sati_set_data_byte(sequence, scsi_io, 9, 0);
344    sati_set_data_byte(sequence, scsi_io, 10, 0);
345    sati_set_data_byte(sequence, scsi_io, 11, 0);
346    sati_set_data_byte(sequence, scsi_io, 12, additional_sense_code);
347    sati_set_data_byte(sequence, scsi_io, 13, additional_sense_code_qualifier);
348    sati_set_data_byte(sequence, scsi_io, 14, 0);
349    sati_set_data_byte(sequence, scsi_io, 15, 0);
350    sati_set_data_byte(sequence, scsi_io, 16, 0);
351    sati_set_data_byte(sequence, scsi_io, 17, 0);
352 }
353 
354 #endif // !defined(DISABLE_SATI_REQUEST_SENSE)
355 
356