#include <sys/cdefs.h>
#include <dev/isci/scil/sci_status.h>
#include <dev/isci/scil/sci_util.h>
#include <dev/isci/scil/sci_controller.h>
#include <dev/isci/scil/scic_controller.h>
#include <dev/isci/scil/scic_user_callback.h>
#include <dev/isci/scil/scif_user_callback.h>
#include <dev/isci/scil/scif_sas_controller.h>
#include <dev/isci/scil/scif_sas_library.h>
#include <dev/isci/scil/scif_sas_logger.h>
SCI_STATUS scif_controller_construct(
SCI_LIBRARY_HANDLE_T library,
SCI_CONTROLLER_HANDLE_T controller,
void * user_object
)
{
SCI_STATUS status = SCI_SUCCESS;
SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) library;
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
SCIF_LOG_TRACE((
sci_base_object_get_logger(library),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_controller_construct(0x%x, 0x%x) enter\n",
library, controller
));
sci_base_controller_construct(
&fw_controller->parent,
sci_base_object_get_logger(fw_library),
scif_sas_controller_state_table,
fw_controller->mdes,
SCIF_SAS_MAX_MEMORY_DESCRIPTORS,
sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object)
);
scif_sas_controller_initialize_state_logging(fw_controller);
sci_object_set_association(fw_controller, user_object);
status = scic_controller_construct(
fw_library->core_object, fw_controller->core_object, fw_controller
);
if (status == SCI_SUCCESS)
{
sci_object_set_association(
(SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller
);
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_RESET
);
}
return status;
}
SCI_STATUS scif_controller_initialize(
SCI_CONTROLLER_HANDLE_T controller
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_controller_initialize(0x%x) enter\n",
controller
));
return fw_controller->state_handlers->initialize_handler(
&fw_controller->parent
);
}
U32 scif_controller_get_suggested_start_timeout(
SCI_CONTROLLER_HANDLE_T controller
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return 0;
return scic_controller_get_suggested_start_timeout(fw_controller->core_object);
}
SCI_STATUS scif_controller_start(
SCI_CONTROLLER_HANDLE_T controller,
U32 timeout
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_controller_start(0x%x, 0x%x) enter\n",
controller, timeout
));
return fw_controller->state_handlers->
start_handler(&fw_controller->parent, timeout);
}
SCI_STATUS scif_controller_stop(
SCI_CONTROLLER_HANDLE_T controller,
U32 timeout
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"scif_controller_stop(0x%x, 0x%x) enter\n",
controller, timeout
));
return fw_controller->state_handlers->
stop_handler(&fw_controller->parent, timeout);
}
SCI_STATUS scif_controller_reset(
SCI_CONTROLLER_HANDLE_T controller
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
"scif_controller_reset(0x%x) enter\n",
controller
));
return fw_controller->state_handlers->
reset_handler(&fw_controller->parent);
}
SCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle(
SCI_CONTROLLER_HANDLE_T controller
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
return fw_controller->core_object;
}
SCI_IO_STATUS scif_controller_start_io(
SCI_CONTROLLER_HANDLE_T controller,
SCI_REMOTE_DEVICE_HANDLE_T remote_device,
SCI_IO_REQUEST_HANDLE_T io_request,
U16 io_tag
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
SCI_STATUS status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request, io_tag
));
if (
sci_pool_empty(fw_controller->hprq.pool)
|| scif_sas_controller_sufficient_resource(controller)
)
{
status = fw_controller->state_handlers->start_io_handler(
(SCI_BASE_CONTROLLER_T*) controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) io_request,
io_tag
);
}
else
status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
return (SCI_IO_STATUS)status;
}
SCI_TASK_STATUS scif_controller_start_task(
SCI_CONTROLLER_HANDLE_T controller,
SCI_REMOTE_DEVICE_HANDLE_T remote_device,
SCI_TASK_REQUEST_HANDLE_T task_request,
U16 io_tag
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
SCI_STATUS status;
if ( (controller == SCI_INVALID_HANDLE)
|| (remote_device == SCI_INVALID_HANDLE)
|| (task_request == SCI_INVALID_HANDLE) )
{
return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE;
}
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
"scif_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, task_request, io_tag
));
if (scif_sas_controller_sufficient_resource(controller))
{
status = fw_controller->state_handlers->start_task_handler(
(SCI_BASE_CONTROLLER_T*) controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) task_request,
io_tag
);
}
else
status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
return (SCI_TASK_STATUS)status;
}
SCI_STATUS scif_controller_complete_io(
SCI_CONTROLLER_HANDLE_T controller,
SCI_REMOTE_DEVICE_HANDLE_T remote_device,
SCI_IO_REQUEST_HANDLE_T io_request
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request
));
return fw_controller->state_handlers->complete_io_handler(
(SCI_BASE_CONTROLLER_T*) controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) io_request
);
}
SCI_STATUS scif_controller_complete_task(
SCI_CONTROLLER_HANDLE_T controller,
SCI_REMOTE_DEVICE_HANDLE_T remote_device,
SCI_TASK_REQUEST_HANDLE_T task_request
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if ( (controller == SCI_INVALID_HANDLE)
|| (remote_device == SCI_INVALID_HANDLE)
|| (task_request == SCI_INVALID_HANDLE) )
{
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
}
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
"scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, task_request
));
return fw_controller->state_handlers->complete_task_handler(
(SCI_BASE_CONTROLLER_T*) controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) task_request
);
}
SCI_STATUS scif_controller_get_domain_handle(
SCI_CONTROLLER_HANDLE_T controller,
U8 port_index,
SCI_DOMAIN_HANDLE_T * domain_handle
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (controller == SCI_INVALID_HANDLE)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (port_index < SCI_MAX_PORTS)
{
*domain_handle = &fw_controller->domains[port_index];
return SCI_SUCCESS;
}
return SCI_FAILURE_INVALID_PORT;
}
void scif_sas_controller_build_mdl(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
sci_base_mde_construct(
&fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
4,
fw_controller->internal_request_entries *
scif_sas_internal_request_get_object_size(),
SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
);
}
SCI_STATUS scif_controller_set_mode(
SCI_CONTROLLER_HANDLE_T controller,
SCI_CONTROLLER_MODE mode
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
SCI_STATUS status = SCI_SUCCESS;
if (
(fw_controller->parent.state_machine.current_state_id
== SCI_BASE_CONTROLLER_STATE_INITIALIZING)
|| (fw_controller->parent.state_machine.current_state_id
== SCI_BASE_CONTROLLER_STATE_INITIALIZED)
)
{
switch (mode)
{
case SCI_MODE_SPEED:
fw_controller->internal_request_entries =
MIN(fw_controller->internal_request_entries, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT);
scif_sas_controller_build_mdl(fw_controller);
break;
case SCI_MODE_SIZE:
fw_controller->internal_request_entries =
MIN(fw_controller->internal_request_entries, SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT);
scif_sas_controller_build_mdl(fw_controller);
break;
default:
status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
break;
}
}
else
status = SCI_FAILURE_INVALID_STATE;
if (status != SCI_SUCCESS)
{
return status;
}
else
{
return scic_controller_set_mode(fw_controller->core_object, mode);
}
}
U32 scif_controller_get_sat_compliance_version(
void
)
{
return 0;
}
U32 scif_controller_get_sat_compliance_version_revision(
void
)
{
return 0;
}
SCI_STATUS scif_user_parameters_set(
SCI_CONTROLLER_HANDLE_T controller,
SCIF_USER_PARAMETERS_T * scif_parms
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
if (scif_parms->sas.is_sata_ncq_enabled != 1 && scif_parms->sas.is_sata_ncq_enabled != 0)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (scif_parms->sas.max_ncq_depth < 1 || scif_parms->sas.max_ncq_depth > 32)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (scif_parms->sas.is_sata_standby_timer_enabled != 1
&& scif_parms->sas.is_sata_standby_timer_enabled != 0)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (scif_parms->sas.is_non_zero_buffer_offsets_enabled != 1
&& scif_parms->sas.is_non_zero_buffer_offsets_enabled != 0)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK
&& scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK_SET
&& scif_parms->sas.reset_type != SCI_SAS_CLEAR_TASK_SET
&& scif_parms->sas.reset_type != SCI_SAS_LOGICAL_UNIT_RESET
&& scif_parms->sas.reset_type != SCI_SAS_I_T_NEXUS_RESET
&& scif_parms->sas.reset_type != SCI_SAS_CLEAR_ACA
&& scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK
&& scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK_SET
&& scif_parms->sas.reset_type != SCI_SAS_QUERY_ASYNCHRONOUS_EVENT
&& scif_parms->sas.reset_type != SCI_SAS_HARD_RESET)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (scif_parms->sas.clear_affiliation_during_controller_stop != 1
&& scif_parms->sas.clear_affiliation_during_controller_stop !=0)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
memcpy((&fw_controller->user_parameters), scif_parms, sizeof(*scif_parms));
return SCI_SUCCESS;
}
#if !defined(DISABLE_INTERRUPTS)
static
BOOL scif_sas_controller_is_overriding_interrupt_coalescence(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
U8 index;
for(index = 0; index < SCI_MAX_DOMAINS; index++)
{
if(fw_controller->domains[index].parent.state_machine.current_state_id ==
SCI_BASE_DOMAIN_STATE_DISCOVERING)
return TRUE;
}
return FALSE;
}
SCI_STATUS scif_controller_set_interrupt_coalescence(
SCI_CONTROLLER_HANDLE_T controller,
U32 coalesce_number,
U32 coalesce_timeout
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T * )controller;
if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
{
U32 curr_coalesce_number;
U32 curr_coalesce_timeout;
SCI_STATUS core_status;
scic_controller_get_interrupt_coalescence (
fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout);
core_status = scic_controller_set_interrupt_coalescence(
fw_controller->core_object, coalesce_number, coalesce_timeout);
if ( core_status == SCI_SUCCESS )
{
fw_controller->saved_interrupt_coalesce_number = (U16)coalesce_number;
fw_controller->saved_interrupt_coalesce_timeout = coalesce_timeout;
}
scic_controller_set_interrupt_coalescence(
fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout);
return core_status;
}
else
{
return scic_controller_set_interrupt_coalescence(
fw_controller->core_object, coalesce_number, coalesce_timeout);
}
}
void scif_controller_get_interrupt_coalescence(
SCI_CONTROLLER_HANDLE_T controller,
U32 * coalesce_number,
U32 * coalesce_timeout
)
{
SCIF_SAS_CONTROLLER_T * scif_controller = (SCIF_SAS_CONTROLLER_T * )controller;
scic_controller_get_interrupt_coalescence(
scif_controller->core_object, coalesce_number, coalesce_timeout);
}
void scif_sas_controller_save_interrupt_coalescence(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
{
scic_controller_get_interrupt_coalescence(
fw_controller->core_object,
(U32*)&(fw_controller->saved_interrupt_coalesce_number),
&(fw_controller->saved_interrupt_coalesce_timeout)
);
scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0);
}
}
void scif_sas_controller_restore_interrupt_coalescence(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
scic_controller_set_interrupt_coalescence(
fw_controller->core_object,
fw_controller->saved_interrupt_coalesce_number,
fw_controller->saved_interrupt_coalesce_timeout
);
}
#endif
void scic_cb_controller_start_complete(
SCI_CONTROLLER_HANDLE_T controller,
SCI_STATUS completion_status
)
{
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
sci_object_get_association(controller);
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
controller, completion_status
));
if (completion_status == SCI_SUCCESS
|| completion_status == SCI_FAILURE_TIMEOUT)
{
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_READY
);
}
scif_cb_controller_start_complete(fw_controller, completion_status);
}
void scic_cb_controller_stop_complete(
SCI_CONTROLLER_HANDLE_T controller,
SCI_STATUS completion_status
)
{
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
sci_object_get_association(controller);
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
controller, completion_status
));
if (completion_status == SCI_SUCCESS)
{
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_STOPPED
);
}
else
{
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_FAILED
);
}
scif_cb_controller_stop_complete(fw_controller, completion_status);
}
void scic_cb_controller_error(
SCI_CONTROLLER_HANDLE_T controller,
SCI_CONTROLLER_ERROR error
)
{
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
sci_object_get_association(controller);
fw_controller->parent.error = error;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"scic_cb_controller_not_ready(0x%x) enter\n",
controller
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_FAILED
);
}
SCI_STATUS scif_sas_controller_continue_io(
SCI_CONTROLLER_HANDLE_T controller,
SCI_REMOTE_DEVICE_HANDLE_T remote_device,
SCI_IO_REQUEST_HANDLE_T io_request
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
return fw_controller->state_handlers->continue_io_handler(
(SCI_BASE_CONTROLLER_T*) controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) io_request
);
}
void scif_sas_controller_destruct(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"scif_sas_controller_destruct(0x%x) enter\n",
fw_controller
));
}
void * scif_sas_controller_allocate_internal_request(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
POINTER_UINT internal_io_address;
if( !sci_pool_empty(fw_controller->internal_request_memory_pool) )
{
sci_pool_get(
fw_controller->internal_request_memory_pool, internal_io_address
);
memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());
return (void *) internal_io_address;
}
else
return NULL;
}
void scif_sas_controller_free_internal_request(
SCIF_SAS_CONTROLLER_T * fw_controller,
void * fw_internal_request_buffer
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_controller_free_internal_request(0x%x, 0x%x) enter\n",
fw_controller, fw_internal_request_buffer
));
if( !sci_pool_full(fw_controller->internal_request_memory_pool) )
{
sci_pool_put(
fw_controller->internal_request_memory_pool,
(POINTER_UINT) fw_internal_request_buffer
);
}
}
void scif_sas_controller_start_high_priority_io(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
POINTER_UINT io_address;
SCIF_SAS_IO_REQUEST_T * fw_io;
SCI_STATUS status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_controller_start_high_priority_io(0x%x) enter\n",
fw_controller
));
while ( !sci_pool_empty(fw_controller->hprq.pool) )
{
sci_pool_get(fw_controller->hprq.pool, io_address);
fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address;
status = fw_controller->state_handlers->start_high_priority_io_handler(
(SCI_BASE_CONTROLLER_T*) fw_controller,
(SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device,
(SCI_BASE_REQUEST_T*) fw_io,
SCI_CONTROLLER_INVALID_IO_TAG
);
}
}
BOOL scif_sas_controller_sufficient_resource(
SCIF_SAS_CONTROLLER_T *fw_controller
)
{
SCIF_SAS_DOMAIN_T * fw_domain;
U32 domain_index;
U32 outstanding_io_count = 0;
U32 high_priority_io_count = 0;
for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++)
{
fw_domain = &fw_controller->domains[domain_index];
outstanding_io_count += fw_domain->request_list.element_count;
}
high_priority_io_count = sci_pool_count(fw_controller->hprq.pool);
if ( (outstanding_io_count + high_priority_io_count) > SCI_MAX_IO_REQUESTS )
return FALSE;
return TRUE;
}
SCI_STATUS scif_sas_controller_complete_high_priority_io(
SCIF_SAS_CONTROLLER_T *fw_controller,
SCIF_SAS_REMOTE_DEVICE_T *remote_device,
SCIF_SAS_REQUEST_T *io_request
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_complete_high_priority_io(0x%x, 0x%x, 0x%x) enter\n",
fw_controller, remote_device, io_request
));
return fw_controller->state_handlers->complete_high_priority_io_handler(
(SCI_BASE_CONTROLLER_T*) fw_controller,
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
(SCI_BASE_REQUEST_T*) io_request
);
}
SCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
SCIF_SAS_SMP_PHY_T * smp_phy;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"scif_controller_allocate_smp_phy(0x%x) enter\n",
fw_controller
));
if( !sci_fast_list_is_empty(&fw_controller->smp_phy_memory_list) )
{
smp_phy = (SCIF_SAS_SMP_PHY_T *)
sci_fast_list_remove_head(&fw_controller->smp_phy_memory_list);
memset((char*)smp_phy,
0,
sizeof(SCIF_SAS_SMP_PHY_T)
);
return smp_phy;
}
else
return NULL;
}
void scif_sas_controller_free_smp_phy(
SCIF_SAS_CONTROLLER_T * fw_controller,
SCIF_SAS_SMP_PHY_T * smp_phy
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"scif_controller_free_smp_phy(0x%x, 0x%x) enter\n",
fw_controller, smp_phy
));
sci_fast_list_insert_tail(
&fw_controller->smp_phy_memory_list,
&smp_phy->list_element
);
}
SCI_STATUS scif_sas_controller_clear_affiliation(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
U8 index;
SCI_STATUS status;
SCIF_SAS_DOMAIN_T * fw_domain;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"scif_sas_controller_clear_affiliation(0x%x) enter\n",
fw_controller
));
index = fw_controller->current_domain_to_clear_affiliation;
if (index < SCI_MAX_DOMAINS)
{
fw_domain = &fw_controller->domains[index];
scif_sas_domain_cancel_smp_activities(fw_domain);
scif_sas_domain_start_clear_affiliation(fw_domain);
status = SCI_WARNING_SEQUENCE_INCOMPLETE;
}
else
{
scif_sas_controller_continue_to_stop(fw_controller);
status = SCI_SUCCESS;
}
return status;
}
void scif_sas_controller_set_default_config_parameters(
SCIF_SAS_CONTROLLER_T * this_controller
)
{
SCIF_USER_PARAMETERS_T * scif_parms = &(this_controller->user_parameters);
scif_parms->sas.is_sata_ncq_enabled = TRUE;
scif_parms->sas.max_ncq_depth = 32;
scif_parms->sas.is_sata_standby_timer_enabled = FALSE;
scif_parms->sas.is_non_zero_buffer_offsets_enabled = FALSE;
scif_parms->sas.reset_type = SCI_SAS_LOGICAL_UNIT_RESET;
scif_parms->sas.clear_affiliation_during_controller_stop = TRUE;
scif_parms->sas.ignore_fua = FALSE;
}
SCI_STATUS scif_sas_controller_release_resource(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
U8 index;
SCIF_SAS_DOMAIN_T * fw_domain;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"scif_sas_controller_release_resource(0x%x) enter\n",
fw_controller
));
for (index = 0; index < SCI_MAX_DOMAINS; index++)
{
fw_domain = &fw_controller->domains[index];
scif_sas_domain_release_resource(fw_controller, fw_domain);
}
return SCI_SUCCESS;
}
#ifdef SCI_LOGGING
void scif_sas_controller_initialize_state_logging(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
sci_base_state_machine_logger_initialize(
&fw_controller->parent.state_machine_logger,
&fw_controller->parent.state_machine,
&fw_controller->parent.parent,
scif_cb_logger_log_states,
"SCIF_SAS_CONTROLLER_T", "base state machine",
SCIF_LOG_OBJECT_CONTROLLER
);
}
void scif_sas_controller_deinitialize_state_logging(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
sci_base_state_machine_logger_deinitialize(
&fw_controller->parent.state_machine_logger,
&fw_controller->parent.state_machine
);
}
#endif