f11c7f6305
The isci driver is for the integrated SAS controller in the Intel C600 (Patsburg) chipset. Source files in sys/dev/isci directory are FreeBSD-specific, and sys/dev/isci/scil subdirectory contains an OS-agnostic library (SCIL) published by Intel to control the SAS controller. This library is used primarily as-is in this driver, with some post-processing to better integrate into the kernel build environment. isci.4 and a README in the sys/dev/isci directory contain a few additional details. This driver is only built for amd64 and i386 targets. Sponsored by: Intel Reviewed by: scottl Approved by: scottl
808 lines
24 KiB
C
808 lines
24 KiB
C
/*-
|
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
|
* redistributing this file, you may do so under either license.
|
|
*
|
|
* GPL LICENSE SUMMARY
|
|
*
|
|
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
* The full GNU General Public License is included in this distribution
|
|
* in the file called LICENSE.GPL.
|
|
*
|
|
* BSD LICENSE
|
|
*
|
|
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
/**
|
|
* @file
|
|
* @brief This file contains the method definitions to translate
|
|
* SCSI Log Sense command based of the SATv2 spec.
|
|
*/
|
|
|
|
#if !defined(DISABLE_SATI_LOG_SENSE)
|
|
|
|
#include <dev/isci/scil/sati_log_sense.h>
|
|
#include <dev/isci/scil/sati_callbacks.h>
|
|
#include <dev/isci/scil/sati_util.h>
|
|
|
|
//******************************************************************************
|
|
//* P R I V A T E M E T H O D S
|
|
//******************************************************************************
|
|
|
|
/**
|
|
* @brief This method constructs the SATI supported log page. This is a log
|
|
* containing the page codes of all the SATI supported log pages.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_supported_log_page_construct(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io
|
|
)
|
|
{
|
|
U32 next_byte;
|
|
//set SPF = 0 and PAGE_CODE = 0
|
|
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
|
|
|
|
//set SUBPAGE_CODE = 0
|
|
sati_set_data_byte(sequence, scsi_io, 1, 0x00);
|
|
|
|
//set the Page Length to (n-3) or 2 because only two log pages are supported
|
|
sati_set_data_byte(sequence, scsi_io, 2, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 3, 0x02);
|
|
|
|
//specify the next byte to be set
|
|
next_byte = 4;
|
|
|
|
if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
|
|
{
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
next_byte,
|
|
SCSI_LOG_PAGE_INFORMATION_EXCEPTION
|
|
);
|
|
next_byte = 5;
|
|
}
|
|
|
|
if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
|
|
{
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
next_byte,
|
|
SCSI_LOG_PAGE_SELF_TEST
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This method sets bytes 4-19 of the self-test log parameter to zero.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_set_parameters_to_zero(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io
|
|
)
|
|
{
|
|
sati_set_data_byte(sequence, scsi_io, 8, 0x00); //log_parameter byte 4
|
|
sati_set_data_byte(sequence, scsi_io, 9, 0x00); //log_parameter byte 5
|
|
sati_set_data_byte(sequence, scsi_io, 10, 0x00); //log_parameter byte 6
|
|
sati_set_data_byte(sequence, scsi_io, 11, 0x00); //log_parameter byte 7
|
|
sati_set_data_byte(sequence, scsi_io, 12, 0x00); //log_parameter byte 8
|
|
sati_set_data_byte(sequence, scsi_io, 13, 0x00); //log_parameter byte 9
|
|
sati_set_data_byte(sequence, scsi_io, 14, 0x00); //log_parameter byte 10
|
|
sati_set_data_byte(sequence, scsi_io, 15, 0x00); //log_parameter byte 11
|
|
sati_set_data_byte(sequence, scsi_io, 16, 0x00); //log_parameter byte 12
|
|
sati_set_data_byte(sequence, scsi_io, 17, 0x00); //log_parameter byte 13
|
|
sati_set_data_byte(sequence, scsi_io, 18, 0x00); //log_parameter byte 14
|
|
sati_set_data_byte(sequence, scsi_io, 19, 0x00); //log_parameter byte 15
|
|
sati_set_data_byte(sequence, scsi_io, 20, 0x00); //log_parameter byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 21, 0x00); //log_parameter byte 17
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x00); //log_parameter byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 23, 0x00); //log_parameter byte 19
|
|
}
|
|
|
|
/**
|
|
* @brief This method translates the ATA Extended SMART self-test log into
|
|
* SCSI Sense Key, Additional Sense Code, and Additional Sense code
|
|
* qualifiers based on the self test status byte in the appropriate
|
|
* descriptor entry.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_translate_sense_values(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
U8 self_test_status_byte
|
|
)
|
|
{
|
|
//byte 17
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
21,
|
|
SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
|
|
);
|
|
|
|
switch(self_test_status_byte)
|
|
{
|
|
case 1:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x81);
|
|
break;
|
|
|
|
case 2:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x82);
|
|
break;
|
|
|
|
case 3:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x83);
|
|
break;
|
|
|
|
case 4:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x84);
|
|
break;
|
|
|
|
case 5:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x85);
|
|
break;
|
|
|
|
case 6:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x86);
|
|
break;
|
|
|
|
case 7:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x87);
|
|
break;
|
|
|
|
case 8:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
|
|
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x88);
|
|
break;
|
|
|
|
default:
|
|
//byte 16
|
|
sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
|
|
//byte 17
|
|
sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
|
|
//byte 18
|
|
sati_set_data_byte(sequence, scsi_io, 22, 0x00);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief This method retrieves the correct self-test results by checking the
|
|
* descriptor index in the extended SMART self-test log. The index is
|
|
* used to determine the appropriate descriptor entry.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_get_self_test_results(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log
|
|
)
|
|
{
|
|
U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
|
|
|
|
/*
|
|
* SATv2 wants data from descriptor N where N is equal to
|
|
* (descriptor_index - parameter_code) + 1. Since parameter
|
|
* code is always 0x0001 just checking descriptor_index.
|
|
*/
|
|
|
|
if(descriptor_index <= 0)
|
|
{
|
|
sati_set_parameters_to_zero(sequence, scsi_io);
|
|
}
|
|
else
|
|
{
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
8,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
|
|
);
|
|
|
|
//Sef-test number unspecified per satv2
|
|
sati_set_data_byte(sequence, scsi_io, 9, 0x00);
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
10,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
11,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
|
|
);
|
|
|
|
//set to zero because it's a 48bit address
|
|
sati_set_data_byte(sequence, scsi_io, 12, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 13, 0x00);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
14,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
15,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
16,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
17,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
18,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
19,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
|
|
);
|
|
|
|
sati_translate_sense_values(
|
|
sequence,
|
|
scsi_io,
|
|
ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This method will construct the first eight bytes of the SCSI self test
|
|
* log page for both cases when SATI sends a ATA read log ext and a smart
|
|
* read log command.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_self_test_log_header_construct(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io
|
|
)
|
|
{
|
|
//PAGE CODE for Self-Test Log Page
|
|
sati_set_data_byte(sequence, scsi_io, 0, 0x10);
|
|
sati_set_data_byte(sequence, scsi_io, 1, 0x00);
|
|
|
|
//PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters
|
|
sati_set_data_byte(sequence, scsi_io, 2, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 3, 0x14);
|
|
|
|
/*
|
|
* Log PARAMETER 0x0001
|
|
* Only sending one log parameter per self-test request.
|
|
*/
|
|
sati_set_data_byte(sequence, scsi_io, 4, 0x00); //log_parameter byte 0
|
|
sati_set_data_byte(sequence, scsi_io, 5, 0x01); //log_parameter byte 1
|
|
|
|
//Set to 0x03 per SATv2 spec
|
|
sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2
|
|
|
|
//Parameter Length set to 0x10 per SATv2 spec
|
|
sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3
|
|
}
|
|
|
|
/**
|
|
* @brief This method will construct the SCSI self test log page from
|
|
* the Extended SMART self-test log response recieved from the
|
|
* ATA device. The response is from a ATA_Read_Log_EXT command
|
|
* issued by SATI.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_extended_self_test_log_page_construct(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
void * ata_data
|
|
)
|
|
{
|
|
ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
|
|
(ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
|
|
|
|
sati_self_test_log_header_construct(sequence, scsi_io);
|
|
|
|
//bytes 4-19
|
|
if( (ata_log->self_test_descriptor_index[0] == 0) &&
|
|
(ata_log->self_test_descriptor_index[1] == 0))
|
|
{
|
|
sati_set_parameters_to_zero(sequence, scsi_io);
|
|
}
|
|
else
|
|
{
|
|
sati_get_self_test_results(sequence, scsi_io, ata_log);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This method will construct the SCSI self test log page from
|
|
* the SMART self-test log response recieved from the ATA device.
|
|
* The response is from a ATA_SMART_Read_Log command issued by SATI.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_self_test_log_page_construct(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
void * ata_data
|
|
)
|
|
{
|
|
ATA_SMART_SELF_TEST_LOG_T * ata_log =
|
|
(ATA_SMART_SELF_TEST_LOG_T*) ata_data;
|
|
|
|
sati_self_test_log_header_construct(sequence, scsi_io);
|
|
|
|
//first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
8,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
|
|
);
|
|
|
|
//Sef-test number unspecified per satv2
|
|
sati_set_data_byte(sequence, scsi_io, 9, 0x00);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
10,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
11,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
|
|
);
|
|
|
|
//set to zero because it's a 28bit address
|
|
sati_set_data_byte(sequence, scsi_io, 12, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 13, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 14, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 15, 0x00);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
16,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
17,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
18,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
19,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
|
|
);
|
|
|
|
sati_translate_sense_values(
|
|
sequence,
|
|
scsi_io,
|
|
ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @brief This method will construct the SCSI information exception log page from
|
|
* the ATA SMART response recieved from the ATA device. The response is
|
|
* from a ATA SMART return status command issued by SATI.
|
|
*
|
|
* @return n/a
|
|
*
|
|
*/
|
|
static
|
|
void sati_information_exception_log_page_contruct(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
void * ata_io
|
|
)
|
|
{
|
|
U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
|
|
U32 mid_register = sati_get_ata_lba_mid(register_fis);
|
|
U32 high_register = sati_get_ata_lba_high(register_fis);
|
|
|
|
//Information Exception Page code
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
0,
|
|
SCSI_LOG_PAGE_INFORMATION_EXCEPTION
|
|
);
|
|
|
|
//Sub-page code
|
|
sati_set_data_byte(sequence, scsi_io, 1, 0x00);
|
|
|
|
//Page length of log parameters
|
|
sati_set_data_byte(sequence, scsi_io, 2, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 3, 0x08);
|
|
|
|
//parameter code
|
|
sati_set_data_byte(sequence, scsi_io, 4, 0x00);
|
|
sati_set_data_byte(sequence, scsi_io, 5, 0x00);
|
|
|
|
//Format and Linking
|
|
sati_set_data_byte(sequence, scsi_io, 6, 0x03);
|
|
//Parameter Length
|
|
sati_set_data_byte(sequence, scsi_io, 7, 0x04);
|
|
|
|
if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
|
|
&& high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
|
|
{
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
8,
|
|
SCSI_ASC_HARDWARE_IMPENDING_FAILURE
|
|
);
|
|
|
|
sati_set_data_byte(
|
|
sequence,
|
|
scsi_io,
|
|
9,
|
|
SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
|
|
);
|
|
}
|
|
else
|
|
{
|
|
sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE);
|
|
sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE);
|
|
}
|
|
//setting most recent temperature reading to 0xFF(not supported) for now.
|
|
sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
|
|
}
|
|
|
|
//******************************************************************************
|
|
//* P U B L I C M E T H O D S
|
|
//******************************************************************************
|
|
|
|
/**
|
|
* @brief This method will translate the SCSI Log Sense command into ATA commands
|
|
* specified by SATv2. ATA commands Read Log EXT and SMART Read Log will
|
|
* be issued by this translation.
|
|
*
|
|
* @return SATI_STATUS Indicates if the command translation succeeded.
|
|
*
|
|
*/
|
|
SATI_STATUS sati_log_sense_translate_command(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
void * ata_io
|
|
)
|
|
{
|
|
U8 * cdb = sati_cb_get_cdb_address(scsi_io);
|
|
SATI_STATUS status = SATI_FAILURE;
|
|
|
|
if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
|
|
(sati_get_cdb_byte(cdb, 3) == 0))
|
|
{
|
|
sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
|
|
(sati_get_cdb_byte(cdb, 8));
|
|
|
|
switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
|
|
{
|
|
//Return Supported Log Pages log page
|
|
case SCSI_LOG_PAGE_SUPPORTED_PAGES :
|
|
sati_supported_log_page_construct(sequence, scsi_io);
|
|
sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE;
|
|
status = SATI_COMPLETE;
|
|
break;
|
|
|
|
//Return Self-Test Results log page
|
|
case SCSI_LOG_PAGE_SELF_TEST :
|
|
|
|
if((sequence->device->capabilities &
|
|
SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
|
|
{
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ILLEGAL_REQUEST,
|
|
SCSI_ASC_INVALID_FIELD_IN_CDB,
|
|
SCSI_ASCQ_INVALID_FIELD_IN_CDB
|
|
);
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
}
|
|
else
|
|
{
|
|
//check if 48-bit Address feature set is supported
|
|
if((sequence->device->capabilities &
|
|
SATI_DEVICE_CAP_48BIT_ENABLE))
|
|
{
|
|
//ATA Read Log Ext with log address set to 0x07
|
|
sati_ata_read_log_ext_construct(
|
|
ata_io,
|
|
sequence,
|
|
ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
|
|
sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
|
|
);
|
|
sequence->type =
|
|
SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
|
|
status = SATI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//ATA Smart Read Log with log address set to 0x06
|
|
sati_ata_smart_read_log_construct(
|
|
ata_io,
|
|
sequence,
|
|
ATA_LOG_PAGE_SMART_SELF_TEST,
|
|
sizeof(ATA_SMART_SELF_TEST_LOG_T)
|
|
);
|
|
sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
|
|
status = SATI_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//Return Informational Exceptions log page
|
|
case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
|
|
if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
|
|
{
|
|
if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
|
|
{
|
|
sati_ata_smart_return_status_construct(
|
|
ata_io,
|
|
sequence,
|
|
ATA_SMART_SUB_CMD_RETURN_STATUS
|
|
);
|
|
sequence->type =
|
|
SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
|
|
status = SATI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ABORTED_COMMAND,
|
|
SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED,
|
|
SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED
|
|
);
|
|
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ILLEGAL_REQUEST,
|
|
SCSI_ASC_INVALID_FIELD_IN_CDB,
|
|
SCSI_ASCQ_INVALID_FIELD_IN_CDB
|
|
);
|
|
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
}
|
|
break;
|
|
default :
|
|
//UNSPECIFIED SATv2r9
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ILLEGAL_REQUEST,
|
|
SCSI_ASC_NO_ADDITIONAL_SENSE ,
|
|
SCSI_ASCQ_NO_ADDITIONAL_SENSE
|
|
);
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
break;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief This method will translate the response to the SATI Log Sense
|
|
* translation. ATA command responses will be translated into the
|
|
* correct SCSI log pages to be returned by SATI.
|
|
*
|
|
* @return SATI_STATUS Indicates if the response translation succeeded.
|
|
*
|
|
*/
|
|
SATI_STATUS sati_log_sense_translate_response(
|
|
SATI_TRANSLATOR_SEQUENCE_T * sequence,
|
|
void * scsi_io,
|
|
void * ata_io
|
|
)
|
|
{
|
|
U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
|
|
SATI_STATUS status = SATI_FAILURE;
|
|
|
|
if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
|
|
{
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ABORTED_COMMAND,
|
|
SCSI_ASC_NO_ADDITIONAL_SENSE ,
|
|
SCSI_ASCQ_NO_ADDITIONAL_SENSE
|
|
);
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
}
|
|
else
|
|
{
|
|
|
|
void * ata_data = sati_cb_get_ata_data_address(ata_io);
|
|
|
|
if(ata_data == NULL)
|
|
{
|
|
return SATI_FAILURE;
|
|
}
|
|
|
|
switch(sequence->type)
|
|
{
|
|
case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
|
|
sati_extended_self_test_log_page_construct(
|
|
sequence, scsi_io, ata_data
|
|
);
|
|
|
|
status = SATI_COMPLETE;
|
|
break;
|
|
|
|
case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
|
|
sati_self_test_log_page_construct(sequence, scsi_io, ata_data);
|
|
status = SATI_COMPLETE;
|
|
break;
|
|
|
|
case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
|
|
//This function needs a d->h register fis, not ata data
|
|
sati_information_exception_log_page_contruct(
|
|
sequence, scsi_io, ata_io
|
|
);
|
|
|
|
status = SATI_COMPLETE;
|
|
break;
|
|
|
|
default:
|
|
sati_scsi_sense_data_construct(
|
|
sequence,
|
|
scsi_io,
|
|
SCSI_STATUS_CHECK_CONDITION,
|
|
SCSI_SENSE_ABORTED_COMMAND,
|
|
SCSI_ASC_NO_ADDITIONAL_SENSE ,
|
|
SCSI_ASCQ_NO_ADDITIONAL_SENSE
|
|
);
|
|
status = SATI_FAILURE_CHECK_RESPONSE_DATA;
|
|
break;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
#endif // !defined(DISABLE_SATI_LOG_SENSE)
|
|
|