xref: /freebsd/sys/dev/isci/scil/sati_atapi.c (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
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 all of the method implementations that
59  *        can be utilized by a user to perform SCSI-to-ATA Translation.
60  *        SATI adheres to the www.t10.org SAT specification.
61  *
62  * For situations where compliance is not observed, the SATI will
63  * return an error indication (most likely INVALID FIELD IN CDB sense data).
64  */
65 
66 #include <dev/isci/scil/sati.h>
67 #include <dev/isci/scil/sati_util.h>
68 #include <dev/isci/scil/sati_atapi.h>
69 #include <dev/isci/scil/sati_callbacks.h>
70 #include <dev/isci/scil/intel_ata.h>
71 #include <dev/isci/scil/intel_scsi.h>
72 #include <dev/isci/scil/intel_sat.h>
73 #include <dev/isci/scil/sati_report_luns.h>
74 
75 
76 //******************************************************************************
77 //* P U B L I C   M E T H O D S
78 //******************************************************************************
79 
80 SATI_STATUS sati_atapi_translate_command(
81    SATI_TRANSLATOR_SEQUENCE_T * sequence,
82    SATI_DEVICE_T              * sati_device,
83    void                       * scsi_io,
84    void                       * atapi_io
85 )
86 {
87    SATI_STATUS   status;
88    U8          * cdb = sati_cb_get_cdb_address(scsi_io);
89 
90    SATA_FIS_REG_H2D_T * register_fis =
91       (SATA_FIS_REG_H2D_T *)sati_cb_get_h2d_register_fis_address(atapi_io);
92 
93    U8 io_direction = SATI_DATA_DIRECTION_IN;
94 
95    //No sense response has been set for the translation sequence yet
96    sequence->is_sense_response_set = FALSE;
97    // Default to no translation response required
98    sequence->is_translate_response_required = FALSE;
99 
100    sequence->number_data_bytes_set = 0;
101    sequence->device  = sati_device;
102    sequence->command_specific_data.scratch = 0;
103 
104    sati_cb_get_data_direction(scsi_io, &io_direction);
105 
106    //set sat protocol.
107    if (io_direction == SATI_DATA_DIRECTION_NONE)
108       sequence->protocol = SAT_PROTOCOL_PACKET_NON_DATA;
109    else if (io_direction == SATI_DATA_DIRECTION_IN)
110       sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
111    else if (io_direction == SATI_DATA_DIRECTION_OUT)
112       sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_OUT;
113 
114    // We don't send Report Luns command out.
115    if  (sati_get_cdb_byte(cdb, 0) == SCSI_REPORT_LUNS)
116    {
117       status = sati_report_luns_translate_command(
118                   sequence, scsi_io, atapi_io
119                );
120    }
121    else if (sati_cb_get_lun(scsi_io) != 0)
122    {
123       sati_scsi_sense_data_construct(
124          sequence,
125          scsi_io,
126          SCSI_STATUS_CHECK_CONDITION,
127          SCSI_SENSE_ILLEGAL_REQUEST,
128          SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
129          0
130       );
131       status = SATI_FAILURE_CHECK_RESPONSE_DATA;
132    }
133    else
134    {
135       if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
136       {  //Request Sense command is required.
137          U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH] =
138             {0x3, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
139 
140          //set the sequence->protocol to DATA_IN anyway;
141          sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
142 
143          //set the cdb for Request Sense using command_specific_data field.
144          memcpy(sequence->command_specific_data.sati_atapi_data.request_sense_cdb,
145                 request_sense_cdb,
146                 SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH
147                );
148       }
149 
150       //build Packet Fis for any other command translation.
151       register_fis->command = ATA_PACKET;
152       register_fis->features |= ATA_PACKET_FEATURE_DMA;
153 
154       register_fis->fis_type = SATA_FIS_TYPE_REGH2D;
155       register_fis->command_flag = 1;
156 
157       status = SATI_SUCCESS;
158    }
159 
160    return status;
161 }
162 
163 
164 SATI_STATUS sati_atapi_translate_command_response(
165    SATI_TRANSLATOR_SEQUENCE_T * sequence,
166    void                       * scsi_io,
167    void                       * atapi_io
168 )
169 {
170    SATI_STATUS   status       = SATI_COMPLETE;
171    U8          * register_fis = sati_cb_get_d2h_register_fis_address(atapi_io);
172    U8            ata_status;
173 
174    /**
175     * If the device fault bit is set in the status register, then
176     * set the sense data and return.
177     */
178    ata_status = (U8) sati_get_ata_status(register_fis);
179    if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
180    {
181       sati_scsi_sense_data_construct(
182          sequence,
183          scsi_io,
184          SCSI_STATUS_CHECK_CONDITION,
185          SCSI_SENSE_HARDWARE_ERROR,
186          SCSI_ASC_INTERNAL_TARGET_FAILURE,
187          SCSI_ASCQ_INTERNAL_TARGET_FAILURE
188       );
189 
190       sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
191 
192       return SATI_FAILURE_CHECK_RESPONSE_DATA;
193    }
194    else if (ata_status & ATA_STATUS_REG_ERROR_BIT)
195    {
196        //reset the register_fis.
197        memset(register_fis, 0, sizeof(SATA_FIS_REG_D2H_T));
198 
199        //Internal Request Sense command is needed.
200        sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
201        return SATI_SEQUENCE_INCOMPLETE;
202    }
203 
204    return status;
205 }
206 
207 void sati_atapi_translate_request_sense_response(
208    SATI_TRANSLATOR_SEQUENCE_T * sequence,
209    void                       * scsi_io,
210    void                       * atapi_io
211 )
212 {
213    //sense data is already in place.
214    SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
215                                  sati_cb_get_response_iu_address(scsi_io);
216 
217    sati_scsi_common_response_iu_construct(
218       rsp_iu,
219       SCSI_STATUS_CHECK_CONDITION,
220       sati_scsi_get_sense_data_length(sequence, scsi_io),
221       SCSI_RESPONSE_DATA_PRES_SENSE_DATA
222    );
223 
224    sequence->is_sense_response_set = TRUE;
225 
226    sequence->state = SATI_SEQUENCE_STATE_FINAL;
227 }
228 
229 
230 U32 sati_atapi_translate_number_of_bytes_transferred(
231    SATI_TRANSLATOR_SEQUENCE_T * sequence,
232    void                       * scsi_io,
233    void                       * atapi_io
234 )
235 {
236    U8* cdb = sati_cb_get_cdb_address(scsi_io);
237    U8 response_data;
238    U32 data_length = 0;
239 
240    switch(cdb[0])
241    {
242       case SCSI_MODE_SENSE_10:
243          sati_cb_get_data_byte(scsi_io, 1, &response_data);
244          data_length = response_data+2;
245          break;
246 
247       case 0x51: //READ DISC INFORMATION
248          sati_cb_get_data_byte(scsi_io, 1, &response_data);
249          data_length = response_data+2;
250          break;
251 
252       default:
253          break;
254    }
255 
256    return data_length;
257 }
258