#include <sys/cdefs.h>
#if !defined(DISABLE_SATI_INQUIRY)
#include <dev/isci/scil/sati_inquiry.h>
#include <dev/isci/scil/sati_callbacks.h>
#include <dev/isci/scil/sati_util.h>
#include <dev/isci/scil/intel_ata.h>
#include <dev/isci/scil/intel_scsi.h>
static
void sati_inquiry_construct_product_revision(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
ata_input_data;
if ( (identify->firmware_revision[4] == 0x20)
&& (identify->firmware_revision[5] == 0x20)
&& (identify->firmware_revision[6] == 0x20)
&& (identify->firmware_revision[7] == 0x20) )
{
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
32,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision),
4,
TRUE
);
}
else
{
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
32,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4,
4,
TRUE
);
}
}
void sati_inquiry_standard_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
ata_input_data;
U32 index;
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
sati_set_data_byte(sequence, scsi_io, 1, 0x80);
else
sati_set_data_byte(sequence, scsi_io, 1, 0x00);
sati_set_data_byte(sequence, scsi_io, 2, 0x05);
sati_set_data_byte(sequence, scsi_io, 3, 0x02);
sati_set_data_byte(sequence, scsi_io, 4, 62);
sati_set_data_byte(sequence, scsi_io, 5, 0x00);
sati_set_data_byte(sequence, scsi_io, 6, 0x00);
sati_set_data_byte(sequence, scsi_io, 7, 0x02);
sati_set_data_byte(sequence, scsi_io, 8, 0x41);
sati_set_data_byte(sequence, scsi_io, 9, 0x54);
sati_set_data_byte(sequence, scsi_io, 10, 0x41);
sati_set_data_byte(sequence, scsi_io, 11, 0x20);
sati_set_data_byte(sequence, scsi_io, 12, 0x20);
sati_set_data_byte(sequence, scsi_io, 13, 0x20);
sati_set_data_byte(sequence, scsi_io, 14, 0x20);
sati_set_data_byte(sequence, scsi_io, 15, 0x20);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
16,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
16,
TRUE
);
sati_inquiry_construct_product_revision(
sequence,
ata_input_data,
scsi_io
);
for (index = 36; index < 58; index++)
sati_set_data_byte(sequence, scsi_io, index, 0);
sati_set_data_byte(sequence, scsi_io, 58, 0);
sati_set_data_byte(sequence, scsi_io, 59, 0x80);
sati_set_data_byte(sequence, scsi_io, 60, 0x0C);
sati_set_data_byte(sequence, scsi_io, 61, 0x20);
sati_set_data_byte(sequence, scsi_io, 62, 0x04);
sati_set_data_byte(sequence, scsi_io, 63, 0x60);
sati_set_data_byte(sequence, scsi_io, 64, 0x04);
sati_set_data_byte(sequence, scsi_io, 65, 0xC0);
sati_set_data_byte(sequence, scsi_io, 66, 0x16);
sati_set_data_byte(sequence, scsi_io, 67, 0x23);
}
static
void sati_inquiry_supported_pages_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io
)
{
sati_set_data_byte(sequence, scsi_io, 0, 0);
sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
sati_set_data_byte(sequence, scsi_io, 2, 0);
sati_set_data_byte(sequence, scsi_io, 3, 4);
sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE);
sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
sati_set_data_byte(sequence, scsi_io, 9, 0);
}
void sati_inquiry_serial_number_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
sati_set_data_byte(sequence, scsi_io, 2, 0x00);
sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
4,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
ATA_IDENTIFY_SERIAL_NUMBER_LEN,
TRUE
);
}
void sati_inquiry_block_device_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
ata_input_data;
U32 offset;
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
sati_set_data_byte(sequence, scsi_io, 2, 0x00);
sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
4,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate),
2,
FALSE
);
sati_set_data_byte(sequence, scsi_io, 6, 0x00);
sati_set_data_byte(
sequence,
scsi_io,
7,
(identify->device_nominal_form_factor & 0x0F)
);
for(offset = 8; offset < 64; offset++)
{
sati_set_data_byte(sequence, scsi_io, offset, 0x00);
}
}
void sati_inquiry_device_id_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
ata_input_data;
U16 byte_offset = 4;
U16 page_length;
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE);
if (identify->command_set_supported_extention
& ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE)
{
sati_set_data_byte(sequence,
scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
);
sati_set_data_byte(sequence,
scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE
);
sati_set_data_byte(sequence, scsi_io, 6, 0);
sati_set_data_byte(sequence, scsi_io, 7, 0x08);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
8,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name),
ATA_IDENTIFY_WWN_LEN,
FALSE
);
byte_offset = 16;
}
sati_set_data_byte(sequence,
scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET
);
byte_offset++;
sati_set_data_byte(sequence,
scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE
);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
byte_offset++;
sati_set_data_byte(
sequence,
scsi_io,
byte_offset,
8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN)
);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
byte_offset++;
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
byte_offset,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
ATA_IDENTIFY_MODEL_NUMBER_LEN,
TRUE
);
byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN;
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
byte_offset,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
ATA_IDENTIFY_SERIAL_NUMBER_LEN,
TRUE
);
byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN;
#if defined(SATI_TRANSPORT_SUPPORTS_SAS) \
&& defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT)
{
SCI_SAS_ADDRESS_T sas_address;
sati_set_data_byte(
sequence,
scsi_io,
byte_offset,
SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
);
byte_offset++;
sati_set_data_byte(
sequence,
scsi_io,
byte_offset,
SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION |
SCSI_NAA_IDENTIFIER_TYPE
);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
byte_offset++;
sati_set_data_byte(sequence, scsi_io, byte_offset, 8);
byte_offset++;
sati_cb_device_get_sas_address(scsi_io, &sas_address);
sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high);
byte_offset += 4;
sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low);
byte_offset += 4;
}
#endif
page_length = byte_offset - 4;
sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8));
sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF));
}
SATI_STATUS sati_inquiry_ata_information_translate_data(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * ata_input_data,
void * scsi_io
)
{
sati_set_data_byte(sequence, scsi_io, 0, 0x00);
sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
sati_set_data_byte(sequence, scsi_io, 2, 0x02);
sati_set_data_byte(sequence, scsi_io, 3, 0x38);
sati_set_data_byte(sequence, scsi_io, 4, 0x00);
sati_set_data_byte(sequence, scsi_io, 5, 0x00);
sati_set_data_byte(sequence, scsi_io, 6, 0x00);
sati_set_data_byte(sequence, scsi_io, 7, 0x00);
sati_set_data_byte(sequence, scsi_io, 8, 0x41);
sati_set_data_byte(sequence, scsi_io, 9, 0x54);
sati_set_data_byte(sequence, scsi_io, 10, 0x41);
sati_set_data_byte(sequence, scsi_io, 11, 0x20);
sati_set_data_byte(sequence, scsi_io, 12, 0x20);
sati_set_data_byte(sequence, scsi_io, 13, 0x20);
sati_set_data_byte(sequence, scsi_io, 14, 0x20);
sati_set_data_byte(sequence, scsi_io, 15, 0x20);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
16,
ata_input_data,
ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
16,
TRUE
);
sati_inquiry_construct_product_revision(
sequence,
ata_input_data,
scsi_io
);
sati_set_data_byte(sequence, scsi_io, 56, 0xEC);
sati_set_data_byte(sequence, scsi_io, 57, 0x00);
sati_set_data_byte(sequence, scsi_io, 58, 0x00);
sati_set_data_byte(sequence, scsi_io, 59, 0x00);
sati_ata_identify_device_copy_data(
sequence,
scsi_io,
60,
ata_input_data,
0,
sizeof(ATA_IDENTIFY_DEVICE_DATA_T),
FALSE
);
sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
return SATI_SEQUENCE_INCOMPLETE;
}
SATI_STATUS sati_inquiry_translate_command(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
void * ata_io
)
{
U8 * cdb = sati_cb_get_cdb_address(scsi_io);
if ( ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0)
&& (sati_get_cdb_byte(cdb, 2) != 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
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
}
sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) |
(sati_get_cdb_byte(cdb, 4));
if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE)
{
switch (sati_get_cdb_byte(cdb, 2))
{
case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE:
sequence->type = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES;
sati_inquiry_supported_pages_translate_data(sequence, scsi_io);
return SATI_COMPLETE;
break;
case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE:
sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER;
break;
case SCSI_INQUIRY_DEVICE_ID_PAGE:
sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID;
break;
case SCSI_INQUIRY_ATA_INFORMATION_PAGE:
if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
{
sati_ata_execute_device_diagnostic_construct(
ata_io,
sequence
);
sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG;
}
else
{
sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION;
}
break;
case SCSI_INQUIRY_BLOCK_DEVICE_PAGE:
sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE;
break;
default:
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
);
return SATI_FAILURE_CHECK_RESPONSE_DATA;
break;
}
}
else
{
sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD;
}
sati_ata_identify_device_construct(ata_io, sequence);
return SATI_SUCCESS;
}
void sati_inquiry_ata_information_finish_translation(
SATI_TRANSLATOR_SEQUENCE_T * sequence,
void * scsi_io,
void * ata_io
)
{
U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
U32 offset;
sati_set_data_byte(sequence, scsi_io, 36, 0x34);
sati_set_data_byte(sequence, scsi_io, 37, 0x00);
sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis));
sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis));
sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis));
sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis));
sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis));
sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis));
sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis));
sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis));
sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis));
sati_set_data_byte(sequence, scsi_io, 47, 0x00);
sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis));
sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis));
for(offset = 50; offset < 56; offset++)
{
sati_set_data_byte(sequence, scsi_io, offset, 0x00);
}
sequence->state = SATI_SEQUENCE_STATE_FINAL;
}
#endif