#include <sys/cdefs.h>
#include <dev/isci/scil/scif_sas_smp_io_request.h>
#include <dev/isci/scil/scif_sas_logger.h>
#include <dev/isci/scil/scif_sas_controller.h>
#include <dev/isci/scil/sci_controller.h>
#include <dev/isci/scil/sci_status.h>
#include <dev/isci/scil/scic_io_request.h>
#include <dev/isci/scil/scic_user_callback.h>
#include <dev/isci/scil/intel_sas.h>
void scif_sas_smp_request_construct(
SCIF_SAS_REQUEST_T * fw_request,
SMP_REQUEST_T * smp_command
)
{
void * command_iu_address =
scic_io_request_get_command_iu_address(fw_request->core_object);
memcpy( (char*) command_iu_address,
smp_command,
sizeof(SMP_REQUEST_T)
);
scic_io_request_construct_smp(fw_request->core_object);
fw_request->protocol_complete_handler
= NULL;
}
static
void scif_sas_smp_protocol_request_construct(
SMP_REQUEST_T * smp_request,
U8 smp_function,
U8 smp_response_length,
U8 smp_request_length
)
{
memset((char*)smp_request, 0, sizeof(SMP_REQUEST_T));
smp_request->header.smp_frame_type = SMP_FRAME_TYPE_REQUEST;
smp_request->header.function = smp_function;
smp_request->header.allocated_response_length = smp_response_length;
smp_request->header.request_length = smp_request_length;
}
static
void * scif_sas_smp_request_build(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
SMP_REQUEST_T * smp_request,
void * external_request_object,
void * external_memory
)
{
if (external_memory != NULL && external_request_object != NULL)
{
scif_sas_io_request_construct_smp(
fw_controller,
fw_device,
external_memory,
(char *)external_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
SCI_CONTROLLER_INVALID_IO_TAG,
smp_request,
external_request_object
);
return external_memory;
}
else
{
void * internal_io_memory;
internal_io_memory = scif_sas_controller_allocate_internal_request(fw_controller);
ASSERT(internal_io_memory != NULL);
if (internal_io_memory != NULL)
{
scif_sas_internal_io_request_construct_smp(
fw_controller,
fw_device,
internal_io_memory,
SCI_CONTROLLER_INVALID_IO_TAG,
smp_request
);
}
else
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_smp_request_build, no memory available!\n"
));
}
return internal_io_memory;
}
}
void * scif_sas_smp_request_construct_report_general(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
SMP_REQUEST_T smp_report_general;
scif_sas_smp_protocol_request_construct(
&smp_report_general,
SMP_FUNCTION_REPORT_GENERAL,
sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32),
0
);
smp_report_general.request.report_general.crc = 0;
SCIF_LOG_INFO((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"SMP REPORT GENERAL - Device:0x%x\n",
fw_device
));
return scif_sas_smp_request_build(
fw_controller, fw_device, &smp_report_general, NULL, NULL);
}
void * scif_sas_smp_request_construct_report_manufacturer_info(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
SMP_REQUEST_T smp_report_manufacturer_info;
scif_sas_smp_protocol_request_construct(
&smp_report_manufacturer_info,
SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION,
sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32),
0
);
smp_report_manufacturer_info.request.report_general.crc = 0;
SCIF_LOG_INFO((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"SMP REPORT MANUFACTURER_INFO - Device:0x%x\n",
fw_device
));
return scif_sas_smp_request_build(
fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL
);
}
void * scif_sas_smp_request_construct_discover(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
U8 phy_identifier,
void * external_request_object,
void * external_memory
)
{
SMP_REQUEST_T smp_discover;
scif_sas_smp_protocol_request_construct(
&smp_discover,
SMP_FUNCTION_DISCOVER,
sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32),
sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
);
smp_discover.request.discover.phy_identifier = phy_identifier;
SCIF_LOG_INFO((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"SMP DISCOVER - Device:0x%x PhyId:0x%x\n",
fw_device, phy_identifier
));
return scif_sas_smp_request_build(
fw_controller, fw_device, &smp_discover,
external_request_object, external_memory
);
}
void * scif_sas_smp_request_construct_report_phy_sata(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
U8 phy_identifier
)
{
SMP_REQUEST_T report_phy_sata;
scif_sas_smp_protocol_request_construct(
&report_phy_sata,
SMP_FUNCTION_REPORT_PHY_SATA,
sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32),
sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
);
report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier;
SCIF_LOG_INFO((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n",
fw_device, phy_identifier
));
return scif_sas_smp_request_build(
fw_controller, fw_device, &report_phy_sata, NULL, NULL);
}
void * scif_sas_smp_request_construct_phy_control(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_REMOTE_DEVICE_T * fw_device,
U8 phy_operation,
U8 phy_identifier,
void * external_request_object,
void * external_memory
)
{
SMP_REQUEST_T phy_control;
scif_sas_smp_protocol_request_construct(
&phy_control,
SMP_FUNCTION_PHY_CONTROL,
0,
sizeof(SMP_REQUEST_PHY_CONTROL_T) / sizeof(U32)
);
phy_control.request.phy_control.phy_operation = phy_operation;
phy_control.request.phy_control.phy_identifier = phy_identifier;
return scif_sas_smp_request_build(
fw_controller, fw_device, &phy_control,
external_request_object, external_memory
);
}
void * scif_sas_smp_request_construct_config_route_info(
struct SCIF_SAS_CONTROLLER * fw_controller,
struct SCIF_SAS_REMOTE_DEVICE * fw_device,
U8 phy_id,
U16 route_index,
SCI_SAS_ADDRESS_T destination_sas_address,
BOOL disable_expander_route_entry
)
{
SMP_REQUEST_T config_route_info;
scif_sas_smp_protocol_request_construct(
&config_route_info,
SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION,
0,
sizeof(SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T) / sizeof(U32)
);
config_route_info.request.configure_route_information.phy_identifier = phy_id;
config_route_info.request.configure_route_information.expander_route_index_high =
((route_index & 0xff00) >> 8);
config_route_info.request.configure_route_information.expander_route_index =
route_index & 0xff;
config_route_info.request.configure_route_information.routed_sas_address[0] =
destination_sas_address.high;
config_route_info.request.configure_route_information.routed_sas_address[1] =
destination_sas_address.low;
if (disable_expander_route_entry == TRUE)
config_route_info.request.configure_route_information.disable_route_entry = 1;
return scif_sas_smp_request_build(
fw_controller, fw_device, &config_route_info,
NULL, NULL
);
}
SCI_STATUS scif_sas_smp_internal_request_retry(
SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
SCIF_SAS_CONTROLLER_T * fw_controller;
SCIF_SAS_IO_REQUEST_T * new_io;
void * new_request_memory = NULL;
U8 retry_count = fw_device->protocol_device.smp_device.io_retry_count;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"scif_sas_smp_internal_request_retry(0x%x, 0x%x) time %d!\n",
fw_device, retry_count
));
fw_controller = fw_device->domain->controller;
switch (fw_device->protocol_device.smp_device.current_smp_request)
{
case SMP_FUNCTION_REPORT_GENERAL:
new_request_memory = scif_sas_smp_request_construct_report_general(
fw_controller, fw_device
);
break;
case SMP_FUNCTION_DISCOVER:
new_request_memory = scif_sas_smp_request_construct_discover(
fw_controller, fw_device,
fw_device->protocol_device.smp_device.current_activity_phy_index,
NULL, NULL
);
break;
case SMP_FUNCTION_REPORT_PHY_SATA:
new_request_memory = scif_sas_smp_request_construct_report_phy_sata(
fw_controller, fw_device,
fw_device->protocol_device.smp_device.current_activity_phy_index
);
break;
default:
break;
}
if (new_request_memory != NULL)
{
new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
new_io->retry_count = ++retry_count;
scif_cb_start_internal_io_task_schedule(
fw_controller,
scif_sas_controller_start_high_priority_io,
fw_controller
);
return SCI_SUCCESS;
}
else
return SCI_FAILURE_INSUFFICIENT_RESOURCES;
}
SCI_STATUS scif_sas_smp_external_request_retry(
SCIF_SAS_IO_REQUEST_T * old_io
)
{
SCIF_SAS_REMOTE_DEVICE_T * fw_device = old_io->parent.device;
SCIF_SAS_CONTROLLER_T * fw_controller;
SCIF_SAS_IO_REQUEST_T * new_io;
void * new_request_memory = NULL;
U8 retry_count = old_io->retry_count;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_device),
SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
"scif_sas_smp_external_request_retry(0x%x) time %d!\n",
old_io
));
fw_controller = fw_device->domain->controller;
sci_fast_list_remove_element(&old_io->parent.list_element);
switch (fw_device->protocol_device.smp_device.current_smp_request)
{
case SMP_FUNCTION_DISCOVER:
new_request_memory = scif_sas_smp_request_construct_discover(
fw_controller, fw_device,
fw_device->protocol_device.smp_device.current_activity_phy_index,
(void *)sci_object_get_association(old_io),
(void *)old_io
);
break;
case SMP_FUNCTION_PHY_CONTROL:
new_request_memory = scif_sas_smp_request_construct_phy_control(
fw_controller, fw_device, PHY_OPERATION_HARD_RESET,
fw_device->protocol_device.smp_device.current_activity_phy_index,
(void *)sci_object_get_association(old_io),
(void *)old_io
);
break;
default:
return SCI_FAILURE;
}
new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
new_io->retry_count = ++retry_count;
sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_request_memory);
scif_cb_start_internal_io_task_schedule(
fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
);
return SCI_SUCCESS;
}