xref: /freebsd/sys/dev/isci/scil/sati_read.c (revision f11c7f63056671247335df83a3fe80b94c6616ac)
1*f11c7f63SJim Harris /*-
2*f11c7f63SJim Harris  * This file is provided under a dual BSD/GPLv2 license.  When using or
3*f11c7f63SJim Harris  * redistributing this file, you may do so under either license.
4*f11c7f63SJim Harris  *
5*f11c7f63SJim Harris  * GPL LICENSE SUMMARY
6*f11c7f63SJim Harris  *
7*f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8*f11c7f63SJim Harris  *
9*f11c7f63SJim Harris  * This program is free software; you can redistribute it and/or modify
10*f11c7f63SJim Harris  * it under the terms of version 2 of the GNU General Public License as
11*f11c7f63SJim Harris  * published by the Free Software Foundation.
12*f11c7f63SJim Harris  *
13*f11c7f63SJim Harris  * This program is distributed in the hope that it will be useful, but
14*f11c7f63SJim Harris  * WITHOUT ANY WARRANTY; without even the implied warranty of
15*f11c7f63SJim Harris  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*f11c7f63SJim Harris  * General Public License for more details.
17*f11c7f63SJim Harris  *
18*f11c7f63SJim Harris  * You should have received a copy of the GNU General Public License
19*f11c7f63SJim Harris  * along with this program; if not, write to the Free Software
20*f11c7f63SJim Harris  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21*f11c7f63SJim Harris  * The full GNU General Public License is included in this distribution
22*f11c7f63SJim Harris  * in the file called LICENSE.GPL.
23*f11c7f63SJim Harris  *
24*f11c7f63SJim Harris  * BSD LICENSE
25*f11c7f63SJim Harris  *
26*f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27*f11c7f63SJim Harris  * All rights reserved.
28*f11c7f63SJim Harris  *
29*f11c7f63SJim Harris  * Redistribution and use in source and binary forms, with or without
30*f11c7f63SJim Harris  * modification, are permitted provided that the following conditions
31*f11c7f63SJim Harris  * are met:
32*f11c7f63SJim Harris  *
33*f11c7f63SJim Harris  *   * Redistributions of source code must retain the above copyright
34*f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer.
35*f11c7f63SJim Harris  *   * Redistributions in binary form must reproduce the above copyright
36*f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer in
37*f11c7f63SJim Harris  *     the documentation and/or other materials provided with the
38*f11c7f63SJim Harris  *     distribution.
39*f11c7f63SJim Harris  *
40*f11c7f63SJim Harris  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41*f11c7f63SJim Harris  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42*f11c7f63SJim Harris  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43*f11c7f63SJim Harris  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44*f11c7f63SJim Harris  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45*f11c7f63SJim Harris  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46*f11c7f63SJim Harris  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47*f11c7f63SJim Harris  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48*f11c7f63SJim Harris  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49*f11c7f63SJim Harris  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50*f11c7f63SJim Harris  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51*f11c7f63SJim Harris  */
52*f11c7f63SJim Harris 
53*f11c7f63SJim Harris #include <sys/cdefs.h>
54*f11c7f63SJim Harris __FBSDID("$FreeBSD$");
55*f11c7f63SJim Harris 
56*f11c7f63SJim Harris /**
57*f11c7f63SJim Harris  * @file
58*f11c7f63SJim Harris  * @brief This file contains the method implementations required to
59*f11c7f63SJim Harris  *        translate the SCSI read (6, 10, 12, or 16-byte) commands.
60*f11c7f63SJim Harris  */
61*f11c7f63SJim Harris 
62*f11c7f63SJim Harris #include <dev/isci/scil/sati_move.h>
63*f11c7f63SJim Harris #include <dev/isci/scil/sati_read.h>
64*f11c7f63SJim Harris #include <dev/isci/scil/sati_callbacks.h>
65*f11c7f63SJim Harris #include <dev/isci/scil/sati_util.h>
66*f11c7f63SJim Harris 
67*f11c7f63SJim Harris #include <dev/isci/scil/intel_ata.h>
68*f11c7f63SJim Harris #include <dev/isci/scil/intel_scsi.h>
69*f11c7f63SJim Harris 
70*f11c7f63SJim Harris //******************************************************************************
71*f11c7f63SJim Harris //* P R I V A T E   M E T H O D S
72*f11c7f63SJim Harris //******************************************************************************
73*f11c7f63SJim Harris 
74*f11c7f63SJim Harris /**
75*f11c7f63SJim Harris  * @brief This method performs the common translation functionality for
76*f11c7f63SJim Harris  *        all SCSI read operations that are 10 bytes in size or larger.
77*f11c7f63SJim Harris  *        Translated/Written items include:
78*f11c7f63SJim Harris  *        - Force Unit Access (FUA)
79*f11c7f63SJim Harris  *        - Sector Count/Transfer Length
80*f11c7f63SJim Harris  *        - Command register
81*f11c7f63SJim Harris  *
82*f11c7f63SJim Harris  * @param[in] sector_count This parameter specifies the number of sectors
83*f11c7f63SJim Harris  *            to be transferred by this request.
84*f11c7f63SJim Harris  * @param[in] device_head This parameter points to device head register
85*f11c7f63SJim Harris  *            that is to be written into the ATA task file (register FIS).
86*f11c7f63SJim Harris  *
87*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
88*f11c7f63SJim Harris  * @see sati_move_set_sector_count() for additional return values.
89*f11c7f63SJim Harris  */
90*f11c7f63SJim Harris static
91*f11c7f63SJim Harris SATI_STATUS sati_read_large_translate_command(
92*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
93*f11c7f63SJim Harris    void                       * scsi_io,
94*f11c7f63SJim Harris    void                       * ata_io,
95*f11c7f63SJim Harris    U32                          sector_count,
96*f11c7f63SJim Harris    U8                         * device_head
97*f11c7f63SJim Harris )
98*f11c7f63SJim Harris {
99*f11c7f63SJim Harris    sequence->data_direction = SATI_DATA_DIRECTION_IN;
100*f11c7f63SJim Harris 
101*f11c7f63SJim Harris    return sati_move_large_translate_command(
102*f11c7f63SJim Harris              sequence,
103*f11c7f63SJim Harris              scsi_io,
104*f11c7f63SJim Harris              ata_io,
105*f11c7f63SJim Harris              sector_count,
106*f11c7f63SJim Harris              device_head
107*f11c7f63SJim Harris           );
108*f11c7f63SJim Harris }
109*f11c7f63SJim Harris 
110*f11c7f63SJim Harris /**
111*f11c7f63SJim Harris  * @brief This method performs the common translation functionality for
112*f11c7f63SJim Harris  *        all SCSI read operations containing a 32-bit logical block
113*f11c7f63SJim Harris  *        address.
114*f11c7f63SJim Harris  *        Translated/Written items include:
115*f11c7f63SJim Harris  *        - Logical Block Address (LBA)
116*f11c7f63SJim Harris  *        - Force Unit Access (FUA)
117*f11c7f63SJim Harris  *        - Sector Count/Transfer Length
118*f11c7f63SJim Harris  *        - Command register
119*f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
120*f11c7f63SJim Harris  *        please reference sati_translate_command().
121*f11c7f63SJim Harris  *
122*f11c7f63SJim Harris  * @param[in] sector_count This parameter specifies the number of sectors
123*f11c7f63SJim Harris  *            to be transferred by this request.
124*f11c7f63SJim Harris  * @param[in] control_byte_offset This parameter specifies the byte offset
125*f11c7f63SJim Harris  *            into the command descriptor block at which the control byte
126*f11c7f63SJim Harris  *            is located.
127*f11c7f63SJim Harris  *
128*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
129*f11c7f63SJim Harris  * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
130*f11c7f63SJim Harris  *      for additional return values.
131*f11c7f63SJim Harris  */
132*f11c7f63SJim Harris static
133*f11c7f63SJim Harris SATI_STATUS sati_read_32_bit_lba_translate_command(
134*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
135*f11c7f63SJim Harris    void                       * scsi_io,
136*f11c7f63SJim Harris    void                       * ata_io,
137*f11c7f63SJim Harris    U32                          sector_count,
138*f11c7f63SJim Harris    U8                           control_byte_offset
139*f11c7f63SJim Harris )
140*f11c7f63SJim Harris {
141*f11c7f63SJim Harris    U8           device_head = 0;
142*f11c7f63SJim Harris    SATI_STATUS  status;
143*f11c7f63SJim Harris 
144*f11c7f63SJim Harris    status = sati_read_large_translate_command(
145*f11c7f63SJim Harris                sequence, scsi_io, ata_io, sector_count, &device_head
146*f11c7f63SJim Harris             );
147*f11c7f63SJim Harris 
148*f11c7f63SJim Harris    if (status == SATI_SUCCESS)
149*f11c7f63SJim Harris    {
150*f11c7f63SJim Harris       status = sati_move_32_bit_lba_translate_command(
151*f11c7f63SJim Harris                   sequence, scsi_io, ata_io, device_head
152*f11c7f63SJim Harris                );
153*f11c7f63SJim Harris    }
154*f11c7f63SJim Harris 
155*f11c7f63SJim Harris    return status;
156*f11c7f63SJim Harris }
157*f11c7f63SJim Harris 
158*f11c7f63SJim Harris //******************************************************************************
159*f11c7f63SJim Harris //* P U B L I C   M E T H O D S
160*f11c7f63SJim Harris //******************************************************************************
161*f11c7f63SJim Harris 
162*f11c7f63SJim Harris /**
163*f11c7f63SJim Harris  * @brief This method will translate the SCSI read command into a
164*f11c7f63SJim Harris  *        corresponding ATA read 6 command.  Depending upon the capabilities
165*f11c7f63SJim Harris  *        supported by the target different ATA commands can be selected.
166*f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
167*f11c7f63SJim Harris  *        please reference sati_translate_command().
168*f11c7f63SJim Harris  *
169*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
170*f11c7f63SJim Harris  * @retval SCI_SUCCESS This is returned if the command translation was
171*f11c7f63SJim Harris  *         successful.
172*f11c7f63SJim Harris  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
173*f11c7f63SJim Harris  *         sense data has been created as a result of something specified
174*f11c7f63SJim Harris  *         in the CDB.
175*f11c7f63SJim Harris  */
176*f11c7f63SJim Harris SATI_STATUS sati_read_6_translate_command(
177*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
178*f11c7f63SJim Harris    void                       * scsi_io,
179*f11c7f63SJim Harris    void                       * ata_io
180*f11c7f63SJim Harris )
181*f11c7f63SJim Harris {
182*f11c7f63SJim Harris    if(sati_device_state_stopped(sequence, scsi_io))
183*f11c7f63SJim Harris    {
184*f11c7f63SJim Harris       return SATI_FAILURE_CHECK_RESPONSE_DATA;
185*f11c7f63SJim Harris    }
186*f11c7f63SJim Harris    else
187*f11c7f63SJim Harris    {
188*f11c7f63SJim Harris       sequence->data_direction = SATI_DATA_DIRECTION_IN;
189*f11c7f63SJim Harris       sequence->type           = SATI_SEQUENCE_READ_6;
190*f11c7f63SJim Harris 
191*f11c7f63SJim Harris       return sati_move_small_translate_command(sequence, scsi_io, ata_io);
192*f11c7f63SJim Harris    }
193*f11c7f63SJim Harris }
194*f11c7f63SJim Harris 
195*f11c7f63SJim Harris /**
196*f11c7f63SJim Harris  * @brief This method will translate the SCSI read 10 command into a
197*f11c7f63SJim Harris  *        corresponding ATA read command.  Depending upon the capabilities
198*f11c7f63SJim Harris  *        supported by the target different ATA commands can be selected.
199*f11c7f63SJim Harris  *        It ensures that all translation required for this command is
200*f11c7f63SJim Harris  *        performed successfully.
201*f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
202*f11c7f63SJim Harris  *        please reference sati_translate_command().
203*f11c7f63SJim Harris  *
204*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
205*f11c7f63SJim Harris  * @see sati_read_32_bit_lba_translate_command() for return values.
206*f11c7f63SJim Harris  */
207*f11c7f63SJim Harris SATI_STATUS sati_read_10_translate_command(
208*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
209*f11c7f63SJim Harris    void                       * scsi_io,
210*f11c7f63SJim Harris    void                       * ata_io
211*f11c7f63SJim Harris )
212*f11c7f63SJim Harris {
213*f11c7f63SJim Harris 
214*f11c7f63SJim Harris    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
215*f11c7f63SJim Harris 
216*f11c7f63SJim Harris    U32 sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
217*f11c7f63SJim Harris                       (sati_get_cdb_byte(cdb, 8));
218*f11c7f63SJim Harris 
219*f11c7f63SJim Harris    if(sati_device_state_stopped(sequence, scsi_io))
220*f11c7f63SJim Harris    {
221*f11c7f63SJim Harris       return SATI_FAILURE_CHECK_RESPONSE_DATA;
222*f11c7f63SJim Harris    }
223*f11c7f63SJim Harris    else
224*f11c7f63SJim Harris    {
225*f11c7f63SJim Harris       sequence->type = SATI_SEQUENCE_READ_10;
226*f11c7f63SJim Harris 
227*f11c7f63SJim Harris       return sati_read_32_bit_lba_translate_command(
228*f11c7f63SJim Harris                 sequence, scsi_io, ata_io, sector_count, 9
229*f11c7f63SJim Harris              );
230*f11c7f63SJim Harris    }
231*f11c7f63SJim Harris }
232*f11c7f63SJim Harris 
233*f11c7f63SJim Harris /**
234*f11c7f63SJim Harris  * @brief This method will translate the SCSI read 12 command into a
235*f11c7f63SJim Harris  *        corresponding ATA read command.  Depending upon the capabilities
236*f11c7f63SJim Harris  *        supported by the target different ATA commands can be selected.
237*f11c7f63SJim Harris  *        It ensures that all translation required for this command is
238*f11c7f63SJim Harris  *        performed successfully.
239*f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
240*f11c7f63SJim Harris  *        please reference sati_translate_command().
241*f11c7f63SJim Harris  *
242*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
243*f11c7f63SJim Harris  * @see sati_read_32_bit_lba_translate_command() for return values.
244*f11c7f63SJim Harris  */
245*f11c7f63SJim Harris SATI_STATUS sati_read_12_translate_command(
246*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
247*f11c7f63SJim Harris    void                       * scsi_io,
248*f11c7f63SJim Harris    void                       * ata_io
249*f11c7f63SJim Harris )
250*f11c7f63SJim Harris {
251*f11c7f63SJim Harris    U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
252*f11c7f63SJim Harris    U32   sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
253*f11c7f63SJim Harris                         (sati_get_cdb_byte(cdb, 7) << 16) |
254*f11c7f63SJim Harris                         (sati_get_cdb_byte(cdb, 8) << 8)  |
255*f11c7f63SJim Harris                         (sati_get_cdb_byte(cdb, 9));
256*f11c7f63SJim Harris 
257*f11c7f63SJim Harris    if(sati_device_state_stopped(sequence, scsi_io))
258*f11c7f63SJim Harris    {
259*f11c7f63SJim Harris       return SATI_FAILURE_CHECK_RESPONSE_DATA;
260*f11c7f63SJim Harris    }
261*f11c7f63SJim Harris    else
262*f11c7f63SJim Harris    {
263*f11c7f63SJim Harris       sequence->type = SATI_SEQUENCE_READ_12;
264*f11c7f63SJim Harris 
265*f11c7f63SJim Harris       return sati_read_32_bit_lba_translate_command(
266*f11c7f63SJim Harris                 sequence, scsi_io, ata_io, sector_count, 11
267*f11c7f63SJim Harris              );
268*f11c7f63SJim Harris    }
269*f11c7f63SJim Harris }
270*f11c7f63SJim Harris 
271*f11c7f63SJim Harris /**
272*f11c7f63SJim Harris  * @brief This method will translate the SCSI read 16 command into a
273*f11c7f63SJim Harris  *        corresponding ATA read command.  Depending upon the capabilities
274*f11c7f63SJim Harris  *        supported by the target different ATA commands can be selected.
275*f11c7f63SJim Harris  *        It ensures that all translation required for this command is
276*f11c7f63SJim Harris  *        performed successfully.
277*f11c7f63SJim Harris  *        For more information on the parameters passed to this method,
278*f11c7f63SJim Harris  *        please reference sati_translate_command().
279*f11c7f63SJim Harris  *
280*f11c7f63SJim Harris  * @return Indicate if the command translation succeeded.
281*f11c7f63SJim Harris  * @see sati_read_large_translate_command(), sati_move_translate_64_bit_lba()
282*f11c7f63SJim Harris  *      for additional return values.
283*f11c7f63SJim Harris  */
284*f11c7f63SJim Harris SATI_STATUS sati_read_16_translate_command(
285*f11c7f63SJim Harris    SATI_TRANSLATOR_SEQUENCE_T * sequence,
286*f11c7f63SJim Harris    void                       * scsi_io,
287*f11c7f63SJim Harris    void                       * ata_io
288*f11c7f63SJim Harris )
289*f11c7f63SJim Harris {
290*f11c7f63SJim Harris    SATI_STATUS   status;
291*f11c7f63SJim Harris    U8            device_head  = 0;
292*f11c7f63SJim Harris    U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
293*f11c7f63SJim Harris    U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
294*f11c7f63SJim Harris                                 (sati_get_cdb_byte(cdb, 11) << 16) |
295*f11c7f63SJim Harris                                 (sati_get_cdb_byte(cdb, 12) << 8)  |
296*f11c7f63SJim Harris                                 (sati_get_cdb_byte(cdb, 13));
297*f11c7f63SJim Harris 
298*f11c7f63SJim Harris    if(sati_device_state_stopped(sequence, scsi_io))
299*f11c7f63SJim Harris    {
300*f11c7f63SJim Harris       return SATI_FAILURE_CHECK_RESPONSE_DATA;
301*f11c7f63SJim Harris    }
302*f11c7f63SJim Harris    else
303*f11c7f63SJim Harris    {
304*f11c7f63SJim Harris       sequence->type = SATI_SEQUENCE_READ_16;
305*f11c7f63SJim Harris 
306*f11c7f63SJim Harris       // Translate the sector count, write command register, and check various
307*f11c7f63SJim Harris       // other parts of the CDB.
308*f11c7f63SJim Harris       status = sati_read_large_translate_command(
309*f11c7f63SJim Harris                   sequence, scsi_io, ata_io, sector_count, &device_head
310*f11c7f63SJim Harris                );
311*f11c7f63SJim Harris 
312*f11c7f63SJim Harris       // Attempt to translate the 64-bit LBA field from the SCSI request
313*f11c7f63SJim Harris       // into the 48-bits of LBA in the ATA register FIS.
314*f11c7f63SJim Harris       if (status == SATI_SUCCESS)
315*f11c7f63SJim Harris       {
316*f11c7f63SJim Harris          sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
317*f11c7f63SJim Harris          status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
318*f11c7f63SJim Harris       }
319*f11c7f63SJim Harris 
320*f11c7f63SJim Harris       return status;
321*f11c7f63SJim Harris    }
322*f11c7f63SJim Harris }
323*f11c7f63SJim Harris 
324