config root man

Current Path : /sys/dev/isci/scil/

FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64
Upload File :
Current File : //sys/dev/isci/scil/scif_sas_controller.c

/*-
 * 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: release/9.1.0/sys/dev/isci/scil/scif_sas_controller.c 231689 2012-02-14 15:58:49Z jimharris $");

/**
 * @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;

   // Validate the user supplied parameters.
   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
   ));

   // 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;

   // Validate the user supplied parameters.
   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;

   // 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;

   // Validate the user supplied parameters.
   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;

   // Validate the user supplied parameters.
   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;

   // Validate the user supplied parameters.
   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;

   // Validate the user supplied parameters.
   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;

   // 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;
   }

   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;

   // 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

Man Man