#include <sys/cdefs.h>
#include <dev/isci/scil/scif_sas_stp_io_request.h>
#include <dev/isci/scil/scif_sas_stp_remote_device.h>
#include <dev/isci/scil/scif_sas_logger.h>
#include <dev/isci/scil/scif_sas_controller.h>
#include <dev/isci/scil/sci_status.h>
#include <dev/isci/scil/scic_io_request.h>
#include <dev/isci/scil/sati.h>
#include <dev/isci/scil/sati_atapi.h>
#include <dev/isci/scil/intel_sat.h>
#include <dev/isci/scil/sati_util.h>
#include <dev/isci/scil/sati_callbacks.h>
static
SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
SCIF_LOG_TRACE((
sci_base_object_get_logger(io_request),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
io_request
));
if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
{
SATA_FIS_REG_H2D_T * fis;
fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
fw_io->parent.device
);
if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
scic_stp_io_request_set_ncq_tag(
fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
);
}
return SCI_SUCCESS;
}
static
SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
SCIF_LOG_TRACE((
sci_base_object_get_logger(io_request),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
io_request
));
if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
{
if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
scif_sas_stp_remote_device_free_ncq_tag(
fw_io->parent.device, fw_io->parent.stp.ncq_tag
);
}
sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
return SCI_SUCCESS;
}
static
SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
SCIF_SAS_REQUEST_T * fw_request,
SCI_STATUS * completion_status
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
fw_controller, fw_device, fw_request, *completion_status
));
if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
scif_sas_stp_remote_device_free_ncq_tag(
fw_request->device, fw_io->parent.stp.ncq_tag
);
if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
((sati_cb_do_translate_response(fw_request)) &&
(*completion_status != SCI_FAILURE_IO_TERMINATED)))
{
SATI_STATUS sati_status = sati_translate_command_response(
&fw_io->parent.stp.sequence, fw_io, fw_io
);
if (sati_status == SATI_COMPLETE)
*completion_status = SCI_SUCCESS;
else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
*completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
{
return SCI_WARNING_SEQUENCE_INCOMPLETE;
}
else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
*completion_status = SCI_SUCCESS_IO_DONE_EARLY;
else
{
*completion_status = SCI_FAILURE;
}
}
else if (*completion_status != SCI_SUCCESS)
{
SCIF_LOG_INFO((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_IO_REQUEST,
"Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
fw_controller, fw_device, fw_request
));
sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
}
return SCI_SUCCESS;
}
#if !defined(DISABLE_ATAPI)
static
SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
SCIF_SAS_REQUEST_T * fw_request,
SCI_STATUS * completion_status
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
SATI_STATUS sati_status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
fw_controller, fw_device, fw_request, *completion_status
));
if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
{
sati_status = sati_atapi_translate_command_response(
&fw_io->parent.stp.sequence, fw_io, fw_io
);
if (sati_status == SATI_COMPLETE)
*completion_status = SCI_SUCCESS;
else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
*completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
{
return SCI_WARNING_SEQUENCE_INCOMPLETE;
}
else
{
*completion_status = SCI_FAILURE;
}
}
else if (*completion_status == SCI_SUCCESS &&
fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
{
sati_atapi_translate_request_sense_response(
&fw_io->parent.stp.sequence, fw_io, fw_io
);
*completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
}
return SCI_SUCCESS;
}
#endif
SCI_STATUS scif_sas_stp_io_request_construct(
SCIF_SAS_IO_REQUEST_T * fw_io
)
{
SATI_STATUS sati_status;
SCI_STATUS sci_status = SCI_FAILURE;
SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_io_request_construct(0x%x) enter\n",
fw_io
));
sati_status = sati_translate_command(
&fw_io->parent.stp.sequence,
&fw_device->protocol_device.stp_device.sati_device,
fw_io,
fw_io
);
if (sati_status == SATI_SUCCESS)
{
sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
fw_io->parent.protocol_complete_handler
= scif_sas_stp_core_cb_io_request_complete_handler;
}
else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
{
SCIC_IO_SATA_PARAMETERS_T parms;
parms.do_translate_sgl = FALSE;
scic_io_request_construct_advanced_sata(
fw_io->parent.core_object, &parms
);
fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
fw_io->parent.protocol_complete_handler
= scif_sas_stp_core_cb_io_request_complete_handler;
sci_status = SCI_SUCCESS;
}
else if (sati_status == SATI_COMPLETE)
sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
else
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"Unexpected SAT translation failure 0x%x\n",
fw_io
));
}
return sci_status;
}
#if !defined(DISABLE_ATAPI)
SCI_STATUS scif_sas_stp_packet_io_request_construct(
SCIF_SAS_IO_REQUEST_T * fw_io
)
{
SATI_STATUS sati_status;
SCI_STATUS sci_status = SCI_FAILURE;
SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
fw_io
));
sati_status = sati_atapi_translate_command(
&fw_io->parent.stp.sequence,
&fw_device->protocol_device.stp_device.sati_device,
fw_io,
fw_io
);
if (sati_status == SATI_SUCCESS)
{
sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
fw_io->parent.protocol_complete_handler
= scif_sas_stp_core_cb_packet_io_request_complete_handler;
}
else if (sati_status == SATI_COMPLETE)
sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
else
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"Unexpected SAT ATAPI translation failure 0x%x\n",
fw_io
));
}
return sci_status;
}
#endif
#if !defined(DISABLE_ATAPI)
U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
SCIF_SAS_IO_REQUEST_T * fw_io
)
{
SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
U32 actual_data_length;
if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
actual_data_length = 0;
else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
{
actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
&fw_io->parent.stp.sequence, fw_io, fw_io);
if (actual_data_length == 0)
actual_data_length =
scic_io_request_get_number_of_bytes_transferred(scic_io);
}
else
actual_data_length =
scic_io_request_get_number_of_bytes_transferred(scic_io);
return actual_data_length;
}
#endif
BOOL scic_cb_io_request_do_copy_rx_frames(
void * scic_user_io_request
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
fw_io
));
if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
{
if (
(fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_12)
|| (fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_16)
|| (
(fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
&& (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
)
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_io),
SCIF_LOG_OBJECT_IO_REQUEST,
"scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
fw_io
));
return TRUE;
}
}
return FALSE;
}
U8 scic_cb_request_get_sat_protocol(
void * scic_user_io_request
)
{
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
return fw_io->parent.stp.sequence.protocol;
}
U8 *scic_cb_io_request_get_virtual_address_from_sgl(
void * scic_user_io_request,
U32 byte_offset
)
{
SCIF_SAS_REQUEST_T *fw_request =
(SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
return scif_cb_io_request_get_virtual_address_from_sgl(
sci_object_get_association(fw_request),
byte_offset
);
}
#ifdef ENABLE_OSSL_COPY_BUFFER
void scic_cb_io_request_copy_buffer(
void * scic_user_io_request,
U8 *source_addr,
U32 offset,
U32 length
)
{
SCIF_SAS_REQUEST_T *fw_request =
(SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
return scif_cb_io_request_copy_buffer(
sci_object_get_association(fw_request),
source_addr,
offset,
length
);
}
#endif
SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
{
scif_sas_stp_io_request_constructed_start_handler,
scif_sas_io_request_constructed_abort_handler,
scif_sas_stp_io_request_constructed_complete_handler,
scif_sas_io_request_default_destruct_handler
};