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