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 the method definitions to translate
59 * SCSI Log Sense command based of the SATv2 spec.
60 */
61
62 #if !defined(DISABLE_SATI_LOG_SENSE)
63
64 #include <dev/isci/scil/sati_log_sense.h>
65 #include <dev/isci/scil/sati_callbacks.h>
66 #include <dev/isci/scil/sati_util.h>
67
68 //******************************************************************************
69 //* P R I V A T E M E T H O D S
70 //******************************************************************************
71
72 /**
73 * @brief This method constructs the SATI supported log page. This is a log
74 * containing the page codes of all the SATI supported log pages.
75 *
76 * @return n/a
77 *
78 */
79 static
sati_supported_log_page_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)80 void sati_supported_log_page_construct(
81 SATI_TRANSLATOR_SEQUENCE_T * sequence,
82 void * scsi_io
83 )
84 {
85 U32 next_byte;
86 //set SPF = 0 and PAGE_CODE = 0
87 sati_set_data_byte(sequence, scsi_io, 0, 0x00);
88
89 //set SUBPAGE_CODE = 0
90 sati_set_data_byte(sequence, scsi_io, 1, 0x00);
91
92 //set the Page Length to (n-3) or 2 because only two log pages are supported
93 sati_set_data_byte(sequence, scsi_io, 2, 0x00);
94 sati_set_data_byte(sequence, scsi_io, 3, 0x02);
95
96 //specify the next byte to be set
97 next_byte = 4;
98
99 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
100 {
101 sati_set_data_byte(
102 sequence,
103 scsi_io,
104 next_byte,
105 SCSI_LOG_PAGE_INFORMATION_EXCEPTION
106 );
107 next_byte = 5;
108 }
109
110 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
111 {
112 sati_set_data_byte(
113 sequence,
114 scsi_io,
115 next_byte,
116 SCSI_LOG_PAGE_SELF_TEST
117 );
118 }
119 }
120
121 /**
122 * @brief This method sets bytes 4-19 of the self-test log parameter to zero.
123 *
124 * @return n/a
125 *
126 */
127 static
sati_set_parameters_to_zero(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)128 void sati_set_parameters_to_zero(
129 SATI_TRANSLATOR_SEQUENCE_T * sequence,
130 void * scsi_io
131 )
132 {
133 sati_set_data_byte(sequence, scsi_io, 8, 0x00); //log_parameter byte 4
134 sati_set_data_byte(sequence, scsi_io, 9, 0x00); //log_parameter byte 5
135 sati_set_data_byte(sequence, scsi_io, 10, 0x00); //log_parameter byte 6
136 sati_set_data_byte(sequence, scsi_io, 11, 0x00); //log_parameter byte 7
137 sati_set_data_byte(sequence, scsi_io, 12, 0x00); //log_parameter byte 8
138 sati_set_data_byte(sequence, scsi_io, 13, 0x00); //log_parameter byte 9
139 sati_set_data_byte(sequence, scsi_io, 14, 0x00); //log_parameter byte 10
140 sati_set_data_byte(sequence, scsi_io, 15, 0x00); //log_parameter byte 11
141 sati_set_data_byte(sequence, scsi_io, 16, 0x00); //log_parameter byte 12
142 sati_set_data_byte(sequence, scsi_io, 17, 0x00); //log_parameter byte 13
143 sati_set_data_byte(sequence, scsi_io, 18, 0x00); //log_parameter byte 14
144 sati_set_data_byte(sequence, scsi_io, 19, 0x00); //log_parameter byte 15
145 sati_set_data_byte(sequence, scsi_io, 20, 0x00); //log_parameter byte 16
146 sati_set_data_byte(sequence, scsi_io, 21, 0x00); //log_parameter byte 17
147 sati_set_data_byte(sequence, scsi_io, 22, 0x00); //log_parameter byte 18
148 sati_set_data_byte(sequence, scsi_io, 23, 0x00); //log_parameter byte 19
149 }
150
151 /**
152 * @brief This method translates the ATA Extended SMART self-test log into
153 * SCSI Sense Key, Additional Sense Code, and Additional Sense code
154 * qualifiers based on the self test status byte in the appropriate
155 * descriptor entry.
156 *
157 * @return n/a
158 *
159 */
160 static
sati_translate_sense_values(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,U8 self_test_status_byte)161 void sati_translate_sense_values(
162 SATI_TRANSLATOR_SEQUENCE_T * sequence,
163 void * scsi_io,
164 U8 self_test_status_byte
165 )
166 {
167 //byte 17
168 sati_set_data_byte(
169 sequence,
170 scsi_io,
171 21,
172 SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
173 );
174
175 switch(self_test_status_byte)
176 {
177 case 1:
178 //byte 16
179 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
180
181 //byte 18
182 sati_set_data_byte(sequence, scsi_io, 22, 0x81);
183 break;
184
185 case 2:
186 //byte 16
187 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
188
189 //byte 18
190 sati_set_data_byte(sequence, scsi_io, 22, 0x82);
191 break;
192
193 case 3:
194 //byte 16
195 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
196
197 //byte 18
198 sati_set_data_byte(sequence, scsi_io, 22, 0x83);
199 break;
200
201 case 4:
202 //byte 16
203 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
204
205 //byte 18
206 sati_set_data_byte(sequence, scsi_io, 22, 0x84);
207 break;
208
209 case 5:
210 //byte 16
211 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
212
213 //byte 18
214 sati_set_data_byte(sequence, scsi_io, 22, 0x85);
215 break;
216
217 case 6:
218 //byte 16
219 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
220
221 //byte 18
222 sati_set_data_byte(sequence, scsi_io, 22, 0x86);
223 break;
224
225 case 7:
226 //byte 16
227 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
228
229 //byte 18
230 sati_set_data_byte(sequence, scsi_io, 22, 0x87);
231 break;
232
233 case 8:
234 //byte 16
235 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
236
237 //byte 18
238 sati_set_data_byte(sequence, scsi_io, 22, 0x88);
239 break;
240
241 default:
242 //byte 16
243 sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
244 //byte 17
245 sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
246 //byte 18
247 sati_set_data_byte(sequence, scsi_io, 22, 0x00);
248 break;
249 }
250
251 }
252
253 /**
254 * @brief This method retrieves the correct self-test results by checking the
255 * descriptor index in the extended SMART self-test log. The index is
256 * used to determine the appropriate descriptor entry.
257 *
258 * @return n/a
259 *
260 */
261 static
sati_get_self_test_results(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log)262 void sati_get_self_test_results(
263 SATI_TRANSLATOR_SEQUENCE_T * sequence,
264 void * scsi_io,
265 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log
266 )
267 {
268 U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
269
270 /*
271 * SATv2 wants data from descriptor N where N is equal to
272 * (descriptor_index - parameter_code) + 1. Since parameter
273 * code is always 0x0001 just checking descriptor_index.
274 */
275
276 if(descriptor_index <= 0)
277 {
278 sati_set_parameters_to_zero(sequence, scsi_io);
279 }
280 else
281 {
282 sati_set_data_byte(
283 sequence,
284 scsi_io,
285 8,
286 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
287 );
288
289 //Sef-test number unspecified per satv2
290 sati_set_data_byte(sequence, scsi_io, 9, 0x00);
291 sati_set_data_byte(
292 sequence,
293 scsi_io,
294 10,
295 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
296 );
297
298 sati_set_data_byte(
299 sequence,
300 scsi_io,
301 11,
302 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
303 );
304
305 //set to zero because it's a 48bit address
306 sati_set_data_byte(sequence, scsi_io, 12, 0x00);
307 sati_set_data_byte(sequence, scsi_io, 13, 0x00);
308
309 sati_set_data_byte(
310 sequence,
311 scsi_io,
312 14,
313 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
314 );
315
316 sati_set_data_byte(
317 sequence,
318 scsi_io,
319 15,
320 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
321 );
322
323 sati_set_data_byte(
324 sequence,
325 scsi_io,
326 16,
327 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
328 );
329
330 sati_set_data_byte(
331 sequence,
332 scsi_io,
333 17,
334 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
335 );
336
337 sati_set_data_byte(
338 sequence,
339 scsi_io,
340 18,
341 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
342 );
343
344 sati_set_data_byte(
345 sequence,
346 scsi_io,
347 19,
348 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
349 );
350
351 sati_translate_sense_values(
352 sequence,
353 scsi_io,
354 ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
355 );
356 }
357 }
358
359 /**
360 * @brief This method will construct the first eight bytes of the SCSI self test
361 * log page for both cases when SATI sends a ATA read log ext and a smart
362 * read log command.
363 *
364 * @return n/a
365 *
366 */
367 static
sati_self_test_log_header_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)368 void sati_self_test_log_header_construct(
369 SATI_TRANSLATOR_SEQUENCE_T * sequence,
370 void * scsi_io
371 )
372 {
373 //PAGE CODE for Self-Test Log Page
374 sati_set_data_byte(sequence, scsi_io, 0, 0x10);
375 sati_set_data_byte(sequence, scsi_io, 1, 0x00);
376
377 //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters
378 sati_set_data_byte(sequence, scsi_io, 2, 0x00);
379 sati_set_data_byte(sequence, scsi_io, 3, 0x14);
380
381 /*
382 * Log PARAMETER 0x0001
383 * Only sending one log parameter per self-test request.
384 */
385 sati_set_data_byte(sequence, scsi_io, 4, 0x00); //log_parameter byte 0
386 sati_set_data_byte(sequence, scsi_io, 5, 0x01); //log_parameter byte 1
387
388 //Set to 0x03 per SATv2 spec
389 sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2
390
391 //Parameter Length set to 0x10 per SATv2 spec
392 sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3
393 }
394
395 /**
396 * @brief This method will construct the SCSI self test log page from
397 * the Extended SMART self-test log response received from the
398 * ATA device. The response is from a ATA_Read_Log_EXT command
399 * issued by SATI.
400 *
401 * @return n/a
402 *
403 */
404 static
sati_extended_self_test_log_page_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_data)405 void sati_extended_self_test_log_page_construct(
406 SATI_TRANSLATOR_SEQUENCE_T * sequence,
407 void * scsi_io,
408 void * ata_data
409 )
410 {
411 ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
412 (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
413
414 sati_self_test_log_header_construct(sequence, scsi_io);
415
416 //bytes 4-19
417 if( (ata_log->self_test_descriptor_index[0] == 0) &&
418 (ata_log->self_test_descriptor_index[1] == 0))
419 {
420 sati_set_parameters_to_zero(sequence, scsi_io);
421 }
422 else
423 {
424 sati_get_self_test_results(sequence, scsi_io, ata_log);
425 }
426 }
427
428 /**
429 * @brief This method will construct the SCSI self test log page from
430 * the SMART self-test log response received from the ATA device.
431 * The response is from a ATA_SMART_Read_Log command issued by SATI.
432 *
433 * @return n/a
434 *
435 */
436 static
sati_self_test_log_page_construct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_data)437 void sati_self_test_log_page_construct(
438 SATI_TRANSLATOR_SEQUENCE_T * sequence,
439 void * scsi_io,
440 void * ata_data
441 )
442 {
443 ATA_SMART_SELF_TEST_LOG_T * ata_log =
444 (ATA_SMART_SELF_TEST_LOG_T*) ata_data;
445
446 sati_self_test_log_header_construct(sequence, scsi_io);
447
448 //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
449 sati_set_data_byte(
450 sequence,
451 scsi_io,
452 8,
453 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
454 );
455
456 //Sef-test number unspecified per satv2
457 sati_set_data_byte(sequence, scsi_io, 9, 0x00);
458
459 sati_set_data_byte(
460 sequence,
461 scsi_io,
462 10,
463 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
464 );
465
466 sati_set_data_byte(
467 sequence,
468 scsi_io,
469 11,
470 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
471 );
472
473 //set to zero because it's a 28bit address
474 sati_set_data_byte(sequence, scsi_io, 12, 0x00);
475 sati_set_data_byte(sequence, scsi_io, 13, 0x00);
476 sati_set_data_byte(sequence, scsi_io, 14, 0x00);
477 sati_set_data_byte(sequence, scsi_io, 15, 0x00);
478
479 sati_set_data_byte(
480 sequence,
481 scsi_io,
482 16,
483 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
484 );
485
486 sati_set_data_byte(
487 sequence,
488 scsi_io,
489 17,
490 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
491 );
492
493 sati_set_data_byte(
494 sequence,
495 scsi_io,
496 18,
497 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
498 );
499
500 sati_set_data_byte(
501 sequence,
502 scsi_io,
503 19,
504 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
505 );
506
507 sati_translate_sense_values(
508 sequence,
509 scsi_io,
510 ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
511 );
512 }
513
514 /**
515 * @brief This method will construct the SCSI information exception log page from
516 * the ATA SMART response received from the ATA device. The response is
517 * from a ATA SMART return status command issued by SATI.
518 *
519 * @return n/a
520 *
521 */
522 static
sati_information_exception_log_page_contruct(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)523 void sati_information_exception_log_page_contruct(
524 SATI_TRANSLATOR_SEQUENCE_T * sequence,
525 void * scsi_io,
526 void * ata_io
527 )
528 {
529 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
530 U32 mid_register = sati_get_ata_lba_mid(register_fis);
531 U32 high_register = sati_get_ata_lba_high(register_fis);
532
533 //Information Exception Page code
534 sati_set_data_byte(
535 sequence,
536 scsi_io,
537 0,
538 SCSI_LOG_PAGE_INFORMATION_EXCEPTION
539 );
540
541 //Sub-page code
542 sati_set_data_byte(sequence, scsi_io, 1, 0x00);
543
544 //Page length of log parameters
545 sati_set_data_byte(sequence, scsi_io, 2, 0x00);
546 sati_set_data_byte(sequence, scsi_io, 3, 0x08);
547
548 //parameter code
549 sati_set_data_byte(sequence, scsi_io, 4, 0x00);
550 sati_set_data_byte(sequence, scsi_io, 5, 0x00);
551
552 //Format and Linking
553 sati_set_data_byte(sequence, scsi_io, 6, 0x03);
554 //Parameter Length
555 sati_set_data_byte(sequence, scsi_io, 7, 0x04);
556
557 if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
558 && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
559 {
560 sati_set_data_byte(
561 sequence,
562 scsi_io,
563 8,
564 SCSI_ASC_HARDWARE_IMPENDING_FAILURE
565 );
566
567 sati_set_data_byte(
568 sequence,
569 scsi_io,
570 9,
571 SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
572 );
573 }
574 else
575 {
576 sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE);
577 sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE);
578 }
579 //setting most recent temperature reading to 0xFF(not supported) for now.
580 sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
581 }
582
583 //******************************************************************************
584 //* P U B L I C M E T H O D S
585 //******************************************************************************
586
587 /**
588 * @brief This method will translate the SCSI Log Sense command into ATA commands
589 * specified by SATv2. ATA commands Read Log EXT and SMART Read Log will
590 * be issued by this translation.
591 *
592 * @return SATI_STATUS Indicates if the command translation succeeded.
593 *
594 */
sati_log_sense_translate_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)595 SATI_STATUS sati_log_sense_translate_command(
596 SATI_TRANSLATOR_SEQUENCE_T * sequence,
597 void * scsi_io,
598 void * ata_io
599 )
600 {
601 U8 * cdb = sati_cb_get_cdb_address(scsi_io);
602 SATI_STATUS status = SATI_FAILURE;
603
604 if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
605 (sati_get_cdb_byte(cdb, 3) == 0))
606 {
607 sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
608 (sati_get_cdb_byte(cdb, 8));
609
610 switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
611 {
612 //Return Supported Log Pages log page
613 case SCSI_LOG_PAGE_SUPPORTED_PAGES :
614 sati_supported_log_page_construct(sequence, scsi_io);
615 sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE;
616 status = SATI_COMPLETE;
617 break;
618
619 //Return Self-Test Results log page
620 case SCSI_LOG_PAGE_SELF_TEST :
621
622 if((sequence->device->capabilities &
623 SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
624 {
625 sati_scsi_sense_data_construct(
626 sequence,
627 scsi_io,
628 SCSI_STATUS_CHECK_CONDITION,
629 SCSI_SENSE_ILLEGAL_REQUEST,
630 SCSI_ASC_INVALID_FIELD_IN_CDB,
631 SCSI_ASCQ_INVALID_FIELD_IN_CDB
632 );
633 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
634 }
635 else
636 {
637 //check if 48-bit Address feature set is supported
638 if((sequence->device->capabilities &
639 SATI_DEVICE_CAP_48BIT_ENABLE))
640 {
641 //ATA Read Log Ext with log address set to 0x07
642 sati_ata_read_log_ext_construct(
643 ata_io,
644 sequence,
645 ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
646 sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
647 );
648 sequence->type =
649 SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
650 status = SATI_SUCCESS;
651 }
652 else
653 {
654 //ATA Smart Read Log with log address set to 0x06
655 sati_ata_smart_read_log_construct(
656 ata_io,
657 sequence,
658 ATA_LOG_PAGE_SMART_SELF_TEST,
659 sizeof(ATA_SMART_SELF_TEST_LOG_T)
660 );
661 sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
662 status = SATI_SUCCESS;
663 }
664 }
665 break;
666
667 //Return Informational Exceptions log page
668 case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
669 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
670 {
671 if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
672 {
673 sati_ata_smart_return_status_construct(
674 ata_io,
675 sequence,
676 ATA_SMART_SUB_CMD_RETURN_STATUS
677 );
678 sequence->type =
679 SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
680 status = SATI_SUCCESS;
681 }
682 else
683 {
684 sati_scsi_sense_data_construct(
685 sequence,
686 scsi_io,
687 SCSI_STATUS_CHECK_CONDITION,
688 SCSI_SENSE_ABORTED_COMMAND,
689 SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED,
690 SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED
691 );
692
693 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
694 }
695 }
696 else
697 {
698 sati_scsi_sense_data_construct(
699 sequence,
700 scsi_io,
701 SCSI_STATUS_CHECK_CONDITION,
702 SCSI_SENSE_ILLEGAL_REQUEST,
703 SCSI_ASC_INVALID_FIELD_IN_CDB,
704 SCSI_ASCQ_INVALID_FIELD_IN_CDB
705 );
706
707 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
708 }
709 break;
710 default :
711 //UNSPECIFIED SATv2r9
712 sati_scsi_sense_data_construct(
713 sequence,
714 scsi_io,
715 SCSI_STATUS_CHECK_CONDITION,
716 SCSI_SENSE_ILLEGAL_REQUEST,
717 SCSI_ASC_NO_ADDITIONAL_SENSE ,
718 SCSI_ASCQ_NO_ADDITIONAL_SENSE
719 );
720 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
721 break;
722 }
723 }
724 return status;
725 }
726
727 /**
728 * @brief This method will translate the response to the SATI Log Sense
729 * translation. ATA command responses will be translated into the
730 * correct SCSI log pages to be returned by SATI.
731 *
732 * @return SATI_STATUS Indicates if the response translation succeeded.
733 *
734 */
sati_log_sense_translate_response(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)735 SATI_STATUS sati_log_sense_translate_response(
736 SATI_TRANSLATOR_SEQUENCE_T * sequence,
737 void * scsi_io,
738 void * ata_io
739 )
740 {
741 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
742 SATI_STATUS status = SATI_FAILURE;
743
744 if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
745 {
746 sati_scsi_sense_data_construct(
747 sequence,
748 scsi_io,
749 SCSI_STATUS_CHECK_CONDITION,
750 SCSI_SENSE_ABORTED_COMMAND,
751 SCSI_ASC_NO_ADDITIONAL_SENSE ,
752 SCSI_ASCQ_NO_ADDITIONAL_SENSE
753 );
754 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
755 }
756 else
757 {
758
759 void * ata_data = sati_cb_get_ata_data_address(ata_io);
760
761 if(ata_data == NULL)
762 {
763 return SATI_FAILURE;
764 }
765
766 switch(sequence->type)
767 {
768 case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
769 sati_extended_self_test_log_page_construct(
770 sequence, scsi_io, ata_data
771 );
772
773 status = SATI_COMPLETE;
774 break;
775
776 case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
777 sati_self_test_log_page_construct(sequence, scsi_io, ata_data);
778 status = SATI_COMPLETE;
779 break;
780
781 case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
782 //This function needs a d->h register fis, not ata data
783 sati_information_exception_log_page_contruct(
784 sequence, scsi_io, ata_io
785 );
786
787 status = SATI_COMPLETE;
788 break;
789
790 default:
791 sati_scsi_sense_data_construct(
792 sequence,
793 scsi_io,
794 SCSI_STATUS_CHECK_CONDITION,
795 SCSI_SENSE_ABORTED_COMMAND,
796 SCSI_ASC_NO_ADDITIONAL_SENSE ,
797 SCSI_ASCQ_NO_ADDITIONAL_SENSE
798 );
799 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
800 break;
801 }
802 }
803 return status;
804 }
805
806 #endif // !defined(DISABLE_SATI_LOG_SENSE)
807
808