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 /**
57 * @file
58 * @brief This file contains all of the method implementations that
59 * provide generic support for SATI. Some methods can be utilized
60 * by a user to construct ATA/ATAPI commands, copy ATA device
61 * structure data, fill in sense data, etc.
62 */
63
64 #include <dev/isci/scil/sati_util.h>
65 #include <dev/isci/scil/sati_callbacks.h>
66 #include <dev/isci/scil/intel_scsi.h>
67 #include <dev/isci/scil/intel_ata.h>
68 #include <dev/isci/scil/intel_sat.h>
69 #include <dev/isci/scil/intel_sas.h>
70
71 /**
72 * @brief This method will set the data direction, protocol, and transfer
73 * kength for an ATA non-data command.
74 *
75 * @pre It is expected that the user will use this method for setting these
76 * values in a non-data ATA command constuct.
77 *
78 * @param[out] ata_io This parameter specifies the ATA IO request structure
79 * for which to build the IDENTIFY DEVICE command.
80 * @param[in] sequence This parameter specifies the translator sequence
81 * for which the command is being constructed.
82 *
83 * @return none.
84 */
sati_ata_non_data_command(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)85 void sati_ata_non_data_command(
86 void * ata_io,
87 SATI_TRANSLATOR_SEQUENCE_T * sequence
88 )
89 {
90 sequence->data_direction = SATI_DATA_DIRECTION_NONE;
91 sequence->protocol = SAT_PROTOCOL_NON_DATA;
92 sequence->ata_transfer_length = 0;
93 }
94
95 /**
96 * @brief This method will construct the ATA identify device command.
97 *
98 * @pre It is expected that the user has properly set the current contents
99 * of the register FIS to 0.
100 *
101 * @param[out] ata_io This parameter specifies the ATA IO request structure
102 * for which to build the IDENTIFY DEVICE command.
103 * @param[in] sequence This parameter specifies the translator sequence
104 * for which the command is being constructed.
105 *
106 * @return none.
107 */
sati_ata_identify_device_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)108 void sati_ata_identify_device_construct(
109 void * ata_io,
110 SATI_TRANSLATOR_SEQUENCE_T * sequence
111 )
112 {
113 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
114
115 sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
116 sequence->data_direction = SATI_DATA_DIRECTION_IN;
117 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
118 sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
119 }
120
121 /**
122 * @brief This method will construct the ATA Execute Device Diagnostic command.
123 *
124 * @param[out] ata_io This parameter specifies the ATA IO request structure
125 * for which to build the IDENTIFY DEVICE command.
126 * @param[in] sequence This parameter specifies the translator sequence
127 * for which the command is being constructed.
128 *
129 * @return none.
130 */
sati_ata_execute_device_diagnostic_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)131 void sati_ata_execute_device_diagnostic_construct(
132 void * ata_io,
133 SATI_TRANSLATOR_SEQUENCE_T * sequence
134 )
135 {
136 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
137
138 sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
139
140 sequence->data_direction = SATI_DATA_DIRECTION_IN;
141 sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
142 sequence->ata_transfer_length = 16;
143 }
144
145 /**
146 * @brief This method will set data bytes in the user data area. If the
147 * caller requests it, the data written will be forced to ascii
148 * printable characters if it isn't already a printable character.
149 * A printable character is considered to be >= 0x20 and <= 0x70.
150 *
151 * @param[in] sequence This parameter specifies the translation sequence
152 * for which to copy and swap the data.
153 * @param[out] destination_scsi_io This parameter specifies the SCSI IO
154 * request containing the destination buffer into which to copy.
155 * @param[in] destination_offset This parameter specifies the offset into
156 * the data buffer where the information will be copied to.
157 * @param[in] source_value This parameter specifies the value retrieved
158 * from the source buffer that is to be copied into the user
159 * buffer area.
160 * @param[in] use_printable_chars This parameter indicates if the copy should
161 * ensure that the value copied is considered an ASCII printable
162 * character (e.g. A, B, " ", etc.). These characters reside
163 * in the 0x20 - 0x7E ASCII range.
164 *
165 * @return none
166 */
167 static
sati_set_ascii_data_byte(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * destination_scsi_io,U32 destination_offset,U8 source_value,BOOL use_printable_chars)168 void sati_set_ascii_data_byte(
169 SATI_TRANSLATOR_SEQUENCE_T * sequence,
170 void * destination_scsi_io,
171 U32 destination_offset,
172 U8 source_value,
173 BOOL use_printable_chars
174 )
175 {
176 // if the user requests that the copied data be ascii printable, then
177 // default to " " (i.e. 0x20) for all non-ascii printable characters.
178 if((use_printable_chars == TRUE)
179 && ((source_value < 0x20) || (source_value > 0x7E)))
180 {
181 source_value = 0x20;
182 }
183
184 sati_set_data_byte(
185 sequence, destination_scsi_io, destination_offset, source_value
186 );
187 }
188
189 /**
190 * @brief This method performs a copy operation using an offset into the
191 * source buffer, an offset into the destination buffer, and a length.
192 * It will perform the byte swap from the 16-bit identify field
193 * into the network byte order SCSI location.
194 *
195 * @param[in] sequence This parameter specifies the translation sequence
196 * for which to copy and swap the data.
197 * @param[out] destination_scsi_io This parameter specifies the SCSI IO
198 * request containing the destination buffer into which to copy.
199 * @param[in] destination_offset This parameter specifies the offset into
200 * the data buffer where the information will be copied to.
201 * @param[in] source_buffer This parameter specifies the source buffer from
202 * which the data will be copied.
203 * @param[in] source_offset This parameter specifies the offset into the
204 * source buffer where the copy shall begin.
205 * @param[in] length This parameter specifies the number of bytes to copy
206 * during this operation.
207 * @param[in] use_printable_chars This parameter indicates if the copy should
208 * ensure that the value copied is considered an ASCII printable
209 * character (e.g. A, B, " ", etc.). These characters reside
210 * in the 0x20 - 0x7E ASCII range.
211 *
212 * @return none
213 */
sati_ata_identify_device_copy_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * destination_scsi_io,U32 destination_offset,U8 * source_buffer,U32 source_offset,U32 length,BOOL use_printable_chars)214 void sati_ata_identify_device_copy_data(
215 SATI_TRANSLATOR_SEQUENCE_T * sequence,
216 void * destination_scsi_io,
217 U32 destination_offset,
218 U8 * source_buffer,
219 U32 source_offset,
220 U32 length,
221 BOOL use_printable_chars
222 )
223 {
224 source_buffer += source_offset;
225 while (length > 0)
226 {
227 sati_set_ascii_data_byte(
228 sequence,
229 destination_scsi_io,
230 destination_offset,
231 *(source_buffer+1),
232 use_printable_chars
233 );
234
235 sati_set_ascii_data_byte(
236 sequence,
237 destination_scsi_io,
238 destination_offset+1,
239 *source_buffer,
240 use_printable_chars
241 );
242
243 destination_offset += 2;
244 source_buffer += 2;
245 length -= 2;
246 }
247 }
248
249 /**
250 * @brief This method performs a copy operation using a source buffer,
251 * an offset into the destination buffer, and a length.
252 *
253 * @param[in] sequence This parameter specifies the translation sequence
254 * for which to copy and swap the data.
255 * @param[out] destination_scsi_io This parameter specifies the SCSI IO
256 * request containing the destination buffer into which to copy.
257 * @param[in] destination_offset This parameter specifies the offset into
258 * the data buffer where the information will be copied to.
259 * @param[in] source_buffer This parameter specifies the source buffer from
260 * which the data will be copied.
261 * @param[in] length This parameter specifies the number of bytes to copy
262 * during this operation.
263 *
264 * @return none
265 */
sati_copy_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * destination_scsi_io,U32 destination_offset,U8 * source_buffer,U32 length)266 void sati_copy_data(
267 SATI_TRANSLATOR_SEQUENCE_T * sequence,
268 void * destination_scsi_io,
269 U32 destination_offset,
270 U8 * source_buffer,
271 U32 length
272 )
273 {
274 while (length > 0)
275 {
276 sati_set_data_byte(
277 sequence, destination_scsi_io, destination_offset, *source_buffer
278 );
279
280 destination_offset++;
281 source_buffer++;
282 length--;
283 }
284 }
285
286 /**
287 * @brief This method extracts the Logical Block Address high and low 32-bit
288 * values and the sector count 32-bit value from the ATA identify
289 * device data.
290 *
291 * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
292 * from which to extract the sector information.
293 * @param[out] lba_high This parameter specifies the upper 32 bits for the
294 * number of logical block addresses for the device. The upper
295 * 16-bits should always be 0, since 48-bits of LBA is the most
296 * supported by an ATA device.
297 * @param[out] lba_low This parameter specifies the lower 32 bits for the
298 * number of logical block addresses for the device.
299 * @param[out] sector_size This parameter specifies the 32-bits of sector
300 * size. If the ATA device doesn't support reporting it's
301 * sector size, then 512 bytes is utilized as the default value.
302 *
303 * @return none
304 */
sati_ata_identify_device_get_sector_info(ATA_IDENTIFY_DEVICE_DATA_T * identify,U32 * lba_high,U32 * lba_low,U32 * sector_size)305 void sati_ata_identify_device_get_sector_info(
306 ATA_IDENTIFY_DEVICE_DATA_T * identify,
307 U32 * lba_high,
308 U32 * lba_low,
309 U32 * sector_size
310 )
311 {
312 // Calculate the values to be returned
313 // Calculation will be different if the SATA device supports
314 // 48-bit addressing. Bit 10 of Word 86 of ATA Identify
315 if (identify->command_set_enabled1
316 & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
317 {
318 // This drive supports 48-bit addressing
319
320 *lba_high = identify->max_48bit_lba[7] << 24;
321 *lba_high |= identify->max_48bit_lba[6] << 16;
322 *lba_high |= identify->max_48bit_lba[5] << 8;
323 *lba_high |= identify->max_48bit_lba[4];
324
325 *lba_low = identify->max_48bit_lba[3] << 24;
326 *lba_low |= identify->max_48bit_lba[2] << 16;
327 *lba_low |= identify->max_48bit_lba[1] << 8;
328 *lba_low |= identify->max_48bit_lba[0];
329 }
330 else
331 {
332 // This device doesn't support 48-bit addressing
333 // Pull out the largest LBA from words 60 and 61.
334 *lba_high = 0;
335 *lba_low = identify->total_num_sectors[3] << 24;
336 *lba_low |= identify->total_num_sectors[2] << 16;
337 *lba_low |= identify->total_num_sectors[1] << 8;
338 *lba_low |= identify->total_num_sectors[0];
339 }
340
341 // If the ATA device reports its sector size (bit 12 of Word 106),
342 // then use that instead.
343 if (identify->physical_logical_sector_info
344 & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
345 {
346 *sector_size = identify->words_per_logical_sector[3] << 24;
347 *sector_size |= identify->words_per_logical_sector[2] << 16;
348 *sector_size |= identify->words_per_logical_sector[1] << 8;
349 *sector_size |= identify->words_per_logical_sector[0];
350 }
351 else
352 {
353 // Default the sector size to 512 bytes
354 *sector_size = 512;
355 }
356 }
357
358 /**
359 * @brief This method will construct the ATA check power mode command.
360 *
361 * @pre It is expected that the user has properly set the current contents
362 * of the register FIS to 0.
363 *
364 * @param[out] ata_io This parameter specifies the ATA IO request structure
365 * for which to build the CHECK POWER MODE command.
366 * @param[in] sequence This parameter specifies the translator sequence
367 * for which the command is being constructed.
368 *
369 * @return none.
370 */
sati_ata_check_power_mode_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)371 void sati_ata_check_power_mode_construct(
372 void * ata_io,
373 SATI_TRANSLATOR_SEQUENCE_T * sequence
374 )
375 {
376 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
377
378 sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
379 sati_ata_non_data_command(ata_io, sequence);
380 }
381
382 /**
383 * @brief This method is utilized to set a specific byte in the sense
384 * data area. It will ensure that the supplied byte offset
385 * isn't larger then the length of the requested sense data.
386 *
387 * @param[in] scsi_io This parameter specifies the user SCSI IO request
388 * for which to set the sense data byte.
389 * @param[in] byte_offset This parameter specifies the byte offset into
390 * the sense data buffer where the data should be written.
391 * @param[in] value This parameter specifies the 8-bit value to be written
392 * into the sense data area.
393 *
394 * @return none
395 */
sati_set_sense_data_byte(U8 * sense_data,U32 max_sense_data_len,U32 byte_offset,U8 value)396 void sati_set_sense_data_byte(
397 U8 * sense_data,
398 U32 max_sense_data_len,
399 U32 byte_offset,
400 U8 value
401 )
402 {
403 // Ensure that we don't attempt to write past the end of the sense
404 // data buffer.
405 if (byte_offset < max_sense_data_len)
406 sense_data[byte_offset] = value;
407 }
408
409 /**
410 * @brief This method will construct the common response IU in the user
411 * request's response IU location.
412 *
413 * @param[out] rsp_iu This parameter specifies the user request's
414 * response IU to be constructed.
415 * @param[in] scsi_status This parameter specifies the SCSI status
416 * value for the user's IO request.
417 * @param[in] sense_data_length This parameter specifies the sense data
418 * length for response IU.
419 * @param[in] data_present The parameter specifies the specific
420 * data present value for response IU.
421 *
422 * @return none
423 */
sati_scsi_common_response_iu_construct(SCI_SSP_RESPONSE_IU_T * rsp_iu,U8 scsi_status,U8 sense_data_length,U8 data_present)424 void sati_scsi_common_response_iu_construct(
425 SCI_SSP_RESPONSE_IU_T * rsp_iu,
426 U8 scsi_status,
427 U8 sense_data_length,
428 U8 data_present
429 )
430 {
431 rsp_iu->sense_data_length[3] = sense_data_length;
432 rsp_iu->sense_data_length[2] = 0;
433 rsp_iu->sense_data_length[1] = 0;
434 rsp_iu->sense_data_length[0] = 0;
435 rsp_iu->status = scsi_status;
436 rsp_iu->data_present = data_present;
437 }
438
439 /**
440 * @brief This method will construct the buffer for sense data
441 * sense data buffer location. Additionally, it will set the user's
442 * SCSI status.
443 *
444 * @param[in,out] scsi_io This parameter specifies the user's IO request
445 * for which to construct the buffer for sense data.
446 * @param[in] scsi_status This parameter specifies the SCSI status
447 * value for the user's IO request.
448 * @param[out] sense_data This parameter
449 *
450 * @return none
451 */
452 static
sati_scsi_get_sense_data_buffer(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 scsi_status,U8 ** sense_data,U32 * sense_len)453 void sati_scsi_get_sense_data_buffer(
454 SATI_TRANSLATOR_SEQUENCE_T * sequence,
455 void * scsi_io,
456 U8 scsi_status,
457 U8 ** sense_data,
458 U32 * sense_len)
459 {
460 #ifdef SATI_TRANSPORT_SUPPORTS_SAS
461 SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
462 sati_cb_get_response_iu_address(scsi_io);
463
464 sati_scsi_common_response_iu_construct(
465 rsp_iu,
466 scsi_status,
467 sati_scsi_get_sense_data_length(sequence, scsi_io),
468 SCSI_RESPONSE_DATA_PRES_SENSE_DATA
469 );
470
471 *sense_data = (U8*) rsp_iu->data;
472 *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes
473 #else
474 *sense_data = sati_cb_get_sense_data_address(scsi_io);
475 *sense_len = sati_cb_get_sense_data_length(scsi_io);
476 sati_cb_set_scsi_status(scsi_io, scsi_status);
477 #endif // SATI_TRANSPORT_SUPPORTS_SAS
478 }
479
480 /**
481 * @brief This method extract response code based on on device settings.
482 *
483 * @return response code
484 */
485 static
sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)486 U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
487 {
488 if (sequence->device->descriptor_sense_enable)
489 {
490 return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
491 }
492 else
493 {
494 return SCSI_FIXED_CURRENT_RESPONSE_CODE;
495 }
496 }
497
498 /**
499 * @brief This method will return length of descriptor sense data for executed command.
500 *
501 * @return sense data length
502 */
503 static
sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)504 U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
505 void * scsi_io)
506 {
507 U8 * cdb = sati_cb_get_cdb_address(scsi_io);
508 //Initial value is descriptor header length
509 U8 length = 8;
510
511 switch (sati_get_cdb_byte(cdb, 0))
512 {
513 #if !defined(DISABLE_SATI_WRITE_LONG)
514 case SCSI_WRITE_LONG_10:
515 case SCSI_WRITE_LONG_16:
516 length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
517 SCSI_INFORMATION_DESCRIPTOR_LENGTH;
518 break;
519 #endif // !defined(DISABLE_SATI_WRITE_LONG)
520 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
521 case SCSI_REASSIGN_BLOCKS:
522 length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
523 SCSI_INFORMATION_DESCRIPTOR_LENGTH;
524 break;
525 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
526 case SCSI_READ_6:
527 case SCSI_READ_10:
528 case SCSI_READ_12:
529 case SCSI_READ_16:
530 case SCSI_WRITE_6:
531 case SCSI_WRITE_10:
532 case SCSI_WRITE_12:
533 case SCSI_WRITE_16:
534 #if !defined(DISABLE_SATI_VERIFY)
535 case SCSI_VERIFY_10:
536 case SCSI_VERIFY_12:
537 case SCSI_VERIFY_16:
538 #endif // !defined(DISABLE_SATI_VERIFY)
539 #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
540 && !defined(DISABLE_SATI_VERIFY) \
541 && !defined(DISABLE_SATI_WRITE)
542
543 case SCSI_WRITE_AND_VERIFY_10:
544 case SCSI_WRITE_AND_VERIFY_12:
545 case SCSI_WRITE_AND_VERIFY_16:
546 #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
547 // && !defined(DISABLE_SATI_VERIFY)
548 // && !defined(DISABLE_SATI_WRITE)
549 length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
550 break;
551 }
552
553 return length;
554 }
555
556 /**
557 * @brief This method will return length of sense data.
558 *
559 * @return sense data length
560 */
sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)561 U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
562 {
563 U8 response_code;
564
565 response_code = sati_scsi_get_sense_data_response_code(sequence);
566
567 switch (response_code)
568 {
569 case SCSI_FIXED_CURRENT_RESPONSE_CODE:
570 case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
571 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
572 break;
573 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
574 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
575 return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
576 break;
577 }
578
579 return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
580 }
581
582 /**
583 * @brief This method will construct the sense data buffer in the user's
584 * sense data buffer location. Additionally, it will set the user's
585 * SCSI status.
586 *
587 * @param[in] sequence This parameter specifies the translation sequence
588 * for which to construct the sense data.
589 * @param[in,out] scsi_io This parameter specifies the user's IO request
590 * for which to construct the sense data.
591 * @param[in] scsi_status This parameter specifies the SCSI status
592 * value for the user's IO request.
593 * @param[in] sense_key This parameter specifies the sense key to
594 * be set for the user's IO request.
595 * @param[in] additional_sense_code This parameter specifies the
596 * additional sense code (ASC) key to be set for the user's
597 * IO request.
598 * @param[in] additional_sense_code_qualifier This parameter specifies
599 * the additional sense code qualifier (ASCQ) key to be set
600 * for the user's IO request.
601 *
602 * @return none
603 */
sati_scsi_sense_data_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 scsi_status,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)604 void sati_scsi_sense_data_construct(
605 SATI_TRANSLATOR_SEQUENCE_T * sequence,
606 void * scsi_io,
607 U8 scsi_status,
608 U8 sense_key,
609 U8 additional_sense_code,
610 U8 additional_sense_code_qualifier
611 )
612 {
613 U8 response_code;
614
615 response_code = sati_scsi_get_sense_data_response_code(sequence);
616
617 switch (response_code)
618 {
619 case SCSI_FIXED_CURRENT_RESPONSE_CODE:
620 case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
621 sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
622 sense_key, additional_sense_code, additional_sense_code_qualifier);
623 break;
624 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
625 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
626 sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
627 sense_key, additional_sense_code, additional_sense_code_qualifier);
628 break;
629 }
630
631 sequence->is_sense_response_set = TRUE;
632 }
633
634 /**
635 * @brief This method will construct the block descriptor in the user's descriptor
636 * sense data buffer location.
637 *
638 * @param[in] sense_data This parameter specifies the user SCSI IO request
639 * for which to set the sense data byte.
640 * @param[in] sense_len This parameter specifies length of the sense data
641 * to be returned by SATI.
642 * @param[out] descriptor_len This parameter returns the length of constructed
643 * descriptor.
644 *
645 * @return none
646 */
647 static
sati_scsi_block_descriptor_construct(U8 * sense_data,U32 sense_len)648 void sati_scsi_block_descriptor_construct(
649 U8 * sense_data,
650 U32 sense_len)
651 {
652 U8 ili = 1;
653
654 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE);
655 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
656 sati_set_sense_data_byte(sense_data, sense_len, 2, 0);
657 sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5));
658 }
659
660 /**
661 * @brief This method will construct the command-specific descriptor for
662 * the descriptor sense data buffer in the user's sense data buffer
663 * location.
664 *
665 * @param[in] sense_data This parameter specifies the user SCSI IO request
666 * for which to set the sense data byte.
667 * @param[in] sense_len This parameter specifies length of the sense data
668 * to be returned by SATI.
669 * @param[out] descriptor_len This parameter returns the length of constructed
670 * descriptor.
671 * @param[in] information_buff This parameter specifies the address for which
672 * to set the command-specific information buffer.
673 *
674 * @return none
675 */
676 static
sati_scsi_command_specific_descriptor_construct(U8 * sense_data,U32 sense_len,U8 * information_buff)677 void sati_scsi_command_specific_descriptor_construct(
678 U8 * sense_data,
679 U32 sense_len,
680 U8 * information_buff)
681 {
682 U8 i;
683
684 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
685 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
686 sati_set_sense_data_byte(sense_data, sense_len, 2, 0);
687 sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
688
689 // fill information buffer
690 // SBC 5.20.1 REASSIGN BLOCKS command overview
691 // If information about the first LBA not reassigned is not available
692 // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
693 for (i=0; i<8; i++)
694 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
695 }
696
697 /**
698 * @brief This method will construct the information descriptor for
699 * the descriptor sense data buffer in the user's sense data buffer
700 * location.
701 *
702 * @param[in] sense_data This parameter specifies the user SCSI IO request
703 * for which to set the sense data byte.
704 * @param[in] sense_len This parameter specifies length of the sense data
705 * to be returned by SATI.
706 * @param[out] descriptor_len This parameter returns the length of constructed
707 * descriptor.
708 * @param[in] information_buff This parameter specifies the address for which
709 * to set the information buffer.
710 *
711 * @return none
712 */
713 static
sati_scsi_information_descriptor_construct(U8 * sense_data,U32 sense_len,U8 * information_buff)714 void sati_scsi_information_descriptor_construct(
715 U8 * sense_data,
716 U32 sense_len,
717 U8 * information_buff)
718 {
719 U8 i;
720 U8 valid = 1;
721
722 sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE);
723 sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
724 sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7));
725 sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
726
727 // fill information buffer
728 for (i=0; i<8; i++)
729 sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
730 }
731
732 /**
733 * @brief This method will construct the descriptors in the user's descriptor
734 * sense data buffer location.
735 *
736 * @param[in,out] scsi_io This parameter specifies the user's IO request
737 * for which to construct the sense data.
738 * @param[in] sense_data This parameter specifies the user SCSI IO request
739 * for which to set the sense data byte.
740 * @param[in] sense_len This parameter specifies length of the sense data
741 * to be returned by SATI.
742 * @param[out] descriptor_len This parameter returns the length of constructed
743 * descriptor.
744 * @param[in] information_buff This parameter specifies the address for which
745 * to set the information buffer.
746 *
747 * @return none
748 */
749 static
sati_scsi_common_descriptors_construct(void * scsi_io,U8 * sense_data,U32 sense_len,U8 * information_buff)750 void sati_scsi_common_descriptors_construct(
751 void * scsi_io,
752 U8 * sense_data,
753 U32 sense_len,
754 U8 * information_buff)
755 {
756 U8 * cdb = sati_cb_get_cdb_address(scsi_io);
757 U8 offset = 0;
758
759 switch (sati_get_cdb_byte(cdb, 0))
760 {
761 #if !defined(DISABLE_SATI_WRITE_LONG)
762 case SCSI_WRITE_LONG_10:
763 case SCSI_WRITE_LONG_16:
764 sati_scsi_block_descriptor_construct(
765 sense_data + offset,
766 sense_len - offset);
767
768 offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
769 sati_scsi_information_descriptor_construct(
770 sense_data + offset,
771 sense_len - offset,
772 information_buff);
773
774 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
775 break;
776 #endif // !defined(DISABLE_SATI_WRITE_LONG)
777 #if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
778 case SCSI_REASSIGN_BLOCKS:
779 sati_scsi_command_specific_descriptor_construct(
780 sense_data + offset,
781 sense_len - offset,
782 NULL);
783
784 offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
785 sati_scsi_information_descriptor_construct(
786 sense_data + offset,
787 sense_len - offset,
788 information_buff);
789
790 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
791 break;
792 #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
793 case SCSI_READ_6:
794 case SCSI_READ_10:
795 case SCSI_READ_12:
796 case SCSI_READ_16:
797 case SCSI_WRITE_6:
798 case SCSI_WRITE_10:
799 case SCSI_WRITE_12:
800 case SCSI_WRITE_16:
801 #if !defined(DISABLE_SATI_VERIFY)
802 case SCSI_VERIFY_10:
803 case SCSI_VERIFY_12:
804 case SCSI_VERIFY_16:
805 #endif // !defined(DISABLE_SATI_VERIFY)
806 #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
807 && !defined(DISABLE_SATI_VERIFY) \
808 && !defined(DISABLE_SATI_WRITE)
809
810 case SCSI_WRITE_AND_VERIFY_10:
811 case SCSI_WRITE_AND_VERIFY_12:
812 case SCSI_WRITE_AND_VERIFY_16:
813 #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
814 // && !defined(DISABLE_SATI_VERIFY)
815 // && !defined(DISABLE_SATI_WRITE)
816 sati_scsi_information_descriptor_construct(
817 sense_data + offset,
818 sense_len - offset,
819 information_buff);
820
821 offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
822 break;
823 }
824 }
825
826 /**
827 * @brief This method will construct the descriptor sense data buffer in
828 * the user's sense data buffer location. Additionally, it will set
829 * the user's SCSI status.
830 *
831 * @param[in] sequence This parameter specifies the translation sequence
832 * for which to construct the sense data.
833 * @param[in,out] scsi_io This parameter specifies the user's IO request
834 * for which to construct the sense data.
835 * @param[in] scsi_status This parameter specifies the SCSI status
836 * value for the user's IO request.
837 * @param[in] sense_key This parameter specifies the sense key to
838 * be set for the user's IO request.
839 * @param[in] additional_sense_code This parameter specifies the
840 * additional sense code (ASC) key to be set for the user's
841 * IO request.
842 * @param[in] additional_sense_code_qualifier This parameter specifies
843 * the additional sense code qualifier (ASCQ) key to be set
844 * for the user's IO request.
845 *
846 * @return none
847 */
sati_scsi_descriptor_sense_data_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)848 void sati_scsi_descriptor_sense_data_construct(
849 SATI_TRANSLATOR_SEQUENCE_T * sequence,
850 void * scsi_io,
851 U8 scsi_status,
852 U8 response_code,
853 U8 sense_key,
854 U8 additional_sense_code,
855 U8 additional_sense_code_qualifier
856 )
857 {
858 U8 * sense_data;
859 U32 sense_len;
860
861 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
862
863 sati_set_sense_data_byte(
864 sense_data,
865 sense_len,
866 0,
867 response_code
868 );
869
870 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key);
871 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code);
872 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier);
873 sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
874 sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
875 sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
876
877 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
878
879 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
880 }
881
882 /**
883 * @brief This method will construct the fixed format sense data buffer
884 * in the user's sense data buffer location. Additionally, it will
885 * set the user's SCSI status.
886 *
887 * @param[in] sequence This parameter specifies the translation sequence
888 * for which to construct the sense data.
889 * @param[in,out] scsi_io This parameter specifies the user's IO request
890 * for which to construct the sense data.
891 * @param[in] scsi_status This parameter specifies the SCSI status
892 * value for the user's IO request.
893 * @param[in] sense_key This parameter specifies the sense key to
894 * be set for the user's IO request.
895 * @param[in] additional_sense_code This parameter specifies the
896 * additional sense code (ASC) key to be set for the user's
897 * IO request.
898 * @param[in] additional_sense_code_qualifier This parameter specifies
899 * the additional sense code qualifier (ASCQ) key to be set
900 * for the user's IO request.
901 *
902 * @return none
903 */
sati_scsi_fixed_sense_data_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)904 void sati_scsi_fixed_sense_data_construct(
905 SATI_TRANSLATOR_SEQUENCE_T * sequence,
906 void * scsi_io,
907 U8 scsi_status,
908 U8 response_code,
909 U8 sense_key,
910 U8 additional_sense_code,
911 U8 additional_sense_code_qualifier
912 )
913 {
914 U8 * sense_data;
915 U32 sense_len;
916
917 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
918
919 // Write out the sense data format per SPC-4.
920 // We utilize the fixed format sense data format.
921
922 sati_set_sense_data_byte(
923 sense_data,
924 sense_len,
925 0,
926 response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
927 );
928
929 sati_set_sense_data_byte(sense_data, sense_len, 1, 0);
930 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key);
931 sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
932 sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
933 sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
934 sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
935 sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7);
936 sati_set_sense_data_byte(sense_data, sense_len, 8, 0);
937 sati_set_sense_data_byte(sense_data, sense_len, 9, 0);
938 sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
939 sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
940 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
941 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
942 sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
943 sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
944 sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
945 sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
946 }
947
948 /**
949 * @brief This method will construct common sense data that will be identical in
950 * both read error sense construct functions.
951 * sati_scsi_read_ncq_error_sense_construct,
952 * sati_scsi_read_error_sense_construct
953 *
954 * @param[in] sense_data This parameter specifies the user SCSI IO request
955 * for which to set the sense data byte.
956 * @param[in] sense_len This parameter specifies length of the sense data
957 * to be returned by SATI.
958 * @param[in] sense_key This parameter specifies the sense key to
959 * be set for the user's IO request.
960 * @param[in] additional_sense_code This parameter specifies the
961 * additional sense code (ASC) key to be set for the user's
962 * IO request.
963 * @param[in] additional_sense_code_qualifier This parameter specifies
964 * the additional sense code qualifier (ASCQ) key to be set
965 * for the user's IO request.
966 *
967 * @return none
968 */
969 static
sati_scsi_common_fixed_sense_construct(U8 * sense_data,U32 sense_len,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)970 void sati_scsi_common_fixed_sense_construct(
971 U8 * sense_data,
972 U32 sense_len,
973 U8 sense_key,
974 U8 additional_sense_code,
975 U8 additional_sense_code_qualifier
976 )
977 {
978
979 sati_set_sense_data_byte(sense_data, sense_len, 1, 0);
980 sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key);
981
982 //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
983
984 sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7);
985 sati_set_sense_data_byte(sense_data, sense_len, 8, 0);
986 sati_set_sense_data_byte(sense_data, sense_len, 9, 0);
987 sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
988 sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
989 sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
990 sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
991 sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
992 sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
993 sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
994 sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
995 }
996
997 /**
998 * @brief This method will construct the descriptor sense data buffer in
999 * the user's sense data buffer location. Additionally, it will set
1000 * the user's SCSI status.
1001 *
1002 * @param[in] sequence This parameter specifies the translation sequence
1003 * for which to construct the sense data.
1004 * @param[in,out] scsi_io This parameter specifies the user's IO request
1005 * for which to construct the sense data.
1006 * @param[in] scsi_status This parameter specifies the SCSI status
1007 * value for the user's IO request.
1008 * @param[in] sense_key This parameter specifies the sense key to
1009 * be set for the user's IO request.
1010 * @param[in] additional_sense_code This parameter specifies the
1011 * additional sense code (ASC) key to be set for the user's
1012 * IO request.
1013 * @param[in] additional_sense_code_qualifier This parameter specifies
1014 * the additional sense code qualifier (ASCQ) key to be set
1015 * for the user's IO request.
1016 *
1017 * @return none
1018 */
1019 static
sati_scsi_common_descriptor_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 * sense_data,U32 sense_len,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier,U8 * information_buff)1020 void sati_scsi_common_descriptor_sense_construct(
1021 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1022 void * scsi_io,
1023 U8 * sense_data,
1024 U32 sense_len,
1025 U8 sense_key,
1026 U8 additional_sense_code,
1027 U8 additional_sense_code_qualifier,
1028 U8 * information_buff
1029 )
1030 {
1031 sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key);
1032 sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code);
1033 sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier);
1034 sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
1035 sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
1036 sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
1037
1038 sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
1039
1040 sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
1041 }
1042
1043 /**
1044 * @brief This method will construct the sense data buffer in the user's
1045 * descriptor sense data buffer location. Additionally, it will set
1046 * the user's SCSI status. This is only used for NCQ uncorrectable
1047 * read errors
1048 *
1049 * @param[in] sequence This parameter specifies the translation sequence
1050 * for which to construct the sense data.
1051 * @param[in,out] scsi_io This parameter specifies the user's IO request
1052 * for which to construct the sense data.
1053 * @param[in] ata_input_data This parameter specifies the user's ATA IO
1054 * response from a Read Log Ext command.
1055 * @param[in] scsi_status This parameter specifies the SCSI status
1056 * value for the user's IO request.
1057 * @param[in] sense_key This parameter specifies the sense key to
1058 * be set for the user's IO request.
1059 * @param[in] additional_sense_code This parameter specifies the
1060 * additional sense code (ASC) key to be set for the user's
1061 * IO request.
1062 * @param[in] additional_sense_code_qualifier This parameter specifies
1063 * the additional sense code qualifier (ASCQ) key to be set
1064 * for the user's IO request.
1065 *
1066 * @return none
1067 */
1068 static
sati_scsi_read_ncq_error_descriptor_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_input_data,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1069 void sati_scsi_read_ncq_error_descriptor_sense_construct(
1070 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1071 void * scsi_io,
1072 void * ata_input_data,
1073 U8 scsi_status,
1074 U8 response_code,
1075 U8 sense_key,
1076 U8 additional_sense_code,
1077 U8 additional_sense_code_qualifier
1078 )
1079 {
1080 U8 * sense_data;
1081 U32 sense_len;
1082
1083 U8 information_buff[8] = {0};
1084
1085 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1086
1087 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1088
1089 sati_set_sense_data_byte(
1090 sense_data,
1091 sense_len,
1092 0,
1093 response_code
1094 );
1095
1096 information_buff[2] = ncq_log->lba_47_40;
1097 information_buff[3] = ncq_log->lba_39_32;
1098 information_buff[4] = ncq_log->lba_31_24;
1099 information_buff[5] = ncq_log->lba_23_16;
1100 information_buff[6] = ncq_log->lba_15_8;
1101 information_buff[7] = ncq_log->lba_7_0;
1102
1103 sati_scsi_common_descriptor_sense_construct(
1104 sequence,
1105 scsi_io,
1106 sense_data,
1107 sense_len,
1108 sense_key,
1109 additional_sense_code,
1110 additional_sense_code_qualifier,
1111 information_buff
1112 );
1113 }
1114
1115 /**
1116 * @brief This method will construct the sense data buffer in the user's
1117 * sense data buffer location. Additionally, it will set the user's
1118 * SCSI status. This is only used for NCQ uncorrectable read errors
1119 *
1120 * @param[in] sequence This parameter specifies the translation sequence
1121 * for which to construct the sense data.
1122 * @param[in,out] scsi_io This parameter specifies the user's IO request
1123 * for which to construct the sense data.
1124 * @param[in] ata_input_data This parameter specifies the user's ATA IO
1125 * response from a Read Log Ext command.
1126 * @param[in] scsi_status This parameter specifies the SCSI status
1127 * value for the user's IO request.
1128 * @param[in] sense_key This parameter specifies the sense key to
1129 * be set for the user's IO request.
1130 * @param[in] additional_sense_code This parameter specifies the
1131 * additional sense code (ASC) key to be set for the user's
1132 * IO request.
1133 * @param[in] additional_sense_code_qualifier This parameter specifies
1134 * the additional sense code qualifier (ASCQ) key to be set
1135 * for the user's IO request.
1136 *
1137 * @return none
1138 */
1139 static
sati_scsi_read_ncq_error_fixed_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_input_data,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1140 void sati_scsi_read_ncq_error_fixed_sense_construct(
1141 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1142 void * scsi_io,
1143 void * ata_input_data,
1144 U8 scsi_status,
1145 U8 response_code,
1146 U8 sense_key,
1147 U8 additional_sense_code,
1148 U8 additional_sense_code_qualifier
1149 )
1150 {
1151 U8 * sense_data;
1152 U32 sense_len;
1153 U8 valid = TRUE;
1154
1155 ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
1156
1157 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1158
1159 if(ncq_log->lba_39_32 > 0)
1160 {
1161 valid = FALSE;
1162 }
1163
1164 sati_set_sense_data_byte(
1165 sense_data,
1166 sense_len,
1167 0,
1168 (valid << 7) | response_code
1169 );
1170
1171 sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24);
1172 sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16);
1173 sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8);
1174 sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0);
1175
1176 sati_scsi_common_fixed_sense_construct(
1177 sense_data,
1178 sense_len,
1179 sense_key,
1180 additional_sense_code,
1181 additional_sense_code_qualifier
1182 );
1183 }
1184
sati_scsi_read_ncq_error_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_input_data,U8 scsi_status,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1185 void sati_scsi_read_ncq_error_sense_construct(
1186 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1187 void * scsi_io,
1188 void * ata_input_data,
1189 U8 scsi_status,
1190 U8 sense_key,
1191 U8 additional_sense_code,
1192 U8 additional_sense_code_qualifier
1193 )
1194 {
1195 U8 response_code;
1196
1197 response_code = sati_scsi_get_sense_data_response_code(sequence);
1198
1199 switch (response_code)
1200 {
1201 case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1202 case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1203 sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1204 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1205 break;
1206 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1207 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1208 sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1209 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1210 break;
1211 }
1212
1213 sequence->is_sense_response_set = TRUE;
1214 }
1215
1216 /**
1217 * @brief This method will construct the sense data buffer in the user's
1218 * sense data buffer location. Additionally, it will set the user's
1219 * SCSI status. This is used for uncorrectable read errors.
1220 *
1221 * @param[in] sequence This parameter specifies the translation sequence
1222 * for which to construct the sense data.
1223 * @param[in,out] scsi_io This parameter specifies the user's IO request
1224 * for which to construct the sense data.
1225 * @param[in] ata_io This parameter is a pointer to the ATA IO data used
1226 * to get the ATA register fis.
1227 * @param[in] scsi_status This parameter specifies the SCSI status
1228 * value for the user's IO request.
1229 * @param[in] sense_key This parameter specifies the sense key to
1230 * be set for the user's IO request.
1231 * @param[in] additional_sense_code This parameter specifies the
1232 * additional sense code (ASC) key to be set for the user's
1233 * IO request.
1234 * @param[in] additional_sense_code_qualifier This parameter specifies
1235 * the additional sense code qualifier (ASCQ) key to be set
1236 * for the user's IO request.
1237 *
1238 * @return none
1239 */
1240 static
sati_scsi_read_error_descriptor_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1241 void sati_scsi_read_error_descriptor_sense_construct(
1242 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1243 void * scsi_io,
1244 void * ata_io,
1245 U8 scsi_status,
1246 U8 response_code,
1247 U8 sense_key,
1248 U8 additional_sense_code,
1249 U8 additional_sense_code_qualifier
1250 )
1251 {
1252 U8 * sense_data;
1253 U32 sense_len;
1254 U8 information_buff[8] = {0};
1255
1256 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1257
1258 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1259
1260 information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
1261 information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
1262 information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
1263 information_buff[5] = sati_get_ata_lba_high(register_fis);
1264 information_buff[6] = sati_get_ata_lba_mid(register_fis);
1265 information_buff[7] = sati_get_ata_lba_low(register_fis);
1266
1267 sati_set_sense_data_byte(
1268 sense_data,
1269 sense_len,
1270 0,
1271 SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
1272 );
1273
1274 sati_scsi_common_descriptor_sense_construct(
1275 sequence,
1276 scsi_io,
1277 sense_data,
1278 sense_len,
1279 sense_key,
1280 additional_sense_code,
1281 additional_sense_code_qualifier,
1282 information_buff
1283 );
1284 }
1285
1286 /**
1287 * @brief This method will construct the sense data buffer in the user's
1288 * sense data buffer location. Additionally, it will set the user's
1289 * SCSI status. This is used for uncorrectable read errors.
1290 *
1291 * @param[in] sequence This parameter specifies the translation sequence
1292 * for which to construct the sense data.
1293 * @param[in,out] scsi_io This parameter specifies the user's IO request
1294 * for which to construct the sense data.
1295 * @param[in] ata_io This parameter is a pointer to the ATA IO data used
1296 * to get the ATA register fis.
1297 * @param[in] scsi_status This parameter specifies the SCSI status
1298 * value for the user's IO request.
1299 * @param[in] sense_key This parameter specifies the sense key to
1300 * be set for the user's IO request.
1301 * @param[in] additional_sense_code This parameter specifies the
1302 * additional sense code (ASC) key to be set for the user's
1303 * IO request.
1304 * @param[in] additional_sense_code_qualifier This parameter specifies
1305 * the additional sense code qualifier (ASCQ) key to be set
1306 * for the user's IO request.
1307 *
1308 * @return none
1309 */
1310 static
sati_scsi_read_error_fixed_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io,U8 scsi_status,U8 response_code,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1311 void sati_scsi_read_error_fixed_sense_construct(
1312 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1313 void * scsi_io,
1314 void * ata_io,
1315 U8 scsi_status,
1316 U8 response_code,
1317 U8 sense_key,
1318 U8 additional_sense_code,
1319 U8 additional_sense_code_qualifier
1320 )
1321 {
1322 U8 * sense_data;
1323 U32 sense_len;
1324 U8 valid = TRUE;
1325
1326 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
1327
1328 sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
1329
1330 if(sati_get_ata_lba_mid_ext(register_fis) > 0)
1331 {
1332 valid = FALSE;
1333 }
1334
1335 sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis));
1336 sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis));
1337 sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis));
1338 sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis));
1339
1340
1341 sati_set_sense_data_byte(
1342 sense_data,
1343 sense_len,
1344 0,
1345 (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
1346 );
1347
1348 sati_scsi_common_fixed_sense_construct(
1349 sense_data,
1350 sense_len,
1351 sense_key,
1352 additional_sense_code,
1353 additional_sense_code_qualifier
1354 );
1355 }
1356
sati_scsi_read_error_sense_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_input_data,U8 scsi_status,U8 sense_key,U8 additional_sense_code,U8 additional_sense_code_qualifier)1357 void sati_scsi_read_error_sense_construct(
1358 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1359 void * scsi_io,
1360 void * ata_input_data,
1361 U8 scsi_status,
1362 U8 sense_key,
1363 U8 additional_sense_code,
1364 U8 additional_sense_code_qualifier
1365 )
1366 {
1367 U8 response_code;
1368
1369 response_code = sati_scsi_get_sense_data_response_code(sequence);
1370
1371 switch (response_code)
1372 {
1373 case SCSI_FIXED_CURRENT_RESPONSE_CODE:
1374 case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
1375 sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1376 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1377 break;
1378 case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
1379 case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
1380 sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
1381 response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
1382 break;
1383 }
1384
1385 sequence->is_sense_response_set = TRUE;
1386 }
1387
1388 /*
1389 * @brief This method builds the scsi response data for a sata task management
1390 * request.
1391 *
1392 * @param[in] sequence This parameter specifies the translation sequence
1393 * for which to construct the sense data.
1394 * @param[in,out] scsi_io This parameter specifies the user's IO request
1395 * for which to construct the sense data.
1396 * @param[in] response_data The response status for the task management
1397 * request.
1398 */
sati_scsi_response_data_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 response_data)1399 void sati_scsi_response_data_construct(
1400 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1401 void * scsi_io,
1402 U8 response_data
1403 )
1404 {
1405 #ifdef SATI_TRANSPORT_SUPPORTS_SAS
1406 SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
1407 sati_cb_get_response_iu_address(scsi_io);
1408 rsp_iu->data_present = 0x01;
1409 rsp_iu->response_data_length[3] = sizeof(U32);
1410 rsp_iu->status = 0;
1411 ((U8 *)rsp_iu->data)[3] = response_data;
1412 #else
1413 #endif // SATI_TRANSPORT_SUPPORTS_SAS
1414 }
1415
1416 /**
1417 * @brief This method checks to make sure that the translation isn't
1418 * exceeding the allocation length specified in the CDB prior
1419 * to retrieving the payload data byte from the user's buffer.
1420 *
1421 * @param[in,out] scsi_io This parameter specifies the user's IO request
1422 * for which to set the user payload data byte.
1423 * @param[in] byte_offset This parameter specifies the offset into
1424 * the user's payload buffer at which to write the supplied
1425 * value.
1426 * @param[in] value This parameter specifies the memory location into
1427 * which to read the value from the user's payload buffer.
1428 *
1429 * @return none
1430 */
sati_get_data_byte(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U32 byte_offset,U8 * value)1431 void sati_get_data_byte(
1432 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1433 void * scsi_io,
1434 U32 byte_offset,
1435 U8 * value
1436 )
1437 {
1438 if (byte_offset < sequence->allocation_length)
1439 sati_cb_get_data_byte(scsi_io, byte_offset, value);
1440 }
1441
1442 /**
1443 * @brief This method checks to make sure that the translation isn't
1444 * exceeding the allocation length specified in the CDB while
1445 * translating payload data into the user's buffer.
1446 *
1447 * @param[in] sequence This parameter specifies the translation sequence
1448 * for which to set the user payload data byte.
1449 * @param[in,out] scsi_io This parameter specifies the user's IO request
1450 * for which to set the user payload data byte.
1451 * @param[in] byte_offset This parameter specifies the offset into
1452 * the user's payload buffer at which to write the supplied
1453 * value.
1454 * @param[in] value This parameter specifies the new value to be
1455 * written out into the user's payload buffer.
1456 *
1457 * @return none
1458 */
sati_set_data_byte(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U32 byte_offset,U8 value)1459 void sati_set_data_byte(
1460 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1461 void * scsi_io,
1462 U32 byte_offset,
1463 U8 value
1464 )
1465 {
1466 if (byte_offset < sequence->allocation_length)
1467 {
1468 sequence->number_data_bytes_set++;
1469 sati_cb_set_data_byte(scsi_io, byte_offset, value);
1470 }
1471 }
1472
1473 /**
1474 * @brief This method checks to make sure that the translation isn't
1475 * exceeding the allocation length specified in the CDB while
1476 * translating payload data into the user's buffer.
1477 *
1478 * @param[in] sequence This parameter specifies the translation sequence
1479 * for which to set the user payload data dword.
1480 * @param[in,out] scsi_io This parameter specifies the user's IO request
1481 * for which to set the user payload data dword.
1482 * @param[in] byte_offset This parameter specifies the offset into
1483 * the user's payload buffer at which to write the supplied
1484 * value.
1485 * @param[in] value This parameter specifies the new value to be
1486 * written out into the user's payload buffer.
1487 *
1488 * @return none
1489 */
sati_set_data_dword(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U32 byte_offset,U32 value)1490 void sati_set_data_dword(
1491 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1492 void * scsi_io,
1493 U32 byte_offset,
1494 U32 value
1495 )
1496 {
1497 /// @todo Check to ensure that the bytes appear correctly (SAS Address).
1498
1499 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
1500 byte_offset++;
1501 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
1502 byte_offset++;
1503 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
1504 byte_offset++;
1505 sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
1506 }
1507
1508 /**
1509 * @brief This method will construct the ATA flush cache command.
1510 *
1511 * @pre It is expected that the user has properly set the current contents
1512 * of the register FIS to 0.
1513 *
1514 * @param[out] ata_io This parameter specifies the ATA IO request structure
1515 * for which to build the FLUSH CACHE command.
1516 * @param[in] sequence This parameter specifies the translator sequence
1517 * for which the command is being constructed.
1518 *
1519 * @return none.
1520 */
sati_ata_flush_cache_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1521 void sati_ata_flush_cache_construct(
1522 void * ata_io,
1523 SATI_TRANSLATOR_SEQUENCE_T * sequence
1524 )
1525 {
1526 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1527
1528 sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
1529 sati_ata_non_data_command(ata_io, sequence);
1530 }
1531
1532 /**
1533 * @brief This method will construct the ATA standby immediate command.
1534 *
1535 * @pre It is expected that the user has properly set the current contents
1536 * of the register FIS to 0.
1537 *
1538 * @param[out] ata_io This parameter specifies the ATA IO request structure
1539 * for which to build the STANDBY IMMEDIATE command.
1540 * @param[in] sequence This parameter specifies the translator sequence
1541 * for which the command is being constructed.
1542 *
1543 * @param[in] count This parameter specifies the time period programmed
1544 * into the Standby Timer. See ATA8 spec for more details
1545 * @return none.
1546 */
sati_ata_standby_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U16 count)1547 void sati_ata_standby_construct(
1548 void * ata_io,
1549 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1550 U16 count
1551 )
1552 {
1553 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1554
1555 sati_set_ata_command(register_fis, ATA_STANDBY);
1556 sati_set_ata_sector_count(register_fis, count);
1557
1558 sequence->device->ata_standby_timer = (U8) count;
1559
1560 sati_ata_non_data_command(ata_io, sequence);
1561 }
1562
1563 /**
1564 * @brief This method will construct the ATA standby immediate command.
1565 *
1566 * @pre It is expected that the user has properly set the current contents
1567 * of the register FIS to 0.
1568 *
1569 * @param[out] ata_io This parameter specifies the ATA IO request structure
1570 * for which to build the STANDBY IMMEDIATE command.
1571 * @param[in] sequence This parameter specifies the translator sequence
1572 * for which the command is being constructed.
1573 *
1574 * @return none.
1575 */
sati_ata_standby_immediate_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1576 void sati_ata_standby_immediate_construct(
1577 void * ata_io,
1578 SATI_TRANSLATOR_SEQUENCE_T * sequence
1579 )
1580 {
1581 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1582
1583 sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
1584 sati_ata_non_data_command(ata_io, sequence);
1585 }
1586
1587 /**
1588 * @brief This method will construct the ATA idle immediate command.
1589 *
1590 * @pre It is expected that the user has properly set the current contents
1591 * of the register FIS to 0.
1592 *
1593 * @param[out] ata_io This parameter specifies the ATA IO request structure
1594 * for which to build the IDLE IMMEDIATE command.
1595 * @param[in] sequence This parameter specifies the translator sequence
1596 * for which the command is being constructed.
1597 *
1598 * @return none.
1599 */
sati_ata_idle_immediate_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1600 void sati_ata_idle_immediate_construct(
1601 void * ata_io,
1602 SATI_TRANSLATOR_SEQUENCE_T * sequence
1603 )
1604 {
1605 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1606
1607 sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1608 sati_set_ata_features(register_fis, 0x00);
1609 sati_set_ata_sector_count(register_fis, 0x00);
1610 sati_set_ata_lba_high(register_fis, 0x00);
1611 sati_set_ata_lba_mid(register_fis, 0x00);
1612 sati_set_ata_lba_low(register_fis, 0x00);
1613 sati_ata_non_data_command(ata_io, sequence);
1614 }
1615
1616 /**
1617 * @brief This method will construct the ATA idle immediate command
1618 for Unload Features.
1619 *
1620 * @pre It is expected that the user has properly set the current contents
1621 * of the register FIS to 0.
1622 *
1623 * @param[out] ata_io This parameter specifies the ATA IO request structure
1624 * for which to build the IDLE IMMEDIATE command.
1625 * @param[in] sequence This parameter specifies the translator sequence
1626 * for which the command is being constructed.
1627 *
1628 * @return none.
1629 */
sati_ata_idle_immediate_unload_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1630 void sati_ata_idle_immediate_unload_construct(
1631 void * ata_io,
1632 SATI_TRANSLATOR_SEQUENCE_T * sequence
1633 )
1634 {
1635 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1636
1637 sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
1638 sati_set_ata_features(register_fis, 0x44);
1639 sati_set_ata_sector_count(register_fis, 0x00);
1640 sati_set_ata_lba_high(register_fis, 0x55);
1641 sati_set_ata_lba_mid(register_fis, 0x4E);
1642 sati_set_ata_lba_low(register_fis, 0x4C);
1643 sati_ata_non_data_command(ata_io, sequence);
1644 }
1645
1646 /**
1647 * @brief This method will construct the ATA IDLE command.\
1648 *
1649 * @pre It is expected that the user has properly set the current contents
1650 * of the register FIS to 0.
1651 *
1652 * @param[out] ata_io This parameter specifies the ATA IO request structure
1653 * for which to build the ATA IDLE command.
1654 * @param[in] sequence This parameter specifies the translator sequence
1655 * for which the command is being constructed.
1656 *
1657 * @return none.
1658 */
sati_ata_idle_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1659 void sati_ata_idle_construct(
1660 void * ata_io,
1661 SATI_TRANSLATOR_SEQUENCE_T * sequence
1662 )
1663 {
1664 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1665
1666 sati_set_ata_command(register_fis, ATA_IDLE);
1667 sati_set_ata_features(register_fis, 0x00);
1668 sati_set_ata_sector_count(register_fis, 0x00);
1669
1670 sequence->device->ata_standby_timer = 0x00;
1671
1672 sati_set_ata_lba_high(register_fis, 0x00);
1673 sati_set_ata_lba_mid(register_fis, 0x00);
1674 sati_set_ata_lba_low(register_fis, 0x00);
1675 sati_ata_non_data_command(ata_io, sequence);
1676 }
1677
1678 /**
1679 * @brief This method will construct the ATA MEDIA EJECT command.
1680 *
1681 * @pre It is expected that the user has properly set the current contents
1682 * of the register FIS to 0.
1683 *
1684 * @param[out] ata_io This parameter specifies the ATA IO request structure
1685 * for which to build the MEDIA EJCT command.
1686 * @param[in] sequence This parameter specifies the translator sequence
1687 * for which the command is being constructed.
1688 *
1689 * @return none.
1690 */
sati_ata_media_eject_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1691 void sati_ata_media_eject_construct(
1692 void * ata_io,
1693 SATI_TRANSLATOR_SEQUENCE_T * sequence
1694 )
1695 {
1696 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1697
1698 sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
1699 sati_ata_non_data_command(ata_io, sequence);
1700 }
1701
1702
1703 /**
1704 * @brief This method will construct the ATA read verify sector(s) command.
1705 *
1706 * @pre It is expected that the user has properly set the current contents
1707 * of the register FIS to 0.
1708 *
1709 * @param[out] ata_io This parameter specifies the ATA IO request structure
1710 * for which to build the ATA READ VERIFY SECTOR(S) command.
1711 * @param[in] sequence This parameter specifies the translator sequence
1712 * for which the command is being constructed.
1713 *
1714 * @return none.
1715 */
sati_ata_read_verify_sectors_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1716 void sati_ata_read_verify_sectors_construct(
1717 void * ata_io,
1718 SATI_TRANSLATOR_SEQUENCE_T * sequence
1719 )
1720 {
1721 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1722
1723 sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
1724
1725 //According to SAT-2 (v7) 9.11.3
1726 sati_set_ata_sector_count(register_fis, 1);
1727
1728 //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
1729 //maximum LBA supported by the ATA device in its current configuration.
1730 //From the unit test, it seems we have to set LBA to a non-zero value.
1731 sati_set_ata_lba_low(register_fis, 1);
1732
1733 sati_ata_non_data_command(ata_io, sequence);
1734 }
1735
1736 /**
1737 * @brief This method will construct a ATA SMART Return Status command so the
1738 * status of the ATA device can be returned. The status of the SMART
1739 * threshold will be returned by this command.
1740 *
1741 * @return N/A
1742 *
1743 */
sati_ata_smart_return_status_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 feature_value)1744 void sati_ata_smart_return_status_construct(
1745 void * ata_io,
1746 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1747 U8 feature_value
1748 )
1749 {
1750 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1751
1752 sati_set_ata_command(register_fis, ATA_SMART);
1753
1754 sati_set_ata_features(register_fis, feature_value);
1755
1756 sati_set_ata_lba_high(register_fis, 0xC2);
1757 sati_set_ata_lba_mid(register_fis, 0x4F);
1758
1759 sati_ata_non_data_command(ata_io, sequence);
1760 }
1761
1762 /**
1763 * @brief This method will construct a ATA SMART Return Status command so the
1764 * status of the ATA device can be returned. The status of the SMART
1765 * threshold will be returned by this command.
1766 *
1767 * @return N/A
1768 *
1769 */
sati_ata_smart_read_log_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 log_address,U32 transfer_length)1770 void sati_ata_smart_read_log_construct(
1771 void * ata_io,
1772 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1773 U8 log_address,
1774 U32 transfer_length
1775 )
1776 {
1777 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1778
1779 sati_set_ata_command(register_fis, ATA_SMART);
1780 sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
1781
1782 sati_set_ata_lba_high(register_fis, 0xC2);
1783 sati_set_ata_lba_mid(register_fis, 0x4F);
1784 sati_set_ata_lba_low(register_fis, log_address);
1785
1786 sequence->data_direction = SATI_DATA_DIRECTION_IN;
1787 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
1788 sequence->ata_transfer_length = transfer_length;
1789 }
1790
1791 /**
1792 * @brief This method will construct a Write Uncorrectable ATA command that
1793 * will write one sector with a pseudo or flagged error. The type of
1794 * error is specified by the feature value.
1795 *
1796 * @return N/A
1797 *
1798 */
sati_ata_write_uncorrectable_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 feature_value)1799 void sati_ata_write_uncorrectable_construct(
1800 void * ata_io,
1801 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1802 U8 feature_value
1803 )
1804 {
1805 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1806
1807 sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
1808 sati_set_ata_features(register_fis, feature_value);
1809 sati_set_ata_sector_count(register_fis, 0x0001);
1810 sati_ata_non_data_command(ata_io, sequence);
1811 }
1812
1813 /**
1814 * @brief This method will construct a Mode Select ATA SET FEATURES command
1815 * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
1816 *
1817 * @return N/A
1818 *
1819 */
sati_ata_set_features_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 feature)1820 void sati_ata_set_features_construct(
1821 void * ata_io,
1822 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1823 U8 feature
1824 )
1825 {
1826 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1827
1828 sati_set_ata_command(register_fis, ATA_SET_FEATURES);
1829 sati_set_ata_features(register_fis, feature);
1830 sati_ata_non_data_command(ata_io, sequence);
1831 }
1832
1833
1834
1835 /**
1836 * @brief This method will construct a Read Log ext ATA command that
1837 * will request a log page based on the log_address.
1838 *
1839 * @param[in] log_address This parameter specifies the log page
1840 * to be returned from Read Log Ext.
1841 *
1842 * @param[in] transfer_length This parameter specifies the size of the
1843 * log page response returned by Read Log Ext.
1844 *
1845 * @return N/A
1846 *
1847 */
sati_ata_read_log_ext_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 log_address,U32 transfer_length)1848 void sati_ata_read_log_ext_construct(
1849 void * ata_io,
1850 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1851 U8 log_address,
1852 U32 transfer_length
1853 )
1854 {
1855 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1856
1857 sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
1858
1859 sati_set_ata_lba_low(register_fis, log_address);
1860 sati_set_ata_lba_mid(register_fis, 0x00);
1861 sati_set_ata_lba_mid_exp(register_fis, 0x00);
1862
1863 sati_set_ata_sector_count(register_fis, 0x01);
1864
1865 sequence->data_direction = SATI_DATA_DIRECTION_IN;
1866 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
1867 sequence->ata_transfer_length = transfer_length;
1868
1869 }
1870
1871 /**
1872 * @brief This method will check if the ATA device is in the stopped power
1873 * state. This is used for all medium access commands for SAT
1874 * compliance. See SAT2r07 section 9.11.1
1875 *
1876 * @param[in] sequence - SATI sequence data with the device state.
1877 *
1878 * @return TRUE If device is stopped
1879 *
1880 */
sati_device_state_stopped(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)1881 BOOL sati_device_state_stopped(
1882 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1883 void * scsi_io
1884 )
1885 {
1886 if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
1887 {
1888 sati_scsi_sense_data_construct(
1889 sequence,
1890 scsi_io,
1891 SCSI_STATUS_CHECK_CONDITION,
1892 SCSI_SENSE_NOT_READY ,
1893 SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
1894 SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
1895 );
1896 return TRUE;
1897 }
1898 return FALSE;
1899 }
1900
1901 /**
1902 * @brief This method will construct a ATA Read Buffer command that
1903 * will request PIO in data containing the target device's buffer.
1904 *
1905 * @param[out] ata_io This parameter specifies the ATA IO request structure
1906 * for which to build the ATA READ VERIFY SECTOR(S) command.
1907 * @param[in] sequence This parameter specifies the translator sequence
1908 * for which the command is being constructed.
1909 * @return N/A
1910 *
1911 */
sati_ata_read_buffer_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1912 void sati_ata_read_buffer_construct(
1913 void * ata_io,
1914 SATI_TRANSLATOR_SEQUENCE_T * sequence
1915 )
1916 {
1917 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1918
1919 sati_set_ata_command(register_fis, ATA_READ_BUFFER);
1920 sequence->data_direction = SATI_DATA_DIRECTION_IN;
1921 sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
1922 sequence->ata_transfer_length = 512;
1923 }
1924
1925
1926 /**
1927 * @brief This method will construct a ATA Write Buffer command that
1928 * will send PIO out data to the target device's buffer.
1929 *
1930 * @param[out] ata_io This parameter specifies the ATA IO request structure
1931 * for which to build the ATA READ VERIFY SECTOR(S) command.
1932 * @param[in] sequence This parameter specifies the translator sequence
1933 * for which the command is being constructed.
1934 * @return N/A
1935 *
1936 */
sati_ata_write_buffer_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence)1937 void sati_ata_write_buffer_construct(
1938 void * ata_io,
1939 SATI_TRANSLATOR_SEQUENCE_T * sequence
1940 )
1941 {
1942 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1943
1944 sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
1945
1946 sequence->data_direction = SATI_DATA_DIRECTION_OUT;
1947 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT;
1948 sequence->ata_transfer_length = 512;
1949 }
1950
1951
1952 /**
1953 * @brief This method will construct a ATA Download Microcode command that
1954 * will send PIO out data containing new firmware for the target drive.
1955 *
1956 * @param[out] ata_io This parameter specifies the ATA IO request structure
1957 * for which to build the ATA READ VERIFY SECTOR(S) command.
1958 * @param[in] sequence This parameter specifies the translator sequence
1959 * for which the command is being constructed.
1960 * @param[in] mode This parameter specifies the download microcode sub-command
1961 * code.
1962 * @param[in] allocation_length This parameter specifies the number of bytes
1963 * being sent to the target device.
1964 * @param[in] buffer_offset This parameter specifies the buffer offset for the
1965 * data sent to the target device.
1966 *
1967 * @return N/A
1968 *
1969 */
sati_ata_download_microcode_construct(void * ata_io,SATI_TRANSLATOR_SEQUENCE_T * sequence,U8 mode,U32 allocation_length,U32 buffer_offset)1970 void sati_ata_download_microcode_construct(
1971 void * ata_io,
1972 SATI_TRANSLATOR_SEQUENCE_T * sequence,
1973 U8 mode,
1974 U32 allocation_length,
1975 U32 buffer_offset
1976 )
1977 {
1978 U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
1979 U32 allocation_blocks = allocation_length >> 9;
1980 U32 buffer_blkoffset = buffer_offset >> 9;
1981
1982 sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
1983 sati_set_ata_features(register_fis, mode);
1984
1985 if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
1986 {
1987 sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
1988 sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
1989 }
1990 else //mode == 0x03
1991 {
1992 sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff));
1993 sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff));
1994 sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff));
1995 sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff));
1996 }
1997
1998 if((allocation_length == 0) && (buffer_offset == 0))
1999 {
2000 sati_ata_non_data_command(ata_io, sequence);
2001 }
2002 else
2003 {
2004 sequence->data_direction = SATI_DATA_DIRECTION_OUT;
2005 sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT;
2006 sequence->ata_transfer_length = allocation_length;
2007 }
2008 }
2009