2012-01-31 19:38:18 +00:00
|
|
|
/*-
|
|
|
|
* 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 implementation of the SCIF_SAS_CONTROLLER
|
|
|
|
* object.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#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>
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
//* P U B L I C M E T H O D S
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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
|
|
|
|
));
|
|
|
|
|
|
|
|
// Construct the base controller. As part of constructing the base
|
|
|
|
// controller we ask it to also manage the MDL iteration for the Core.
|
|
|
|
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 the core controller was successfully constructed, then
|
|
|
|
// finish construction of the framework controller.
|
|
|
|
if (status == SCI_SUCCESS)
|
|
|
|
{
|
|
|
|
// Set the association in the core controller to this framework
|
|
|
|
// controller.
|
|
|
|
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;
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Currently we aren't adding any additional time into the suggested
|
|
|
|
// timeout value for the start operation. Simply utilize the core
|
|
|
|
// value.
|
|
|
|
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;
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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;
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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;
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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;
|
2012-02-09 17:50:24 +00:00
|
|
|
SCI_STATUS status;
|
2012-01-31 19:38:18 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
)
|
|
|
|
{
|
2012-02-09 17:50:24 +00:00
|
|
|
status = fw_controller->state_handlers->start_io_handler(
|
2012-01-31 19:38:18 +00:00
|
|
|
(SCI_BASE_CONTROLLER_T*) controller,
|
|
|
|
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
|
|
|
|
(SCI_BASE_REQUEST_T*) io_request,
|
|
|
|
io_tag
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
2012-02-09 17:50:24 +00:00
|
|
|
status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
|
|
|
|
|
|
|
|
return (SCI_IO_STATUS)status;
|
2012-01-31 19:38:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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;
|
2012-02-09 17:50:24 +00:00
|
|
|
SCI_STATUS status;
|
2012-01-31 19:38:18 +00:00
|
|
|
|
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if ( (controller == SCI_INVALID_HANDLE)
|
|
|
|
|| (remote_device == SCI_INVALID_HANDLE)
|
|
|
|
|| (task_request == SCI_INVALID_HANDLE) )
|
|
|
|
{
|
2012-02-09 17:50:24 +00:00
|
|
|
return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE;
|
2012-01-31 19:38:18 +00:00
|
|
|
}
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
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
|
|
|
|
));
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
if (scif_sas_controller_sufficient_resource(controller))
|
|
|
|
{
|
2012-02-09 17:50:24 +00:00
|
|
|
status = fw_controller->state_handlers->start_task_handler(
|
2012-01-31 19:38:18 +00:00
|
|
|
(SCI_BASE_CONTROLLER_T*) controller,
|
|
|
|
(SCI_BASE_REMOTE_DEVICE_T*) remote_device,
|
|
|
|
(SCI_BASE_REQUEST_T*) task_request,
|
|
|
|
io_tag
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
2012-02-09 17:50:24 +00:00
|
|
|
status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
|
|
|
|
|
|
|
|
return (SCI_TASK_STATUS)status;
|
2012-01-31 19:38:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if ( (controller == SCI_INVALID_HANDLE)
|
|
|
|
|| (remote_device == SCI_INVALID_HANDLE)
|
|
|
|
|| (task_request == SCI_INVALID_HANDLE) )
|
|
|
|
{
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
}
|
|
|
|
|
2012-02-07 17:45:11 +00:00
|
|
|
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
|
|
|
|
));
|
|
|
|
|
2012-01-31 19:38:18 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
// Validate the user supplied parameters.
|
|
|
|
if (controller == SCI_INVALID_HANDLE)
|
|
|
|
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
|
|
|
|
|
|
|
// Retrieve the domain handle if the supplied index is legitimate.
|
|
|
|
if (port_index < SCI_MAX_PORTS)
|
|
|
|
{
|
|
|
|
*domain_handle = &fw_controller->domains[port_index];
|
|
|
|
return SCI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SCI_FAILURE_INVALID_PORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method builds the memory descriptor list for this
|
|
|
|
* controller.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller This parameter specifies the framework
|
|
|
|
* controller object for which to build the MDL.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
void scif_sas_controller_build_mdl(
|
|
|
|
SCIF_SAS_CONTROLLER_T * fw_controller
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// one internal request for each domain.
|
|
|
|
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
|
|
|
|
{
|
|
|
|
// Currently, the framework doesn't change any configurations for
|
|
|
|
// speed or size modes. Default to speed mode basically.
|
|
|
|
return scic_controller_set_mode(fw_controller->core_object, mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
U32 scif_controller_get_sat_compliance_version(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/// @todo Fix return of SAT compliance version.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
U32 scif_controller_get_sat_compliance_version_revision(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/// @todo Fix return of SAT compliance revision.
|
|
|
|
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;
|
|
|
|
|
|
|
|
//validate all the registry entries before overwriting the default parameter
|
|
|
|
//values.
|
|
|
|
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));
|
|
|
|
|
|
|
|
// In the future more could be done to prevent setting parameters at the
|
|
|
|
// wrong time, but for now we'll simply set the values even if it is too
|
|
|
|
// late for them to take affect.
|
|
|
|
return SCI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#if !defined(DISABLE_INTERRUPTS)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This routine check each domain of the controller to see if
|
|
|
|
* any domain is overriding interrupt coalescence.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller frame controller
|
|
|
|
* @param[in] fw_smp_phy The smp phy to be freed.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
|
|
|
|
///when framework is in the middle of temporarily overriding the interrupt
|
|
|
|
///coalescence values, user's request of setting interrupt coalescence
|
|
|
|
///will be saved. As soon as the framework done the temporary overriding,
|
|
|
|
///it will serve user's request to set new interrupt coalescence.
|
|
|
|
if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
|
|
|
|
{
|
|
|
|
U32 curr_coalesce_number;
|
|
|
|
U32 curr_coalesce_timeout;
|
|
|
|
SCI_STATUS core_status;
|
|
|
|
|
|
|
|
// save current interrupt coalescence info.
|
|
|
|
scic_controller_get_interrupt_coalescence (
|
|
|
|
fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout);
|
|
|
|
|
|
|
|
//try user's request out in the core, but immediately restore core's
|
|
|
|
//current setting.
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
//restore current interrupt coalescence.
|
|
|
|
scic_controller_set_interrupt_coalescence(
|
|
|
|
fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout);
|
|
|
|
|
|
|
|
return core_status;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
///If framework is not internally overriding the interrupt coalescence,
|
|
|
|
///serve user's request immediately by passing the reqeust to core.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method will save the interrupt coalescence values. If
|
|
|
|
* the interrupt coalescence values have already been saved,
|
|
|
|
* then this method performs no operations.
|
|
|
|
*
|
|
|
|
* @param[in,out] fw_controller This parameter specifies the controller
|
|
|
|
* for which to save the interrupt coalescence values.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
void scif_sas_controller_save_interrupt_coalescence(
|
|
|
|
SCIF_SAS_CONTROLLER_T * fw_controller
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
|
|
|
|
{
|
|
|
|
// Override core's interrupt coalescing settings during SMP
|
|
|
|
// DISCOVER process cause' there is only 1 outstanding SMP
|
|
|
|
// request per domain is allowed.
|
|
|
|
scic_controller_get_interrupt_coalescence(
|
|
|
|
fw_controller->core_object,
|
|
|
|
(U32*)&(fw_controller->saved_interrupt_coalesce_number),
|
|
|
|
&(fw_controller->saved_interrupt_coalesce_timeout)
|
|
|
|
);
|
|
|
|
|
|
|
|
// Temporarily disable the interrupt coalescing.
|
|
|
|
scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method will restore the interrupt coalescence values. If
|
|
|
|
* the interrupt coalescence values have not already been saved,
|
|
|
|
* then this method performs no operations.
|
|
|
|
*
|
|
|
|
* @param[in,out] fw_controller This parameter specifies the controller
|
|
|
|
* for which to restore the interrupt coalescence values.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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 // !defined(DISABLE_INTERRUPTS)
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// Even the initialization of the core controller timed out, framework
|
|
|
|
// controller should still transit to READY state.
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
//* P R O T E C T E D M E T H O D S
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method is utilized to continue an internal IO operation
|
|
|
|
* on the controller. This method is utilized for SAT translated
|
|
|
|
* requests that generate multiple ATA commands in order to fulfill
|
|
|
|
* the original SCSI request.
|
|
|
|
*
|
|
|
|
* @param[in] controller This parameter specifies the controller on which
|
|
|
|
* to continue an internal IO request.
|
|
|
|
* @param[in] remote_device This parameter specifies the remote device
|
|
|
|
* on which to continue an internal IO request.
|
|
|
|
* @param[in] io_request This parameter specifies the IO request to be
|
|
|
|
* continue.
|
|
|
|
*
|
|
|
|
* @return Indicate if the continue operation was successful.
|
|
|
|
* @retval SCI_SUCCESS This value is returned if the operation succeeded.
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method will attempt to destruct a framework controller.
|
|
|
|
* This includes free any resources retreived from the user (e.g.
|
|
|
|
* timers).
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller This parameter specifies the framework
|
|
|
|
* controller to destructed.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// INTERNAL REQUEST RELATED METHODS
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This routine is to allocate the memory for creating a new internal
|
|
|
|
* request.
|
|
|
|
*
|
|
|
|
* @param[in] scif_controller handle to frame controller
|
|
|
|
*
|
|
|
|
* @return void* address to internal request memory
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
);
|
|
|
|
|
|
|
|
//clean the memory.
|
|
|
|
memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());
|
|
|
|
|
|
|
|
return (void *) internal_io_address;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This routine is to free the memory for a completed internal request.
|
|
|
|
*
|
|
|
|
* @param[in] scif_controller handle to frame controller
|
|
|
|
* @param[in] fw_internal_io The internal IO to be freed.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
));
|
|
|
|
|
|
|
|
//return the memory to to pool.
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief this routine is called by OS' DPC to start io requests from internal
|
|
|
|
* high priority request queue
|
|
|
|
* @param[in] fw_controller The framework controller.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method will check how many outstanding IOs currently and number
|
|
|
|
* of IOs in high priority queue, if the overall number exceeds the max_tc,
|
|
|
|
* return FALSE.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller The framework controller.
|
|
|
|
*
|
|
|
|
* @return BOOL Indicate whether there is sufficient resource to start an IO.
|
|
|
|
* @retvalue TRUE The controller has sufficient resource.
|
|
|
|
* @retvalue FALSE There is not sufficient resource available.
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method is the starting point to complete high prority io for a
|
|
|
|
* controller then down to domain, device.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller The framework controller
|
|
|
|
* @param[in] remote_device The framework remote device.
|
|
|
|
* @param[in] io_request The high priority io request to be completed.
|
|
|
|
*
|
|
|
|
* @return SCI_STATUS indicate the completion status from framework down to the
|
|
|
|
* core.
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
));
|
|
|
|
|
|
|
|
//call controller's new added complete_high_priority_io_handler
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief This routine is to allocate the memory for creating a smp phy object.
|
|
|
|
*
|
|
|
|
* @param[in] scif_controller handle to frame controller
|
|
|
|
*
|
|
|
|
* @return SCIF_SAS_SMP_PHY_T * An allocated space for smp phy. If failed to allocate,
|
|
|
|
* return NULL.
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
|
|
|
|
//clean the memory.
|
|
|
|
memset((char*)smp_phy,
|
|
|
|
0,
|
|
|
|
sizeof(SCIF_SAS_SMP_PHY_T)
|
|
|
|
);
|
|
|
|
|
|
|
|
return smp_phy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This routine is to free the memory for a released smp phy.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller The framework controller, a smp phy is released
|
|
|
|
* to its memory.
|
|
|
|
* @param[in] fw_smp_phy The smp phy to be freed.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
));
|
|
|
|
|
|
|
|
//return the memory to the list.
|
|
|
|
sci_fast_list_insert_tail(
|
|
|
|
&fw_controller->smp_phy_memory_list,
|
|
|
|
&smp_phy->list_element
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method clear affiliation for all the EA SATA devices associated
|
|
|
|
* to this controller.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller This parameter specifies the framework
|
|
|
|
* controller object for whose remote devices are to be stopped.
|
|
|
|
*
|
|
|
|
* @return This method returns a value indicating if the operation completed.
|
|
|
|
* @retval SCI_COMPLETE This value indicates that all the EA SATA devices'
|
|
|
|
* affiliation was cleared.
|
|
|
|
* @retval SCI_INCOMPLETE This value indicates clear affiliation activity is
|
|
|
|
* yet to be completed.
|
|
|
|
*/
|
|
|
|
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];
|
|
|
|
|
|
|
|
//Need to stop all the on-going smp activities before clearing affiliation.
|
|
|
|
scif_sas_domain_cancel_smp_activities(fw_domain);
|
|
|
|
|
|
|
|
scif_sas_domain_start_clear_affiliation(fw_domain);
|
|
|
|
|
|
|
|
status = SCI_WARNING_SEQUENCE_INCOMPLETE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ //the controller has done clear affiliation work to all its domains.
|
|
|
|
scif_sas_controller_continue_to_stop(fw_controller);
|
|
|
|
status = SCI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method sets SCIF user parameters to
|
|
|
|
* default values. Users can override these values utilizing
|
|
|
|
* the sciF_user_parameters_set() methods.
|
|
|
|
*
|
|
|
|
* @param[in] controller This parameter specifies the controller for
|
|
|
|
* which to set the configuration parameters to their
|
|
|
|
* default values.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This method releases resource for framework controller and associated
|
|
|
|
* objects.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller This parameter specifies the framework
|
|
|
|
* controller and associated objects whose resources are to be released.
|
|
|
|
*
|
|
|
|
* @return This method returns a value indicating if the operation succeeded.
|
|
|
|
* @retval SCI_SUCCESS This value indicates that resource release succeeded.
|
|
|
|
* @retval SCI_FAILURE This value indicates certain failure during the process
|
|
|
|
* of resource release.
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
));
|
|
|
|
|
|
|
|
//currently the only resource to be released is domain's timer.
|
|
|
|
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
|
|
|
|
/**
|
|
|
|
* This method will start state transition logging for the framework
|
|
|
|
* controller object.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller The framework controller object on which to
|
|
|
|
* observe state changes.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method will remove the logging of state transitions from the framework
|
|
|
|
* controller object.
|
|
|
|
*
|
|
|
|
* @param[in] fw_controller The framework controller to change.
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
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 // SCI_LOGGING
|