1f11c7f63SJim Harris /*-
2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3*718cf2ccSPedro F. Giffuni *
4f11c7f63SJim Harris * This file is provided under a dual BSD/GPLv2 license. When using or
5f11c7f63SJim Harris * redistributing this file, you may do so under either license.
6f11c7f63SJim Harris *
7f11c7f63SJim Harris * GPL LICENSE SUMMARY
8f11c7f63SJim Harris *
9f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10f11c7f63SJim Harris *
11f11c7f63SJim Harris * This program is free software; you can redistribute it and/or modify
12f11c7f63SJim Harris * it under the terms of version 2 of the GNU General Public License as
13f11c7f63SJim Harris * published by the Free Software Foundation.
14f11c7f63SJim Harris *
15f11c7f63SJim Harris * This program is distributed in the hope that it will be useful, but
16f11c7f63SJim Harris * WITHOUT ANY WARRANTY; without even the implied warranty of
17f11c7f63SJim Harris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18f11c7f63SJim Harris * General Public License for more details.
19f11c7f63SJim Harris *
20f11c7f63SJim Harris * You should have received a copy of the GNU General Public License
21f11c7f63SJim Harris * along with this program; if not, write to the Free Software
22f11c7f63SJim Harris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23f11c7f63SJim Harris * The full GNU General Public License is included in this distribution
24f11c7f63SJim Harris * in the file called LICENSE.GPL.
25f11c7f63SJim Harris *
26f11c7f63SJim Harris * BSD LICENSE
27f11c7f63SJim Harris *
28f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29f11c7f63SJim Harris * All rights reserved.
30f11c7f63SJim Harris *
31f11c7f63SJim Harris * Redistribution and use in source and binary forms, with or without
32f11c7f63SJim Harris * modification, are permitted provided that the following conditions
33f11c7f63SJim Harris * are met:
34f11c7f63SJim Harris *
35f11c7f63SJim Harris * * Redistributions of source code must retain the above copyright
36f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer.
37f11c7f63SJim Harris * * Redistributions in binary form must reproduce the above copyright
38f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer in
39f11c7f63SJim Harris * the documentation and/or other materials provided with the
40f11c7f63SJim Harris * distribution.
41f11c7f63SJim Harris *
42f11c7f63SJim Harris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43f11c7f63SJim Harris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44f11c7f63SJim Harris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45f11c7f63SJim Harris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46f11c7f63SJim Harris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47f11c7f63SJim Harris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48f11c7f63SJim Harris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49f11c7f63SJim Harris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50f11c7f63SJim Harris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51f11c7f63SJim Harris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52f11c7f63SJim Harris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53f11c7f63SJim Harris */
54f11c7f63SJim Harris
55f11c7f63SJim Harris #include <sys/cdefs.h>
56f11c7f63SJim Harris /**
57f11c7f63SJim Harris * @file
58f11c7f63SJim Harris * @brief This file contains the method implementations required to
59f11c7f63SJim Harris * translate the SCSI mode sense (6 and 10-byte) commands.
60f11c7f63SJim Harris */
61f11c7f63SJim Harris
62f11c7f63SJim Harris #if !defined(DISABLE_SATI_MODE_SENSE)
63f11c7f63SJim Harris
64f11c7f63SJim Harris #include <dev/isci/scil/sati_mode_sense.h>
65f11c7f63SJim Harris #include <dev/isci/scil/sati_mode_pages.h>
66f11c7f63SJim Harris #include <dev/isci/scil/sati_callbacks.h>
67f11c7f63SJim Harris #include <dev/isci/scil/sati_util.h>
68f11c7f63SJim Harris #include <dev/isci/scil/intel_scsi.h>
69f11c7f63SJim Harris #include <dev/isci/scil/intel_ata.h>
70f11c7f63SJim Harris
71f11c7f63SJim Harris //******************************************************************************
72f11c7f63SJim Harris //* P R I V A T E M E T H O D S
73f11c7f63SJim Harris //******************************************************************************
74f11c7f63SJim Harris
75f11c7f63SJim Harris #define STANDBY_TIMER_DISABLED 0x00
76f11c7f63SJim Harris #define STANDBY_TIMER_ENABLED 0x01
77f11c7f63SJim Harris #define STANDBY_TIMER_SUPPORTED 0x2000
78f11c7f63SJim Harris
79f11c7f63SJim Harris
80f11c7f63SJim Harris
81f11c7f63SJim Harris /**
82f11c7f63SJim Harris * @brief This method indicates if the supplied page control is supported
83f11c7f63SJim Harris * by this translation implementation. Currently savable parameters
84f11c7f63SJim Harris * (i.e. non-volatile) are not supported.
85f11c7f63SJim Harris * For more information on the parameters passed to this method,
86f11c7f63SJim Harris * please reference sati_translate_command().
87f11c7f63SJim Harris *
88f11c7f63SJim Harris * @return This method returns an indication of whether the page control
89f11c7f63SJim Harris * specified in the SCSI CDB is supported.
90f11c7f63SJim Harris * @retval SATI_SUCCESS This value is returned if the page control is
91f11c7f63SJim Harris * supported.
92f11c7f63SJim Harris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
93f11c7f63SJim Harris * page control is not supported.
94f11c7f63SJim Harris */
95f11c7f63SJim Harris static
sati_mode_sense_is_page_control_supported(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)96f11c7f63SJim Harris SATI_STATUS sati_mode_sense_is_page_control_supported(
97f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
98f11c7f63SJim Harris void * scsi_io
99f11c7f63SJim Harris )
100f11c7f63SJim Harris {
101f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
102f11c7f63SJim Harris
103f11c7f63SJim Harris switch (sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT)
104f11c7f63SJim Harris {
105f11c7f63SJim Harris case SCSI_MODE_SENSE_PC_CURRENT:
106f11c7f63SJim Harris case SCSI_MODE_SENSE_PC_DEFAULT:
107f11c7f63SJim Harris case SCSI_MODE_SENSE_PC_CHANGEABLE:
108f11c7f63SJim Harris return SATI_SUCCESS;
109f11c7f63SJim Harris break;
110f11c7f63SJim Harris
111f11c7f63SJim Harris default:
112f11c7f63SJim Harris case SCSI_MODE_SENSE_PC_SAVED:
113f11c7f63SJim Harris sati_scsi_sense_data_construct(
114f11c7f63SJim Harris sequence,
115f11c7f63SJim Harris scsi_io,
116f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION,
117f11c7f63SJim Harris SCSI_SENSE_ILLEGAL_REQUEST,
118f11c7f63SJim Harris SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED,
119f11c7f63SJim Harris SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED
120f11c7f63SJim Harris );
121f11c7f63SJim Harris return SATI_FAILURE_CHECK_RESPONSE_DATA;
122f11c7f63SJim Harris break;
123f11c7f63SJim Harris }
124f11c7f63SJim Harris }
125f11c7f63SJim Harris
126f11c7f63SJim Harris /**
127f11c7f63SJim Harris * @brief This method indicates if the page code field in the SCSI CDB
128f11c7f63SJim Harris * is supported by this translation.
129f11c7f63SJim Harris * For more information on the parameters passed to this method,
130f11c7f63SJim Harris * please reference sati_translate_command().
131f11c7f63SJim Harris *
132f11c7f63SJim Harris * @param[in] cdb_length This parameter specifies the length of the SCSI
133f11c7f63SJim Harris * CDB being translated (e.g. 6-byte, 10-byte, 12-byte, etc.)
134f11c7f63SJim Harris *
135f11c7f63SJim Harris * @return This method returns an indication as to whether the page code
136f11c7f63SJim Harris * in the CDB is supported.
137f11c7f63SJim Harris * @retval SATI_SUCCESS This value is returned if the page code is
138f11c7f63SJim Harris * supported.
139f11c7f63SJim Harris * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
140f11c7f63SJim Harris * page code is not supported.
141f11c7f63SJim Harris */
142f11c7f63SJim Harris static
sati_mode_sense_is_page_code_supported(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 cdb_length)143f11c7f63SJim Harris SATI_STATUS sati_mode_sense_is_page_code_supported(
144f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
145f11c7f63SJim Harris void * scsi_io,
146f11c7f63SJim Harris U8 cdb_length
147f11c7f63SJim Harris )
148f11c7f63SJim Harris {
149f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
150f11c7f63SJim Harris
151f11c7f63SJim Harris switch (sati_get_cdb_byte(cdb, 2) & SCSI_MODE_SENSE_PAGE_CODE_ENABLE)
152f11c7f63SJim Harris {
153f11c7f63SJim Harris case SCSI_MODE_PAGE_CACHING:
154f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
155f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CACHING;
156f11c7f63SJim Harris else
157f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CACHING;
158f11c7f63SJim Harris break;
159f11c7f63SJim Harris
160f11c7f63SJim Harris case SCSI_MODE_PAGE_ALL_PAGES:
161f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
162f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES;
163f11c7f63SJim Harris else
164f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES;
165f11c7f63SJim Harris break;
166f11c7f63SJim Harris
167f11c7f63SJim Harris case SCSI_MODE_PAGE_READ_WRITE_ERROR:
168f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
169f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR;
170f11c7f63SJim Harris else
171f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR;
172f11c7f63SJim Harris break;
173f11c7f63SJim Harris
174f11c7f63SJim Harris case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
175f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
176f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT;
177f11c7f63SJim Harris else
178f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT;
179f11c7f63SJim Harris break;
180f11c7f63SJim Harris
181f11c7f63SJim Harris case SCSI_MODE_PAGE_CONTROL:
182f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
183f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CONTROL;
184f11c7f63SJim Harris else
185f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CONTROL;
186f11c7f63SJim Harris break;
187f11c7f63SJim Harris
188f11c7f63SJim Harris case SCSI_MODE_PAGE_POWER_CONDITION:
189f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
190f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION;
191f11c7f63SJim Harris else
192f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION;
193f11c7f63SJim Harris break;
194f11c7f63SJim Harris
195f11c7f63SJim Harris case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
196f11c7f63SJim Harris // The informational exceptions control page is only useful
197f11c7f63SJim Harris // if SMART is supported.
198f11c7f63SJim Harris if ((sequence->device->capabilities | SATI_DEVICE_CAP_SMART_SUPPORT)
199f11c7f63SJim Harris == 0)
200f11c7f63SJim Harris {
201f11c7f63SJim Harris // For a MODE SENSE, utilize INVALID FIELD IN CDB,
202f11c7f63SJim Harris // For a MODE SELECT, utilize INVALID FIELD IN PARAMETER LIST.
203f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
204f11c7f63SJim Harris {
205f11c7f63SJim Harris sati_scsi_sense_data_construct(
206f11c7f63SJim Harris sequence,
207f11c7f63SJim Harris scsi_io,
208f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION,
209f11c7f63SJim Harris SCSI_SENSE_ILLEGAL_REQUEST,
210f11c7f63SJim Harris SCSI_ASC_INVALID_FIELD_IN_CDB,
211f11c7f63SJim Harris SCSI_ASCQ_INVALID_FIELD_IN_CDB
212f11c7f63SJim Harris );
213f11c7f63SJim Harris }
214f11c7f63SJim Harris else
215f11c7f63SJim Harris {
216f11c7f63SJim Harris sati_scsi_sense_data_construct(
217f11c7f63SJim Harris sequence,
218f11c7f63SJim Harris scsi_io,
219f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION,
220f11c7f63SJim Harris SCSI_SENSE_ILLEGAL_REQUEST,
221f11c7f63SJim Harris SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
222f11c7f63SJim Harris SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
223f11c7f63SJim Harris );
224f11c7f63SJim Harris }
225f11c7f63SJim Harris
226f11c7f63SJim Harris return SATI_FAILURE_CHECK_RESPONSE_DATA;
227f11c7f63SJim Harris }
228f11c7f63SJim Harris
229f11c7f63SJim Harris if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
230f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL;
231f11c7f63SJim Harris else
232f11c7f63SJim Harris sequence->type = SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL;
233f11c7f63SJim Harris break;
234f11c7f63SJim Harris
235f11c7f63SJim Harris default:
236f11c7f63SJim Harris sati_scsi_sense_data_construct(
237f11c7f63SJim Harris sequence,
238f11c7f63SJim Harris scsi_io,
239f11c7f63SJim Harris SCSI_STATUS_CHECK_CONDITION,
240f11c7f63SJim Harris SCSI_SENSE_ILLEGAL_REQUEST,
241f11c7f63SJim Harris SCSI_ASC_INVALID_FIELD_IN_CDB,
242f11c7f63SJim Harris SCSI_ASCQ_INVALID_FIELD_IN_CDB
243f11c7f63SJim Harris );
244f11c7f63SJim Harris return SATI_FAILURE_CHECK_RESPONSE_DATA;
245f11c7f63SJim Harris break;
246f11c7f63SJim Harris }
247f11c7f63SJim Harris
248f11c7f63SJim Harris return SATI_SUCCESS;
249f11c7f63SJim Harris }
250f11c7f63SJim Harris
251f11c7f63SJim Harris //******************************************************************************
252f11c7f63SJim Harris //* P R O T E C T E D M E T H O D S
253f11c7f63SJim Harris //******************************************************************************
254f11c7f63SJim Harris
255f11c7f63SJim Harris /**
256f11c7f63SJim Harris * @brief This method will calculate the size of the mode sense data header.
257f11c7f63SJim Harris * This includes the block descriptor if one is requested.
258f11c7f63SJim Harris *
259f11c7f63SJim Harris * @param[in] scsi_io This parameter specifies the user's SCSI IO object
260f11c7f63SJim Harris * for which to calculate the mode page header.
261f11c7f63SJim Harris * @param[in] cdb_size This parameter specifies the number of bytes
262f11c7f63SJim Harris * associated with the CDB for which to calculate the header.
263f11c7f63SJim Harris *
264f11c7f63SJim Harris * @return This method returns the size, in bytes, for the mode page header.
265f11c7f63SJim Harris */
sati_mode_sense_calculate_page_header(void * scsi_io,U8 cdb_size)266f11c7f63SJim Harris U16 sati_mode_sense_calculate_page_header(
267f11c7f63SJim Harris void * scsi_io,
268f11c7f63SJim Harris U8 cdb_size
269f11c7f63SJim Harris )
270f11c7f63SJim Harris {
271f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
272f11c7f63SJim Harris U16 page_length = 0;
273f11c7f63SJim Harris
274f11c7f63SJim Harris // The Mode page header length is different for 6-byte vs. 10-byte CDBs.
275f11c7f63SJim Harris if (cdb_size == 6)
276f11c7f63SJim Harris page_length += SCSI_MODE_SENSE_6_HEADER_LENGTH;
277f11c7f63SJim Harris else
278f11c7f63SJim Harris page_length += SCSI_MODE_SENSE_10_HEADER_LENGTH;
279f11c7f63SJim Harris
280f11c7f63SJim Harris // Are block descriptors disabled (DBD)? 0 indicates they are enabled.
281f11c7f63SJim Harris if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
282f11c7f63SJim Harris {
283f11c7f63SJim Harris // The LLBAA bit is not defined for 6-byte mode sense requests.
284f11c7f63SJim Harris if ( (cdb_size == 10)
285f11c7f63SJim Harris && (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE) )
286f11c7f63SJim Harris page_length += SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
287f11c7f63SJim Harris else
288f11c7f63SJim Harris page_length += SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
289f11c7f63SJim Harris }
290f11c7f63SJim Harris
291f11c7f63SJim Harris return page_length;
292f11c7f63SJim Harris }
293f11c7f63SJim Harris
294f11c7f63SJim Harris /**
295f11c7f63SJim Harris * @brief This method performs command translation common to all mode sense
296f11c7f63SJim Harris * requests (6 or 10 byte).
297f11c7f63SJim Harris * For more information on the parameters passed to this method,
298f11c7f63SJim Harris * please reference sati_translate_command().
299f11c7f63SJim Harris *
300f11c7f63SJim Harris * @param[in] cdb_length This parameter specifies the number of bytes
301f11c7f63SJim Harris * in the CDB (6 or 10).
302f11c7f63SJim Harris *
303f11c7f63SJim Harris * @return This method returns an indication as to whether the translation
304f11c7f63SJim Harris * succeeded.
305f11c7f63SJim Harris * @retval SCI_SUCCESS This value is returned if translation succeeded.
306f11c7f63SJim Harris * @see sati_mode_sense_is_page_control_supported() or
307f11c7f63SJim Harris * sati_mode_sense_is_page_code_supported() for more information.
308f11c7f63SJim Harris */
sati_mode_sense_translate_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io,U8 cdb_length)309f11c7f63SJim Harris SATI_STATUS sati_mode_sense_translate_command(
310f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
311f11c7f63SJim Harris void * scsi_io,
312f11c7f63SJim Harris void * ata_io,
313f11c7f63SJim Harris U8 cdb_length
314f11c7f63SJim Harris )
315f11c7f63SJim Harris {
316f11c7f63SJim Harris SATI_STATUS status;
317f11c7f63SJim Harris
318f11c7f63SJim Harris /**
319f11c7f63SJim Harris * Validate that the supplied page control (PC) field is supported.
320f11c7f63SJim Harris */
321f11c7f63SJim Harris status = sati_mode_sense_is_page_control_supported(sequence, scsi_io);
322f11c7f63SJim Harris if (status != SATI_SUCCESS)
323f11c7f63SJim Harris return status;
324f11c7f63SJim Harris
325f11c7f63SJim Harris /**
326f11c7f63SJim Harris * Validate that the supplied page code is supported.
327f11c7f63SJim Harris */
328f11c7f63SJim Harris status = sati_mode_sense_is_page_code_supported(sequence,scsi_io,cdb_length);
329f11c7f63SJim Harris if (status != SATI_SUCCESS)
330f11c7f63SJim Harris return status;
331f11c7f63SJim Harris
332f11c7f63SJim Harris sati_ata_identify_device_construct(ata_io, sequence);
333f11c7f63SJim Harris
334f11c7f63SJim Harris return SATI_SUCCESS;
335f11c7f63SJim Harris }
336f11c7f63SJim Harris
337f11c7f63SJim Harris /**
338f11c7f63SJim Harris * @brief This method will build the standard block descriptor for a MODE
339f11c7f63SJim Harris * SENSE 6 or 10 byte request.
340f11c7f63SJim Harris * For more information on the parameters passed to this method,
341f11c7f63SJim Harris * please reference sati_translate_command().
342f11c7f63SJim Harris *
343f11c7f63SJim Harris * @param[in] identify This parameter specifies the IDENTIFY DEVICE data
344f11c7f63SJim Harris * associated with the SCSI IO.
345f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
346f11c7f63SJim Harris * buffer at which to build the block descriptor.
347f11c7f63SJim Harris *
348f11c7f63SJim Harris * @return This method returns the size of the block descriptor built.
349f11c7f63SJim Harris */
sati_mode_sense_build_std_block_descriptor(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)350f11c7f63SJim Harris U32 sati_mode_sense_build_std_block_descriptor(
351f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
352f11c7f63SJim Harris void * scsi_io,
353f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
354f11c7f63SJim Harris U32 offset
355f11c7f63SJim Harris )
356f11c7f63SJim Harris {
357f11c7f63SJim Harris U32 lba_low = 0;
358f11c7f63SJim Harris U32 lba_high = 0;
359f11c7f63SJim Harris U32 sector_size = 0;
360f11c7f63SJim Harris
361f11c7f63SJim Harris // Extract the sector information (sector size, logical blocks) from
362f11c7f63SJim Harris // the retrieved ATA identify device data.
363f11c7f63SJim Harris sati_ata_identify_device_get_sector_info(
364f11c7f63SJim Harris identify, &lba_high, &lba_low, §or_size
365f11c7f63SJim Harris );
366f11c7f63SJim Harris
367f11c7f63SJim Harris // Fill in the 4-byte logical block address field.
368f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset, (U8)((lba_low>>24) & 0xFF));
369f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_low>>16) & 0xFF));
370f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_low>>8) & 0xFF));
371f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_low & 0xFF));
372f11c7f63SJim Harris
373f11c7f63SJim Harris // Clear the reserved field.
374f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+4, 0);
375f11c7f63SJim Harris
376f11c7f63SJim Harris // Fill in the three byte Block Length field
377f11c7f63SJim Harris sati_set_data_byte(sequence,scsi_io, offset+5, (U8)((sector_size>>16) & 0xFF));
378f11c7f63SJim Harris sati_set_data_byte(sequence,scsi_io, offset+6, (U8)((sector_size>>8) & 0xFF));
379f11c7f63SJim Harris sati_set_data_byte(sequence,scsi_io, offset+7, (U8)(sector_size & 0xFF));
380f11c7f63SJim Harris
381f11c7f63SJim Harris return SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
382f11c7f63SJim Harris }
383f11c7f63SJim Harris
384f11c7f63SJim Harris /**
385f11c7f63SJim Harris * @brief This method simply copies the mode sense data into the buffer
386f11c7f63SJim Harris * at the location specified by page_start. The buffer copied is
387f11c7f63SJim Harris * determined by page_control (e.g. current, default, or changeable
388f11c7f63SJim Harris * values).
389f11c7f63SJim Harris * For more information on the parameters passed to this method,
390f11c7f63SJim Harris * please reference sati_translate_command().
391f11c7f63SJim Harris *
392f11c7f63SJim Harris * @param[in] page_start This parameter specifies the starting offset at
393f11c7f63SJim Harris * which to copy the mode page data.
394f11c7f63SJim Harris * @param[in] page_control This parameter specifies the page control
395f11c7f63SJim Harris * indicating the source buffer to be copied.
396f11c7f63SJim Harris * @param[in] page_code This specifies the mode sense page to copy.
397f11c7f63SJim Harris *
398f11c7f63SJim Harris * @return This method returns the size of the mode page data being copied.
399f11c7f63SJim Harris */
sati_mode_sense_copy_initial_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U32 page_start,U8 page_control,U8 page_code)400f11c7f63SJim Harris U32 sati_mode_sense_copy_initial_data(
401f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
402f11c7f63SJim Harris void * scsi_io,
403f11c7f63SJim Harris U32 page_start,
404f11c7f63SJim Harris U8 page_control,
405f11c7f63SJim Harris U8 page_code
406f11c7f63SJim Harris )
407f11c7f63SJim Harris {
408f11c7f63SJim Harris U16 page_index = sati_mode_page_get_page_index(page_code);
409f11c7f63SJim Harris U32 page_length = sat_mode_page_sizes[page_index];
410f11c7f63SJim Harris
411f11c7f63SJim Harris // Find out if the current values are requested or if the default
412f11c7f63SJim Harris // values are being requested.
413f11c7f63SJim Harris if (page_control == SCSI_MODE_SENSE_PC_CHANGEABLE)
414f11c7f63SJim Harris {
415f11c7f63SJim Harris // Copy the changeable mode page information.
416f11c7f63SJim Harris sati_copy_data(
417f11c7f63SJim Harris sequence,
418f11c7f63SJim Harris scsi_io,
419f11c7f63SJim Harris page_start,
420f11c7f63SJim Harris sat_changeable_mode_pages[page_index],
421f11c7f63SJim Harris page_length
422f11c7f63SJim Harris );
423f11c7f63SJim Harris }
424f11c7f63SJim Harris else
425f11c7f63SJim Harris {
426f11c7f63SJim Harris // Copy the default static values template to the user data area.
427f11c7f63SJim Harris sati_copy_data(
428f11c7f63SJim Harris sequence,
429f11c7f63SJim Harris scsi_io,
430f11c7f63SJim Harris page_start,
431f11c7f63SJim Harris sat_default_mode_pages[page_index],
432f11c7f63SJim Harris page_length
433f11c7f63SJim Harris );
434f11c7f63SJim Harris }
435f11c7f63SJim Harris
436f11c7f63SJim Harris return page_length;
437f11c7f63SJim Harris }
438f11c7f63SJim Harris
439f11c7f63SJim Harris /**
440f11c7f63SJim Harris * @brief This method performs the read/write error recovery mode page
441f11c7f63SJim Harris * specific data translation based upon the contents of the remote
442f11c7f63SJim Harris * device IDENTIFY DEVICE data.
443f11c7f63SJim Harris * For more information on the parameters passed to this method,
444f11c7f63SJim Harris * please reference sati_translate_command().
445f11c7f63SJim Harris *
446f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
447f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
448f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
449f11c7f63SJim Harris * buffer where the translated data is to be written.
450f11c7f63SJim Harris *
451f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
452f11c7f63SJim Harris * translated.
453f11c7f63SJim Harris */
sati_mode_sense_read_write_error_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)454f11c7f63SJim Harris U32 sati_mode_sense_read_write_error_translate_data(
455f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
456f11c7f63SJim Harris void * scsi_io,
457f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
458f11c7f63SJim Harris U32 offset
459f11c7f63SJim Harris )
460f11c7f63SJim Harris {
461f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
462f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
463f11c7f63SJim Harris U32 page_length;
464f11c7f63SJim Harris
465f11c7f63SJim Harris page_length = sati_mode_sense_copy_initial_data(
466f11c7f63SJim Harris sequence,
467f11c7f63SJim Harris scsi_io,
468f11c7f63SJim Harris offset,
469f11c7f63SJim Harris page_control,
470f11c7f63SJim Harris SCSI_MODE_PAGE_READ_WRITE_ERROR
471f11c7f63SJim Harris );
472f11c7f63SJim Harris
473f11c7f63SJim Harris // Currently we do not override any bits in this mode page from the
474f11c7f63SJim Harris // identify data.
475f11c7f63SJim Harris
476f11c7f63SJim Harris return page_length;
477f11c7f63SJim Harris }
478f11c7f63SJim Harris
479f11c7f63SJim Harris /**
480f11c7f63SJim Harris * @brief This method performs the disconnect/reconnect mode page
481f11c7f63SJim Harris * specific data translation based upon the contents of the remote
482f11c7f63SJim Harris * device IDENTIFY DEVICE data.
483f11c7f63SJim Harris * For more information on the parameters passed to this method,
484f11c7f63SJim Harris * please reference sati_translate_command().
485f11c7f63SJim Harris *
486f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
487f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
488f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
489f11c7f63SJim Harris * buffer where the translated data is to be written.
490f11c7f63SJim Harris *
491f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
492f11c7f63SJim Harris * translated.
493f11c7f63SJim Harris */
sati_mode_sense_disconnect_reconnect_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)494f11c7f63SJim Harris U32 sati_mode_sense_disconnect_reconnect_translate_data(
495f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
496f11c7f63SJim Harris void * scsi_io,
497f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
498f11c7f63SJim Harris U32 offset
499f11c7f63SJim Harris )
500f11c7f63SJim Harris {
501f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
502f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
503f11c7f63SJim Harris U32 page_length;
504f11c7f63SJim Harris
505f11c7f63SJim Harris page_length = sati_mode_sense_copy_initial_data(
506f11c7f63SJim Harris sequence,
507f11c7f63SJim Harris scsi_io,
508f11c7f63SJim Harris offset,
509f11c7f63SJim Harris page_control,
510f11c7f63SJim Harris SCSI_MODE_PAGE_DISCONNECT_RECONNECT
511f11c7f63SJim Harris );
512f11c7f63SJim Harris
513f11c7f63SJim Harris // Currently we do not override any bits in this mode page from the
514f11c7f63SJim Harris // identify data.
515f11c7f63SJim Harris
516f11c7f63SJim Harris return page_length;
517f11c7f63SJim Harris }
518f11c7f63SJim Harris
519f11c7f63SJim Harris /**
520f11c7f63SJim Harris * @brief This method performs the caching mode page specific data
521f11c7f63SJim Harris * translation based upon the contents of the remote device IDENTIFY
522f11c7f63SJim Harris * DEVICE data.
523f11c7f63SJim Harris * For more information on the parameters passed to this method,
524f11c7f63SJim Harris * please reference sati_translate_command().
525f11c7f63SJim Harris *
526f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
527f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
528f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
529f11c7f63SJim Harris * buffer where the translated data is to be written.
530f11c7f63SJim Harris *
531f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
532f11c7f63SJim Harris * translated.
533f11c7f63SJim Harris */
sati_mode_sense_caching_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)534f11c7f63SJim Harris U32 sati_mode_sense_caching_translate_data(
535f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
536f11c7f63SJim Harris void * scsi_io,
537f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
538f11c7f63SJim Harris U32 offset
539f11c7f63SJim Harris )
540f11c7f63SJim Harris {
541f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
542f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
543f11c7f63SJim Harris U32 page_length;
544f11c7f63SJim Harris
545f11c7f63SJim Harris page_length = sati_mode_sense_copy_initial_data(
546f11c7f63SJim Harris sequence,
547f11c7f63SJim Harris scsi_io,
548f11c7f63SJim Harris offset,
549f11c7f63SJim Harris page_control,
550f11c7f63SJim Harris SCSI_MODE_PAGE_CACHING
551f11c7f63SJim Harris );
552f11c7f63SJim Harris
553f11c7f63SJim Harris // If the request queried for the current values, then
554f11c7f63SJim Harris // we need to translate the data from the IDENTIFY DEVICE request.
555f11c7f63SJim Harris if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
556f11c7f63SJim Harris {
557f11c7f63SJim Harris U8 value;
558f11c7f63SJim Harris
559f11c7f63SJim Harris // Update the Write Cache Enabled (WCE) bit in the mode page data
560f11c7f63SJim Harris // buffer based on the identify response.
561f11c7f63SJim Harris if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_WCE_ENABLE) != 0)
562f11c7f63SJim Harris {
563f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, offset+2, &value);
564f11c7f63SJim Harris value |= SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT;
565f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+2, value);
566f11c7f63SJim Harris //This byte has been set twice and needs to be decremented
567f11c7f63SJim Harris sequence->number_data_bytes_set--;
568f11c7f63SJim Harris }
569f11c7f63SJim Harris
570f11c7f63SJim Harris // Update the Disable Read Ahead (DRA) bit in the mode page data
571f11c7f63SJim Harris // buffer based on the identify response.
572f11c7f63SJim Harris if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_RA_ENABLE) == 0)
573f11c7f63SJim Harris {
574f11c7f63SJim Harris // In SATA the polarity of the bits is inverse.
575f11c7f63SJim Harris // - SCSI = Disable Read Ahead
576f11c7f63SJim Harris // - ATA = Read Ahead
577f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, offset+12, &value);
578f11c7f63SJim Harris value |= SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT;
579f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+12, value);
580f11c7f63SJim Harris
581f11c7f63SJim Harris //This byte has been set twice, the first time in
582f11c7f63SJim Harris //sati_mode_sense_copy_initial_data. number_data_bytes_set
583f11c7f63SJim Harris //needs to be decremented
584f11c7f63SJim Harris sequence->number_data_bytes_set--;
585f11c7f63SJim Harris }
586f11c7f63SJim Harris }
587f11c7f63SJim Harris
588f11c7f63SJim Harris return page_length;
589f11c7f63SJim Harris }
590f11c7f63SJim Harris
591f11c7f63SJim Harris /**
592f11c7f63SJim Harris * @brief This method performs the control mode page specific data
593f11c7f63SJim Harris * translation based upon the contents of the remote device
594f11c7f63SJim Harris * IDENTIFY DEVICE data.
595f11c7f63SJim Harris * For more information on the parameters passed to this method,
596f11c7f63SJim Harris * please reference sati_translate_command().
597f11c7f63SJim Harris *
598f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
599f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
600f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
601f11c7f63SJim Harris * buffer where the translated data is to be written.
602f11c7f63SJim Harris *
603f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
604f11c7f63SJim Harris * translated.
605f11c7f63SJim Harris */
sati_mode_sense_control_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)606f11c7f63SJim Harris U32 sati_mode_sense_control_translate_data(
607f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
608f11c7f63SJim Harris void * scsi_io,
609f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
610f11c7f63SJim Harris U32 offset
611f11c7f63SJim Harris )
612f11c7f63SJim Harris {
613f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
614f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
615f11c7f63SJim Harris U32 page_length;
616f11c7f63SJim Harris U8 value;
617f11c7f63SJim Harris
618f11c7f63SJim Harris page_length = sati_mode_sense_copy_initial_data(
619f11c7f63SJim Harris sequence,
620f11c7f63SJim Harris scsi_io,
621f11c7f63SJim Harris offset,
622f11c7f63SJim Harris page_control,
623f11c7f63SJim Harris SCSI_MODE_PAGE_CONTROL
624f11c7f63SJim Harris );
625f11c7f63SJim Harris
626f11c7f63SJim Harris if (sequence->device->descriptor_sense_enable)
627f11c7f63SJim Harris {
628f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, offset+2,
629f11c7f63SJim Harris &value);
630f11c7f63SJim Harris
631f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+2,
632f11c7f63SJim Harris value | SCSI_MODE_SELECT_MODE_PAGE_D_SENSE);
633f11c7f63SJim Harris }
634f11c7f63SJim Harris
635f11c7f63SJim Harris return page_length;
636f11c7f63SJim Harris }
637f11c7f63SJim Harris
638f11c7f63SJim Harris /**
639f11c7f63SJim Harris * @brief This method performs the informational exceptions control mode
640f11c7f63SJim Harris * page specific data translation based upon the contents of the
641f11c7f63SJim Harris * remote device IDENTIFY DEVICE data.
642f11c7f63SJim Harris * For more information on the parameters passed to this method,
643f11c7f63SJim Harris * please reference sati_translate_command().
644f11c7f63SJim Harris *
645f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
646f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
647f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
648f11c7f63SJim Harris * buffer where the translated data is to be written.
649f11c7f63SJim Harris *
650f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
651f11c7f63SJim Harris * translated.
652f11c7f63SJim Harris */
sati_mode_sense_informational_excp_control_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)653f11c7f63SJim Harris U32 sati_mode_sense_informational_excp_control_translate_data(
654f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
655f11c7f63SJim Harris void * scsi_io,
656f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
657f11c7f63SJim Harris U32 offset
658f11c7f63SJim Harris )
659f11c7f63SJim Harris {
660f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
661f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
662f11c7f63SJim Harris U32 page_length;
663f11c7f63SJim Harris
664f11c7f63SJim Harris page_length = sati_mode_sense_copy_initial_data(
665f11c7f63SJim Harris sequence,
666f11c7f63SJim Harris scsi_io,
667f11c7f63SJim Harris offset,
668f11c7f63SJim Harris page_control,
669f11c7f63SJim Harris SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
670f11c7f63SJim Harris );
671f11c7f63SJim Harris
672f11c7f63SJim Harris // If the request queried for the current values, then
673f11c7f63SJim Harris // we need to translate the data from the IDENTIFY DEVICE request.
674f11c7f63SJim Harris if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
675f11c7f63SJim Harris {
676f11c7f63SJim Harris U8 value;
677f11c7f63SJim Harris
678f11c7f63SJim Harris sati_get_data_byte(sequence, scsi_io, offset+2, &value);
679f11c7f63SJim Harris
680f11c7f63SJim Harris // Determine if the SMART feature set is supported and enabled.
681f11c7f63SJim Harris if ( (identify->command_set_supported0
682f11c7f63SJim Harris & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
683f11c7f63SJim Harris && (identify->command_set_enabled0
684f11c7f63SJim Harris & ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE) )
685f11c7f63SJim Harris {
686f11c7f63SJim Harris // Clear the DXCPT field since the SMART feature is supported/enabled.
687f11c7f63SJim Harris value &= ~SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
688f11c7f63SJim Harris }
689f11c7f63SJim Harris else
690f11c7f63SJim Harris {
691f11c7f63SJim Harris // Set the Disable Exception Control (DXCPT) field since the SMART
692f11c7f63SJim Harris // feature is not supported or enabled.
693f11c7f63SJim Harris value |= SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
694f11c7f63SJim Harris }
695f11c7f63SJim Harris
696f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset+2, value);
697f11c7f63SJim Harris
698f11c7f63SJim Harris //This byte has been set twice, the first time in
699f11c7f63SJim Harris //sati_mode_sense_copy_initial_data. number_data_bytes_set
700f11c7f63SJim Harris //needs to be decremented
701f11c7f63SJim Harris sequence->number_data_bytes_set--;
702f11c7f63SJim Harris }
703f11c7f63SJim Harris
704f11c7f63SJim Harris return page_length;
705f11c7f63SJim Harris }
706f11c7f63SJim Harris
707f11c7f63SJim Harris /**
708f11c7f63SJim Harris * @brief This method performs the Power Condition mode page
709f11c7f63SJim Harris * specific data translation based upon the contents of the
710f11c7f63SJim Harris * remote device IDENTIFY DEVICE data.
711f11c7f63SJim Harris * For more information on the parameters passed to this method,
712f11c7f63SJim Harris * please reference sati_translate_command().
713f11c7f63SJim Harris *
714f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
715f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
716f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
717f11c7f63SJim Harris * buffer where the translated data is to be written.
718f11c7f63SJim Harris *
719f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
720f11c7f63SJim Harris * translated.
721f11c7f63SJim Harris */
sati_mode_sense_power_condition_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)722f11c7f63SJim Harris U32 sati_mode_sense_power_condition_translate_data(
723f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
724f11c7f63SJim Harris void * scsi_io,
725f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
726f11c7f63SJim Harris U32 offset
727f11c7f63SJim Harris )
728f11c7f63SJim Harris {
729f11c7f63SJim Harris U8 * cdb = sati_cb_get_cdb_address(scsi_io);
730f11c7f63SJim Harris U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
731f11c7f63SJim Harris
732f11c7f63SJim Harris U8 ata_sb_timer;
733f11c7f63SJim Harris
734f11c7f63SJim Harris //Represents tenths of seconds
735f11c7f63SJim Harris U32 standby_timer = 0x00000000;
736f11c7f63SJim Harris
737f11c7f63SJim Harris U8 standby_enabled = STANDBY_TIMER_DISABLED;
738f11c7f63SJim Harris
739f11c7f63SJim Harris if ((page_control == SCSI_MODE_SENSE_PC_CURRENT) &&
740f11c7f63SJim Harris (identify->capabilities1 & STANDBY_TIMER_SUPPORTED))
741f11c7f63SJim Harris {
742f11c7f63SJim Harris standby_enabled = STANDBY_TIMER_ENABLED;
743f11c7f63SJim Harris
744f11c7f63SJim Harris ata_sb_timer = sequence->device->ata_standby_timer;
745f11c7f63SJim Harris
746f11c7f63SJim Harris //converting ATA timer values into SCSI timer values
747f11c7f63SJim Harris if(ata_sb_timer <= 0xF0)
748f11c7f63SJim Harris {
749f11c7f63SJim Harris standby_timer = ata_sb_timer * 50;
750f11c7f63SJim Harris }
751f11c7f63SJim Harris else if(ata_sb_timer <= 0xFB)
752f11c7f63SJim Harris {
753f11c7f63SJim Harris standby_timer = ((ata_sb_timer - 240) * 18000);
754f11c7f63SJim Harris }
755f11c7f63SJim Harris else if(ata_sb_timer == 0xFC)
756f11c7f63SJim Harris {
757f11c7f63SJim Harris standby_timer = 12600;
758f11c7f63SJim Harris }
759f11c7f63SJim Harris else if(ata_sb_timer == 0xFD)
760f11c7f63SJim Harris {
761f11c7f63SJim Harris standby_timer = 432000;
762f11c7f63SJim Harris }
763f11c7f63SJim Harris else if(ata_sb_timer == 0xFF)
764f11c7f63SJim Harris {
765f11c7f63SJim Harris standby_timer = 12750;
766f11c7f63SJim Harris }
767f11c7f63SJim Harris else
768f11c7f63SJim Harris {
769f11c7f63SJim Harris standby_timer = 0xFFFFFFFF;
770f11c7f63SJim Harris }
771f11c7f63SJim Harris }
772f11c7f63SJim Harris
773f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset, SCSI_MODE_PAGE_POWER_CONDITION);
774f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 1, (SCSI_MODE_PAGE_1A_LENGTH - 2));
775f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 2, 0x00);
776f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 3, standby_enabled);
777f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 4, 0x00);
778f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 5, 0x00);
779f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 6, 0x00);
780f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 7, 0x00);
781f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 8, (U8) (standby_timer >> 24));
782f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 9, (U8) (standby_timer >> 16));
783f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 10, (U8) (standby_timer >> 8));
784f11c7f63SJim Harris sati_set_data_byte(sequence, scsi_io, offset + 11, (U8) standby_timer);
785f11c7f63SJim Harris
786f11c7f63SJim Harris return SCSI_MODE_PAGE_1A_LENGTH;
787f11c7f63SJim Harris }
788f11c7f63SJim Harris
789f11c7f63SJim Harris /**
790f11c7f63SJim Harris * @brief This method performs the all pages mode page specific data
791f11c7f63SJim Harris * translation based upon the contents of the remote device
792f11c7f63SJim Harris * IDENTIFY DEVICE data. The ALL PAGES mode sense request asks
793f11c7f63SJim Harris * for all of mode pages and sub-pages in a single page.
794f11c7f63SJim Harris * The mode pages are added in ascending order.
795f11c7f63SJim Harris * For more information on the parameters passed to this method,
796f11c7f63SJim Harris * please reference sati_translate_command().
797f11c7f63SJim Harris *
798f11c7f63SJim Harris * @param[in] identify This parameter specifies the remote device's
799f11c7f63SJim Harris * IDENTIFY DEVICE data received as part of the IO request.
800f11c7f63SJim Harris * @param[in] offset This parameter specifies the offset into the data
801f11c7f63SJim Harris * buffer where the translated data is to be written.
802f11c7f63SJim Harris *
803f11c7f63SJim Harris * @return This method returns the size of the mode page data that was
804f11c7f63SJim Harris * translated.
805f11c7f63SJim Harris */
sati_mode_sense_all_pages_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 offset)806f11c7f63SJim Harris U32 sati_mode_sense_all_pages_translate_data(
807f11c7f63SJim Harris SATI_TRANSLATOR_SEQUENCE_T * sequence,
808f11c7f63SJim Harris void * scsi_io,
809f11c7f63SJim Harris ATA_IDENTIFY_DEVICE_DATA_T * identify,
810f11c7f63SJim Harris U32 offset
811f11c7f63SJim Harris )
812f11c7f63SJim Harris {
813f11c7f63SJim Harris offset += sati_mode_sense_read_write_error_translate_data(
814f11c7f63SJim Harris sequence, scsi_io, identify, offset
815f11c7f63SJim Harris );
816f11c7f63SJim Harris
817f11c7f63SJim Harris offset += sati_mode_sense_disconnect_reconnect_translate_data(
818f11c7f63SJim Harris sequence, scsi_io, identify, offset
819f11c7f63SJim Harris );
820f11c7f63SJim Harris
821f11c7f63SJim Harris offset += sati_mode_sense_caching_translate_data(
822f11c7f63SJim Harris sequence, scsi_io, identify, offset
823f11c7f63SJim Harris );
824f11c7f63SJim Harris
825f11c7f63SJim Harris offset += sati_mode_sense_control_translate_data(
826f11c7f63SJim Harris sequence, scsi_io, identify, offset
827f11c7f63SJim Harris );
828f11c7f63SJim Harris
829f11c7f63SJim Harris offset += sati_mode_sense_informational_excp_control_translate_data(
830f11c7f63SJim Harris sequence, scsi_io, identify, offset
831f11c7f63SJim Harris );
832f11c7f63SJim Harris
833f11c7f63SJim Harris return offset;
834f11c7f63SJim Harris }
835f11c7f63SJim Harris
836f11c7f63SJim Harris #endif // !defined(DISABLE_SATI_MODE_SENSE)
837f11c7f63SJim Harris
838