linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] isci: core
@ 2011-03-10 10:54 Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 01/10] isci/core: controller Dan Williams
                   ` (12 more replies)
  0 siblings, 13 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

As first introduced in "[RFC PATCH 0/6] isci: initial driver release
(part1: intro and lldd) " [1], the isci driver is split into an lldd
layer that interfaces with libsas and a core layer that interfaces with
the hardware.  Quoting from the original introduction:

   Driver overview:
   The hardware accelerates all the protocol fast paths (SSP, STP
   FPDMA and UDMA), and relies on the the driver for everything
   else.  One example is legacy sata pio reads which are managed
   "manually" by their own state machine in the driver.  The driver
   submits the read and when the data fis comes back the hardware,
   not having acceleration for pio operations, assigns it to an
   unidentified frame queue.  The core then associates that frame
   with the pending pio request, copies the data into the location
   specified by the original sgl, and completes the command up to
   the lldd.

Since the initial import the core has shed about 10k lines of code.
The todo list has also shrunk, we have eliminated the os abstractions
(formerly in drivers/scsi/isci/deprecated.c), and usages of phys_to_virt
and virt_to_phys have been replaced with proper dma api and kmap calls.

The full driver and history is available in git:

   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git master

The libsas-pending branch contains proposed libsas fixes (pending
acceptance into scsi-misc):

   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git libsas-pending

The x86-pending branch contains a proposed api for mapping bios roms so
the driver can retrieve configuration parameters (pending acceptance
into -tip):

   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git x86-pending

--
Dan for the isci driver team


[1]: http://marc.info/?l=linux-scsi&m=129703780424729&w=2

---

Dan Williams (10):
      isci/core: controller
      isci/core: phy
      isci/core: port
      isci/core: remote device
      isci/core: remote node context
      isci/core: stp
      isci/core: request (general, ssp and smp)
      isci/core: unsolicited frame handling and registers
      isci/core: base state machine and memory descriptors
      isci/core: common definitions and utility functions


 drivers/scsi/isci/core/intel_ata.h                 |  554 +++
 drivers/scsi/isci/core/intel_sas.h                 |  948 +++++
 drivers/scsi/isci/core/intel_sat.h                 |   95 
 drivers/scsi/isci/core/intel_sata.h                |  280 +
 drivers/scsi/isci/core/intel_scsi.h                |  474 ++
 drivers/scsi/isci/core/sati_device.h               |  156 +
 drivers/scsi/isci/core/sati_translator_sequence.h  |  304 ++
 drivers/scsi/isci/core/sati_types.h                |  145 +
 drivers/scsi/isci/core/sci_base_controller.h       |  306 ++
 .../isci/core/sci_base_memory_descriptor_list.c    |  159 +
 .../isci/core/sci_base_memory_descriptor_list.h    |  153 +
 drivers/scsi/isci/core/sci_base_phy.h              |  200 +
 drivers/scsi/isci/core/sci_base_port.h             |  203 +
 drivers/scsi/isci/core/sci_base_remote_device.h    |  274 +
 drivers/scsi/isci/core/sci_base_request.h          |  195 +
 drivers/scsi/isci/core/sci_base_state.h            |   90 
 drivers/scsi/isci/core/sci_base_state_machine.c    |  182 +
 drivers/scsi/isci/core/sci_base_state_machine.h    |  141 +
 drivers/scsi/isci/core/sci_controller.h            |   98 +
 drivers/scsi/isci/core/sci_controller_constants.h  |  215 +
 .../scsi/isci/core/sci_memory_descriptor_list.h    |  168 +
 drivers/scsi/isci/core/sci_object.h                |   98 +
 drivers/scsi/isci/core/sci_pool.h                  |  199 +
 drivers/scsi/isci/core/sci_status.h                |  409 ++
 drivers/scsi/isci/core/sci_util.c                  |  101 +
 drivers/scsi/isci/core/sci_util.h                  |  108 +
 drivers/scsi/isci/core/scic_config_parameters.h    |  346 ++
 drivers/scsi/isci/core/scic_controller.h           |  495 +++
 drivers/scsi/isci/core/scic_io_request.h           |  511 +++
 drivers/scsi/isci/core/scic_phy.h                  |  305 ++
 drivers/scsi/isci/core/scic_port.h                 |  195 +
 drivers/scsi/isci/core/scic_remote_device.h        |  294 ++
 drivers/scsi/isci/core/scic_sds_controller.c       | 3804 ++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_controller.h       |  722 ++++
 .../scsi/isci/core/scic_sds_controller_registers.h |  463 ++
 drivers/scsi/isci/core/scic_sds_pci.h              |   94 
 drivers/scsi/isci/core/scic_sds_phy.c              | 2726 ++++++++++++++
 drivers/scsi/isci/core/scic_sds_phy.h              |  476 +++
 drivers/scsi/isci/core/scic_sds_phy_registers.h    |  248 +
 drivers/scsi/isci/core/scic_sds_port.c             | 2915 +++++++++++++++
 drivers/scsi/isci/core/scic_sds_port.h             |  499 +++
 .../isci/core/scic_sds_port_configuration_agent.c  |  863 +++++
 .../isci/core/scic_sds_port_configuration_agent.h  |  108 +
 drivers/scsi/isci/core/scic_sds_port_registers.h   |  147 +
 drivers/scsi/isci/core/scic_sds_remote_device.c    | 2079 +++++++++++
 drivers/scsi/isci/core/scic_sds_remote_device.h    |  570 +++
 .../scsi/isci/core/scic_sds_remote_node_context.c  | 1247 +++++++
 .../scsi/isci/core/scic_sds_remote_node_context.h  |  323 ++
 .../scsi/isci/core/scic_sds_remote_node_table.c    |  600 +++
 .../scsi/isci/core/scic_sds_remote_node_table.h    |  195 +
 drivers/scsi/isci/core/scic_sds_request.c          | 2174 +++++++++++
 drivers/scsi/isci/core/scic_sds_request.h          |  469 ++
 .../scsi/isci/core/scic_sds_smp_remote_device.c    |  325 ++
 drivers/scsi/isci/core/scic_sds_smp_request.c      |  669 ++++
 drivers/scsi/isci/core/scic_sds_smp_request.h      |   69 
 drivers/scsi/isci/core/scic_sds_ssp_request.c      |  268 +
 .../scsi/isci/core/scic_sds_stp_packet_request.c   |  834 ++++
 .../scsi/isci/core/scic_sds_stp_packet_request.h   |  153 +
 drivers/scsi/isci/core/scic_sds_stp_pio_request.h  |  116 +
 .../scsi/isci/core/scic_sds_stp_remote_device.c    |  908 +++++
 drivers/scsi/isci/core/scic_sds_stp_request.c      | 1941 ++++++++++
 drivers/scsi/isci/core/scic_sds_stp_request.h      |  221 +
 .../isci/core/scic_sds_unsolicited_frame_control.c |  383 ++
 .../isci/core/scic_sds_unsolicited_frame_control.h |  286 ++
 drivers/scsi/isci/core/scic_task_request.h         |  147 +
 drivers/scsi/isci/core/scu_completion_codes.h      |  283 +
 drivers/scsi/isci/core/scu_constants.h             |  151 +
 drivers/scsi/isci/core/scu_event_codes.h           |  336 ++
 drivers/scsi/isci/core/scu_registers.h             | 1830 ++++++++++
 drivers/scsi/isci/core/scu_remote_node_context.h   |  229 +
 drivers/scsi/isci/core/scu_task_context.h          |  942 +++++
 drivers/scsi/isci/core/scu_unsolicited_frame.h     |  117 +
 drivers/scsi/isci/core/scu_viit_data.h             |  178 +
 73 files changed, 39509 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/intel_ata.h
 create mode 100644 drivers/scsi/isci/core/intel_sas.h
 create mode 100644 drivers/scsi/isci/core/intel_sat.h
 create mode 100644 drivers/scsi/isci/core/intel_sata.h
 create mode 100644 drivers/scsi/isci/core/intel_scsi.h
 create mode 100644 drivers/scsi/isci/core/sati_device.h
 create mode 100644 drivers/scsi/isci/core/sati_translator_sequence.h
 create mode 100644 drivers/scsi/isci/core/sati_types.h
 create mode 100644 drivers/scsi/isci/core/sci_base_controller.h
 create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
 create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
 create mode 100644 drivers/scsi/isci/core/sci_base_phy.h
 create mode 100644 drivers/scsi/isci/core/sci_base_port.h
 create mode 100644 drivers/scsi/isci/core/sci_base_remote_device.h
 create mode 100644 drivers/scsi/isci/core/sci_base_request.h
 create mode 100644 drivers/scsi/isci/core/sci_base_state.h
 create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.c
 create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.h
 create mode 100644 drivers/scsi/isci/core/sci_controller.h
 create mode 100644 drivers/scsi/isci/core/sci_controller_constants.h
 create mode 100644 drivers/scsi/isci/core/sci_memory_descriptor_list.h
 create mode 100644 drivers/scsi/isci/core/sci_object.h
 create mode 100644 drivers/scsi/isci/core/sci_pool.h
 create mode 100644 drivers/scsi/isci/core/sci_status.h
 create mode 100644 drivers/scsi/isci/core/sci_util.c
 create mode 100644 drivers/scsi/isci/core/sci_util.h
 create mode 100644 drivers/scsi/isci/core/scic_config_parameters.h
 create mode 100644 drivers/scsi/isci/core/scic_controller.h
 create mode 100644 drivers/scsi/isci/core/scic_io_request.h
 create mode 100644 drivers/scsi/isci/core/scic_phy.h
 create mode 100644 drivers/scsi/isci/core/scic_port.h
 create mode 100644 drivers/scsi/isci/core/scic_remote_device.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller_registers.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_pci.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy_registers.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_port.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_registers.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_remote_device.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_ssp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_pio_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_remote_device.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
 create mode 100644 drivers/scsi/isci/core/scic_task_request.h
 create mode 100644 drivers/scsi/isci/core/scu_completion_codes.h
 create mode 100644 drivers/scsi/isci/core/scu_constants.h
 create mode 100644 drivers/scsi/isci/core/scu_event_codes.h
 create mode 100644 drivers/scsi/isci/core/scu_registers.h
 create mode 100644 drivers/scsi/isci/core/scu_remote_node_context.h
 create mode 100644 drivers/scsi/isci/core/scu_task_context.h
 create mode 100644 drivers/scsi/isci/core/scu_unsolicited_frame.h
 create mode 100644 drivers/scsi/isci/core/scu_viit_data.h

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [RFC PATCH 01/10] isci/core: controller
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 02/10] isci/core: phy Dan Williams
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Controller state machines and hardware interface.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/sci_base_controller.h       |  306 ++
 drivers/scsi/isci/core/sci_controller.h            |   98 +
 drivers/scsi/isci/core/sci_controller_constants.h  |  215 +
 drivers/scsi/isci/core/scic_controller.h           |  495 +++
 drivers/scsi/isci/core/scic_sds_controller.c       | 3804 ++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_controller.h       |  722 ++++
 .../scsi/isci/core/scic_sds_controller_registers.h |  463 ++
 7 files changed, 6103 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_controller.h
 create mode 100644 drivers/scsi/isci/core/sci_controller.h
 create mode 100644 drivers/scsi/isci/core/sci_controller_constants.h
 create mode 100644 drivers/scsi/isci/core/scic_controller.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_controller_registers.h

diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h
new file mode 100644
index 0000000..36c5340
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_controller.h
@@ -0,0 +1,306 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_CONTROLLER_H_
+#define _SCI_BASE_CONTROLLER_H_
+
+#include "intel_sas.h"
+#include "sci_controller_constants.h"
+#include "sci_base_state.h"
+#include "sci_base_memory_descriptor_list.h"
+#include "sci_base_state_machine.h"
+#include "sci_object.h"
+
+struct sci_base_memory_descriptor_list;
+
+/**
+ * enum sci_base_controller_states - This enumeration depicts all the states
+ *    for the common controller state machine.
+ *
+ *
+ */
+enum sci_base_controller_states {
+	/**
+	 * Simply the initial state for the base controller state machine.
+	 */
+	SCI_BASE_CONTROLLER_STATE_INITIAL = 0,
+
+	/**
+	 * This state indicates that the controller is reset.  The memory for
+	 * the controller is in it's initial state, but the controller requires
+	 * initialization.
+	 * This state is entered from the INITIAL state.
+	 * This state is entered from the RESETTING state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_RESET,
+
+	/**
+	 * This state is typically an action state that indicates the controller
+	 * is in the process of initialization.  In this state no new IO operations
+	 * are permitted.
+	 * This state is entered from the RESET state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_INITIALIZING,
+
+	/**
+	 * This state indicates that the controller has been successfully
+	 * initialized.  In this state no new IO operations are permitted.
+	 * This state is entered from the INITIALIZING state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_INITIALIZED,
+
+	/**
+	 * This state indicates the the controller is in the process of becoming
+	 * ready (i.e. starting).  In this state no new IO operations are permitted.
+	 * This state is entered from the INITIALIZED state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_STARTING,
+
+	/**
+	 * This state indicates the controller is now ready.  Thus, the user
+	 * is able to perform IO operations on the controller.
+	 * This state is entered from the STARTING state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_READY,
+
+	/**
+	 * This state is typically an action state that indicates the controller
+	 * is in the process of resetting.  Thus, the user is unable to perform
+	 * IO operations on the controller.  A reset is considered destructive in
+	 * most cases.
+	 * This state is entered from the READY state.
+	 * This state is entered from the FAILED state.
+	 * This state is entered from the STOPPED state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_RESETTING,
+
+	/**
+	 * This state indicates that the controller is in the process of stopping.
+	 * In this state no new IO operations are permitted, but existing IO
+	 * operations are allowed to complete.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_STOPPING,
+
+	/**
+	 * This state indicates that the controller has successfully been stopped.
+	 * In this state no new IO operations are permitted.
+	 * This state is entered from the STOPPING state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_STOPPED,
+
+	/**
+	 * This state indicates that the controller could not successfully be
+	 * initialized.  In this state no new IO operations are permitted.
+	 * This state is entered from the INITIALIZING state.
+	 * This state is entered from the STARTING state.
+	 * This state is entered from the STOPPING state.
+	 * This state is entered from the RESETTING state.
+	 */
+	SCI_BASE_CONTROLLER_STATE_FAILED,
+
+	SCI_BASE_CONTROLLER_MAX_STATES
+
+};
+
+/**
+ * struct sci_base_controller - The base controller object abstracts the fields
+ *    common to all SCI controller objects.
+ *
+ *
+ */
+struct sci_base_controller {
+	/**
+	 * The field specifies that the parent object for the base controller
+	 * is the base object itself.
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This field points to the memory descriptor list associated with this
+	 * controller.  The MDL indicates the memory requirements necessary for
+	 * this controller object.
+	 */
+	struct sci_base_memory_descriptor_list mdl;
+
+	/**
+	 * This field contains the information for the base controller state
+	 * machine.
+	 */
+	struct sci_base_state_machine state_machine;
+};
+
+/* Forward declarations */
+struct sci_base_remote_device;
+struct sci_base_request;
+
+typedef enum sci_status
+(*sci_base_controller_handler_t)(struct sci_base_controller *);
+
+typedef enum sci_status
+(*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32);
+
+typedef enum sci_status
+(*sci_base_controller_request_handler_t)(struct sci_base_controller *,
+					 struct sci_base_remote_device *,
+					 struct sci_base_request *);
+
+typedef enum sci_status
+(*sci_base_controller_start_request_handler_t)(struct sci_base_controller *,
+					       struct sci_base_remote_device *,
+					       struct sci_base_request *, u16);
+
+/**
+ * struct sci_base_controller_state_handler - This structure contains all of
+ *    the state handler methods common to base controller state machines.
+ *    Handler methods provide the ability to change the behavior for user
+ *    requests or transitions depending on the state the machine is in.
+ *
+ *
+ */
+struct sci_base_controller_state_handler {
+	/**
+	 * The start_handler specifies the method invoked when a user attempts to
+	 * start a controller.
+	 */
+	sci_base_controller_timed_handler_t start;
+
+	/**
+	 * The stop_handler specifies the method invoked when a user attempts to
+	 * stop a controller.
+	 */
+	sci_base_controller_timed_handler_t stop;
+
+	/**
+	 * The reset_handler specifies the method invoked when a user attempts to
+	 * reset a controller.
+	 */
+	sci_base_controller_handler_t reset;
+
+	/**
+	 * The initialize_handler specifies the method invoked when a user
+	 * attempts to initialize a controller.
+	 */
+	sci_base_controller_handler_t initialize;
+
+	/**
+	 * The start_io_handler specifies the method invoked when a user
+	 * attempts to start an IO request for a controller.
+	 */
+	sci_base_controller_start_request_handler_t start_io;
+
+	/**
+	 * The complete_io_handler specifies the method invoked when a user
+	 * attempts to complete an IO request for a controller.
+	 */
+	sci_base_controller_request_handler_t complete_io;
+
+	/**
+	 * The continue_io_handler specifies the method invoked when a user
+	 * attempts to continue an IO request for a controller.
+	 */
+	sci_base_controller_request_handler_t continue_io;
+
+	/**
+	 * The start_task_handler specifies the method invoked when a user
+	 * attempts to start a task management request for a controller.
+	 */
+	sci_base_controller_start_request_handler_t start_task;
+
+	/**
+	 * The complete_task_handler specifies the method invoked when a user
+	 * attempts to complete a task management request for a controller.
+	 */
+	sci_base_controller_request_handler_t complete_task;
+
+};
+
+/**
+ * sci_base_controller_construct() - Construct the base controller
+ * @this_controller: This parameter specifies the base controller to be
+ *    constructed.
+ * @state_table: This parameter specifies the table of state definitions to be
+ *    utilized for the controller state machine.
+ * @mde_array: This parameter specifies the array of memory descriptor entries
+ *    to be managed by this list.
+ * @mde_array_length: This parameter specifies the size of the array of entries.
+ * @next_mdl: This parameter specifies a subsequent MDL object to be managed by
+ *    this MDL object.
+ * @oem_parameters: This parameter specifies the original equipment
+ *    manufacturer parameters to be utilized by this controller object.
+ *
+ */
+static inline void sci_base_controller_construct(
+	struct sci_base_controller *scic_base,
+	const struct sci_base_state *state_table,
+	struct sci_physical_memory_descriptor *mdes,
+	u32 mde_count,
+	struct sci_base_memory_descriptor_list *next_mdl)
+{
+	scic_base->parent.private = NULL;
+
+	sci_base_state_machine_construct(
+		&scic_base->state_machine,
+		&scic_base->parent,
+		state_table,
+		SCI_BASE_CONTROLLER_STATE_INITIAL
+		);
+
+	sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl);
+
+	sci_base_state_machine_start(&scic_base->state_machine);
+}
+
+#endif /* _SCI_BASE_CONTROLLER_H_ */
diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h
new file mode 100644
index 0000000..5c7774e
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_controller.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_CONTROLLER_H_
+#define _SCI_CONTROLLER_H_
+
+/**
+ * This file contains all of the interface methods that can be called by an SCI
+ *    user on all SCI controller objects.
+ *
+ *
+ */
+
+
+struct sci_base_memory_descriptor_list;
+struct scic_sds_controller;
+
+#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF
+
+/**
+ * sci_controller_get_memory_descriptor_list_handle() - This method simply
+ *    returns a handle for the memory descriptor list associated with the
+ *    supplied controller.  The descriptor list provides DMA safe/capable
+ *    memory requirements for this controller.
+ * @controller: This parameter specifies the controller for which to retrieve
+ *    the DMA safe memory descriptor list.
+ *
+ * The user must adhere to the alignment requirements specified in memory
+ * descriptor.  In situations where the operating environment does not offer
+ * memory allocation utilities supporting alignment, then it is the
+ * responsibility of the user to manually align the memory buffer for SCI.
+ * Thus, the user may have to allocate a larger buffer to meet the alignment.
+ * Additionally, the user will need to remember the actual memory allocation
+ * addresses in order to ensure the memory can be properly freed when necessary
+ * to do so. This method will return a valid handle, but the MDL may not be
+ * accurate until after the user has invoked the associated
+ * sci_controller_initialize() routine. A pointer to a physical memory
+ * descriptor array.
+ */
+struct sci_base_memory_descriptor_list *
+	sci_controller_get_memory_descriptor_list_handle(
+	struct scic_sds_controller *controller);
+
+
+#endif  /* _SCI_CONTROLLER_H_ */
+
diff --git a/drivers/scsi/isci/core/sci_controller_constants.h b/drivers/scsi/isci/core/sci_controller_constants.h
new file mode 100644
index 0000000..06c34c7
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_controller_constants.h
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_CONTROLLER_CONSTANTS_H_
+#define _SCI_CONTROLLER_CONSTANTS_H_
+
+/**
+ * This file contains constant values that change based on the type of core or
+ *    framework being managed.  These constants are exported in order to
+ *    provide the user with information as to the bounds (i.e. how many) of
+ *    specific objects.
+ *
+ *
+ */
+
+
+#ifdef SCIC_SDS_4_ENABLED
+
+#ifndef SCI_MAX_PHYS
+/**
+ *
+ *
+ * This constant defines the maximum number of phy objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This is tied directly
+ * to silicon capabilities.
+ */
+#define SCI_MAX_PHYS  (4)
+#endif
+
+#ifndef SCI_MAX_PORTS
+/**
+ *
+ *
+ * This constant defines the maximum number of port objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This is tied directly
+ * to silicon capabilities.
+ */
+#define SCI_MAX_PORTS SCI_MAX_PHYS
+#endif
+
+#ifndef SCI_MIN_SMP_PHYS
+/**
+ *
+ *
+ * This constant defines the minimum number of SMP phy objects that can be
+ * supported for a single expander level. This was determined by using 36
+ * physical phys and room for 2 virtual phys.
+ */
+#define SCI_MIN_SMP_PHYS  (38)
+#endif
+
+#ifndef SCI_MAX_SMP_PHYS
+/**
+ *
+ *
+ * This constant defines the maximum number of SMP phy objects that can be
+ * supported for the SCU Driver Standard (SDS) library. This number can be
+ * increased if required.
+ */
+#define SCI_MAX_SMP_PHYS  (384)
+#endif
+
+#ifndef SCI_MAX_REMOTE_DEVICES
+/**
+ *
+ *
+ * This constant defines the maximum number of remote device objects that can
+ * be supported for the SCU Driver Standard (SDS) library.  This is tied
+ * directly to silicon capabilities.
+ */
+#define SCI_MAX_REMOTE_DEVICES (256)
+#endif
+
+#ifndef SCI_MIN_REMOTE_DEVICES
+/**
+ *
+ *
+ * This constant defines the minimum number of remote device objects that can
+ * be supported for the SCU Driver Standard (SDS) library.  This # can be
+ * configured for minimum memory environments to any value less than
+ * SCI_MAX_REMOTE_DEVICES
+ */
+#define SCI_MIN_REMOTE_DEVICES (16)
+#endif
+
+#ifndef SCI_MAX_IO_REQUESTS
+/**
+ *
+ *
+ * This constant defines the maximum number of IO request objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This is tied directly
+ * to silicon capabilities.
+ */
+#define SCI_MAX_IO_REQUESTS (256)
+#endif
+
+#ifndef SCI_MIN_IO_REQUESTS
+/**
+ *
+ *
+ * This constant defines the minimum number of IO request objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This # can be
+ * configured for minimum memory environments to any value less than
+ * SCI_MAX_IO_REQUESTS.
+ */
+#define SCI_MIN_IO_REQUESTS (1)
+#endif
+
+#ifndef SCI_MAX_MSIX_MESSAGES
+/**
+ *
+ *
+ * This constant defines the maximum number of MSI-X interrupt vectors/messages
+ * supported for an SCU hardware controller instance.
+ */
+#define SCI_MAX_MSIX_MESSAGES  (2)
+#endif
+
+#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS
+/**
+ *
+ *
+ * This constant defines the maximum number of Scatter-Gather Elements to be
+ * used by any SCI component.
+ */
+#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130
+#endif
+
+#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS
+/**
+ *
+ *
+ * This constant defines the minimum number of Scatter-Gather Elements to be
+ * used by any SCI component.
+ */
+#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1
+#endif
+
+#else /* SCIC_SDS_4_ENABLED */
+
+#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)"
+
+#endif /* SCIC_SDS_4_ENABLED */
+
+/**
+ *
+ *
+ * This constant defines the maximum number of controllers that can occur in a
+ * single silicon package.
+ */
+#define SCI_MAX_CONTROLLERS 2
+
+/**
+ *
+ *
+ * The maximum number of supported domain objects is currently tied to the
+ * maximum number of support port objects.
+ */
+#define SCI_MAX_DOMAINS  SCI_MAX_PORTS
+
+
+#endif  /* _SCI_CONTROLLER_CONSTANTS_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h
new file mode 100644
index 0000000..481e0de
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_controller.h
@@ -0,0 +1,495 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_CONTROLLER_H_
+#define _SCIC_CONTROLLER_H_
+
+/**
+ * This file contains all of the interface methods that can be called by an
+ *    SCIC user on a controller object.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+#include "sci_controller.h"
+#include "scic_config_parameters.h"
+
+struct scic_sds_request;
+struct scic_sds_phy;
+struct scic_sds_port;
+struct scic_sds_remote_device;
+
+
+enum sci_controller_mode {
+	SCI_MODE_SPEED,		/* Optimized for performance */
+	SCI_MODE_SIZE		/* Optimized for memory use */
+};
+
+
+/**
+ * scic_controller_construct() - This method will attempt to construct a
+ *    controller object utilizing the supplied parameter information.
+ * @c: This parameter specifies the controller to be constructed.
+ * @scu_base: mapped base address of the scu registers
+ * @smu_base: mapped base address of the smu registers
+ *
+ * Indicate if the controller was successfully constructed or if it failed in
+ * some way. SCI_SUCCESS This value is returned if the controller was
+ * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned
+ * if the interrupt coalescence timer may cause SAS compliance issues for SMP
+ * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE
+ * This value is returned if the controller does not support the supplied type.
+ * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the
+ * controller does not support the supplied initialization data version.
+ */
+enum sci_status scic_controller_construct(struct scic_sds_controller *c,
+					  void __iomem *scu_base,
+					  void __iomem *smu_base);
+
+/**
+ * scic_controller_enable_interrupts() - This method will enable all controller
+ *    interrupts.
+ * @controller: This parameter specifies the controller for which to enable
+ *    interrupts.
+ *
+ */
+void scic_controller_enable_interrupts(
+	struct scic_sds_controller *controller);
+
+/**
+ * scic_controller_disable_interrupts() - This method will disable all
+ *    controller interrupts.
+ * @controller: This parameter specifies the controller for which to disable
+ *    interrupts.
+ *
+ */
+void scic_controller_disable_interrupts(
+	struct scic_sds_controller *controller);
+
+
+/**
+ * scic_controller_initialize() - This method will initialize the controller
+ *    hardware managed by the supplied core controller object.  This method
+ *    will bring the physical controller hardware out of reset and enable the
+ *    core to determine the capabilities of the hardware being managed.  Thus,
+ *    the core controller can determine it's exact physical (DMA capable)
+ *    memory requirements.
+ * @controller: This parameter specifies the controller to be initialized.
+ *
+ * The SCI Core user must have called scic_controller_construct() on the
+ * supplied controller object previously. Indicate if the controller was
+ * successfully initialized or if it failed in some way. SCI_SUCCESS This value
+ * is returned if the controller hardware was successfully initialized.
+ */
+enum sci_status scic_controller_initialize(
+	struct scic_sds_controller *controller);
+
+/**
+ * scic_controller_get_suggested_start_timeout() - This method returns the
+ *    suggested scic_controller_start() timeout amount.  The user is free to
+ *    use any timeout value, but this method provides the suggested minimum
+ *    start timeout value.  The returned value is based upon empirical
+ *    information determined as a result of interoperability testing.
+ * @controller: the handle to the controller object for which to return the
+ *    suggested start timeout.
+ *
+ * This method returns the number of milliseconds for the suggested start
+ * operation timeout.
+ */
+u32 scic_controller_get_suggested_start_timeout(
+	struct scic_sds_controller *controller);
+
+/**
+ * scic_controller_start() - This method will start the supplied core
+ *    controller.  This method will start the staggered spin up operation.  The
+ *    SCI User completion callback is called when the following conditions are
+ *    met: -# the return status of this method is SCI_SUCCESS. -# after all of
+ *    the phys have successfully started or been given the opportunity to start.
+ * @controller: the handle to the controller object to start.
+ * @timeout: This parameter specifies the number of milliseconds in which the
+ *    start operation should complete.
+ *
+ * The SCI Core user must have filled in the physical memory descriptor
+ * structure via the sci_controller_get_memory_descriptor_list() method. The
+ * SCI Core user must have invoked the scic_controller_initialize() method
+ * prior to invoking this method. The controller must be in the INITIALIZED or
+ * STARTED state. Indicate if the controller start method succeeded or failed
+ * in some way. SCI_SUCCESS if the start operation succeeded.
+ * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED
+ * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the
+ * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if
+ * there are inconsistent or invalid values in the supplied
+ * struct sci_physical_memory_descriptor array.
+ */
+enum sci_status scic_controller_start(
+	struct scic_sds_controller *controller,
+	u32 timeout);
+
+/**
+ * scic_controller_stop() - This method will stop an individual controller
+ *    object.This method will invoke the associated user callback upon
+ *    completion.  The completion callback is called when the following
+ *    conditions are met: -# the method return status is SCI_SUCCESS. -# the
+ *    controller has been quiesced. This method will ensure that all IO
+ *    requests are quiesced, phys are stopped, and all additional operation by
+ *    the hardware is halted.
+ * @controller: the handle to the controller object to stop.
+ * @timeout: This parameter specifies the number of milliseconds in which the
+ *    stop operation should complete.
+ *
+ * The controller must be in the STARTED or STOPPED state. Indicate if the
+ * controller stop method succeeded or failed in some way. SCI_SUCCESS if the
+ * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the
+ * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the
+ * controller is not either in the STARTED or STOPPED states.
+ */
+enum sci_status scic_controller_stop(
+	struct scic_sds_controller *controller,
+	u32 timeout);
+
+/**
+ * scic_controller_reset() - This method will reset the supplied core
+ *    controller regardless of the state of said controller.  This operation is
+ *    considered destructive.  In other words, all current operations are wiped
+ *    out.  No IO completions for outstanding devices occur.  Outstanding IO
+ *    requests are not aborted or completed at the actual remote device.
+ * @controller: the handle to the controller object to reset.
+ *
+ * Indicate if the controller reset method succeeded or failed in some way.
+ * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if
+ * the controller reset operation is unable to complete.
+ */
+enum sci_status scic_controller_reset(
+	struct scic_sds_controller *controller);
+
+/**
+ * scic_controller_start_io() - This method is called by the SCI user to
+ *    send/start an IO request. If the method invocation is successful, then
+ *    the IO request has been queued to the hardware for processing.
+ * @controller: the handle to the controller object for which to start an IO
+ *    request.
+ * @remote_device: the handle to the remote device object for which to start an
+ *    IO request.
+ * @io_request: the handle to the io request object to start.
+ * @io_tag: This parameter specifies a previously allocated IO tag that the
+ *    user desires to be utilized for this request. This parameter is optional.
+ *     The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value
+ *    for this parameter.
+ *
+ * - IO tags are a protected resource.  It is incumbent upon the SCI Core user
+ * to ensure that each of the methods that may allocate or free available IO
+ * tags are handled in a mutually exclusive manner.  This method is one of said
+ * methods requiring proper critical code section protection (e.g. semaphore,
+ * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags.  As a
+ * result, it is expected the user will have set the NCQ tag field in the host
+ * to device register FIS prior to calling this method.  There is also a
+ * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking
+ * the scic_controller_start_io() method. scic_controller_allocate_tag() for
+ * more information on allocating a tag. Indicate if the controller
+ * successfully started the IO request. SCI_IO_SUCCESS if the IO request was
+ * successfully started. Determine the failure situations and return values.
+ */
+enum sci_io_status scic_controller_start_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *io_request,
+	u16 io_tag);
+
+
+/**
+ * scic_controller_start_task() - This method is called by the SCIC user to
+ *    send/start a framework task management request.
+ * @controller: the handle to the controller object for which to start the task
+ *    management request.
+ * @remote_device: the handle to the remote device object for which to start
+ *    the task management request.
+ * @task_request: the handle to the task request object to start.
+ * @io_tag: This parameter specifies a previously allocated IO tag that the
+ *    user desires to be utilized for this request.  Note this not the io_tag
+ *    of the request being managed.  It is to be utilized for the task request
+ *    itself. This parameter is optional.  The user is allowed to supply
+ *    SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
+ *
+ * - IO tags are a protected resource.  It is incumbent upon the SCI Core user
+ * to ensure that each of the methods that may allocate or free available IO
+ * tags are handled in a mutually exclusive manner.  This method is one of said
+ * methods requiring proper critical code section protection (e.g. semaphore,
+ * spin-lock, etc.). - The user must synchronize this task with completion
+ * queue processing.  If they are not synchronized then it is possible for the
+ * io requests that are being managed by the task request can complete before
+ * starting the task request. scic_controller_allocate_tag() for more
+ * information on allocating a tag. Indicate if the controller successfully
+ * started the IO request. SCI_TASK_SUCCESS if the task request was
+ * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is
+ * returned if there is/are task(s) outstanding that require termination or
+ * completion before this request can succeed.
+ */
+enum sci_task_status scic_controller_start_task(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *task_request,
+	u16 io_tag);
+
+/**
+ * scic_controller_complete_task() - This method will perform core specific
+ *    completion operations for task management request. After this method is
+ *    invoked, the user should consider the task request as invalid until it is
+ *    properly reused (i.e. re-constructed).
+ * @controller: The handle to the controller object for which to complete the
+ *    task management request.
+ * @remote_device: The handle to the remote device object for which to complete
+ *    the task management request.
+ * @task_request: the handle to the task management request object to complete.
+ *
+ * Indicate if the controller successfully completed the task management
+ * request. SCI_SUCCESS if the completion process was successful.
+ */
+enum sci_status scic_controller_complete_task(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *task_request);
+
+
+/**
+ * scic_controller_terminate_request() - This method is called by the SCI Core
+ *    user to terminate an ongoing (i.e. started) core IO request.  This does
+ *    not abort the IO request at the target, but rather removes the IO request
+ *    from the host controller.
+ * @controller: the handle to the controller object for which to terminate a
+ *    request.
+ * @remote_device: the handle to the remote device object for which to
+ *    terminate a request.
+ * @request: the handle to the io or task management request object to
+ *    terminate.
+ *
+ * Indicate if the controller successfully began the terminate process for the
+ * IO request. SCI_SUCCESS if the terminate process was successfully started
+ * for the request. Determine the failure situations and return values.
+ */
+enum sci_status scic_controller_terminate_request(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *request);
+
+/**
+ * scic_controller_complete_io() - This method will perform core specific
+ *    completion operations for an IO request.  After this method is invoked,
+ *    the user should consider the IO request as invalid until it is properly
+ *    reused (i.e. re-constructed).
+ * @controller: The handle to the controller object for which to complete the
+ *    IO request.
+ * @remote_device: The handle to the remote device object for which to complete
+ *    the IO request.
+ * @io_request: the handle to the io request object to complete.
+ *
+ * - IO tags are a protected resource.  It is incumbent upon the SCI Core user
+ * to ensure that each of the methods that may allocate or free available IO
+ * tags are handled in a mutually exclusive manner.  This method is one of said
+ * methods requiring proper critical code section protection (e.g. semaphore,
+ * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
+ * Core user, using the scic_controller_allocate_io_tag() method, then it is
+ * the responsibility of the caller to invoke the scic_controller_free_io_tag()
+ * method to free the tag (i.e. this method will not free the IO tag). Indicate
+ * if the controller successfully completed the IO request. SCI_SUCCESS if the
+ * completion process was successful.
+ */
+enum sci_status scic_controller_complete_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *io_request);
+
+
+/**
+ * scic_controller_get_port_handle() - This method simply provides the user
+ *    with a unique handle for a given SAS/SATA core port index.
+ * @controller: This parameter represents the handle to the controller object
+ *    from which to retrieve a port (SAS or SATA) handle.
+ * @port_index: This parameter specifies the port index in the controller for
+ *    which to retrieve the port handle. 0 <= port_index < maximum number of
+ *    phys.
+ * @port_handle: This parameter specifies the retrieved port handle to be
+ *    provided to the caller.
+ *
+ * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS
+ * This value is returned if the retrieval was successful.
+ * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is
+ * not in the supported range.
+ */
+enum sci_status scic_controller_get_port_handle(
+	struct scic_sds_controller *controller,
+	u8 port_index,
+	struct scic_sds_port **port_handle);
+
+/**
+ * scic_controller_get_phy_handle() - This method simply provides the user with
+ *    a unique handle for a given SAS/SATA phy index/identifier.
+ * @controller: This parameter represents the handle to the controller object
+ *    from which to retrieve a phy (SAS or SATA) handle.
+ * @phy_index: This parameter specifies the phy index in the controller for
+ *    which to retrieve the phy handle. 0 <= phy_index < maximum number of phys.
+ * @phy_handle: This parameter specifies the retrieved phy handle to be
+ *    provided to the caller.
+ *
+ * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This
+ * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY
+ * This value is returned if the supplied phy id is not in the supported range.
+ */
+enum sci_status scic_controller_get_phy_handle(
+	struct scic_sds_controller *controller,
+	u8 phy_index,
+	struct scic_sds_phy **phy_handle);
+
+/**
+ * scic_controller_allocate_io_tag() - This method will allocate a tag from the
+ *    pool of free IO tags. Direct allocation of IO tags by the SCI Core user
+ *    is optional. The scic_controller_start_io() method will allocate an IO
+ *    tag if this method is not utilized and the tag is not supplied to the IO
+ *    construct routine.  Direct allocation of IO tags may provide additional
+ *    performance improvements in environments capable of supporting this usage
+ *    model.  Additionally, direct allocation of IO tags also provides
+ *    additional flexibility to the SCI Core user.  Specifically, the user may
+ *    retain IO tags across the lives of multiple IO requests.
+ * @controller: the handle to the controller object for which to allocate the
+ *    tag.
+ *
+ * IO tags are a protected resource.  It is incumbent upon the SCI Core user to
+ * ensure that each of the methods that may allocate or free available IO tags
+ * are handled in a mutually exclusive manner.  This method is one of said
+ * methods requiring proper critical code section protection (e.g. semaphore,
+ * spin-lock, etc.). An unsigned integer representing an available IO tag.
+ * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no
+ * currently available tags to be allocated. All return other values indicate a
+ * legitimate tag.
+ */
+u16 scic_controller_allocate_io_tag(
+	struct scic_sds_controller *controller);
+
+/**
+ * scic_controller_free_io_tag() - This method will free an IO tag to the pool
+ *    of free IO tags. This method provides the SCI Core user more flexibility
+ *    with regards to IO tags.  The user may desire to keep an IO tag after an
+ *    IO request has completed, because they plan on re-using the tag for a
+ *    subsequent IO request.  This method is only legal if the tag was
+ *    allocated via scic_controller_allocate_io_tag().
+ * @controller: This parameter specifies the handle to the controller object
+ *    for which to free/return the tag.
+ * @io_tag: This parameter represents the tag to be freed to the pool of
+ *    available tags.
+ *
+ * - IO tags are a protected resource.  It is incumbent upon the SCI Core user
+ * to ensure that each of the methods that may allocate or free available IO
+ * tags are handled in a mutually exclusive manner.  This method is one of said
+ * methods requiring proper critical code section protection (e.g. semaphore,
+ * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
+ * Core user, using the scic_controller_allocate_io_tag() method, then it is
+ * the responsibility of the caller to invoke this method to free the tag. This
+ * method returns an indication of whether the tag was successfully put back
+ * (freed) to the pool of available tags. SCI_SUCCESS This return value
+ * indicates the tag was successfully placed into the pool of available IO
+ * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag
+ * is not a valid IO tag value.
+ */
+enum sci_status scic_controller_free_io_tag(
+	struct scic_sds_controller *controller,
+	u16 io_tag);
+
+
+
+
+/**
+ * scic_controller_set_mode() - This method allows the user to configure the
+ *    SCI core into either a performance mode or a memory savings mode.
+ * @controller: This parameter represents the handle to the controller object
+ *    for which to update the operating mode.
+ * @mode: This parameter specifies the new mode for the controller.
+ *
+ * Indicate if the user successfully change the operating mode of the
+ * controller. SCI_SUCCESS The user successfully updated the mode.
+ */
+enum sci_status scic_controller_set_mode(
+	struct scic_sds_controller *controller,
+	enum sci_controller_mode mode);
+
+
+/**
+ * scic_controller_set_interrupt_coalescence() - This method allows the user to
+ *    configure the interrupt coalescence.
+ * @controller: This parameter represents the handle to the controller object
+ *    for which its interrupt coalesce register is overridden.
+ * @coalesce_number: Used to control the number of entries in the Completion
+ *    Queue before an interrupt is generated. If the number of entries exceed
+ *    this number, an interrupt will be generated. The valid range of the input
+ *    is [0, 256]. A setting of 0 results in coalescing being disabled.
+ * @coalesce_timeout: Timeout value in microseconds. The valid range of the
+ *    input is [0, 2700000] . A setting of 0 is allowed and results in no
+ *    interrupt coalescing timeout.
+ *
+ * Indicate if the user successfully set the interrupt coalesce parameters.
+ * SCI_SUCCESS The user successfully updated the interrutp coalescence.
+ * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.
+ */
+enum sci_status scic_controller_set_interrupt_coalescence(
+	struct scic_sds_controller *controller,
+	u32 coalesce_number,
+	u32 coalesce_timeout);
+
+struct device;
+struct scic_sds_controller *scic_controller_alloc(struct device *dev);
+
+
+#endif  /* _SCIC_CONTROLLER_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
new file mode 100644
index 0000000..180bb1e
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -0,0 +1,3804 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 <linux/device.h>
+#include "scic_controller.h"
+#include "scic_phy.h"
+#include "scic_port.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_controller_registers.h"
+#include "scic_sds_pci.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_port_configuration_agent.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_completion_codes.h"
+#include "scu_constants.h"
+#include "scu_event_codes.h"
+#include "scu_remote_node_context.h"
+#include "scu_task_context.h"
+#include "scu_unsolicited_frame.h"
+
+#define SCU_CONTEXT_RAM_INIT_STALL_TIME      200
+
+/**
+ * smu_dcc_get_max_ports() -
+ *
+ * This macro returns the maximum number of logical ports supported by the
+ * hardware. The caller passes in the value read from the device context
+ * capacity register and this macro will mash and shift the value appropriately.
+ */
+#define smu_dcc_get_max_ports(dcc_value) \
+	(\
+		(((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \
+		 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \
+	)
+
+/**
+ * smu_dcc_get_max_task_context() -
+ *
+ * This macro returns the maximum number of task contexts supported by the
+ * hardware. The caller passes in the value read from the device context
+ * capacity register and this macro will mash and shift the value appropriately.
+ */
+#define smu_dcc_get_max_task_context(dcc_value)	\
+	(\
+		(((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \
+		 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \
+	)
+
+/**
+ * smu_dcc_get_max_remote_node_context() -
+ *
+ * This macro returns the maximum number of remote node contexts supported by
+ * the hardware. The caller passes in the value read from the device context
+ * capacity register and this macro will mash and shift the value appropriately.
+ */
+#define smu_dcc_get_max_remote_node_context(dcc_value) \
+	(\
+		(((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \
+		 >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \
+	)
+
+
+static void scic_sds_controller_power_control_timer_handler(
+	void *controller);
+#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT  3
+#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT  3
+
+/**
+ *
+ *
+ * The number of milliseconds to wait for a phy to start.
+ */
+#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT      100
+
+/**
+ *
+ *
+ * The number of milliseconds to wait while a given phy is consuming power
+ * before allowing another set of phys to consume power. Ultimately, this will
+ * be specified by OEM parameter.
+ */
+#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
+
+/**
+ * COMPLETION_QUEUE_CYCLE_BIT() -
+ *
+ * This macro will return the cycle bit of the completion queue entry
+ */
+#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
+
+/**
+ * NORMALIZE_GET_POINTER() -
+ *
+ * This macro will normalize the completion queue get pointer so its value can
+ * be used as an index into an array
+ */
+#define NORMALIZE_GET_POINTER(x) \
+	((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
+
+/**
+ * NORMALIZE_PUT_POINTER() -
+ *
+ * This macro will normalize the completion queue put pointer so its value can
+ * be used as an array inde
+ */
+#define NORMALIZE_PUT_POINTER(x) \
+	((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
+
+
+/**
+ * NORMALIZE_GET_POINTER_CYCLE_BIT() -
+ *
+ * This macro will normalize the completion queue cycle pointer so it matches
+ * the completion queue cycle bit
+ */
+#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
+	((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
+
+/**
+ * NORMALIZE_EVENT_POINTER() -
+ *
+ * This macro will normalize the completion queue event entry so its value can
+ * be used as an index.
+ */
+#define NORMALIZE_EVENT_POINTER(x) \
+	(\
+		((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \
+		>> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT	\
+	)
+
+/**
+ * INCREMENT_COMPLETION_QUEUE_GET() -
+ *
+ * This macro will increment the controllers completion queue index value and
+ * possibly toggle the cycle bit if the completion queue index wraps back to 0.
+ */
+#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
+	INCREMENT_QUEUE_GET(\
+		(index), \
+		(cycle), \
+		(controller)->completion_queue_entries,	\
+		SMU_CQGR_CYCLE_BIT \
+		)
+
+/**
+ * INCREMENT_EVENT_QUEUE_GET() -
+ *
+ * This macro will increment the controllers event queue index value and
+ * possibly toggle the event cycle bit if the event queue index wraps back to 0.
+ */
+#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
+	INCREMENT_QUEUE_GET(\
+		(index), \
+		(cycle), \
+		(controller)->completion_event_entries,	\
+		SMU_CQGR_EVENT_CYCLE_BIT \
+		)
+
+struct sci_base_memory_descriptor_list *
+sci_controller_get_memory_descriptor_list_handle(struct scic_sds_controller *scic)
+{
+       return &scic->parent.mdl;
+}
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller Initialization Methods
+ * ****************************************************************************- */
+
+/**
+ * This timer is used to start another phy after we have given up on the
+ *    previous phy to transition to the ready state.
+ *
+ *
+ */
+static void scic_sds_controller_phy_startup_timeout_handler(
+	void *controller)
+{
+	enum sci_status status;
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	this_controller->phy_startup_timer_pending = false;
+
+	status = SCI_FAILURE;
+
+	while (status != SCI_SUCCESS) {
+		status = scic_sds_controller_start_next_phy(this_controller);
+	}
+}
+
+/**
+ *
+ *
+ * This method initializes the phy startup operations for controller start.
+ */
+enum sci_status scic_sds_controller_initialize_phy_startup(
+	struct scic_sds_controller *this_controller)
+{
+	this_controller->phy_startup_timer = isci_event_timer_create(
+		this_controller,
+		scic_sds_controller_phy_startup_timeout_handler,
+		this_controller
+		);
+
+	if (this_controller->phy_startup_timer == NULL) {
+		return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+	} else {
+		this_controller->next_phy_to_start = 0;
+		this_controller->phy_startup_timer_pending = false;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ *
+ * This method initializes the power control operations for the controller
+ * object.
+ */
+void scic_sds_controller_initialize_power_control(
+	struct scic_sds_controller *this_controller)
+{
+	this_controller->power_control.timer = isci_event_timer_create(
+		this_controller,
+		scic_sds_controller_power_control_timer_handler,
+		this_controller
+		);
+
+	memset(
+		this_controller->power_control.requesters,
+		0,
+		sizeof(this_controller->power_control.requesters)
+		);
+
+	this_controller->power_control.phys_waiting = 0;
+}
+
+/* --------------------------------------------------------------------------- */
+
+#define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT       (32)
+#define SCU_TASK_CONTEXT_ALIGNMENT              (256)
+#define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
+#define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT  (1024)
+#define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT  (64)
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ * This method builds the memory descriptor table for this controller.
+ * @this_controller: This parameter specifies the controller object for which
+ *    to build the memory table.
+ *
+ */
+void scic_sds_controller_build_memory_descriptor_table(
+	struct scic_sds_controller *this_controller)
+{
+	sci_base_mde_construct(
+		&this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
+		SCU_COMPLETION_RAM_ALIGNMENT,
+		(sizeof(u32) * this_controller->completion_queue_entries),
+		(SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
+		);
+
+	sci_base_mde_construct(
+		&this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
+		SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
+		this_controller->remote_node_entries * sizeof(union scu_remote_node_context),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+
+	sci_base_mde_construct(
+		&this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
+		SCU_TASK_CONTEXT_ALIGNMENT,
+		this_controller->task_context_entries * sizeof(struct scu_task_context),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+
+	/*
+	 * The UF buffer address table size must be programmed to a power
+	 * of 2.  Find the first power of 2 that is equal to or greater then
+	 * the number of unsolicited frame buffers to be utilized. */
+	scic_sds_unsolicited_frame_control_set_address_table_count(
+		&this_controller->uf_control
+		);
+
+	sci_base_mde_construct(
+		&this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
+		SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
+		scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+}
+
+/**
+ * This method validates the driver supplied memory descriptor table.
+ * @this_controller:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_controller_validate_memory_descriptor_table(
+	struct scic_sds_controller *this_controller)
+{
+	bool mde_list_valid;
+
+	mde_list_valid = sci_base_mde_is_valid(
+		&this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
+		SCU_COMPLETION_RAM_ALIGNMENT,
+		(sizeof(u32) * this_controller->completion_queue_entries),
+		(SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
+		);
+
+	if (mde_list_valid == false)
+		return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+	mde_list_valid = sci_base_mde_is_valid(
+		&this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
+		SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
+		this_controller->remote_node_entries * sizeof(union scu_remote_node_context),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+
+	if (mde_list_valid == false)
+		return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+	mde_list_valid = sci_base_mde_is_valid(
+		&this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
+		SCU_TASK_CONTEXT_ALIGNMENT,
+		this_controller->task_context_entries * sizeof(struct scu_task_context),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+
+	if (mde_list_valid == false)
+		return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+	mde_list_valid = sci_base_mde_is_valid(
+		&this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
+		SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
+		scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
+		SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+		);
+
+	if (mde_list_valid == false)
+		return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method initializes the controller with the physical memory addresses
+ *    that are used to communicate with the driver.
+ * @this_controller:
+ *
+ */
+void scic_sds_controller_ram_initialization(
+	struct scic_sds_controller *this_controller)
+{
+	struct sci_physical_memory_descriptor *mde;
+
+	/*
+	 * The completion queue is actually placed in cacheable memory
+	 * Therefore it no longer comes out of memory in the MDL. */
+	mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
+	this_controller->completion_queue = (u32 *)mde->virtual_address;
+	SMU_CQBAR_WRITE(this_controller, mde->physical_address);
+
+	/*
+	 * Program the location of the Remote Node Context table
+	 * into the SCU. */
+	mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
+	this_controller->remote_node_context_table = (union scu_remote_node_context *)
+						     mde->virtual_address;
+	SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
+
+	/* Program the location of the Task Context table into the SCU. */
+	mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
+	this_controller->task_context_table = (struct scu_task_context *)
+					      mde->virtual_address;
+	SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
+
+	mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
+	scic_sds_unsolicited_frame_control_construct(
+		&this_controller->uf_control, mde, this_controller
+		);
+
+	/*
+	 * Inform the silicon as to the location of the UF headers and
+	 * address table. */
+	SCU_UFHBAR_WRITE(
+		this_controller,
+		this_controller->uf_control.headers.physical_address);
+	SCU_PUFATHAR_WRITE(
+		this_controller,
+		this_controller->uf_control.address_table.physical_address);
+}
+
+/**
+ * This method initializes the task context data for the controller.
+ * @this_controller:
+ *
+ */
+void scic_sds_controller_assign_task_entries(
+	struct scic_sds_controller *this_controller)
+{
+	u32 task_assignment;
+
+	/*
+	 * Assign all the TCs to function 0
+	 * TODO: Do we actually need to read this register to write it back? */
+	task_assignment = SMU_TCA_READ(this_controller, 0);
+
+	task_assignment =
+		(
+			task_assignment
+			| (SMU_TCA_GEN_VAL(STARTING, 0))
+			| (SMU_TCA_GEN_VAL(ENDING,  this_controller->task_context_entries - 1))
+			| (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
+		);
+
+	SMU_TCA_WRITE(this_controller, 0, task_assignment);
+}
+
+/**
+ * This method initializes the hardware completion queue.
+ *
+ *
+ */
+void scic_sds_controller_initialize_completion_queue(
+	struct scic_sds_controller *this_controller)
+{
+	u32 index;
+	u32 completion_queue_control_value;
+	u32 completion_queue_get_value;
+	u32 completion_queue_put_value;
+
+	this_controller->completion_queue_get = 0;
+
+	completion_queue_control_value = (
+		SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
+		| SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
+		);
+
+	SMU_CQC_WRITE(this_controller, completion_queue_control_value);
+
+	/* Set the completion queue get pointer and enable the queue */
+	completion_queue_get_value = (
+		(SMU_CQGR_GEN_VAL(POINTER, 0))
+		| (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
+		| (SMU_CQGR_GEN_BIT(ENABLE))
+		| (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
+		);
+
+	SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
+
+	/* Set the completion queue put pointer */
+	completion_queue_put_value = (
+		(SMU_CQPR_GEN_VAL(POINTER, 0))
+		| (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
+		);
+
+	SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
+
+	/* Initialize the cycle bit of the completion queue entries */
+	for (index = 0; index < this_controller->completion_queue_entries; index++) {
+		/*
+		 * If get.cycle_bit != completion_queue.cycle_bit
+		 * its not a valid completion queue entry
+		 * so at system start all entries are invalid */
+		this_controller->completion_queue[index] = 0x80000000;
+	}
+}
+
+/**
+ * This method initializes the hardware unsolicited frame queue.
+ *
+ *
+ */
+void scic_sds_controller_initialize_unsolicited_frame_queue(
+	struct scic_sds_controller *this_controller)
+{
+	u32 frame_queue_control_value;
+	u32 frame_queue_get_value;
+	u32 frame_queue_put_value;
+
+	/* Write the queue size */
+	frame_queue_control_value =
+		SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
+
+	SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
+
+	/* Setup the get pointer for the unsolicited frame queue */
+	frame_queue_get_value = (
+		SCU_UFQGP_GEN_VAL(POINTER, 0)
+		|  SCU_UFQGP_GEN_BIT(ENABLE_BIT)
+		);
+
+	SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
+
+	/* Setup the put pointer for the unsolicited frame queue */
+	frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
+
+	SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
+}
+
+/**
+ * This method enables the hardware port task scheduler.
+ *
+ *
+ */
+void scic_sds_controller_enable_port_task_scheduler(
+	struct scic_sds_controller *this_controller)
+{
+	u32 port_task_scheduler_value;
+
+	port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
+
+	port_task_scheduler_value |=
+		(SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
+
+	SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ *
+ *
+ * This macro is used to delay between writes to the AFE registers during AFE
+ * initialization.
+ */
+#define AFE_REGISTER_WRITE_DELAY 10
+
+/* Initialize the AFE for this phy index. We need to read the AFE setup from
+ * the OEM parameters none
+ */
+void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
+{
+	u32 afe_status;
+	u32 phy_id;
+
+	/* Clear DFX Status registers */
+	scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f);
+	udelay(AFE_REGISTER_WRITE_DELAY);
+
+	/* Configure bias currents to normal */
+	if (is_a0())
+		scu_afe_register_write(scic, afe_bias_control, 0x00005500);
+	else
+		scu_afe_register_write(scic, afe_bias_control, 0x00005A00);
+
+	udelay(AFE_REGISTER_WRITE_DELAY);
+
+	/* Enable PLL */
+	if (is_b0())
+		scu_afe_register_write(scic, afe_pll_control0, 0x80040A08);
+	else
+		scu_afe_register_write(scic, afe_pll_control0, 0x80040908);
+
+	udelay(AFE_REGISTER_WRITE_DELAY);
+
+	/* Wait for the PLL to lock */
+	do {
+		afe_status = scu_afe_register_read(
+			scic, afe_common_block_status);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+	} while ((afe_status & 0x00001000) == 0);
+
+	if (is_b0()) {
+		/* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
+		scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+	}
+
+	for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
+		if (is_b0()) {
+			 /* Configure transmitter SSC parameters */
+			scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+		} else {
+			/*
+			 * All defaults, except the Receive Word Alignament/Comma Detect
+			 * Enable....(0xe800) */
+			scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+
+			scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+		}
+
+		/*
+		 * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+		 * & increase TX int & ext bias 20%....(0xe85c) */
+		if (is_a0())
+			scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003D4);
+		else if (is_a2())
+			scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003F0);
+		else {
+			 /* Power down TX and RX (PWRDNTX and PWRDNRX) */
+			scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+
+			/*
+			 * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+			 * & increase TX int & ext bias 20%....(0xe85c) */
+			scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4);
+		}
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		if (is_a0() || is_a2()) {
+			/* Enable TX equalization (0xe824) */
+			scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+		}
+
+		/*
+		 * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
+		 * RDD=0x0(RX Detect Enabled) ....(0xe800) */
+		scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		/* Leave DFE/FFE on */
+		if (is_a0())
+			scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F09983F);
+		else if (is_a2())
+			scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F);
+		else {
+			scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F);
+			udelay(AFE_REGISTER_WRITE_DELAY);
+			/* Enable TX equalization (0xe824) */
+			scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
+		}
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03);
+		udelay(AFE_REGISTER_WRITE_DELAY);
+	}
+
+	/* Transfer control to the PEs */
+	scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00);
+	udelay(AFE_REGISTER_WRITE_DELAY);
+}
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller Internal Start/Stop Routines
+ * ****************************************************************************- */
+
+
+/**
+ * This method will attempt to transition into the ready state for the
+ *    controller and indicate that the controller start operation has completed
+ *    if all criteria are met.
+ * @this_controller: This parameter indicates the controller object for which
+ *    to transition to ready.
+ * @status: This parameter indicates the status value to be pass into the call
+ *    to scic_cb_controller_start_complete().
+ *
+ * none.
+ */
+static void scic_sds_controller_transition_to_ready(
+	struct scic_sds_controller *this_controller,
+	enum sci_status status)
+{
+	if (this_controller->parent.state_machine.current_state_id
+	    == SCI_BASE_CONTROLLER_STATE_STARTING) {
+		/*
+		 * We move into the ready state, because some of the phys/ports
+		 * may be up and operational. */
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(this_controller),
+			SCI_BASE_CONTROLLER_STATE_READY
+			);
+
+		isci_event_controller_start_complete(this_controller, status);
+	}
+}
+
+/**
+ * This method is the general timeout handler for the controller. It will take
+ *    the correct timetout action based on the current controller state
+ */
+void scic_sds_controller_timeout_handler(
+	struct scic_sds_controller *scic)
+{
+	enum sci_base_controller_states current_state;
+
+	current_state = sci_base_state_machine_get_state(
+		scic_sds_controller_get_base_state_machine(scic));
+
+	if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING) {
+		scic_sds_controller_transition_to_ready(
+			scic, SCI_FAILURE_TIMEOUT);
+	} else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING) {
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(scic),
+			SCI_BASE_CONTROLLER_STATE_FAILED);
+		isci_event_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT);
+	} else	/* / @todo Now what do we want to do in this case? */
+		dev_err(scic_to_dev(scic),
+			"%s: Controller timer fired when controller was not "
+			"in a state being timed.\n",
+			__func__);
+}
+
+/**
+ * scic_sds_controller_get_port_configuration_mode
+ * @this_controller: This is the controller to use to determine if we are using
+ *    manual or automatic port configuration.
+ *
+ * SCIC_PORT_CONFIGURATION_MODE
+ */
+enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
+	struct scic_sds_controller *this_controller)
+{
+	u32 index;
+	enum SCIC_PORT_CONFIGURATION_MODE mode;
+
+	mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+
+	for (index = 0; index < SCI_MAX_PORTS; index++) {
+		if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) {
+			mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
+			break;
+		}
+	}
+
+	return mode;
+}
+
+enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
+{
+	u32 index;
+	enum sci_status port_status;
+	enum sci_status status = SCI_SUCCESS;
+
+	for (index = 0; index < scic->logical_port_entries; index++) {
+		struct scic_sds_port *sci_port = &scic->port_table[index];
+		SCI_BASE_PORT_HANDLER_T stop;
+
+		stop = sci_port->state_handlers->parent.stop_handler;
+		port_status = stop(&sci_port->parent);
+
+		if ((port_status != SCI_SUCCESS) &&
+		    (port_status != SCI_FAILURE_INVALID_STATE)) {
+			status = SCI_FAILURE;
+
+			dev_warn(scic_to_dev(scic),
+				 "%s: Controller stop operation failed to "
+				 "stop port %d because of status %d.\n",
+				 __func__,
+				 sci_port->logical_port_index,
+				 port_status);
+		}
+	}
+
+	return status;
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_controller_phy_timer_start(
+	struct scic_sds_controller *this_controller)
+{
+	isci_event_timer_start(
+		this_controller,
+		this_controller->phy_startup_timer,
+		SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
+		);
+
+	this_controller->phy_startup_timer_pending = true;
+}
+
+/**
+ *
+ *
+ *
+ */
+void scic_sds_controller_phy_timer_stop(
+	struct scic_sds_controller *this_controller)
+{
+	isci_event_timer_stop(
+		this_controller,
+		this_controller->phy_startup_timer
+		);
+
+	this_controller->phy_startup_timer_pending = false;
+}
+
+/**
+ * This method is called internally by the controller object to start the next
+ *    phy on the controller.  If all the phys have been starte, then this
+ *    method will attempt to transition the controller to the READY state and
+ *    inform the user (scic_cb_controller_start_complete()).
+ * @this_controller: This parameter specifies the controller object for which
+ *    to start the next phy.
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_controller_start_next_phy(
+	struct scic_sds_controller *this_controller)
+{
+	enum sci_status status;
+
+	status = SCI_SUCCESS;
+
+	if (this_controller->phy_startup_timer_pending == false) {
+		if (this_controller->next_phy_to_start == SCI_MAX_PHYS) {
+			bool is_controller_start_complete = true;
+			struct scic_sds_phy *the_phy;
+			u8 index;
+
+			for (index = 0; index < SCI_MAX_PHYS; index++) {
+				the_phy = &this_controller->phy_table[index];
+
+				if (scic_sds_phy_get_port(the_phy) != NULL) {
+					/**
+					 * The controller start operation is complete if and only
+					 * if:
+					 * - all links have been given an opportunity to start
+					 * - have no indication of a connected device
+					 * - have an indication of a connected device and it has
+					 *   finished the link training process.
+					 */
+					if (
+						(
+							(the_phy->is_in_link_training == false)
+							&& (the_phy->parent.state_machine.current_state_id
+							    == SCI_BASE_PHY_STATE_INITIAL)
+						)
+						|| (
+							(the_phy->is_in_link_training == false)
+							&& (the_phy->parent.state_machine.current_state_id
+							    == SCI_BASE_PHY_STATE_STOPPED)
+							)
+						|| (
+							(the_phy->is_in_link_training == true)
+							&& (the_phy->parent.state_machine.current_state_id
+							    == SCI_BASE_PHY_STATE_STARTING)
+							)
+						) {
+						is_controller_start_complete = false;
+						break;
+					}
+				}
+			}
+
+			/*
+			 * The controller has successfully finished the start process.
+			 * Inform the SCI Core user and transition to the READY state. */
+			if (is_controller_start_complete == true) {
+				scic_sds_controller_transition_to_ready(
+					this_controller, SCI_SUCCESS
+					);
+				scic_sds_controller_phy_timer_stop(this_controller);
+			}
+		} else {
+			struct scic_sds_phy *the_phy;
+
+			the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
+
+			if (
+				scic_sds_controller_get_port_configuration_mode(this_controller)
+				== SCIC_PORT_MANUAL_CONFIGURATION_MODE
+				) {
+				if (scic_sds_phy_get_port(the_phy) == NULL) {
+					this_controller->next_phy_to_start++;
+
+					/*
+					 * Caution recursion ahead be forwarned
+					 *
+					 * The PHY was never added to a PORT in MPC mode so start the next phy in sequence
+					 * This phy will never go link up and will not draw power the OEM parameters either
+					 * configured the phy incorrectly for the PORT or it was never assigned to a PORT */
+					return scic_sds_controller_start_next_phy(this_controller);
+				}
+			}
+
+			status = scic_sds_phy_start(the_phy);
+
+			if (status == SCI_SUCCESS) {
+				scic_sds_controller_phy_timer_start(this_controller);
+			} else {
+				dev_warn(scic_to_dev(this_controller),
+					 "%s: Controller stop operation failed "
+					 "to stop phy %d because of status "
+					 "%d.\n",
+					 __func__,
+					 this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
+					 status);
+			}
+
+			this_controller->next_phy_to_start++;
+		}
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_controller:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_controller_stop_phys(
+	struct scic_sds_controller *this_controller)
+{
+	u32 index;
+	enum sci_status status;
+	enum sci_status phy_status;
+
+	status = SCI_SUCCESS;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		phy_status = scic_sds_phy_stop(&this_controller->phy_table[index]);
+
+		if (
+			(phy_status != SCI_SUCCESS)
+			&& (phy_status != SCI_FAILURE_INVALID_STATE)
+			) {
+			status = SCI_FAILURE;
+
+			dev_warn(scic_to_dev(this_controller),
+				 "%s: Controller stop operation failed to stop "
+				 "phy %d because of status %d.\n",
+				 __func__,
+				 this_controller->phy_table[index].phy_index, phy_status);
+		}
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_controller:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_controller_stop_devices(
+	struct scic_sds_controller *this_controller)
+{
+	u32 index;
+	enum sci_status status;
+	enum sci_status device_status;
+
+	status = SCI_SUCCESS;
+
+	for (index = 0; index < this_controller->remote_node_entries; index++) {
+		if (this_controller->device_table[index] != NULL) {
+			/* / @todo What timeout value do we want to provide to this request? */
+			device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
+
+			if ((device_status != SCI_SUCCESS) &&
+			    (device_status != SCI_FAILURE_INVALID_STATE)) {
+				dev_warn(scic_to_dev(this_controller),
+					 "%s: Controller stop operation failed "
+					 "to stop device 0x%p because of "
+					 "status %d.\n",
+					 __func__,
+					 this_controller->device_table[index], device_status);
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller Power Control (Staggered Spinup)
+ * ****************************************************************************- */
+
+/**
+ *
+ *
+ * This method starts the power control timer for this controller object.
+ */
+static void scic_sds_controller_power_control_timer_start(
+	struct scic_sds_controller *this_controller)
+{
+	isci_event_timer_start(
+		this_controller, this_controller->power_control.timer,
+		SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
+		);
+
+	this_controller->power_control.timer_started = true;
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_controller_power_control_timer_handler(
+	void *controller)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	if (this_controller->power_control.phys_waiting == 0) {
+		this_controller->power_control.timer_started = false;
+	} else {
+		struct scic_sds_phy *the_phy = NULL;
+		u8 i;
+
+		for (i = 0;
+		     (i < SCI_MAX_PHYS)
+		     && (this_controller->power_control.phys_waiting != 0);
+		     i++) {
+			if (this_controller->power_control.requesters[i] != NULL) {
+				the_phy = this_controller->power_control.requesters[i];
+				this_controller->power_control.requesters[i] = NULL;
+				this_controller->power_control.phys_waiting--;
+				break;
+			}
+		}
+
+		/*
+		 * It doesn't matter if the power list is empty, we need to start the
+		 * timer in case another phy becomes ready. */
+		scic_sds_controller_power_control_timer_start(this_controller);
+
+		scic_sds_phy_consume_power_handler(the_phy);
+	}
+}
+
+/**
+ * This method inserts the phy in the stagger spinup control queue.
+ * @this_controller:
+ *
+ *
+ */
+void scic_sds_controller_power_control_queue_insert(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_phy *the_phy)
+{
+	BUG_ON(the_phy == NULL);
+
+	if (
+		(this_controller->power_control.timer_started)
+		&& (this_controller->power_control.requesters[the_phy->phy_index] == NULL)
+		) {
+		this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
+		this_controller->power_control.phys_waiting++;
+	} else {
+		scic_sds_controller_power_control_timer_start(this_controller);
+		scic_sds_phy_consume_power_handler(the_phy);
+	}
+}
+
+/**
+ * This method removes the phy from the stagger spinup control queue.
+ * @this_controller:
+ *
+ *
+ */
+void scic_sds_controller_power_control_queue_remove(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_phy *the_phy)
+{
+	BUG_ON(the_phy == NULL);
+
+	if (this_controller->power_control.requesters[the_phy->phy_index] != NULL) {
+		this_controller->power_control.phys_waiting--;
+	}
+
+	this_controller->power_control.requesters[the_phy->phy_index] = NULL;
+}
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller Completion Routines
+ * ****************************************************************************- */
+
+/**
+ * This method returns a true value if the completion queue has entries that
+ *    can be processed
+ * @this_controller:
+ *
+ * bool true if the completion queue has entries to process false if the
+ * completion queue has no entries to process
+ */
+static bool scic_sds_controller_completion_queue_has_entries(
+	struct scic_sds_controller *this_controller)
+{
+	u32 get_value = this_controller->completion_queue_get;
+	u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
+
+	if (
+		NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
+		== COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
+		) {
+		return true;
+	}
+
+	return false;
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ * This method processes a task completion notification.  This is called from
+ *    within the controller completion handler.
+ * @this_controller:
+ * @completion_entry:
+ *
+ */
+static void scic_sds_controller_task_completion(
+	struct scic_sds_controller *this_controller,
+	u32 completion_entry)
+{
+	u32 index;
+	struct scic_sds_request *io_request;
+
+	index = SCU_GET_COMPLETION_INDEX(completion_entry);
+	io_request = this_controller->io_request_table[index];
+
+	/* Make sure that we really want to process this IO request */
+	if (
+		(io_request != NULL)
+		&& (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
+		&& (
+			scic_sds_io_tag_get_sequence(io_request->io_tag)
+			== this_controller->io_request_sequence[index]
+			)
+		) {
+		/* Yep this is a valid io request pass it along to the io request handler */
+		scic_sds_io_request_tc_completion(io_request, completion_entry);
+	}
+}
+
+/**
+ * This method processes an SDMA completion event.  This is called from within
+ *    the controller completion handler.
+ * @this_controller:
+ * @completion_entry:
+ *
+ */
+static void scic_sds_controller_sdma_completion(
+	struct scic_sds_controller *this_controller,
+	u32 completion_entry)
+{
+	u32 index;
+	struct scic_sds_request *io_request;
+	struct scic_sds_remote_device *device;
+
+	index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+	switch (scu_get_command_request_type(completion_entry)) {
+	case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
+	case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
+		io_request = this_controller->io_request_table[index];
+		dev_warn(scic_to_dev(this_controller),
+			 "%s: SCIC SDS Completion type SDMA %x for io request "
+			 "%p\n",
+			 __func__,
+			 completion_entry,
+			 io_request);
+		/* @todo For a post TC operation we need to fail the IO
+		 * request
+		 */
+		break;
+
+	case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
+	case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
+	case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
+		device = this_controller->device_table[index];
+		dev_warn(scic_to_dev(this_controller),
+			 "%s: SCIC SDS Completion type SDMA %x for remote "
+			 "device %p\n",
+			 __func__,
+			 completion_entry,
+			 device);
+		/* @todo For a port RNC operation we need to fail the
+		 * device
+		 */
+		break;
+
+	default:
+		dev_warn(scic_to_dev(this_controller),
+			 "%s: SCIC SDS Completion unknown SDMA completion "
+			 "type %x\n",
+			 __func__,
+			 completion_entry);
+		break;
+
+	}
+}
+
+/**
+ *
+ * @this_controller:
+ * @completion_entry:
+ *
+ * This method processes an unsolicited frame message.  This is called from
+ * within the controller completion handler. none
+ */
+static void scic_sds_controller_unsolicited_frame(
+	struct scic_sds_controller *this_controller,
+	u32 completion_entry)
+{
+	u32 index;
+	u32 frame_index;
+
+	struct scu_unsolicited_frame_header *frame_header;
+	struct scic_sds_phy *phy;
+	struct scic_sds_remote_device *device;
+
+	enum sci_status result = SCI_FAILURE;
+
+	frame_index = SCU_GET_FRAME_INDEX(completion_entry);
+
+	frame_header
+		= this_controller->uf_control.buffers.array[frame_index].header;
+	this_controller->uf_control.buffers.array[frame_index].state
+		= UNSOLICITED_FRAME_IN_USE;
+
+	if (SCU_GET_FRAME_ERROR(completion_entry)) {
+		/*
+		 * / @todo If the IAF frame or SIGNATURE FIS frame has an error will
+		 * /       this cause a problem? We expect the phy initialization will
+		 * /       fail if there is an error in the frame. */
+		scic_sds_controller_release_frame(this_controller, frame_index);
+		return;
+	}
+
+	if (frame_header->is_address_frame) {
+		index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+		phy = &this_controller->phy_table[index];
+		if (phy != NULL) {
+			result = scic_sds_phy_frame_handler(phy, frame_index);
+		}
+	} else {
+
+		index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+		if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+			/*
+			 * This is a signature fis or a frame from a direct attached SATA
+			 * device that has not yet been created.  In either case forwared
+			 * the frame to the PE and let it take care of the frame data. */
+			index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+			phy = &this_controller->phy_table[index];
+			result = scic_sds_phy_frame_handler(phy, frame_index);
+		} else {
+			if (index < this_controller->remote_node_entries)
+				device = this_controller->device_table[index];
+			else
+				device = NULL;
+
+			if (device != NULL)
+				result = scic_sds_remote_device_frame_handler(device, frame_index);
+			else
+				scic_sds_controller_release_frame(this_controller, frame_index);
+		}
+	}
+
+	if (result != SCI_SUCCESS) {
+		/*
+		 * / @todo Is there any reason to report some additional error message
+		 * /       when we get this failure notifiction? */
+	}
+}
+
+/**
+ * This method processes an event completion entry.  This is called from within
+ *    the controller completion handler.
+ * @this_controller:
+ * @completion_entry:
+ *
+ */
+static void scic_sds_controller_event_completion(
+	struct scic_sds_controller *this_controller,
+	u32 completion_entry)
+{
+	u32 index;
+	struct scic_sds_request *io_request;
+	struct scic_sds_remote_device *device;
+	struct scic_sds_phy *phy;
+
+	index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+	switch (scu_get_event_type(completion_entry)) {
+	case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
+		/* / @todo The driver did something wrong and we need to fix the condtion. */
+		dev_err(scic_to_dev(this_controller),
+			"%s: SCIC Controller 0x%p received SMU command error "
+			"0x%x\n",
+			__func__,
+			this_controller,
+			completion_entry);
+		break;
+
+	case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
+	case SCU_EVENT_TYPE_SMU_ERROR:
+	case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
+		/*
+		 * / @todo This is a hardware failure and its likely that we want to
+		 * /       reset the controller. */
+		dev_err(scic_to_dev(this_controller),
+			"%s: SCIC Controller 0x%p received fatal controller "
+			"event  0x%x\n",
+			__func__,
+			this_controller,
+			completion_entry);
+		break;
+
+	case SCU_EVENT_TYPE_TRANSPORT_ERROR:
+		io_request = this_controller->io_request_table[index];
+		scic_sds_io_request_event_handler(io_request, completion_entry);
+		break;
+
+	case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
+		switch (scu_get_event_specifier(completion_entry)) {
+		case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
+		case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
+			io_request = this_controller->io_request_table[index];
+			if (io_request != NULL)
+				scic_sds_io_request_event_handler(io_request, completion_entry);
+			else
+				dev_warn(scic_to_dev(this_controller),
+					 "%s: SCIC Controller 0x%p received "
+					 "event 0x%x for io request object "
+					 "that doesnt exist.\n",
+					 __func__,
+					 this_controller,
+					 completion_entry);
+
+			break;
+
+		case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
+			device = this_controller->device_table[index];
+			if (device != NULL)
+				scic_sds_remote_device_event_handler(device, completion_entry);
+			else
+				dev_warn(scic_to_dev(this_controller),
+					 "%s: SCIC Controller 0x%p received "
+					 "event 0x%x for remote device object "
+					 "that doesnt exist.\n",
+					 __func__,
+					 this_controller,
+					 completion_entry);
+
+			break;
+		}
+		break;
+
+	case SCU_EVENT_TYPE_BROADCAST_CHANGE:
+	/*
+	 * direct the broadcast change event to the phy first and then let
+	 * the phy redirect the broadcast change to the port object */
+	case SCU_EVENT_TYPE_ERR_CNT_EVENT:
+	/*
+	 * direct error counter event to the phy object since that is where
+	 * we get the event notification.  This is a type 4 event. */
+	case SCU_EVENT_TYPE_OSSP_EVENT:
+		index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+		phy = &this_controller->phy_table[index];
+		scic_sds_phy_event_handler(phy, completion_entry);
+		break;
+
+	case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+	case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+	case SCU_EVENT_TYPE_RNC_OPS_MISC:
+		if (index < this_controller->remote_node_entries) {
+			device = this_controller->device_table[index];
+
+			if (device != NULL)
+				scic_sds_remote_device_event_handler(device, completion_entry);
+		} else
+			dev_err(scic_to_dev(this_controller),
+				"%s: SCIC Controller 0x%p received event 0x%x "
+				"for remote device object 0x%0x that doesnt "
+				"exist.\n",
+				__func__,
+				this_controller,
+				completion_entry,
+				index);
+
+		break;
+
+	default:
+		dev_warn(scic_to_dev(this_controller),
+			 "%s: SCIC Controller received unknown event code %x\n",
+			 __func__,
+			 completion_entry);
+		break;
+	}
+}
+
+/**
+ * This method is a private routine for processing the completion queue entries.
+ * @this_controller:
+ *
+ */
+static void scic_sds_controller_process_completions(
+	struct scic_sds_controller *this_controller)
+{
+	u32 completion_count = 0;
+	u32 completion_entry;
+	u32 get_index;
+	u32 get_cycle;
+	u32 event_index;
+	u32 event_cycle;
+
+	dev_dbg(scic_to_dev(this_controller),
+		"%s: completion queue begining get:0x%08x\n",
+		__func__,
+		this_controller->completion_queue_get);
+
+	/* Get the component parts of the completion queue */
+	get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
+	get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
+
+	event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
+	event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
+
+	while (
+		NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
+		== COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
+		) {
+		completion_count++;
+
+		completion_entry = this_controller->completion_queue[get_index];
+		INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
+
+		dev_dbg(scic_to_dev(this_controller),
+			"%s: completion queue entry:0x%08x\n",
+			__func__,
+			completion_entry);
+
+		switch (SCU_GET_COMPLETION_TYPE(completion_entry)) {
+		case SCU_COMPLETION_TYPE_TASK:
+			scic_sds_controller_task_completion(this_controller, completion_entry);
+			break;
+
+		case SCU_COMPLETION_TYPE_SDMA:
+			scic_sds_controller_sdma_completion(this_controller, completion_entry);
+			break;
+
+		case SCU_COMPLETION_TYPE_UFI:
+			scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
+			break;
+
+		case SCU_COMPLETION_TYPE_EVENT:
+			INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+			scic_sds_controller_event_completion(this_controller, completion_entry);
+			break;
+
+		case SCU_COMPLETION_TYPE_NOTIFY:
+			/*
+			 * Presently we do the same thing with a notify event that we do with the
+			 * other event codes. */
+			INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+			scic_sds_controller_event_completion(this_controller, completion_entry);
+			break;
+
+		default:
+			dev_warn(scic_to_dev(this_controller),
+				 "%s: SCIC Controller received unknown "
+				 "completion type %x\n",
+				 __func__,
+				 completion_entry);
+			break;
+		}
+	}
+
+	/* Update the get register if we completed one or more entries */
+	if (completion_count > 0) {
+		this_controller->completion_queue_get =
+			SMU_CQGR_GEN_BIT(ENABLE)
+			| SMU_CQGR_GEN_BIT(EVENT_ENABLE)
+			| event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
+			| get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index);
+
+		SMU_CQGR_WRITE(this_controller,
+			       this_controller->completion_queue_get);
+	}
+
+	dev_dbg(scic_to_dev(this_controller),
+		"%s: completion queue ending get:0x%08x\n",
+		__func__,
+		this_controller->completion_queue_get);
+
+}
+
+bool scic_sds_controller_isr(struct scic_sds_controller *scic)
+{
+	if (scic_sds_controller_completion_queue_has_entries(scic)) {
+		return true;
+	} else {
+		/*
+		 * we have a spurious interrupt it could be that we have already
+		 * emptied the completion queue from a previous interrupt */
+		SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION);
+
+		/*
+		 * There is a race in the hardware that could cause us not to be notified
+		 * of an interrupt completion if we do not take this step.  We will mask
+		 * then unmask the interrupts so if there is another interrupt pending
+		 * the clearing of the interrupt source we get the next interrupt message. */
+		SMU_IMR_WRITE(scic, 0xFF000000);
+		SMU_IMR_WRITE(scic, 0x00000000);
+	}
+
+	return false;
+}
+
+void scic_sds_controller_completion_handler(struct scic_sds_controller *scic)
+{
+	/* Empty out the completion queue */
+	if (scic_sds_controller_completion_queue_has_entries(scic))
+		scic_sds_controller_process_completions(scic);
+
+	/* Clear the interrupt and enable all interrupts again */
+	SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION);
+	/* Could we write the value of SMU_ISR_COMPLETION? */
+	SMU_IMR_WRITE(scic, 0xFF000000);
+	SMU_IMR_WRITE(scic, 0x00000000);
+}
+
+bool scic_sds_controller_error_isr(struct scic_sds_controller *scic)
+{
+	u32 interrupt_status;
+
+	interrupt_status = SMU_ISR_READ(scic);
+
+	interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+	if (interrupt_status != 0) {
+		/*
+		 * There is an error interrupt pending so let it through and handle
+		 * in the callback */
+		return true;
+	}
+
+	/*
+	 * There is a race in the hardware that could cause us not to be notified
+	 * of an interrupt completion if we do not take this step.  We will mask
+	 * then unmask the error interrupts so if there was another interrupt
+	 * pending we will be notified.
+	 * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */
+	SMU_IMR_WRITE(scic, 0x000000FF);
+	SMU_IMR_WRITE(scic, 0x00000000);
+
+	return false;
+}
+
+void scic_sds_controller_error_handler(struct scic_sds_controller *scic)
+{
+	u32 interrupt_status;
+
+	interrupt_status = SMU_ISR_READ(scic);
+
+	if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
+	    scic_sds_controller_completion_queue_has_entries(scic)) {
+
+		scic_sds_controller_process_completions(scic);
+		SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND);
+
+	} else {
+		dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__,
+			interrupt_status);
+
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(scic),
+			SCI_BASE_CONTROLLER_STATE_FAILED);
+
+		return;
+	}
+
+	/*
+	 * If we dont process any completions I am not sure that we want to do this.
+	 * We are in the middle of a hardware fault and should probably be reset. */
+	SMU_IMR_WRITE(scic, 0x00000000);
+}
+
+
+u32 scic_sds_controller_get_object_size(void)
+{
+	return sizeof(struct scic_sds_controller);
+}
+
+
+void scic_sds_controller_link_up(
+	struct scic_sds_controller *scic,
+	struct scic_sds_port *sci_port,
+	struct scic_sds_phy *sci_phy)
+{
+	scic_sds_controller_phy_handler_t link_up;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	link_up = scic_sds_controller_state_handler_table[state].link_up;
+
+	if (link_up)
+		link_up(scic, sci_port, sci_phy);
+	else
+		dev_dbg(scic_to_dev(scic),
+			"%s: SCIC Controller linkup event from phy %d in "
+			"unexpected state %d\n",
+			__func__,
+			sci_phy->phy_index,
+			sci_base_state_machine_get_state(
+				scic_sds_controller_get_base_state_machine(
+					scic)));
+}
+
+
+void scic_sds_controller_link_down(
+	struct scic_sds_controller *scic,
+	struct scic_sds_port *sci_port,
+	struct scic_sds_phy *sci_phy)
+{
+	u32 state;
+	scic_sds_controller_phy_handler_t link_down;
+
+	state = scic->parent.state_machine.current_state_id;
+	link_down = scic_sds_controller_state_handler_table[state].link_down;
+
+	if (link_down)
+		link_down(scic, sci_port, sci_phy);
+	else
+		dev_dbg(scic_to_dev(scic),
+			"%s: SCIC Controller linkdown event from phy %d in "
+			"unexpected state %d\n",
+			__func__,
+			sci_phy->phy_index, state);
+}
+
+/**
+ * This method is called by the remote device to inform the controller
+ * that this remote device has started.
+ *
+ */
+
+void scic_sds_controller_remote_device_started(struct scic_sds_controller *scic,
+					       struct scic_sds_remote_device *sci_dev)
+{
+	u32 state;
+	scic_sds_controller_device_handler_t started;
+
+	state = scic->parent.state_machine.current_state_id;
+	started = scic_sds_controller_state_handler_table[state].remote_device_started_handler;
+
+	if (started)
+		started(scic, sci_dev);
+	else {
+		dev_dbg(scic_to_dev(scic),
+			 "%s: SCIC Controller 0x%p remote device started event "
+			 "from device 0x%p in unexpected state  %d\n",
+			 __func__, scic, sci_dev, state);
+	}
+}
+
+/**
+ * This is a helper method to determine if any remote devices on this
+ * controller are still in the stopping state.
+ *
+ */
+bool scic_sds_controller_has_remote_devices_stopping(
+	struct scic_sds_controller *this_controller)
+{
+	u32 index;
+
+	for (index = 0; index < this_controller->remote_node_entries; index++) {
+		if ((this_controller->device_table[index] != NULL) &&
+		   (this_controller->device_table[index]->parent.state_machine.current_state_id
+		    == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING))
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * This method is called by the remote device to inform the controller
+ * object that the remote device has stopped.
+ *
+ */
+
+void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic,
+					       struct scic_sds_remote_device *sci_dev)
+{
+
+	u32 state;
+	scic_sds_controller_device_handler_t stopped;
+
+	state = scic->parent.state_machine.current_state_id;
+	stopped = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler;
+
+	if (stopped)
+		stopped(scic, sci_dev);
+	else {
+		dev_dbg(scic_to_dev(scic),
+			"%s: SCIC Controller 0x%p remote device stopped event "
+			"from device 0x%p in unexpected state  %d\n",
+			__func__, scic, sci_dev, state);
+	}
+}
+
+
+
+/**
+ * This method will write to the SCU PCP register the request value. The method
+ *    is used to suspend/resume ports, devices, and phys.
+ * @this_controller:
+ *
+ *
+ */
+void scic_sds_controller_post_request(
+	struct scic_sds_controller *this_controller,
+	u32 request)
+{
+	dev_dbg(scic_to_dev(this_controller),
+		"%s: SCIC Controller 0x%p post request 0x%08x\n",
+		__func__,
+		this_controller,
+		request);
+
+	SMU_PCP_WRITE(this_controller, request);
+}
+
+/**
+ * This method will copy the soft copy of the task context into the physical
+ *    memory accessible by the controller.
+ * @this_controller: This parameter specifies the controller for which to copy
+ *    the task context.
+ * @this_request: This parameter specifies the request for which the task
+ *    context is being copied.
+ *
+ * After this call is made the SCIC_SDS_IO_REQUEST object will always point to
+ * the physical memory version of the task context. Thus, all subsequent
+ * updates to the task context are performed in the TC table (i.e. DMAable
+ * memory). none
+ */
+void scic_sds_controller_copy_task_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_request *this_request)
+{
+	struct scu_task_context *task_context_buffer;
+
+	task_context_buffer = scic_sds_controller_get_task_context_buffer(
+		this_controller, this_request->io_tag
+		);
+
+	memcpy(
+		task_context_buffer,
+		this_request->task_context_buffer,
+		SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac)
+		);
+
+	/*
+	 * Now that the soft copy of the TC has been copied into the TC
+	 * table accessible by the silicon.  Thus, any further changes to
+	 * the TC (e.g. TC termination) occur in the appropriate location. */
+	this_request->task_context_buffer = task_context_buffer;
+}
+
+/**
+ * This method returns the task context buffer for the given io tag.
+ * @this_controller:
+ * @io_tag:
+ *
+ * struct scu_task_context*
+ */
+struct scu_task_context *scic_sds_controller_get_task_context_buffer(
+	struct scic_sds_controller *this_controller,
+	u16 io_tag
+	) {
+	u16 task_index = scic_sds_io_tag_get_index(io_tag);
+
+	if (task_index < this_controller->task_context_entries) {
+		return &this_controller->task_context_table[task_index];
+	}
+
+	return NULL;
+}
+
+/**
+ * This method returnst the sequence value from the io tag value
+ * @this_controller:
+ * @io_tag:
+ *
+ * u16
+ */
+
+/**
+ * This method returns the IO request associated with the tag value
+ * @this_controller:
+ * @io_tag:
+ *
+ * SCIC_SDS_IO_REQUEST_T* NULL if there is no valid IO request at the tag value
+ */
+struct scic_sds_request *scic_sds_controller_get_io_request_from_tag(
+	struct scic_sds_controller *this_controller,
+	u16 io_tag
+	) {
+	u16 task_index;
+	u16 task_sequence;
+
+	task_index = scic_sds_io_tag_get_index(io_tag);
+
+	if (task_index  < this_controller->task_context_entries) {
+		if (this_controller->io_request_table[task_index] != NULL) {
+			task_sequence = scic_sds_io_tag_get_sequence(io_tag);
+
+			if (task_sequence == this_controller->io_request_sequence[task_index]) {
+				return this_controller->io_request_table[task_index];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * This method allocates remote node index and the reserves the remote node
+ *    context space for use. This method can fail if there are no more remote
+ *    node index available.
+ * @this_controller: This is the controller object which contains the set of
+ *    free remote node ids
+ * @the_devce: This is the device object which is requesting the a remote node
+ *    id
+ * @node_id: This is the remote node id that is assinged to the device if one
+ *    is available
+ *
+ * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
+ * node index available.
+ */
+enum sci_status scic_sds_controller_allocate_remote_node_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device,
+	u16 *node_id)
+{
+	u16 node_index;
+	u32 remote_node_count = scic_sds_remote_device_node_count(the_device);
+
+	node_index = scic_sds_remote_node_table_allocate_remote_node(
+		&this_controller->available_remote_nodes, remote_node_count
+		);
+
+	if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+		this_controller->device_table[node_index] = the_device;
+
+		*node_id = node_index;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+}
+
+/**
+ * This method frees the remote node index back to the available pool.  Once
+ *    this is done the remote node context buffer is no longer valid and can
+ *    not be used.
+ * @this_controller:
+ * @the_device:
+ * @node_id:
+ *
+ */
+void scic_sds_controller_free_remote_node_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device,
+	u16 node_id)
+{
+	u32 remote_node_count = scic_sds_remote_device_node_count(the_device);
+
+	if (this_controller->device_table[node_id] == the_device) {
+		this_controller->device_table[node_id] = NULL;
+
+		scic_sds_remote_node_table_release_remote_node_index(
+			&this_controller->available_remote_nodes, remote_node_count, node_id
+			);
+	}
+}
+
+/**
+ * This method returns the union scu_remote_node_context for the specified remote
+ *    node id.
+ * @this_controller:
+ * @node_id:
+ *
+ * union scu_remote_node_context*
+ */
+union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(
+	struct scic_sds_controller *this_controller,
+	u16 node_id
+	) {
+	if (
+		(node_id < this_controller->remote_node_entries)
+		&& (this_controller->device_table[node_id] != NULL)
+		) {
+		return &this_controller->remote_node_context_table[node_id];
+	}
+
+	return NULL;
+}
+
+/**
+ *
+ * @resposne_buffer: This is the buffer into which the D2H register FIS will be
+ *    constructed.
+ * @frame_header: This is the frame header returned by the hardware.
+ * @frame_buffer: This is the frame buffer returned by the hardware.
+ *
+ * This method will combind the frame header and frame buffer to create a SATA
+ * D2H register FIS none
+ */
+void scic_sds_controller_copy_sata_response(
+	void *response_buffer,
+	void *frame_header,
+	void *frame_buffer)
+{
+	memcpy(
+		response_buffer,
+		frame_header,
+		sizeof(u32)
+		);
+
+	memcpy(
+		(char *)((char *)response_buffer + sizeof(u32)),
+		frame_buffer,
+		sizeof(struct sata_fis_reg_d2h) - sizeof(u32)
+		);
+}
+
+/**
+ * This method releases the frame once this is done the frame is available for
+ *    re-use by the hardware.  The data contained in the frame header and frame
+ *    buffer is no longer valid. The UF queue get pointer is only updated if UF
+ *    control indicates this is appropriate.
+ * @this_controller:
+ * @frame_index:
+ *
+ */
+void scic_sds_controller_release_frame(
+	struct scic_sds_controller *this_controller,
+	u32 frame_index)
+{
+	if (scic_sds_unsolicited_frame_control_release_frame(
+		    &this_controller->uf_control, frame_index) == true)
+		SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
+}
+
+/**
+ * This method sets user parameters and OEM parameters to default values.
+ *    Users can override these values utilizing the scic_user_parameters_set()
+ *    and scic_oem_parameters_set() methods.
+ * @controller: This parameter specifies the controller for which to set the
+ *    configuration parameters to their default values.
+ *
+ */
+static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic)
+{
+	u16 index;
+
+	/* Default to no SSC operation. */
+	scic->oem_parameters.sds1.controller.do_enable_ssc = false;
+
+	/* Initialize all of the port parameter information to narrow ports. */
+	for (index = 0; index < SCI_MAX_PORTS; index++) {
+		scic->oem_parameters.sds1.ports[index].phy_mask = 0;
+	}
+
+	/* Initialize all of the phy parameter information. */
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		/*
+		 * Default to 3G (i.e. Gen 2) for now.  User can override if
+		 * they choose. */
+		scic->user_parameters.sds1.phys[index].max_speed_generation = 2;
+
+		/* the frequencies cannot be 0 */
+		scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
+		scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
+		scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
+
+		/*
+		 * Previous Vitesse based expanders had a arbitration issue that
+		 * is worked around by having the upper 32-bits of SAS address
+		 * with a value greater then the Vitesse company identifier.
+		 * Hence, usage of 0x5FCFFFFF. */
+		scic->oem_parameters.sds1.phys[index].sas_address.low = 0x00000001;
+		scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;
+	}
+
+	scic->user_parameters.sds1.stp_inactivity_timeout = 5;
+	scic->user_parameters.sds1.ssp_inactivity_timeout = 5;
+	scic->user_parameters.sds1.stp_max_occupancy_timeout = 5;
+	scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
+	scic->user_parameters.sds1.no_outbound_task_timeout = 20;
+}
+
+
+enum sci_status scic_controller_construct(struct scic_sds_controller *controller,
+					  void __iomem *scu_base,
+					  void __iomem *smu_base)
+{
+	u8 index;
+
+	sci_base_controller_construct(
+		&controller->parent,
+		scic_sds_controller_state_table,
+		controller->memory_descriptors,
+		ARRAY_SIZE(controller->memory_descriptors),
+		NULL
+		);
+
+	controller->scu_registers = scu_base;
+	controller->smu_registers = smu_base;
+
+	scic_sds_port_configuration_agent_construct(&controller->port_agent);
+
+	/* Construct the ports for this controller */
+	for (index = 0; index < SCI_MAX_PORTS; index++)
+		scic_sds_port_construct(&controller->port_table[index],
+					index, controller);
+	scic_sds_port_construct(&controller->port_table[index],
+				SCIC_SDS_DUMMY_PORT, controller);
+
+	/* Construct the phys for this controller */
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		/* Add all the PHYs to the dummy port */
+		scic_sds_phy_construct(
+			&controller->phy_table[index],
+			&controller->port_table[SCI_MAX_PORTS],
+			index
+			);
+	}
+
+	controller->invalid_phy_mask = 0;
+
+	/* Set the default maximum values */
+	controller->completion_event_entries      = SCU_EVENT_COUNT;
+	controller->completion_queue_entries      = SCU_COMPLETION_QUEUE_COUNT;
+	controller->remote_node_entries           = SCI_MAX_REMOTE_DEVICES;
+	controller->logical_port_entries          = SCI_MAX_PORTS;
+	controller->task_context_entries          = SCU_IO_REQUEST_COUNT;
+	controller->uf_control.buffers.count      = SCU_UNSOLICITED_FRAME_COUNT;
+	controller->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT;
+
+	/* Initialize the User and OEM parameters to default values. */
+	scic_sds_controller_set_default_config_parameters(controller);
+
+	return SCI_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_initialize(
+	struct scic_sds_controller *scic)
+{
+	enum sci_status status = SCI_FAILURE_INVALID_STATE;
+	sci_base_controller_handler_t initialize;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	initialize = scic_sds_controller_state_handler_table[state].base.initialize;
+
+	if (initialize)
+		status = initialize(&scic->parent);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller initialize operation requested "
+			 "in invalid state %d\n",
+			 __func__,
+			 sci_base_state_machine_get_state(
+				 scic_sds_controller_get_base_state_machine(
+					 scic)));
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+u32 scic_controller_get_suggested_start_timeout(
+	struct scic_sds_controller *sc)
+{
+	/* Validate the user supplied parameters. */
+	if (sc == NULL)
+		return 0;
+
+	/*
+	 * The suggested minimum timeout value for a controller start operation:
+	 *
+	 *     Signature FIS Timeout
+	 *   + Phy Start Timeout
+	 *   + Number of Phy Spin Up Intervals
+	 *   ---------------------------------
+	 *   Number of milliseconds for the controller start operation.
+	 *
+	 * NOTE: The number of phy spin up intervals will be equivalent
+	 *       to the number of phys divided by the number phys allowed
+	 *       per interval - 1 (once OEM parameters are supported).
+	 *       Currently we assume only 1 phy per interval. */
+
+	return SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+		+ SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
+		+ ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_start(
+	struct scic_sds_controller *scic,
+	u32 timeout)
+{
+	enum sci_status status = SCI_FAILURE_INVALID_STATE;
+	sci_base_controller_timed_handler_t start;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	start = scic_sds_controller_state_handler_table[state].base.start;
+
+	if (start)
+		status = start(&scic->parent, timeout);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller start operation requested in "
+			 "invalid state %d\n",
+			 __func__,
+			 sci_base_state_machine_get_state(
+				 scic_sds_controller_get_base_state_machine(
+					 scic)));
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_stop(
+	struct scic_sds_controller *scic,
+	u32 timeout)
+{
+	enum sci_status status = SCI_FAILURE_INVALID_STATE;
+	sci_base_controller_timed_handler_t stop;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	stop = scic_sds_controller_state_handler_table[state].base.stop;
+
+	if (stop)
+		status = stop(&scic->parent, timeout);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller stop operation requested in "
+			 "invalid state %d\n",
+			 __func__,
+			 sci_base_state_machine_get_state(
+				 scic_sds_controller_get_base_state_machine(
+					 scic)));
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_reset(
+	struct scic_sds_controller *scic)
+{
+	enum sci_status status = SCI_FAILURE_INVALID_STATE;
+	sci_base_controller_handler_t reset;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	reset = scic_sds_controller_state_handler_table[state].base.reset;
+
+	if (reset)
+		status = reset(&scic->parent);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller reset operation requested in "
+			 "invalid state %d\n",
+			 __func__,
+			 sci_base_state_machine_get_state(
+				 scic_sds_controller_get_base_state_machine(
+					 scic)));
+
+	return status;
+}
+
+enum sci_io_status scic_controller_start_io(
+	struct scic_sds_controller *scic,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *io_request,
+	u16 io_tag)
+{
+	u32 state;
+	sci_base_controller_start_request_handler_t start_io;
+
+	state = scic->parent.state_machine.current_state_id;
+	start_io = scic_sds_controller_state_handler_table[state].base.start_io;
+
+	return start_io(&scic->parent,
+			(struct sci_base_remote_device *) remote_device,
+			(struct sci_base_request *)io_request, io_tag);
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_terminate_request(
+	struct scic_sds_controller *scic,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *request)
+{
+	sci_base_controller_request_handler_t terminate_request;
+	u32 state;
+
+	state = scic->parent.state_machine.current_state_id;
+	terminate_request = scic_sds_controller_state_handler_table[state].terminate_request;
+
+	return terminate_request(&scic->parent,
+				 (struct sci_base_remote_device *)remote_device,
+				 (struct sci_base_request *)request);
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_complete_io(
+	struct scic_sds_controller *scic,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *io_request)
+{
+	u32 state;
+	sci_base_controller_request_handler_t complete_io;
+
+	state = scic->parent.state_machine.current_state_id;
+	complete_io = scic_sds_controller_state_handler_table[state].base.complete_io;
+
+	return complete_io(&scic->parent,
+			   (struct sci_base_remote_device *)remote_device,
+			   (struct sci_base_request *)io_request);
+}
+
+/* --------------------------------------------------------------------------- */
+
+
+enum sci_task_status scic_controller_start_task(
+	struct scic_sds_controller *scic,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *task_request,
+	u16 task_tag)
+{
+	u32 state;
+	sci_base_controller_start_request_handler_t start_task;
+	enum sci_task_status status = SCI_TASK_FAILURE_INVALID_STATE;
+
+	state = scic->parent.state_machine.current_state_id;
+	start_task = scic_sds_controller_state_handler_table[state].base.start_task;
+
+	if (start_task)
+		status = start_task(&scic->parent,
+				    (struct sci_base_remote_device *)remote_device,
+				    (struct sci_base_request *)task_request,
+				    task_tag);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller starting task from invalid "
+			 "state\n",
+			 __func__);
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_complete_task(
+	struct scic_sds_controller *scic,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *task_request)
+{
+	u32 state;
+	sci_base_controller_request_handler_t complete_task;
+	enum sci_status status = SCI_FAILURE_INVALID_STATE;
+
+	state = scic->parent.state_machine.current_state_id;
+	complete_task = scic_sds_controller_state_handler_table[state].base.complete_task;
+
+	if (complete_task)
+		status = complete_task(&scic->parent,
+				       (struct sci_base_remote_device *)remote_device,
+				       (struct sci_base_request *)task_request);
+	else
+		dev_warn(scic_to_dev(scic),
+			 "%s: SCIC Controller completing task from invalid "
+			 "state\n",
+			 __func__);
+
+	return status;
+}
+
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_get_port_handle(
+	struct scic_sds_controller *scic,
+	u8 port_index,
+	struct scic_sds_port **port_handle)
+{
+	if (port_index < scic->logical_port_entries) {
+		*port_handle = &scic->port_table[port_index];
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_PORT;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_get_phy_handle(
+	struct scic_sds_controller *scic,
+	u8 phy_index,
+	struct scic_sds_phy **phy_handle)
+{
+	if (phy_index < ARRAY_SIZE(scic->phy_table)) {
+		*phy_handle = &scic->phy_table[phy_index];
+
+		return SCI_SUCCESS;
+	}
+
+	dev_err(scic_to_dev(scic),
+		"%s: Controller:0x%p PhyId:0x%x invalid phy index\n",
+		__func__, scic, phy_index);
+
+	return SCI_FAILURE_INVALID_PHY;
+}
+
+/* --------------------------------------------------------------------------- */
+
+u16 scic_controller_allocate_io_tag(
+	struct scic_sds_controller *scic)
+{
+	u16 task_context;
+	u16 sequence_count;
+
+	if (!sci_pool_empty(scic->tci_pool)) {
+		sci_pool_get(scic->tci_pool, task_context);
+
+		sequence_count = scic->io_request_sequence[task_context];
+
+		return scic_sds_io_tag_construct(sequence_count, task_context);
+	}
+
+	return SCI_CONTROLLER_INVALID_IO_TAG;
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_free_io_tag(
+	struct scic_sds_controller *scic,
+	u16 io_tag)
+{
+	u16 sequence;
+	u16 index;
+
+	BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG);
+
+	sequence = scic_sds_io_tag_get_sequence(io_tag);
+	index    = scic_sds_io_tag_get_index(io_tag);
+
+	if (!sci_pool_full(scic->tci_pool)) {
+		if (sequence == scic->io_request_sequence[index]) {
+			scic_sds_io_sequence_increment(
+				scic->io_request_sequence[index]);
+
+			sci_pool_put(scic->tci_pool, index);
+
+			return SCI_SUCCESS;
+		}
+	}
+
+	return SCI_FAILURE_INVALID_IO_TAG;
+}
+
+/* --------------------------------------------------------------------------- */
+
+void scic_controller_enable_interrupts(
+	struct scic_sds_controller *scic)
+{
+	BUG_ON(scic->smu_registers == NULL);
+	SMU_IMR_WRITE(scic, 0x00000000);
+}
+
+/* --------------------------------------------------------------------------- */
+
+void scic_controller_disable_interrupts(
+	struct scic_sds_controller *scic)
+{
+	BUG_ON(scic->smu_registers == NULL);
+	SMU_IMR_WRITE(scic, 0xffffffff);
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_controller_set_mode(
+	struct scic_sds_controller *scic,
+	enum sci_controller_mode operating_mode)
+{
+	enum sci_status status          = SCI_SUCCESS;
+
+	if ((scic->parent.state_machine.current_state_id ==
+				SCI_BASE_CONTROLLER_STATE_INITIALIZING) ||
+	    (scic->parent.state_machine.current_state_id ==
+				SCI_BASE_CONTROLLER_STATE_INITIALIZED)) {
+		switch (operating_mode) {
+		case SCI_MODE_SPEED:
+			scic->remote_node_entries      = SCI_MAX_REMOTE_DEVICES;
+			scic->task_context_entries     = SCU_IO_REQUEST_COUNT;
+			scic->uf_control.buffers.count =
+				SCU_UNSOLICITED_FRAME_COUNT;
+			scic->completion_event_entries = SCU_EVENT_COUNT;
+			scic->completion_queue_entries =
+				SCU_COMPLETION_QUEUE_COUNT;
+			scic_sds_controller_build_memory_descriptor_table(scic);
+			break;
+
+		case SCI_MODE_SIZE:
+			scic->remote_node_entries      = SCI_MIN_REMOTE_DEVICES;
+			scic->task_context_entries     = SCI_MIN_IO_REQUESTS;
+			scic->uf_control.buffers.count =
+				SCU_MIN_UNSOLICITED_FRAMES;
+			scic->completion_event_entries = SCU_MIN_EVENTS;
+			scic->completion_queue_entries =
+				SCU_MIN_COMPLETION_QUEUE_ENTRIES;
+			scic_sds_controller_build_memory_descriptor_table(scic);
+			break;
+
+		default:
+			status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+			break;
+		}
+	} else
+		status = SCI_FAILURE_INVALID_STATE;
+
+	return status;
+}
+
+/**
+ * scic_sds_controller_reset_hardware() -
+ *
+ * This method will reset the controller hardware.
+ */
+void scic_sds_controller_reset_hardware(
+	struct scic_sds_controller *scic)
+{
+	/* Disable interrupts so we dont take any spurious interrupts */
+	scic_controller_disable_interrupts(scic);
+
+	/* Reset the SCU */
+	SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF);
+
+	/* Delay for 1ms to before clearing the CQP and UFQPR. */
+	udelay(1000);
+
+	/* The write to the CQGR clears the CQP */
+	SMU_CQGR_WRITE(scic, 0x00000000);
+
+	/* The write to the UFQGP clears the UFQPR */
+	SCU_UFQGP_WRITE(scic, 0x00000000);
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_user_parameters_set(
+	struct scic_sds_controller *scic,
+	union scic_user_parameters *scic_parms)
+{
+	if (
+		(scic->parent.state_machine.current_state_id
+		 == SCI_BASE_CONTROLLER_STATE_RESET)
+		|| (scic->parent.state_machine.current_state_id
+		    == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+		|| (scic->parent.state_machine.current_state_id
+		    == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+		) {
+		u16 index;
+
+		/*
+		 * Validate the user parameters.  If they are not legal, then
+		 * return a failure. */
+		for (index = 0; index < SCI_MAX_PHYS; index++) {
+			if (!(scic_parms->sds1.phys[index].max_speed_generation
+			     <= SCIC_SDS_PARM_MAX_SPEED
+			     && scic_parms->sds1.phys[index].max_speed_generation
+			     > SCIC_SDS_PARM_NO_SPEED))
+				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+			if (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3)
+				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+			if (
+			    (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
+			    (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
+			    (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
+			    )
+				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+		}
+
+		if ((scic_parms->sds1.stp_inactivity_timeout == 0) ||
+		   (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
+		   (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
+		   (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
+		   (scic_parms->sds1.no_outbound_task_timeout == 0))
+			return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+		memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms));
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/* --------------------------------------------------------------------------- */
+
+void scic_user_parameters_get(
+	struct scic_sds_controller *scic,
+	union scic_user_parameters *scic_parms)
+{
+	memcpy(scic_parms, (&scic->user_parameters), sizeof(*scic_parms));
+}
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_oem_parameters_set(
+	struct scic_sds_controller *scic,
+	union scic_oem_parameters *scic_parms)
+{
+	if (
+		(scic->parent.state_machine.current_state_id
+		 == SCI_BASE_CONTROLLER_STATE_RESET)
+		|| (scic->parent.state_machine.current_state_id
+		    == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+		|| (scic->parent.state_machine.current_state_id
+		    == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+		) {
+		u16 index;
+
+		/*
+		 * Validate the oem parameters.  If they are not legal, then
+		 * return a failure. */
+		for (index = 0; index < SCI_MAX_PORTS; index++) {
+			if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) {
+				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+			}
+		}
+
+		for (index = 0; index < SCI_MAX_PHYS; index++) {
+			if (
+				scic_parms->sds1.phys[index].sas_address.high == 0
+				&& scic_parms->sds1.phys[index].sas_address.low  == 0
+				) {
+				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+			}
+		}
+
+		memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms));
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/* --------------------------------------------------------------------------- */
+
+void scic_oem_parameters_get(
+	struct scic_sds_controller *scic,
+	union scic_oem_parameters *scic_parms)
+{
+	memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms));
+}
+
+/* --------------------------------------------------------------------------- */
+
+
+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
+#define INTERRUPT_COALESCE_TIMEOUT_MAX_US                    2700000
+#define INTERRUPT_COALESCE_NUMBER_MAX                        256
+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN                7
+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX                28
+
+enum sci_status scic_controller_set_interrupt_coalescence(
+	struct scic_sds_controller *scic_controller,
+	u32 coalesce_number,
+	u32 coalesce_timeout)
+{
+	u8 timeout_encode = 0;
+	u32 min = 0;
+	u32 max = 0;
+
+	/* Check if the input parameters fall in the range. */
+	if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
+		return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+	/*
+	 *  Defined encoding for interrupt coalescing timeout:
+	 *              Value   Min      Max     Units
+	 *              -----   ---      ---     -----
+	 *              0       -        -       Disabled
+	 *              1       13.3     20.0    ns
+	 *              2       26.7     40.0
+	 *              3       53.3     80.0
+	 *              4       106.7    160.0
+	 *              5       213.3    320.0
+	 *              6       426.7    640.0
+	 *              7       853.3    1280.0
+	 *              8       1.7      2.6     us
+	 *              9       3.4      5.1
+	 *              10      6.8      10.2
+	 *              11      13.7     20.5
+	 *              12      27.3     41.0
+	 *              13      54.6     81.9
+	 *              14      109.2    163.8
+	 *              15      218.5    327.7
+	 *              16      436.9    655.4
+	 *              17      873.8    1310.7
+	 *              18      1.7      2.6     ms
+	 *              19      3.5      5.2
+	 *              20      7.0      10.5
+	 *              21      14.0     21.0
+	 *              22      28.0     41.9
+	 *              23      55.9     83.9
+	 *              24      111.8    167.8
+	 *              25      223.7    335.5
+	 *              26      447.4    671.1
+	 *              27      894.8    1342.2
+	 *              28      1.8      2.7     s
+	 *              Others Undefined */
+
+	/*
+	 * Use the table above to decide the encode of interrupt coalescing timeout
+	 * value for register writing. */
+	if (coalesce_timeout == 0)
+		timeout_encode = 0;
+	else{
+		/* make the timeout value in unit of (10 ns). */
+		coalesce_timeout = coalesce_timeout * 100;
+		min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
+		max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
+
+		/* get the encode of timeout for register writing. */
+		for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
+		      timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
+		      timeout_encode++) {
+			if (min <= coalesce_timeout &&  max > coalesce_timeout)
+				break;
+			else if (coalesce_timeout >= max && coalesce_timeout < min * 2
+				 && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) {
+				if ((coalesce_timeout - max) < (2 * min - coalesce_timeout))
+					break;
+				else{
+					timeout_encode++;
+					break;
+				}
+			} else {
+				max = max * 2;
+				min = min * 2;
+			}
+		}
+
+		if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1)
+			/* the value is out of range. */
+			return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+	}
+
+	SMU_ICC_WRITE(
+		scic_controller,
+		(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) |
+		 SMU_ICC_GEN_VAL(TIMER, timeout_encode))
+		);
+
+	scic_controller->interrupt_coalesce_number = (u16)coalesce_number;
+	scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100;
+
+	return SCI_SUCCESS;
+}
+
+
+struct scic_sds_controller *scic_controller_alloc(struct device *dev)
+{
+	return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL);
+}
+
+/*
+ * *****************************************************************************
+ * * DEFAULT STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which, if it was used, would
+ *    be cast to a struct scic_sds_remote_device.
+ * @io_request: This is the struct sci_base_request which, if it was used, would be
+ *    cast to a SCIC_SDS_IO_REQUEST.
+ * @io_tag: This is the IO tag to be assigned to the IO request or
+ *    SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * This method is called when the struct scic_sds_controller default start io/task
+ * handler is in place. - Issue a warning message enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_controller_default_start_operation_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request,
+	u16 io_tag)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	dev_warn(scic_to_dev(this_controller),
+		 "%s: SCIC Controller requested to start an io/task from "
+		 "invalid state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_controller_get_base_state_machine(
+				 this_controller)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which, if it was used, would
+ *    be cast to a struct scic_sds_remote_device.
+ * @io_request: This is the struct sci_base_request which, if it was used, would be
+ *    cast to a SCIC_SDS_IO_REQUEST.
+ *
+ * This method is called when the struct scic_sds_controller default request handler
+ * is in place. - Issue a warning message enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_controller_default_request_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	dev_warn(scic_to_dev(this_controller),
+		"%s: SCIC Controller request operation from invalid state %d\n",
+		__func__,
+		sci_base_state_machine_get_state(
+			scic_sds_controller_get_base_state_machine(
+				this_controller)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/*
+ * *****************************************************************************
+ * * GENERAL (COMMON) STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: The struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state
+ * reset handler is in place. - Transition to
+ * SCI_BASE_CONTROLLER_STATE_RESETTING enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_controller_general_reset_handler(
+	struct sci_base_controller *controller)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	/*
+	 * The reset operation is not a graceful cleanup just perform the state
+	 * transition. */
+	sci_base_state_machine_change_state(
+		scic_sds_controller_get_base_state_machine(this_controller),
+		SCI_BASE_CONTROLLER_STATE_RESETTING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * * RESET STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: This is the struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ *
+ * This method is the struct scic_sds_controller initialize handler for the reset
+ * state. - Currently this function does nothing enum sci_status SCI_FAILURE This
+ * function is not yet implemented and is a valid request from the reset state.
+ */
+static enum sci_status scic_sds_controller_reset_state_initialize_handler(
+	struct sci_base_controller *controller)
+{
+	u32 index;
+	enum sci_status result = SCI_SUCCESS;
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	sci_base_state_machine_change_state(
+		scic_sds_controller_get_base_state_machine(this_controller),
+		SCI_BASE_CONTROLLER_STATE_INITIALIZING
+		);
+
+	this_controller->timeout_timer = isci_event_timer_create(
+		this_controller,
+		(void (*)(void *))scic_sds_controller_timeout_handler,
+		(void (*)(void *))controller);
+
+	scic_sds_controller_initialize_phy_startup(this_controller);
+
+	scic_sds_controller_initialize_power_control(this_controller);
+
+	/*
+	 * There is nothing to do here for B0 since we do not have to
+	 * program the AFE registers.
+	 * / @todo The AFE settings are supposed to be correct for the B0 but
+	 * /       presently they seem to be wrong. */
+	scic_sds_controller_afe_initialization(this_controller);
+
+	if (SCI_SUCCESS == result) {
+		u32 status;
+		u32 terminate_loop;
+
+		/* Take the hardware out of reset */
+		SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
+
+		/*
+		 * / @todo Provide meaningfull error code for hardware failure
+		 * result = SCI_FAILURE_CONTROLLER_HARDWARE; */
+		result = SCI_FAILURE;
+		terminate_loop = 100;
+
+		while (terminate_loop-- && (result != SCI_SUCCESS)) {
+			/* Loop until the hardware reports success */
+			udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME);
+			status = SMU_SMUCSR_READ(this_controller);
+
+			if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) {
+				result = SCI_SUCCESS;
+			}
+		}
+	}
+
+	if (result == SCI_SUCCESS) {
+		u32 max_supported_ports;
+		u32 max_supported_devices;
+		u32 max_supported_io_requests;
+		u32 device_context_capacity;
+
+		/*
+		 * Determine what are the actaul device capacities that the
+		 * hardware will support */
+		device_context_capacity = SMU_DCC_READ(this_controller);
+
+		max_supported_ports =
+			smu_dcc_get_max_ports(device_context_capacity);
+		max_supported_devices =
+			smu_dcc_get_max_remote_node_context(device_context_capacity);
+		max_supported_io_requests =
+			smu_dcc_get_max_task_context(device_context_capacity);
+
+		/* Make all PEs that are unassigned match up with the logical ports */
+		for (index = 0; index < max_supported_ports; index++) {
+			scu_register_write(
+				this_controller,
+				this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
+				index
+				);
+		}
+
+		/* Record the smaller of the two capacity values */
+		this_controller->logical_port_entries =
+			min(max_supported_ports, this_controller->logical_port_entries);
+
+		this_controller->task_context_entries =
+			min(max_supported_io_requests, this_controller->task_context_entries);
+
+		this_controller->remote_node_entries =
+			min(max_supported_devices, this_controller->remote_node_entries);
+
+		/*
+		 * Now that we have the correct hardware reported minimum values
+		 * build the MDL for the controller.  Default to a performance
+		 * configuration. */
+		scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
+	}
+
+	/* Initialize hardware PCI Relaxed ordering in DMA engines */
+	if (result == SCI_SUCCESS) {
+		u32 dma_configuration;
+
+		/* Configure the payload DMA */
+		dma_configuration = SCU_PDMACR_READ(this_controller);
+		dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+		SCU_PDMACR_WRITE(this_controller, dma_configuration);
+
+		/* Configure the control DMA */
+		dma_configuration = SCU_CDMACR_READ(this_controller);
+		dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+		SCU_CDMACR_WRITE(this_controller, dma_configuration);
+	}
+
+	/*
+	 * Initialize the PHYs before the PORTs because the PHY registers
+	 * are accessed during the port initialization. */
+	if (result == SCI_SUCCESS) {
+		/* Initialize the phys */
+		for (index = 0;
+		     (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
+		     index++) {
+			result = scic_sds_phy_initialize(
+				&this_controller->phy_table[index],
+				&this_controller->scu_registers->peg0.pe[index].tl,
+				&this_controller->scu_registers->peg0.pe[index].ll
+				);
+		}
+	}
+
+	if (result == SCI_SUCCESS) {
+		/* Initialize the logical ports */
+		for (index = 0;
+		     (index < this_controller->logical_port_entries)
+		     && (result == SCI_SUCCESS);
+		     index++) {
+			result = scic_sds_port_initialize(
+				&this_controller->port_table[index],
+				&this_controller->scu_registers->peg0.ptsg.port[index],
+				&this_controller->scu_registers->peg0.ptsg.protocol_engine,
+				&this_controller->scu_registers->peg0.viit[index]
+				);
+		}
+	}
+
+	if (SCI_SUCCESS == result) {
+		result = scic_sds_port_configuration_agent_initialize(
+			this_controller,
+			&this_controller->port_agent
+			);
+	}
+
+	/* Advance the controller state machine */
+	if (result == SCI_SUCCESS) {
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(this_controller),
+			SCI_BASE_CONTROLLER_STATE_INITIALIZED
+			);
+	} else {
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(this_controller),
+			SCI_BASE_CONTROLLER_STATE_FAILED
+			);
+	}
+
+	return result;
+}
+
+/*
+ * *****************************************************************************
+ * * INITIALIZED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: This is the struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @timeout: This is the allowed time for the controller object to reach the
+ *    started state.
+ *
+ * This method is the struct scic_sds_controller start handler for the initialized
+ * state. - Validate we have a good memory descriptor table - Initialze the
+ * physical memory before programming the hardware - Program the SCU hardware
+ * with the physical memory addresses passed in the memory descriptor table. -
+ * Initialzie the TCi pool - Initialize the RNi pool - Initialize the
+ * completion queue - Initialize the unsolicited frame data - Take the SCU port
+ * task scheduler out of reset - Start the first phy object. - Transition to
+ * SCI_BASE_CONTROLLER_STATE_STARTING. enum sci_status SCI_SUCCESS if all of the
+ * controller start operations complete
+ * SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the memory
+ * descriptor fields is invalid.
+ */
+static enum sci_status scic_sds_controller_initialized_state_start_handler(
+	struct sci_base_controller *controller,
+	u32 timeout)
+{
+	u16 index;
+	enum sci_status result;
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	/* Make sure that the SCI User filled in the memory descriptor table correctly */
+	result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
+
+	if (result == SCI_SUCCESS) {
+		/* The memory descriptor list looks good so program the hardware */
+		scic_sds_controller_ram_initialization(this_controller);
+	}
+
+	if (result == SCI_SUCCESS) {
+		/* Build the TCi free pool */
+		sci_pool_initialize(this_controller->tci_pool);
+		for (index = 0; index < this_controller->task_context_entries; index++) {
+			sci_pool_put(this_controller->tci_pool, index);
+		}
+
+		/* Build the RNi free pool */
+		scic_sds_remote_node_table_initialize(
+			&this_controller->available_remote_nodes,
+			this_controller->remote_node_entries
+			);
+	}
+
+	if (result == SCI_SUCCESS) {
+		/*
+		 * Before anything else lets make sure we will not be interrupted
+		 * by the hardware. */
+		scic_controller_disable_interrupts(this_controller);
+
+		/* Enable the port task scheduler */
+		scic_sds_controller_enable_port_task_scheduler(this_controller);
+
+		/* Assign all the task entries to this controller physical function */
+		scic_sds_controller_assign_task_entries(this_controller);
+
+		/* Now initialze the completion queue */
+		scic_sds_controller_initialize_completion_queue(this_controller);
+
+		/* Initialize the unsolicited frame queue for use */
+		scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
+	}
+
+	/* Start all of the ports on this controller */
+	for (index = 0; index < this_controller->logical_port_entries &&
+			result == SCI_SUCCESS; index++) {
+		struct scic_sds_port *sci_port = &this_controller->port_table[index];
+
+		result = sci_port->state_handlers->parent.start_handler(&sci_port->parent);
+	}
+
+	if (result == SCI_SUCCESS) {
+		scic_sds_controller_start_next_phy(this_controller);
+
+		isci_event_timer_start(this_controller,
+				    this_controller->timeout_timer,
+				    timeout);
+
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(this_controller),
+			SCI_BASE_CONTROLLER_STATE_STARTING
+			);
+	}
+
+	return result;
+}
+
+/*
+ * *****************************************************************************
+ * * INITIALIZED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: This is struct scic_sds_controller which receives the link up
+ *    notification.
+ * @port: This is struct scic_sds_port with which the phy is associated.
+ * @phy: This is the struct scic_sds_phy which has gone link up.
+ *
+ * This method is called when the struct scic_sds_controller is in the starting state
+ * link up handler is called.  This method will perform the following: - Stop
+ * the phy timer - Start the next phy - Report the link up condition to the
+ * port object none
+ */
+static void scic_sds_controller_starting_state_link_up_handler(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	scic_sds_controller_phy_timer_stop(this_controller);
+
+	this_controller->port_agent.link_up_handler(
+		this_controller, &this_controller->port_agent, port, phy
+		);
+	/* scic_sds_port_link_up(port, phy); */
+
+	scic_sds_controller_start_next_phy(this_controller);
+}
+
+/**
+ *
+ * @controller: This is struct scic_sds_controller which receives the link down
+ *    notification.
+ * @port: This is struct scic_sds_port with which the phy is associated.
+ * @phy: This is the struct scic_sds_phy which has gone link down.
+ *
+ * This method is called when the struct scic_sds_controller is in the starting state
+ * link down handler is called. - Report the link down condition to the port
+ * object none
+ */
+static void scic_sds_controller_starting_state_link_down_handler(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	this_controller->port_agent.link_down_handler(
+		this_controller, &this_controller->port_agent, port, phy
+		);
+	/* scic_sds_port_link_down(port, phy); */
+}
+
+/*
+ * *****************************************************************************
+ * * READY STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: The struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @timeout: The timeout for when the stop operation should report a failure.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state
+ * stop handler is called. - Start the timeout timer - Transition to
+ * SCI_BASE_CONTROLLER_STATE_STOPPING. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_controller_ready_state_stop_handler(
+	struct sci_base_controller *controller,
+	u32 timeout)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	isci_event_timer_start(this_controller,
+			    this_controller->timeout_timer,
+			    timeout);
+
+	sci_base_state_machine_change_state(
+		scic_sds_controller_get_base_state_machine(this_controller),
+		SCI_BASE_CONTROLLER_STATE_STOPPING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ * @io_tag: This is the IO tag to be assigned to the IO request or
+ *    SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state and
+ * the start io handler is called. - Start the io request on the remote device
+ * - if successful - assign the io_request to the io_request_table - post the
+ * request to the hardware enum sci_status SCI_SUCCESS if the start io operation
+ * succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
+ * allocated for the io request. SCI_FAILURE_INVALID_STATE if one or more
+ * objects are not in a valid state to accept io requests. How does the io_tag
+ * parameter get assigned to the io request?
+ */
+static enum sci_status scic_sds_controller_ready_state_start_io_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request,
+	u16 io_tag)
+{
+	enum sci_status status;
+
+	struct scic_sds_controller *this_controller;
+	struct scic_sds_request *the_request;
+	struct scic_sds_remote_device *the_device;
+
+	this_controller = (struct scic_sds_controller *)controller;
+	the_request = (struct scic_sds_request *)io_request;
+	the_device = (struct scic_sds_remote_device *)remote_device;
+
+	status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
+
+	if (status == SCI_SUCCESS) {
+		this_controller->io_request_table[
+			scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+		scic_sds_controller_post_request(
+			this_controller,
+			scic_sds_request_get_post_context(the_request)
+			);
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state and
+ * the complete io handler is called. - Complete the io request on the remote
+ * device - if successful - remove the io_request to the io_request_table
+ * enum sci_status SCI_SUCCESS if the start io operation succeeds
+ * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to
+ * accept io requests.
+ */
+static enum sci_status scic_sds_controller_ready_state_complete_io_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request)
+{
+	u16 index;
+	enum sci_status status;
+	struct scic_sds_controller *this_controller;
+	struct scic_sds_request *the_request;
+	struct scic_sds_remote_device *the_device;
+
+	this_controller = (struct scic_sds_controller *)controller;
+	the_request = (struct scic_sds_request *)io_request;
+	the_device = (struct scic_sds_remote_device *)remote_device;
+
+	status = scic_sds_remote_device_complete_io(
+		this_controller, the_device, the_request);
+
+	if (status == SCI_SUCCESS) {
+		index = scic_sds_io_tag_get_index(the_request->io_tag);
+		this_controller->io_request_table[index] = NULL;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state and
+ * the continue io handler is called. enum sci_status
+ */
+static enum sci_status scic_sds_controller_ready_state_continue_io_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request)
+{
+	struct scic_sds_controller *this_controller;
+	struct scic_sds_request *the_request;
+
+	the_request     = (struct scic_sds_request *)io_request;
+	this_controller = (struct scic_sds_controller *)controller;
+
+	this_controller->io_request_table[
+		scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+	scic_sds_controller_post_request(
+		this_controller,
+		scic_sds_request_get_post_context(the_request)
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ * @task_tag: This is the task tag to be assigned to the task request or
+ *    SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state and
+ * the start task handler is called. - The remote device is requested to start
+ * the task request - if successful - assign the task to the io_request_table -
+ * post the request to the SCU hardware enum sci_status SCI_SUCCESS if the start io
+ * operation succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could
+ * not be allocated for the io request. SCI_FAILURE_INVALID_STATE if one or
+ * more objects are not in a valid state to accept io requests. How does the io
+ * tag get assigned in this code path?
+ */
+static enum sci_status scic_sds_controller_ready_state_start_task_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request,
+	u16 task_tag)
+{
+	struct scic_sds_controller *this_controller = (struct scic_sds_controller *)
+						 controller;
+	struct scic_sds_request *the_request     = (struct scic_sds_request *)
+					      io_request;
+	struct scic_sds_remote_device *the_device      = (struct scic_sds_remote_device *)
+						    remote_device;
+	enum sci_status status;
+
+	status = scic_sds_remote_device_start_task(
+		this_controller, the_device, the_request
+		);
+
+	if (status == SCI_SUCCESS) {
+		this_controller->io_request_table[
+			scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+		scic_sds_controller_post_request(
+			this_controller,
+			scic_sds_request_get_post_context(the_request)
+			);
+	} else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) {
+		this_controller->io_request_table[
+			scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+		/*
+		 * We will let framework know this task request started successfully,
+		 * although core is still woring on starting the request (to post tc when
+		 * RNC is resumed.) */
+		status = SCI_SUCCESS;
+	}
+	return status;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ * This method is called when the struct scic_sds_controller is in the ready state and
+ * the terminate request handler is called. - call the io request terminate
+ * function - if successful - post the terminate request to the SCU hardware
+ * enum sci_status SCI_SUCCESS if the start io operation succeeds
+ * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to
+ * accept io requests.
+ */
+static enum sci_status scic_sds_controller_ready_state_terminate_request_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request)
+{
+	struct scic_sds_controller *this_controller = (struct scic_sds_controller *)
+						 controller;
+	struct scic_sds_request *the_request     = (struct scic_sds_request *)
+					      io_request;
+	enum sci_status status;
+
+	status = scic_sds_io_request_terminate(the_request);
+	if (status == SCI_SUCCESS) {
+		/*
+		 * Utilize the original post context command and or in the POST_TC_ABORT
+		 * request sub-type. */
+		scic_sds_controller_post_request(
+			this_controller,
+			scic_sds_request_get_post_context(the_request)
+			| SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
+			);
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @controller: This is struct scic_sds_controller which receives the link up
+ *    notification.
+ * @port: This is struct scic_sds_port with which the phy is associated.
+ * @phy: This is the struct scic_sds_phy which has gone link up.
+ *
+ * This method is called when the struct scic_sds_controller is in the starting state
+ * link up handler is called.  This method will perform the following: - Stop
+ * the phy timer - Start the next phy - Report the link up condition to the
+ * port object none
+ */
+static void scic_sds_controller_ready_state_link_up_handler(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	this_controller->port_agent.link_up_handler(
+		this_controller, &this_controller->port_agent, port, phy
+		);
+}
+
+/**
+ *
+ * @controller: This is struct scic_sds_controller which receives the link down
+ *    notification.
+ * @port: This is struct scic_sds_port with which the phy is associated.
+ * @phy: This is the struct scic_sds_phy which has gone link down.
+ *
+ * This method is called when the struct scic_sds_controller is in the starting state
+ * link down handler is called. - Report the link down condition to the port
+ * object none
+ */
+static void scic_sds_controller_ready_state_link_down_handler(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	this_controller->port_agent.link_down_handler(
+		this_controller, &this_controller->port_agent, port, phy
+		);
+}
+
+/*
+ * *****************************************************************************
+ * * STOPPING STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ * @io_request: This is the struct sci_base_request which is cast to a
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ * This method is called when the struct scic_sds_controller is in a stopping state
+ * and the complete io handler is called. - This function is not yet
+ * implemented enum sci_status SCI_FAILURE
+ */
+static enum sci_status scic_sds_controller_stopping_state_complete_io_handler(
+	struct sci_base_controller *controller,
+	struct sci_base_remote_device *remote_device,
+	struct sci_base_request *io_request)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)controller;
+
+	/* / @todo Implement this function */
+	return SCI_FAILURE;
+}
+
+/**
+ *
+ * @controller: This is struct sci_base_controller object which is cast into a
+ *    struct scic_sds_controller object.
+ * @remote_device: This is struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device object.
+ *
+ * This method is called when the struct scic_sds_controller is in a stopping state
+ * and the remote device has stopped.
+ **/
+void scic_sds_controller_stopping_state_device_stopped_handler(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device
+)
+{
+	if (!scic_sds_controller_has_remote_devices_stopping(controller)) {
+		sci_base_state_machine_change_state(
+			&controller->parent.state_machine,
+			SCI_BASE_CONTROLLER_STATE_STOPPED
+		);
+	}
+}
+
+const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = {
+	[SCI_BASE_CONTROLLER_STATE_INITIAL] = {
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_RESET] = {
+		.base.initialize   = scic_sds_controller_reset_state_initialize_handler,
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {
+		.base.start        = scic_sds_controller_initialized_state_start_handler,
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_STARTING] = {
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+		.link_up           = scic_sds_controller_starting_state_link_up_handler,
+		.link_down	   = scic_sds_controller_starting_state_link_down_handler
+	},
+	[SCI_BASE_CONTROLLER_STATE_READY] = {
+		.base.stop         = scic_sds_controller_ready_state_stop_handler,
+		.base.reset        = scic_sds_controller_general_reset_handler,
+		.base.start_io     = scic_sds_controller_ready_state_start_io_handler,
+		.base.complete_io  = scic_sds_controller_ready_state_complete_io_handler,
+		.base.continue_io  = scic_sds_controller_ready_state_continue_io_handler,
+		.base.start_task   = scic_sds_controller_ready_state_start_task_handler,
+		.base.complete_task = scic_sds_controller_ready_state_complete_io_handler,
+		.terminate_request = scic_sds_controller_ready_state_terminate_request_handler,
+		.link_up           = scic_sds_controller_ready_state_link_up_handler,
+		.link_down	   = scic_sds_controller_ready_state_link_down_handler
+	},
+	[SCI_BASE_CONTROLLER_STATE_RESETTING] = {
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_STOPPING] = {
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_stopping_state_complete_io_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+		.remote_device_stopped_handler = scic_sds_controller_stopping_state_device_stopped_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_STOPPED] = {
+		.base.reset        = scic_sds_controller_general_reset_handler,
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+	[SCI_BASE_CONTROLLER_STATE_FAILED] = {
+		.base.reset        = scic_sds_controller_general_reset_handler,
+		.base.start_io     = scic_sds_controller_default_start_operation_handler,
+		.base.complete_io  = scic_sds_controller_default_request_handler,
+		.base.continue_io  = scic_sds_controller_default_request_handler,
+		.terminate_request = scic_sds_controller_default_request_handler,
+	},
+};
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on entry
+ * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the
+ * controllers initial state. none This function should initialze the
+ * controller object.
+ */
+static void scic_sds_controller_initial_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	sci_base_state_machine_change_state(
+		&this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on exit
+ * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the
+ * controller starting timeout timer. none
+ */
+static void scic_sds_controller_starting_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *scic = (struct scic_sds_controller *)object;
+
+	isci_event_timer_stop(scic, scic->timeout_timer);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on entry
+ * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the
+ * controllers ready state. none
+ */
+static void scic_sds_controller_ready_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	/* set the default interrupt coalescence number and timeout value. */
+	scic_controller_set_interrupt_coalescence(
+		this_controller, 0x10, 250);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on exit
+ * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none
+ */
+static void scic_sds_controller_ready_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	/* disable interrupt coalescence. */
+	scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on entry
+ * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the
+ * controllers ready state. - Stop the phys on this controller - Stop the ports
+ * on this controller - Stop all of the remote devices on this controller none
+ */
+static void scic_sds_controller_stopping_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	/* Stop all of the components for this controller */
+	scic_sds_controller_stop_phys(this_controller);
+	scic_sds_controller_stop_ports(this_controller);
+	scic_sds_controller_stop_devices(this_controller);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on exit
+ * from the SCI_BASE_CONTROLLER_STATE_STOPPING. - This function stops the
+ * controller stopping timeout timer. none
+ */
+static void scic_sds_controller_stopping_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	isci_event_timer_stop(this_controller, this_controller->timeout_timer);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
+ *    object.
+ *
+ * This method implements the actions taken by the struct scic_sds_controller on entry
+ * to the SCI_BASE_CONTROLLER_STATE_RESETTING. - Set the state handlers to the
+ * controllers resetting state. - Write to the SCU hardware reset register to
+ * force a reset - Transition to the SCI_BASE_CONTROLLER_STATE_RESET none
+ */
+static void scic_sds_controller_resetting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *this_controller;
+
+	this_controller = (struct scic_sds_controller *)object;
+
+	scic_sds_controller_reset_hardware(this_controller);
+
+	sci_base_state_machine_change_state(
+		scic_sds_controller_get_base_state_machine(this_controller),
+		SCI_BASE_CONTROLLER_STATE_RESET
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_controller_state_table[] = {
+	[SCI_BASE_CONTROLLER_STATE_INITIAL] = {
+		.enter_state = scic_sds_controller_initial_state_enter,
+	},
+	[SCI_BASE_CONTROLLER_STATE_RESET] = {},
+	[SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {},
+	[SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {},
+	[SCI_BASE_CONTROLLER_STATE_STARTING] = {
+		.exit_state  = scic_sds_controller_starting_state_exit,
+	},
+	[SCI_BASE_CONTROLLER_STATE_READY] = {
+		.enter_state = scic_sds_controller_ready_state_enter,
+		.exit_state  = scic_sds_controller_ready_state_exit,
+	},
+	[SCI_BASE_CONTROLLER_STATE_RESETTING] = {
+		.enter_state = scic_sds_controller_resetting_state_enter,
+	},
+	[SCI_BASE_CONTROLLER_STATE_STOPPING] = {
+		.enter_state = scic_sds_controller_stopping_state_enter,
+		.exit_state = scic_sds_controller_stopping_state_exit,
+	},
+	[SCI_BASE_CONTROLLER_STATE_STOPPED] = {},
+	[SCI_BASE_CONTROLLER_STATE_FAILED] = {}
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h
new file mode 100644
index 0000000..9b8e55d
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_controller.h
@@ -0,0 +1,722 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_CONTROLLER_H_
+#define _SCIC_SDS_CONTROLLER_H_
+
+#include <linux/string.h>
+
+/**
+ * This file contains the structures, constants and prototypes used for the
+ *    core controller object.
+ *
+ *
+ */
+
+#include "sci_pool.h"
+#include "sci_controller_constants.h"
+#include "sci_memory_descriptor_list.h"
+#include "sci_base_controller.h"
+#include "scic_config_parameters.h"
+#include "scic_sds_port.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_remote_node_table.h"
+#include "scu_registers.h"
+#include "scu_constants.h"
+#include "scu_remote_node_context.h"
+#include "scu_task_context.h"
+#include "scu_unsolicited_frame.h"
+#include "scic_sds_unsolicited_frame_control.h"
+#include "scic_sds_port_configuration_agent.h"
+#include "scic_sds_pci.h"
+
+struct scic_sds_remote_device;
+struct scic_sds_request;
+struct scic_sds_controller;
+
+
+#define SCU_COMPLETION_RAM_ALIGNMENT            (64)
+
+/**
+ * enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS -
+ *
+ * This enumeration depects the types of MDEs that are going to be created for
+ * the controller object.
+ */
+enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS {
+	/**
+	 * Completion queue MDE entry
+	 */
+	SCU_MDE_COMPLETION_QUEUE,
+
+	/**
+	 * Remote node context MDE entry
+	 */
+	SCU_MDE_REMOTE_NODE_CONTEXT,
+
+	/**
+	 * Task context MDE entry
+	 */
+	SCU_MDE_TASK_CONTEXT,
+
+	/**
+	 * Unsolicited frame buffer MDE entrys this is the start of the unsolicited
+	 * frame buffer entries.
+	 */
+	SCU_MDE_UF_BUFFER,
+
+	SCU_MAX_MDES
+};
+
+
+/**
+ *
+ *
+ * Allowed PORT configuration modes APC Automatic PORT configuration mode is
+ * defined by the OEM configuration parameters providing no PHY_MASK parameters
+ * for any PORT. i.e. There are no phys assigned to any of the ports at start.
+ * MPC Manual PORT configuration mode is defined by the OEM configuration
+ * parameters providing a PHY_MASK value for any PORT.  It is assumed that any
+ * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
+ * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
+ * being assigned is sufficient to declare manual PORT configuration.
+ */
+enum SCIC_PORT_CONFIGURATION_MODE {
+	SCIC_PORT_MANUAL_CONFIGURATION_MODE,
+	SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
+};
+
+/**
+ * struct scic_power_control -
+ *
+ * This structure defines the fields for managing power control for direct
+ * attached disk devices.
+ */
+struct scic_power_control {
+	/**
+	 * This field is set when the power control timer is running and cleared when
+	 * it is not.
+	 */
+	bool timer_started;
+
+	/**
+	 * This field is the handle to the driver timer object.  This timer is used to
+	 * control when the directed attached disks can consume power.
+	 */
+	void *timer;
+
+	/**
+	 * This field is used to keep track of how many phys are put into the
+	 * requesters field.
+	 */
+	u8 phys_waiting;
+
+	/**
+	 * This field is an array of phys that we are waiting on. The phys are direct
+	 * mapped into requesters via struct scic_sds_phy.phy_index
+	 */
+	struct scic_sds_phy *requesters[SCI_MAX_PHYS];
+
+};
+
+/**
+ * struct scic_sds_controller -
+ *
+ * This structure represents the SCU contoller object.
+ */
+struct scic_sds_controller {
+	/**
+	 * The struct sci_base_controller is the parent object for the struct scic_sds_controller
+	 * object.
+	 */
+	struct sci_base_controller parent;
+
+	/**
+	 * This field is the driver timer object handler used to time the controller
+	 * object start and stop requests.
+	 */
+	void *timeout_timer;
+
+	/**
+	 * This field contains the user parameters to be utilized for this
+	 * core controller object.
+	 */
+	union scic_user_parameters user_parameters;
+
+	/**
+	 * This field contains the OEM parameters to be utilized for this
+	 * core controller object.
+	 */
+	union scic_oem_parameters oem_parameters;
+
+	/**
+	 * This field contains the port configuration agent for this controller.
+	 */
+	struct scic_sds_port_configuration_agent port_agent;
+
+	/**
+	 * This field is the array of port objects that are controlled by this
+	 * controller object.  There is one dummy port object also contained within
+	 * this controller object.
+	 */
+	struct scic_sds_port port_table[SCI_MAX_PORTS + 1];
+
+	/**
+	 * This field is the array of phy objects that are controlled by this
+	 * controller object.
+	 */
+	struct scic_sds_phy phy_table[SCI_MAX_PHYS];
+
+	/**
+	 * This field is the array of device objects that are currently constructed
+	 * for this controller object.  This table is used as a fast lookup of device
+	 * objects that need to handle device completion notifications from the
+	 * hardware. The table is RNi based.
+	 */
+	struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];
+
+	/**
+	 * This field is the array of IO request objects that are currently active for
+	 * this controller object.  This table is used as a fast lookup of the io
+	 * request object that need to handle completion queue notifications.  The
+	 * table is TCi based.
+	 */
+	struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS];
+
+	/**
+	 * This field is the free RNi data structure
+	 */
+	struct scic_remote_node_table available_remote_nodes;
+
+	/**
+	 * This field is the TCi pool used to manage the task context index.
+	 */
+	SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS);
+
+	/**
+	 * This filed is the struct scic_power_control data used to controll when direct
+	 * attached devices can consume power.
+	 */
+	struct scic_power_control power_control;
+
+	/**
+	 * This field is the array of sequence values for the IO Tag fields.  Even
+	 * though only 4 bits of the field is used for the sequence the sequence is 16
+	 * bits in size so the sequence can be bitwise or'd with the TCi to build the
+	 * IO Tag value.
+	 */
+	u16 io_request_sequence[SCI_MAX_IO_REQUESTS];
+
+	/**
+	 * This field in the array of sequence values for the RNi.  These are used
+	 * to control io request build to io request start operations.  The sequence
+	 * value is recorded into an io request when it is built and is checked on
+	 * the io request start operation to make sure that there was not a device
+	 * hot plug between the build and start operation.
+	 */
+	u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES];
+
+	/**
+	 * This field is a pointer to the memory allocated by the driver for the task
+	 * context table.  This data is shared between the hardware and software.
+	 */
+	struct scu_task_context *task_context_table;
+
+	/**
+	 * This field is a pointer to the memory allocated by the driver for the
+	 * remote node context table.  This table is shared between the hardware and
+	 * software.
+	 */
+	union scu_remote_node_context *remote_node_context_table;
+
+	/**
+	 * This field is the array of physical memory requiremets for this controller
+	 * object.
+	 */
+	struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES];
+
+	/**
+	 * This field is a pointer to the completion queue.  This memory is
+	 * written to by the hardware and read by the software.
+	 */
+	u32 *completion_queue;
+
+	/**
+	 * This field is the software copy of the completion queue get pointer.  The
+	 * controller object writes this value to the hardware after processing the
+	 * completion entries.
+	 */
+	u32 completion_queue_get;
+
+	/**
+	 * This field is the minimum of the number of hardware supported port entries
+	 * and the software requested port entries.
+	 */
+	u32 logical_port_entries;
+
+	/**
+	 * This field is the minimum number of hardware supported completion queue
+	 * entries and the software requested completion queue entries.
+	 */
+	u32 completion_queue_entries;
+
+	/**
+	 * This field is the minimum number of hardware supported event entries and
+	 * the software requested event entries.
+	 */
+	u32 completion_event_entries;
+
+	/**
+	 * This field is the minimum number of devices supported by the hardware and
+	 * the number of devices requested by the software.
+	 */
+	u32 remote_node_entries;
+
+	/**
+	 * This field is the minimum number of IO requests supported by the hardware
+	 * and the number of IO requests requested by the software.
+	 */
+	u32 task_context_entries;
+
+	/**
+	 * This object contains all of the unsolicited frame specific
+	 * data utilized by the core controller.
+	 */
+	struct scic_sds_unsolicited_frame_control uf_control;
+
+	/* Phy Startup Data */
+	/**
+	 * This field is the driver timer handle for controller phy request startup.
+	 * On controller start the controller will start each PHY individually in
+	 * order of phy index.
+	 */
+	void *phy_startup_timer;
+
+	/**
+	 * This field is set when the phy_startup_timer is running and is cleared when
+	 * the phy_startup_timer is stopped.
+	 */
+	bool phy_startup_timer_pending;
+
+	/**
+	 * This field is the index of the next phy start.  It is initialized to 0 and
+	 * increments for each phy index that is started.
+	 */
+	u32 next_phy_to_start;
+
+	/**
+	 * This field controlls the invalid link up notifications to the SCI_USER.  If
+	 * an invalid_link_up notification is reported a bit for the PHY index is set
+	 * so further notifications are not made.  Once the PHY object reports link up
+	 * and is made part of a port then this bit for the PHY index is cleared.
+	 */
+	u8 invalid_phy_mask;
+
+	/*
+	 * This field saves the current interrupt coalescing number of the controller.
+	 */
+	u16 interrupt_coalesce_number;
+
+	/*
+	 * This field saves the current interrupt coalescing timeout value in microseconds.
+	 */
+	u32 interrupt_coalesce_timeout;
+
+	/**
+	 * This field is a pointer to the memory mapped register space for the
+	 * struct smu_registers.
+	 */
+	struct smu_registers __iomem *smu_registers;
+
+	/**
+	 * This field is a pointer to the memory mapped register space for the
+	 * struct scu_registers.
+	 */
+	struct scu_registers __iomem *scu_registers;
+
+};
+
+typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *,
+						  struct scic_sds_port *,
+						  struct scic_sds_phy *);
+
+typedef void (*scic_sds_controller_device_handler_t)(struct scic_sds_controller *,
+						  struct scic_sds_remote_device *);
+
+
+/**
+ * struct scic_sds_controller_state_handler -
+ *
+ * This structure contains the SDS core specific definition for the state
+ * handlers.
+ */
+struct scic_sds_controller_state_handler {
+	struct sci_base_controller_state_handler base;
+
+	sci_base_controller_request_handler_t terminate_request;
+	scic_sds_controller_phy_handler_t link_up;
+	scic_sds_controller_phy_handler_t link_down;
+	scic_sds_controller_device_handler_t remote_device_started_handler;
+	scic_sds_controller_device_handler_t remote_device_stopped_handler;
+};
+
+extern const struct scic_sds_controller_state_handler
+	scic_sds_controller_state_handler_table[];
+extern const struct sci_base_state scic_sds_controller_state_table[];
+
+/**
+ * INCREMENT_QUEUE_GET() -
+ *
+ * This macro will increment the specified index to and if the index wraps to 0
+ * it will toggel the cycle bit.
+ */
+#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \
+	{ \
+		if ((index) + 1 == entry_count) {	\
+			(index) = 0; \
+			(cycle) = (cycle) ^ (bit_toggle); \
+		} else { \
+			index = index + 1; \
+		} \
+	}
+
+/**
+ * scic_sds_controller_get_base_state_machine() -
+ *
+ * This is a helper macro that gets the base state machine for the controller
+ * object
+ */
+#define scic_sds_controller_get_base_state_machine(this_controller) \
+	(&(this_controller)->parent.state_machine)
+
+/**
+ * scic_sds_controller_get_port_configuration_agent() -
+ *
+ * This is a helper macro to get the port configuration agent from the
+ * controller object.
+ */
+#define scic_sds_controller_get_port_configuration_agent(controller) \
+	(&(controller)->port_agent)
+
+/**
+ * smu_register_write() -
+ *
+ * This macro writes to the smu_register for this controller
+ */
+#define smu_register_write(controller, reg, value) \
+	scic_sds_pci_write_smu_dword((controller), &(reg), (value))
+
+/**
+ * smu_register_read() -
+ *
+ * This macro reads the smu_register for this controller
+ */
+#define smu_register_read(controller, reg) \
+	scic_sds_pci_read_smu_dword((controller), &(reg))
+
+/**
+ * scu_register_write() -
+ *
+ * This mcaro writes the scu_register for this controller
+ */
+#define scu_register_write(controller, reg, value) \
+	scic_sds_pci_write_scu_dword((controller), &(reg), (value))
+
+/**
+ * scu_register_read() -
+ *
+ * This macro reads the scu_register for this controller
+ */
+#define scu_register_read(controller, reg) \
+	scic_sds_pci_read_scu_dword((controller), &(reg))
+
+/**
+ * scic_sds_controller_get_protocol_engine_group() -
+ *
+ * This macro returns the protocol engine group for this controller object.
+ * Presently we only support protocol engine group 0 so just return that
+ */
+#define scic_sds_controller_get_protocol_engine_group(controller) 0
+
+/**
+ * scic_sds_io_tag_construct() -
+ *
+ * This macro constructs an IO tag from the sequence and index values.
+ */
+#define scic_sds_io_tag_construct(sequence, task_index)	\
+	((sequence) << 12 | (task_index))
+
+/**
+ * scic_sds_io_tag_get_sequence() -
+ *
+ * This macro returns the IO sequence from the IO tag value.
+ */
+#define scic_sds_io_tag_get_sequence(io_tag) \
+	(((io_tag) & 0xF000) >> 12)
+
+/**
+ * scic_sds_io_tag_get_index() -
+ *
+ * This macro returns the TCi from the io tag value
+ */
+#define scic_sds_io_tag_get_index(io_tag) \
+	((io_tag) & 0x0FFF)
+
+/**
+ * scic_sds_io_sequence_increment() -
+ *
+ * This is a helper macro to increment the io sequence count. We may find in
+ * the future that it will be faster to store the sequence count in such a way
+ * as we dont perform the shift operation to build io tag values so therefore
+ * need a way to incrment them correctly
+ */
+#define scic_sds_io_sequence_increment(value) \
+	((value) = (((value) + 1) & 0x000F))
+
+#define scic_sds_remote_device_node_count(device) \
+	(\
+		(\
+			(device)->target_protocols.u.bits.attached_stp_target \
+			&& ((device)->is_direct_attached != true) \
+		) \
+		? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT	\
+	)
+
+/**
+ * scic_sds_controller_set_invalid_phy() -
+ *
+ * This macro will set the bit in the invalid phy mask for this controller
+ * object.  This is used to control messages reported for invalid link up
+ * notifications.
+ */
+#define scic_sds_controller_set_invalid_phy(controller, phy) \
+	((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))
+
+/**
+ * scic_sds_controller_clear_invalid_phy() -
+ *
+ * This macro will clear the bit in the invalid phy mask for this controller
+ * object.  This is used to control messages reported for invalid link up
+ * notifications.
+ */
+#define scic_sds_controller_clear_invalid_phy(controller, phy) \
+	((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
+
+/* --------------------------------------------------------------------------- */
+
+u32 scic_sds_controller_get_object_size(void);
+
+/* --------------------------------------------------------------------------- */
+
+
+/* --------------------------------------------------------------------------- */
+
+enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
+	struct scic_sds_controller *this_controller);
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_controller_post_request(
+	struct scic_sds_controller *this_controller,
+	u32 request);
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_controller_release_frame(
+	struct scic_sds_controller *this_controller,
+	u32 frame_index);
+
+void scic_sds_controller_copy_sata_response(
+	void *response_buffer,
+	void *frame_header,
+	void *frame_buffer);
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_controller_allocate_remote_node_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device,
+	u16 *node_id);
+
+void scic_sds_controller_free_remote_node_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device,
+	u16 node_id);
+
+union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(
+	struct scic_sds_controller *this_controller,
+	u16 node_id);
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_request *scic_sds_controller_get_io_request_from_tag(
+	struct scic_sds_controller *this_controller,
+	u16 io_tag);
+
+
+struct scu_task_context *scic_sds_controller_get_task_context_buffer(
+	struct scic_sds_controller *this_controller,
+	u16 io_tag);
+
+/*
+ * *****************************************************************************
+ * * CORE CONTROLLER POWER CONTROL METHODS
+ * ***************************************************************************** */
+
+
+void scic_sds_controller_power_control_queue_insert(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_phy *the_phy);
+
+void scic_sds_controller_power_control_queue_remove(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_phy *the_phy);
+
+/*
+ * *****************************************************************************
+ * * CORE CONTROLLER PHY MESSAGE PROCESSING
+ * ***************************************************************************** */
+
+void scic_sds_controller_link_up(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *the_port,
+	struct scic_sds_phy *the_phy);
+
+void scic_sds_controller_link_down(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_port *the_port,
+	struct scic_sds_phy *the_phy);
+
+/*
+ * *****************************************************************************
+ * * CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING
+ * ***************************************************************************** */
+
+bool scic_sds_controller_has_remote_devices_stopping(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_remote_device_started(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device);
+
+void scic_sds_controller_remote_device_stopped(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_remote_device *the_device);
+
+
+/*
+ * *****************************************************************************
+ * * CORE CONTROLLER PRIVATE METHODS
+ * ***************************************************************************** */
+
+enum sci_status scic_sds_controller_validate_memory_descriptor_table(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_ram_initialization(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_assign_task_entries(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_afe_initialization(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_enable_port_task_scheduler(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_initialize_completion_queue(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_initialize_unsolicited_frame_queue(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_phy_timer_stop(
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_controller_start_next_phy(
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_controller_stop_phys(
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_controller_stop_ports(
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_controller_stop_devices(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_copy_task_context(
+	struct scic_sds_controller *this_controller,
+	struct scic_sds_request *this_request);
+
+void scic_sds_controller_timeout_handler(
+	struct scic_sds_controller *controller);
+
+void scic_sds_controller_initialize_power_control(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_register_setup(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_reset_hardware(
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_controller_initialize_phy_startup(
+	struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_build_memory_descriptor_table(
+	struct scic_sds_controller *this_controller);
+
+#endif /* _SCIC_SDS_CONTROLLER_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_controller_registers.h b/drivers/scsi/isci/core/scic_sds_controller_registers.h
new file mode 100644
index 0000000..b7bec92
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_controller_registers.h
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_
+#define _SCIC_SDS_CONTROLLER_REGISTERS_H_
+
+/**
+ * This file contains macros used to perform the register reads/writes to the
+ *    SCU hardware.
+ *
+ *
+ */
+
+#include "scu_registers.h"
+#include "scic_sds_controller.h"
+
+/**
+ * scic_sds_controller_smu_register_read() -
+ *
+ * SMU_REGISTER_ACCESS_MACROS
+ */
+#define scic_sds_controller_smu_register_read(controller, reg) \
+	smu_register_read(\
+		(controller), \
+		(controller)->smu_registers->reg \
+		)
+
+#define scic_sds_controller_smu_register_write(controller, reg, value) \
+	smu_register_write(\
+		(controller), \
+		(controller)->smu_registers->reg, \
+		(value)	\
+		)
+
+/**
+ * scu_afe_register_write() -
+ *
+ * AFE_REGISTER_ACCESS_MACROS
+ */
+#define scu_afe_register_write(controller, reg, value) \
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->afe.reg, \
+		(value)	\
+		)
+
+#define scu_afe_txreg_write(controller, phy, reg, value) \
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\
+		(value) \
+		)
+
+#define scu_afe_register_read(controller, reg) \
+	scu_register_read(\
+		(controller), \
+		(controller)->scu_registers->afe.reg \
+		)
+
+/**
+ * scu_controller_viit_register_write() -
+ *
+ * VIIT_REGISTER_ACCESS_MACROS
+ */
+#define scu_controller_viit_register_write(controller, index, reg, value) \
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->peg0.viit[index].reg, \
+		value \
+		)
+
+/*
+ * *****************************************************************************
+ * * SMU REGISTERS
+ * ***************************************************************************** */
+
+/**
+ * SMU_PCP_WRITE() -
+ *
+ * struct smu_registers
+ */
+#define SMU_PCP_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, post_context_port, value \
+		)
+
+#define SMU_TCR_READ(controller, value)	\
+	scic_sds_controller_smu_register_read(\
+		controller, task_context_range \
+		)
+
+#define SMU_TCR_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, task_context_range, value \
+		)
+
+#define SMU_HTTBAR_WRITE(controller, address) \
+	{ \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			host_task_table_lower, \
+			lower_32_bits(address) \
+			); \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			host_task_table_upper, \
+			upper_32_bits(address) \
+			); \
+	}
+
+#define SMU_CQBAR_WRITE(controller, address) \
+	{ \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			completion_queue_lower,	\
+			lower_32_bits(address) \
+			); \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			completion_queue_upper,	\
+			upper_32_bits(address) \
+			); \
+	}
+
+#define SMU_CQGR_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, completion_queue_get, value	\
+		)
+
+#define SMU_CQGR_READ(controller, value) \
+	scic_sds_controller_smu_register_read(\
+		controller, completion_queue_get \
+		)
+
+#define SMU_CQPR_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, completion_queue_put, value	\
+		)
+
+#define SMU_RNCBAR_WRITE(controller, address) \
+	{ \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			remote_node_context_lower, \
+			lower_32_bits(address) \
+			); \
+		scic_sds_controller_smu_register_write(\
+			controller, \
+			remote_node_context_upper, \
+			upper_32_bits(address) \
+			); \
+	}
+
+#define SMU_AMR_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, address_modifier \
+		)
+
+#define SMU_IMR_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, interrupt_mask \
+		)
+
+#define SMU_IMR_WRITE(controller, mask)	\
+	scic_sds_controller_smu_register_write(\
+		controller, interrupt_mask, mask \
+		)
+
+#define SMU_ISR_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, interrupt_status \
+		)
+
+#define SMU_ISR_WRITE(controller, status) \
+	scic_sds_controller_smu_register_write(\
+		controller, interrupt_status, status \
+		)
+
+#define SMU_ICC_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, interrupt_coalesce_control \
+		)
+
+#define SMU_ICC_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, interrupt_coalesce_control, value \
+		)
+
+#define SMU_CQC_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, completion_queue_control, value \
+		)
+
+#define SMU_SMUSRCR_WRITE(controller, value) \
+	scic_sds_controller_smu_register_write(\
+		controller, soft_reset_control, value \
+		)
+
+#define SMU_TCA_WRITE(controller, index, value)	\
+	scic_sds_controller_smu_register_write(\
+		controller, task_context_assignment[index], value \
+		)
+
+#define SMU_TCA_READ(controller, index)	\
+	scic_sds_controller_smu_register_read(\
+		controller, task_context_assignment[index] \
+		)
+
+#define SMU_DCC_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, device_context_capacity \
+		)
+
+#define SMU_DFC_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, device_function_capacity \
+		)
+
+#define SMU_SMUCSR_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, control_status \
+		)
+
+#define SMU_CQPR_READ(controller) \
+	scic_sds_controller_smu_register_read(\
+		controller, completion_queue_put \
+		)
+
+
+/**
+ * scic_sds_controller_scu_register_read() -
+ *
+ * SCU_REGISTER_ACCESS_MACROS
+ */
+#define scic_sds_controller_scu_register_read(controller, reg) \
+	scu_register_read(\
+		(controller), \
+		(controller)->scu_registers->reg \
+		)
+
+#define scic_sds_controller_scu_register_write(controller, reg, value) \
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->reg, \
+		(value)	\
+		)
+
+
+/*
+ * ****************************************************************************
+ * *  SCU SDMA REGISTERS
+ * **************************************************************************** */
+
+/**
+ * scu_sdma_register_read() -
+ *
+ * SCU_SDMA_REGISTER_ACCESS_MACROS
+ */
+#define scu_sdma_register_read(controller, reg)	\
+	scu_register_read(\
+		(controller), \
+		(controller)->scu_registers->sdma.reg \
+		)
+
+#define scu_sdma_register_write(controller, reg, value)	\
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->sdma.reg, \
+		(value)	\
+		)
+
+/**
+ * SCU_PUFATHAR_WRITE() -
+ *
+ * struct scu_sdma_registers
+ */
+#define SCU_PUFATHAR_WRITE(controller, address)	\
+	{ \
+		scu_sdma_register_write(\
+			controller, \
+			uf_address_table_lower,	\
+			lower_32_bits(address) \
+			); \
+		scu_sdma_register_write(\
+			controller, \
+			uf_address_table_upper,	\
+			upper_32_bits(address) \
+			); \
+	}
+
+#define SCU_UFHBAR_WRITE(controller, address) \
+	{ \
+		scu_sdma_register_write(\
+			controller, \
+			uf_header_base_address_lower, \
+			lower_32_bits(address) \
+			); \
+		scu_sdma_register_write(\
+			controller, \
+			uf_header_base_address_upper, \
+			upper_32_bits(address) \
+			); \
+	}
+
+#define SCU_UFQC_READ(controller) \
+	scu_sdma_register_read(\
+		controller,  \
+		unsolicited_frame_queue_control	\
+		)
+
+#define SCU_UFQC_WRITE(controller, value) \
+	scu_sdma_register_write(\
+		controller, \
+		unsolicited_frame_queue_control, \
+		value \
+		)
+
+#define SCU_UFQPP_READ(controller) \
+	scu_sdma_register_read(\
+		controller, \
+		unsolicited_frame_put_pointer \
+		)
+
+#define SCU_UFQPP_WRITE(controller, value) \
+	scu_sdma_register_write(\
+		controller, \
+		unsolicited_frame_put_pointer, \
+		value \
+		)
+
+#define SCU_UFQGP_WRITE(controller, value) \
+	scu_sdma_register_write(\
+		controller, \
+		unsolicited_frame_get_pointer, \
+		value \
+		)
+
+#define SCU_PDMACR_READ(controller) \
+	scu_sdma_register_read(\
+		controller, \
+		pdma_configuration \
+		)
+
+#define SCU_PDMACR_WRITE(controller, value) \
+	scu_sdma_register_write(\
+		controller, \
+		pdma_configuration, \
+		value \
+		)
+
+#define SCU_CDMACR_READ(controller) \
+	scu_sdma_register_read(\
+		controller, \
+		cdma_configuration \
+		)
+
+#define SCU_CDMACR_WRITE(controller, value) \
+	scu_sdma_register_write(\
+		controller, \
+		cdma_configuration, \
+		value \
+		)
+
+/*
+ * *****************************************************************************
+ * * SCU Port Task Scheduler Group Registers
+ * ***************************************************************************** */
+
+/**
+ * scu_ptsg_register_read() -
+ *
+ * SCU_PTSG_REGISTER_ACCESS_MACROS
+ */
+#define scu_ptsg_register_read(controller, reg)	\
+	scu_register_read(\
+		(controller), \
+		(controller)->scu_registers->peg0.ptsg.reg \
+		)
+
+#define scu_ptsg_register_write(controller, reg, value)	\
+	scu_register_write(\
+		(controller), \
+		(controller)->scu_registers->peg0.ptsg.reg, \
+		(value)	\
+		)
+
+/**
+ * SCU_PTSGCR_READ() -
+ *
+ * SCU_PTSG_REGISTERS
+ */
+#define SCU_PTSGCR_READ(controller) \
+	scu_ptsg_register_read(\
+		(controller), \
+		control	\
+		)
+
+#define SCU_PTSGCR_WRITE(controller, value) \
+	scu_ptsg_register_write(\
+		(controller), \
+		control, \
+		value \
+		)
+
+#define SCU_PTSGRTC_READ(controller) \
+	scu_ptsg_register_read(\
+		contoller, \
+		real_time_clock	\
+		)
+
+#endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 02/10] isci/core: phy
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 01/10] isci/core: controller Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 03/10] isci/core: port Dan Williams
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Phy state machines and hardware interface.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/sci_base_phy.h           |  200 ++
 drivers/scsi/isci/core/scic_phy.h               |  305 +++
 drivers/scsi/isci/core/scic_sds_phy.c           | 2726 +++++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_phy.h           |  476 ++++
 drivers/scsi/isci/core/scic_sds_phy_registers.h |  248 ++
 5 files changed, 3955 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_phy.h
 create mode 100644 drivers/scsi/isci/core/scic_phy.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_phy_registers.h

diff --git a/drivers/scsi/isci/core/sci_base_phy.h b/drivers/scsi/isci/core/sci_base_phy.h
new file mode 100644
index 0000000..7e2c7e3
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_phy.h
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_PHY_H_
+#define _SCI_BASE_PHY_H_
+
+/**
+ * This file contains all of the structures, constants, and methods common to
+ *    all phy object definitions.
+ *
+ *
+ */
+
+#include "sci_base_state_machine.h"
+
+/**
+ * enum sci_base_phy_states - This enumeration depicts the standard states
+ *    common to all phy state machine implementations.
+ *
+ *
+ */
+enum sci_base_phy_states {
+	/**
+	 * Simply the initial state for the base domain state machine.
+	 */
+	SCI_BASE_PHY_STATE_INITIAL,
+
+	/**
+	 * This state indicates that the phy has successfully been stopped.
+	 * In this state no new IO operations are permitted on this phy.
+	 * This state is entered from the INITIAL state.
+	 * This state is entered from the STARTING state.
+	 * This state is entered from the READY state.
+	 * This state is entered from the RESETTING state.
+	 */
+	SCI_BASE_PHY_STATE_STOPPED,
+
+	/**
+	 * This state indicates that the phy is in the process of becomming
+	 * ready.  In this state no new IO operations are permitted on this phy.
+	 * This state is entered from the STOPPED state.
+	 * This state is entered from the READY state.
+	 * This state is entered from the RESETTING state.
+	 */
+	SCI_BASE_PHY_STATE_STARTING,
+
+	/**
+	 * This state indicates the the phy is now ready.  Thus, the user
+	 * is able to perform IO operations utilizing this phy as long as it
+	 * is currently part of a valid port.
+	 * This state is entered from the STARTING state.
+	 */
+	SCI_BASE_PHY_STATE_READY,
+
+	/**
+	 * This state indicates that the phy is in the process of being reset.
+	 * In this state no new IO operations are permitted on this phy.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_PHY_STATE_RESETTING,
+
+	/**
+	 * Simply the final state for the base phy state machine.
+	 */
+	SCI_BASE_PHY_STATE_FINAL,
+};
+
+/**
+ * struct sci_base_phy - This structure defines all of the fields common to PHY
+ *    objects.
+ *
+ *
+ */
+struct sci_base_phy {
+	/**
+	 * This field depicts the parent object (struct sci_base_object) for the phy.
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This field contains the information for the base phy state machine.
+	 */
+	struct sci_base_state_machine state_machine;
+};
+
+typedef enum sci_status (*sci_base_phy_handler_t)(struct sci_base_phy *);
+
+/**
+ * struct sci_base_phy_state_handler - This structure contains all of the state
+ *    handler methods common to base phy state machines.  Handler methods
+ *    provide the ability to change the behavior for user requests or
+ *    transitions depending on the state the machine is in.
+ *
+ *
+ */
+struct sci_base_phy_state_handler {
+	/**
+	 * The start_handler specifies the method invoked when there is an
+	 * attempt to start a phy.
+	 */
+	sci_base_phy_handler_t start_handler;
+
+	/**
+	 * The stop_handler specifies the method invoked when there is an
+	 * attempt to stop a phy.
+	 */
+	sci_base_phy_handler_t stop_handler;
+
+	/**
+	 * The reset_handler specifies the method invoked when there is an
+	 * attempt to reset a phy.
+	 */
+	sci_base_phy_handler_t reset_handler;
+
+	/**
+	 * The destruct_handler specifies the method invoked when attempting to
+	 * destruct a phy.
+	 */
+	sci_base_phy_handler_t destruct_handler;
+
+};
+
+/**
+ * sci_base_phy_construct() - Construct the base phy
+ * @this_phy: This parameter specifies the base phy to be constructed.
+ * @state_table: This parameter specifies the table of state definitions to be
+ *    utilized for the phy state machine.
+ *
+ */
+static inline void sci_base_phy_construct(
+	struct sci_base_phy *base_phy,
+	const struct sci_base_state *state_table)
+{
+	base_phy->parent.private = NULL;
+	sci_base_state_machine_construct(
+		&base_phy->state_machine,
+		&base_phy->parent,
+		state_table,
+		SCI_BASE_PHY_STATE_INITIAL
+		);
+
+	sci_base_state_machine_start(
+		&base_phy->state_machine
+		);
+}
+
+
+#endif /* _SCI_BASE_PHY_H_ */
diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h
new file mode 100644
index 0000000..bf0d3be
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_phy.h
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_PHY_H_
+#define _SCIC_PHY_H_
+
+/**
+ * This file contains all of the interface methods that can be called by an
+ *    SCIC user on a phy (SAS or SATA) object.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+
+#include "intel_sata.h"
+#include "intel_sas.h"
+
+struct scic_sds_phy;
+struct scic_sds_port;
+
+
+enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy);
+
+/**
+ * struct scic_phy_properties - This structure defines the properties common to
+ *    all phys that can be retrieved.
+ *
+ *
+ */
+struct scic_phy_properties {
+	/**
+	 * This field specifies the port that currently contains the
+	 * supplied phy.  This field may be set to NULL
+	 * if the phy is not currently contained in a port.
+	 */
+	struct scic_sds_port *owning_port;
+
+	/**
+	 * This field specifies the link rate at which the phy is
+	 * currently operating.
+	 */
+	enum sci_sas_link_rate negotiated_link_rate;
+
+	/**
+	 * This field indicates the protocols supported by the phy.
+	 */
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+	/**
+	 * This field specifies the index of the phy in relation to other
+	 * phys within the controller.  This index is zero relative.
+	 */
+	u8 index;
+
+};
+
+/**
+ * struct scic_sas_phy_properties - This structure defines the properties,
+ *    specific to a SAS phy, that can be retrieved.
+ *
+ *
+ */
+struct scic_sas_phy_properties {
+	/**
+	 * This field delineates the Identify Address Frame received
+	 * from the remote end point.
+	 */
+	struct sci_sas_identify_address_frame received_iaf;
+
+	/**
+	 * This field delineates the Phy capabilities structure received
+	 * from the remote end point.
+	 */
+	struct sas_capabilities received_capabilities;
+
+};
+
+/**
+ * struct scic_sata_phy_properties - This structure defines the properties,
+ *    specific to a SATA phy, that can be retrieved.
+ *
+ *
+ */
+struct scic_sata_phy_properties {
+	/**
+	 * This field delineates the signature FIS received from the
+	 * attached target.
+	 */
+	struct sata_fis_reg_d2h signature_fis;
+
+	/**
+	 * This field specifies to the user if a port selector is connected
+	 * on the specified phy.
+	 */
+	bool is_port_selector_present;
+
+};
+
+/**
+ * enum scic_phy_counter_id - This enumeration depicts the various pieces of
+ *    optional information that can be retrieved for a specific phy.
+ *
+ *
+ */
+enum scic_phy_counter_id {
+	/**
+	 * This PHY information field tracks the number of frames received.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_FRAME,
+
+	/**
+	 * This PHY information field tracks the number of frames transmitted.
+	 */
+	SCIC_PHY_COUNTER_TRANSMITTED_FRAME,
+
+	/**
+	 * This PHY information field tracks the number of DWORDs received.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD,
+
+	/**
+	 * This PHY information field tracks the number of DWORDs transmitted.
+	 */
+	SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD,
+
+	/**
+	 * This PHY information field tracks the number of times DWORD
+	 * synchronization was lost.
+	 */
+	SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR,
+
+	/**
+	 * This PHY information field tracks the number of received DWORDs with
+	 * running disparity errors.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR,
+
+	/**
+	 * This PHY information field tracks the number of received frames with a
+	 * CRC error (not including short or truncated frames).
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR,
+
+	/**
+	 * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
+	 * primitives received.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT,
+
+	/**
+	 * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
+	 * primitives transmitted.
+	 */
+	SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT,
+
+	/**
+	 * This PHY information field tracks the number of times the inactivity
+	 * timer for connections on the phy has been utilized.
+	 */
+	SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED,
+
+	/**
+	 * This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
+	 * primitives received.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT,
+
+	/**
+	 * This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
+	 * primitives transmitted.
+	 */
+	SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT,
+
+	/**
+	 * This PHY information field tracks the number of CREDIT BLOCKED
+	 * primitives received.
+	 * @note Depending on remote device implementation, credit blocks
+	 *       may occur regularly.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED,
+
+	/**
+	 * This PHY information field contains the number of short frames
+	 * received.  A short frame is simply a frame smaller then what is
+	 * allowed by either the SAS or SATA specification.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME,
+
+	/**
+	 * This PHY information field contains the number of frames received after
+	 * credit has been exhausted.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT,
+
+	/**
+	 * This PHY information field contains the number of frames received after
+	 * a DONE has been received.
+	 */
+	SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE,
+
+	/**
+	 * This PHY information field contains the number of times the phy
+	 * failed to achieve DWORD synchronization during speed negotiation.
+	 */
+	SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR
+};
+
+
+/**
+ * scic_sas_phy_get_properties() - This method will enable the user to retrieve
+ *    information specific to a SAS phy, such as: the received identify address
+ *    frame, received phy capabilities, etc.
+ * @phy: this parameter specifies the phy for which to retrieve properties.
+ * @properties: This parameter specifies the properties structure into which to
+ *    copy the requested information.
+ *
+ * This method returns an indication as to whether the SAS phy properties were
+ * successfully retrieved. SCI_SUCCESS This value is returned if the SAS
+ * properties are successfully retrieved. SCI_FAILURE This value is returned if
+ * the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy).
+ */
+enum sci_status scic_sas_phy_get_properties(
+	struct scic_sds_phy *phy,
+	struct scic_sas_phy_properties *properties);
+
+/**
+ * scic_sata_phy_get_properties() - This method will enable the user to
+ *    retrieve information specific to a SATA phy, such as: the received
+ *    signature FIS, if a port selector is present, etc.
+ * @phy: this parameter specifies the phy for which to retrieve properties.
+ * @properties: This parameter specifies the properties structure into which to
+ *    copy the requested information.
+ *
+ * This method returns an indication as to whether the SATA phy properties were
+ * successfully retrieved. SCI_SUCCESS This value is returned if the SATA
+ * properties are successfully retrieved. SCI_FAILURE This value is returned if
+ * the SATA properties are not successfully retrieved (e.g. It's not a SATA
+ * Phy).
+ */
+enum sci_status scic_sata_phy_get_properties(
+	struct scic_sds_phy *phy,
+	struct scic_sata_phy_properties *properties);
+
+
+
+
+
+
+
+#endif  /* _SCIC_PHY_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c
new file mode 100644
index 0000000..2717458
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy.c
@@ -0,0 +1,2726 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_ata.h"
+#include "intel_sata.h"
+#include "sci_base_state.h"
+#include "sci_base_state_machine.h"
+#include "scic_phy.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_phy_registers.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_node_context.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_event_codes.h"
+
+#define SCIC_SDS_PHY_MIN_TIMER_COUNT  (SCI_MAX_PHYS)
+#define SCIC_SDS_PHY_MAX_TIMER_COUNT  (SCI_MAX_PHYS)
+
+/* Maximum arbitration wait time in micro-seconds */
+#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME  (700)
+
+enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy)
+{
+	return sci_phy->max_negotiated_speed;
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY Internal Methods
+ * ***************************************************************************** */
+
+/**
+ * This method will initialize the phy transport layer registers
+ * @this_phy:
+ * @transport_layer_registers
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_phy_transport_layer_initialization(
+	struct scic_sds_phy *this_phy,
+	struct scu_transport_layer_registers __iomem *transport_layer_registers)
+{
+	u32 tl_control;
+
+	this_phy->transport_layer_registers = transport_layer_registers;
+
+	SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
+
+	/* Hardware team recommends that we enable the STP prefetch for all transports */
+	tl_control = SCU_TLCR_READ(this_phy);
+	tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
+	SCU_TLCR_WRITE(this_phy, tl_control);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method will initialize the phy link layer registers
+ * @sci_phy:
+ * @link_layer_registers:
+ *
+ * enum sci_status
+ */
+static enum sci_status
+scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy,
+				       struct scu_link_layer_registers __iomem *link_layer_registers)
+{
+	struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
+	int phy_idx = sci_phy->phy_index;
+	struct sci_phy_user_params *phy_user = &scic->user_parameters.sds1.phys[phy_idx];
+	struct sci_phy_oem_params *phy_oem = &scic->oem_parameters.sds1.phys[phy_idx];
+	u32 phy_configuration;
+	struct sas_capabilities phy_capabilities;
+	u32 parity_check = 0;
+	u32 parity_count = 0;
+	u32 llctl, link_rate;
+	u32 clksm_value = 0;
+
+	sci_phy->link_layer_registers = link_layer_registers;
+
+	/* Set our IDENTIFY frame data */
+	#define SCI_END_DEVICE 0x01
+
+	SCU_SAS_TIID_WRITE(sci_phy, (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) |
+				     SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) |
+				     SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
+				     SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
+				     SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE)));
+
+	/* Write the device SAS Address */
+	SCU_SAS_TIDNH_WRITE(sci_phy, 0xFEDCBA98);
+	SCU_SAS_TIDNL_WRITE(sci_phy, phy_idx);
+
+	/* Write the source SAS Address */
+	SCU_SAS_TISSAH_WRITE(sci_phy, phy_oem->sas_address.high);
+	SCU_SAS_TISSAL_WRITE(sci_phy, phy_oem->sas_address.low);
+
+	/* Clear and Set the PHY Identifier */
+	SCU_SAS_TIPID_WRITE(sci_phy, 0x00000000);
+	SCU_SAS_TIPID_WRITE(sci_phy, SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx));
+
+	/* Change the initial state of the phy configuration register */
+	phy_configuration = SCU_SAS_PCFG_READ(sci_phy);
+
+	/* Hold OOB state machine in reset */
+	phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+	SCU_SAS_PCFG_WRITE(sci_phy, phy_configuration);
+
+	/* Configure the SNW capabilities */
+	phy_capabilities.u.all = 0;
+	phy_capabilities.u.bits.start                      = 1;
+	phy_capabilities.u.bits.gen3_without_ssc_supported = 1;
+	phy_capabilities.u.bits.gen2_without_ssc_supported = 1;
+	phy_capabilities.u.bits.gen1_without_ssc_supported = 1;
+	if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) {
+		phy_capabilities.u.bits.gen3_with_ssc_supported = 1;
+		phy_capabilities.u.bits.gen2_with_ssc_supported = 1;
+		phy_capabilities.u.bits.gen1_with_ssc_supported = 1;
+	}
+
+	/*
+	 * The SAS specification indicates that the phy_capabilities that
+	 * are transmitted shall have an even parity.  Calculate the parity. */
+	parity_check = phy_capabilities.u.all;
+	while (parity_check != 0) {
+		if (parity_check & 0x1)
+			parity_count++;
+		parity_check >>= 1;
+	}
+
+	/*
+	 * If parity indicates there are an odd number of bits set, then
+	 * set the parity bit to 1 in the phy capabilities. */
+	if ((parity_count % 2) != 0)
+		phy_capabilities.u.bits.parity = 1;
+
+	SCU_SAS_PHYCAP_WRITE(sci_phy, phy_capabilities.u.all);
+
+	/* Set the enable spinup period but disable the ability to send
+	 * notify enable spinup
+	 */
+	SCU_SAS_ENSPINUP_WRITE(sci_phy, SCU_ENSPINUP_GEN_VAL(COUNT,
+			       phy_user->notify_enable_spin_up_insertion_frequency));
+
+	/* Write the ALIGN Insertion Ferequency for connected phy and
+	 * inpendent of connected state
+	 */
+	clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED,
+			phy_user->in_connection_align_insertion_frequency);
+
+	clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
+			phy_user->align_insertion_frequency);
+
+	SCU_SAS_CLKSM_WRITE(sci_phy, clksm_value);
+
+	/* @todo Provide a way to write this register correctly */
+	scu_link_layer_register_write(sci_phy, afe_lookup_table_control, 0x02108421);
+
+	llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
+		(u8)scic->user_parameters.sds1.no_outbound_task_timeout);
+
+	switch(phy_user->max_speed_generation) {
+	case SCIC_SDS_PARM_GEN3_SPEED:
+		link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3;
+		break;
+	case SCIC_SDS_PARM_GEN2_SPEED:
+		link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2;
+		break;
+	default:
+		link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1;
+		break;
+	}
+	llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
+
+	scu_link_layer_register_write(sci_phy, link_layer_control, llctl);
+
+	if (is_a0() || is_a2()) {
+		/* Program the max ARB time for the PHY to 700us so we inter-operate with
+		 * the PMC expander which shuts down PHYs if the expander PHY generates too
+		 * many breaks.  This time value will guarantee that the initiator PHY will
+		 * generate the break.
+		 */
+		scu_link_layer_register_write(sci_phy,
+					      maximum_arbitration_wait_timer_timeout,
+					      SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME);
+	}
+
+	/*
+	 * Set the link layer hang detection to 500ms (0x1F4) from its default
+	 * value of 128ms.  Max value is 511 ms. */
+	scu_link_layer_register_write(sci_phy, link_layer_hang_detection_timeout,
+				      0x1F4);
+
+	/* We can exit the initial state to the stopped state */
+	sci_base_state_machine_change_state(scic_sds_phy_get_base_state_machine(sci_phy),
+					    SCI_BASE_PHY_STATE_STOPPED);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This function will handle the sata SIGNATURE FIS timeout condition.  It will
+ * restart the starting substate machine since we dont know what has actually
+ * happening.
+ */
+void scic_sds_phy_sata_timeout(void *phy)
+{
+	struct scic_sds_phy *sci_phy = phy;
+
+	dev_dbg(sciphy_to_dev(sci_phy),
+		 "%s: SCIC SDS Phy 0x%p did not receive signature fis before "
+		 "timeout.\n",
+		 __func__,
+		 sci_phy);
+
+	sci_base_state_machine_stop(
+		scic_sds_phy_get_starting_substate_machine(sci_phy));
+
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(sci_phy),
+		SCI_BASE_PHY_STATE_STARTING
+		);
+}
+
+/**
+ * This method will construct the struct scic_sds_phy object
+ * @this_phy:
+ * @owning_port:
+ * @phy_index:
+ *
+ */
+void scic_sds_phy_construct(
+	struct scic_sds_phy *this_phy,
+	struct scic_sds_port *owning_port,
+	u8 phy_index)
+{
+	/*
+	 * Call the base constructor first
+	 */
+	sci_base_phy_construct(
+		&this_phy->parent,
+		scic_sds_phy_state_table
+		);
+
+	/* Copy the rest of the input data to our locals */
+	this_phy->owning_port = owning_port;
+	this_phy->phy_index = phy_index;
+	this_phy->bcn_received_while_port_unassigned = false;
+	this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+	this_phy->link_layer_registers = NULL;
+	this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
+	this_phy->sata_timeout_timer = NULL;
+
+	/* Clear out the identification buffer data */
+	memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type));
+
+	/* Initialize the the substate machines */
+	sci_base_state_machine_construct(
+		&this_phy->starting_substate_machine,
+		&this_phy->parent.parent,
+		scic_sds_phy_starting_substates,
+		SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
+		);
+}
+
+/**
+ * This method returns the port currently containing this phy. If the phy is
+ *    currently contained by the dummy port, then the phy is considered to not
+ *    be part of a port.
+ * @this_phy: This parameter specifies the phy for which to retrieve the
+ *    containing port.
+ *
+ * This method returns a handle to a port that contains the supplied phy.
+ * NULL This value is returned if the phy is not part of a real
+ * port (i.e. it's contained in the dummy port). !NULL All other
+ * values indicate a handle/pointer to the port containing the phy.
+ */
+struct scic_sds_port *scic_sds_phy_get_port(
+	struct scic_sds_phy *this_phy)
+{
+	if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT)
+		return NULL;
+
+	return this_phy->owning_port;
+}
+
+/**
+ * This method will assign a port to the phy object.
+ * @out]: this_phy This parameter specifies the phy for which to assign a port
+ *    object.
+ *
+ *
+ */
+void scic_sds_phy_set_port(
+	struct scic_sds_phy *this_phy,
+	struct scic_sds_port *the_port)
+{
+	this_phy->owning_port = the_port;
+
+	if (this_phy->bcn_received_while_port_unassigned) {
+		this_phy->bcn_received_while_port_unassigned = false;
+		scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
+	}
+}
+
+/**
+ * This method will initialize the constructed phy
+ * @sci_phy:
+ * @link_layer_registers:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_initialize(
+	struct scic_sds_phy *sci_phy,
+		struct scu_transport_layer_registers __iomem *transport_layer_registers,
+		struct scu_link_layer_registers __iomem *link_layer_registers)
+{
+	/* Create the SIGNATURE FIS Timeout timer for this phy */
+	sci_phy->sata_timeout_timer = isci_event_timer_create(
+		scic_sds_phy_get_controller(sci_phy),
+		scic_sds_phy_sata_timeout,
+		sci_phy
+		);
+
+	/* Perfrom the initialization of the TL hardware */
+	scic_sds_phy_transport_layer_initialization(sci_phy, transport_layer_registers);
+
+	/* Perofrm the initialization of the PE hardware */
+	scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers);
+
+	/*
+	 * There is nothing that needs to be done in this state just
+	 * transition to the stopped state. */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(sci_phy),
+		SCI_BASE_PHY_STATE_STOPPED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method assigns the direct attached device ID for this phy.
+ *
+ * @this_phy The phy for which the direct attached device id is to
+ *       be assigned.
+ * @device_id The direct attached device ID to assign to the phy.
+ *       This will either be the RNi for the device or an invalid RNi if there
+ *       is no current device assigned to the phy.
+ */
+void scic_sds_phy_setup_transport(
+	struct scic_sds_phy *this_phy,
+	u32 device_id)
+{
+	u32 tl_control;
+
+	SCU_STPTLDARNI_WRITE(this_phy, device_id);
+
+	/*
+	 * The read should guarantee that the first write gets posted
+	 * before the next write
+	 */
+	tl_control = SCU_TLCR_READ(this_phy);
+	tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
+	SCU_TLCR_WRITE(this_phy, tl_control);
+}
+
+/**
+ *
+ * @this_phy: The phy object to be suspended.
+ *
+ * This function will perform the register reads/writes to suspend the SCU
+ * hardware protocol engine. none
+ */
+void scic_sds_phy_suspend(
+	struct scic_sds_phy *this_phy)
+{
+	u32 scu_sas_pcfg_value;
+
+	scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+	scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+	scic_sds_phy_setup_transport(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
+}
+
+/**
+ *
+ * @this_phy: The phy object to resume.
+ *
+ * This function will perform the register reads/writes required to resume the
+ * SCU hardware protocol engine. none
+ */
+void scic_sds_phy_resume(
+	struct scic_sds_phy *this_phy)
+{
+	u32 scu_sas_pcfg_value;
+
+	scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+
+	scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
+
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+}
+
+/**
+ * This method returns the local sas address assigned to this phy.
+ * @this_phy: This parameter specifies the phy for which to retrieve the local
+ *    SAS address.
+ * @sas_address: This parameter specifies the location into which to copy the
+ *    local SAS address.
+ *
+ */
+void scic_sds_phy_get_sas_address(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_address *sas_address)
+{
+	sas_address->high = SCU_SAS_TISSAH_READ(this_phy);
+	sas_address->low  = SCU_SAS_TISSAL_READ(this_phy);
+}
+
+/**
+ * This method returns the remote end-point (i.e. attached) sas address
+ *    assigned to this phy.
+ * @this_phy: This parameter specifies the phy for which to retrieve the remote
+ *    end-point SAS address.
+ * @sas_address: This parameter specifies the location into which to copy the
+ *    remote end-point SAS address.
+ *
+ */
+void scic_sds_phy_get_attached_sas_address(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_address *sas_address)
+{
+	sas_address->high
+		= this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high;
+	sas_address->low
+		= this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low;
+}
+
+/**
+ * This method returns the supported protocols assigned to this phy
+ * @this_phy:
+ *
+ *
+ */
+void scic_sds_phy_get_protocols(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_identify_address_frame_protocols *protocols)
+{
+	protocols->u.all = (u16)(SCU_SAS_TIID_READ(this_phy) & 0x0000FFFF);
+}
+
+/**
+ *
+ * @this_phy: The parameter is the phy object for which the attached phy
+ *    protcols are to be returned.
+ *
+ * This method returns the supported protocols for the attached phy.  If this
+ * is a SAS phy the protocols are returned from the identify address frame. If
+ * this is a SATA phy then protocols are made up and the target phy is an STP
+ * target phy. The caller will get the entire set of bits for the protocol
+ * value.
+ */
+void scic_sds_phy_get_attached_phy_protocols(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_identify_address_frame_protocols *protocols)
+{
+	protocols->u.all = 0;
+
+	if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+		protocols->u.all =
+			this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all;
+	} else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) {
+		protocols->u.bits.stp_target = 1;
+	}
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY Handler Redirects
+ * ***************************************************************************** */
+
+/**
+ * This method will attempt to start the phy object. This request is only valid
+ *    when the phy is in the stopped state
+ * @sci_phy:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy)
+{
+	return sci_phy->state_handlers->parent.start_handler(&sci_phy->parent);
+}
+
+/**
+ * This method will attempt to stop the phy object.
+ * @sci_phy:
+ *
+ * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE
+ * if the phy is not in a valid state to stop
+ */
+enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy)
+{
+	return sci_phy->state_handlers->parent.stop_handler(&sci_phy->parent);
+}
+
+/**
+ * This method will attempt to reset the phy.  This request is only valid when
+ *    the phy is in an ready state
+ * @this_phy:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_reset(
+	struct scic_sds_phy *this_phy)
+{
+	return this_phy->state_handlers->parent.reset_handler(
+		       &this_phy->parent
+		       );
+}
+
+/**
+ * This method will process the event code received.
+ * @this_phy:
+ * @event_code:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	return this_phy->state_handlers->event_handler(this_phy, event_code);
+}
+
+/**
+ * This method will process the frame index received.
+ * @this_phy:
+ * @frame_index:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_frame_handler(
+	struct scic_sds_phy *this_phy,
+	u32 frame_index)
+{
+	return this_phy->state_handlers->frame_handler(this_phy, frame_index);
+}
+
+/**
+ * This method will give the phy permission to consume power
+ * @this_phy:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_consume_power_handler(
+	struct scic_sds_phy *this_phy)
+{
+	return this_phy->state_handlers->consume_power_handler(this_phy);
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC PHY Public Methods
+ * ***************************************************************************** */
+
+
+enum sci_status scic_sas_phy_get_properties(
+	struct scic_sds_phy *sci_phy,
+	struct scic_sas_phy_properties *properties)
+{
+	if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+		memcpy(
+			&properties->received_iaf,
+			&sci_phy->phy_type.sas.identify_address_frame_buffer,
+			sizeof(struct sci_sas_identify_address_frame)
+			);
+
+		properties->received_capabilities.u.all
+			= SCU_SAS_RECPHYCAP_READ(sci_phy);
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE;
+}
+
+
+enum sci_status scic_sata_phy_get_properties(
+	struct scic_sds_phy *sci_phy,
+	struct scic_sata_phy_properties *properties)
+{
+	if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) {
+		memcpy(
+			&properties->signature_fis,
+			&sci_phy->phy_type.sata.signature_fis_buffer,
+			sizeof(struct sata_fis_reg_d2h)
+			);
+
+		/* / @todo add support for port selectors. */
+		properties->is_port_selector_present = false;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE;
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY HELPER FUNCTIONS
+ * ***************************************************************************** */
+
+
+/**
+ *
+ * @this_phy: The phy object that received SAS PHY DETECTED.
+ *
+ * This method continues the link training for the phy as if it were a SAS PHY
+ * instead of a SATA PHY. This is done because the completion queue had a SAS
+ * PHY DETECTED event when the state machine was expecting a SATA PHY event.
+ * none
+ */
+static void scic_sds_phy_start_sas_link_training(
+	struct scic_sds_phy *this_phy)
+{
+	u32 phy_control;
+
+	phy_control = SCU_SAS_PCFG_READ(this_phy);
+	phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);
+	SCU_SAS_PCFG_WRITE(this_phy, phy_control);
+
+	sci_base_state_machine_change_state(
+		&this_phy->starting_substate_machine,
+		SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
+		);
+
+	this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
+}
+
+/**
+ *
+ * @this_phy: The phy object that received a SATA SPINUP HOLD event
+ *
+ * This method continues the link training for the phy as if it were a SATA PHY
+ * instead of a SAS PHY.  This is done because the completion queue had a SATA
+ * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none
+ */
+static void scic_sds_phy_start_sata_link_training(
+	struct scic_sds_phy *this_phy)
+{
+	sci_base_state_machine_change_state(
+		&this_phy->starting_substate_machine,
+		SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
+		);
+
+	this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+}
+
+/**
+ * This method performs processing common to all protocols upon completion of
+ *    link training.
+ * @this_phy: This parameter specifies the phy object for which link training
+ *    has completed.
+ * @max_link_rate: This parameter specifies the maximum link rate to be
+ *    associated with this phy.
+ * @next_state: This parameter specifies the next state for the phy's starting
+ *    sub-state machine.
+ *
+ */
+static void scic_sds_phy_complete_link_training(
+	struct scic_sds_phy *this_phy,
+	enum sci_sas_link_rate max_link_rate,
+	u32 next_state)
+{
+	this_phy->max_negotiated_speed = max_link_rate;
+
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_starting_substate_machine(this_phy), next_state
+		);
+}
+
+/**
+ *
+ * @this_phy: The struct scic_sds_phy object to restart.
+ *
+ * This method restarts the struct scic_sds_phy objects base state machine in the
+ * starting state from any starting substate. none
+ */
+static void scic_sds_phy_restart_starting_state(
+	struct scic_sds_phy *this_phy)
+{
+	/* Stop the current substate machine */
+	sci_base_state_machine_stop(
+		scic_sds_phy_get_starting_substate_machine(this_phy)
+		);
+
+	/* Re-enter the base state machine starting state */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(this_phy),
+		SCI_BASE_PHY_STATE_STARTING
+		);
+}
+
+/* ****************************************************************************
+   * SCIC SDS PHY general handlers
+   ************************************************************************** */
+static enum sci_status scic_sds_phy_starting_substate_general_stop_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+	this_phy = (struct scic_sds_phy *)phy;
+
+	sci_base_state_machine_stop(&this_phy->starting_substate_machine);
+
+	sci_base_state_machine_change_state(&phy->state_machine,
+						 SCI_BASE_PHY_STATE_STOPPED);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY EVENT_HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. -
+ * decode the event - sas phy detected causes a state transition to the wait
+ * for speed event notification. - any other events log a warning message and
+ * set a failure status enum sci_status SCI_SUCCESS on any valid event notification
+ * SCI_FAILURE on any unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		scic_sds_phy_start_sas_link_training(this_phy);
+		this_phy->is_in_link_training = true;
+		break;
+
+	case SCU_EVENT_SATA_SPINUP_HOLD:
+		scic_sds_phy_start_sata_link_training(this_phy);
+		this_phy->is_in_link_training = true;
+		break;
+
+	default:
+		dev_dbg(sciphy_to_dev(this_phy),
+			"%s: PHY starting substate machine received "
+			"unexpected event_code %x\n",
+			__func__,
+			event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. -
+ * decode the event - sas phy detected returns us back to this state. - speed
+ * event detected causes a state transition to the wait for iaf. - identify
+ * timeout is an un-expected event and the state machine is restarted. - link
+ * failure events restart the starting state machine - any other events log a
+ * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid
+ * event notification SCI_FAILURE on any unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		/*
+		 * Why is this being reported again by the controller?
+		 * We would re-enter this state so just stay here */
+		break;
+
+	case SCU_EVENT_SAS_15:
+	case SCU_EVENT_SAS_15_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+			);
+		break;
+
+	case SCU_EVENT_SAS_30:
+	case SCU_EVENT_SAS_30_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+			);
+		break;
+
+	case SCU_EVENT_SAS_60:
+	case SCU_EVENT_SAS_60_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+			);
+		break;
+
+	case SCU_EVENT_SATA_SPINUP_HOLD:
+		/*
+		 * We were doing SAS PHY link training and received a SATA PHY event
+		 * continue OOB/SN as if this were a SATA PHY */
+		scic_sds_phy_start_sata_link_training(this_phy);
+		break;
+
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. -
+ * decode the event - sas phy detected event backs up the state machine to the
+ * await speed notification. - identify timeout is an un-expected event and the
+ * state machine is restarted. - link failure events restart the starting state
+ * machine - any other events log a warning message and set a failure status
+ * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any
+ * unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		/* Backup the state machine */
+		scic_sds_phy_start_sas_link_training(this_phy);
+		break;
+
+	case SCU_EVENT_SATA_SPINUP_HOLD:
+		/*
+		 * We were doing SAS PHY link training and received a SATA PHY event
+		 * continue OOB/SN as if this were a SATA PHY */
+		scic_sds_phy_start_sata_link_training(this_phy);
+		break;
+
+	case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
+	case SCU_EVENT_LINK_FAILURE:
+	case SCU_EVENT_HARD_RESET_RECEIVED:
+		/* Start the oob/sn state machine over again */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. -
+ * decode the event - link failure events restart the starting state machine -
+ * any other events log a warning message and set a failure status enum sci_status
+ * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event
+ * notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			"%s: PHY starting substate machine received unexpected "
+			"event_code %x\n",
+			__func__,
+			event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. -
+ * decode the event - link failure events restart the starting state machine -
+ * sata spinup hold events are ignored since they are expected - any other
+ * events log a warning message and set a failure status enum sci_status SCI_SUCCESS
+ * on a link failure event SCI_FAILURE on any unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	case SCU_EVENT_SATA_SPINUP_HOLD:
+		/* These events are received every 10ms and are expected while in this state */
+		break;
+
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		/*
+		 * There has been a change in the phy type before OOB/SN for the
+		 * SATA finished start down the SAS link traning path. */
+		scic_sds_phy_start_sas_link_training(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. -
+ * decode the event - link failure events restart the starting state machine -
+ * sata spinup hold events are ignored since they are expected - sata phy
+ * detected event change to the wait speed event - any other events log a
+ * warning message and set a failure status enum sci_status SCI_SUCCESS on a link
+ * failure event SCI_FAILURE on any unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	case SCU_EVENT_SATA_SPINUP_HOLD:
+		/*
+		 * These events might be received since we dont know how many may be in
+		 * the completion queue while waiting for power */
+		break;
+
+	case SCU_EVENT_SATA_PHY_DETECTED:
+		this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+
+		/* We have received the SATA PHY notification change state */
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_starting_substate_machine(this_phy),
+			SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+			);
+		break;
+
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		/*
+		 * There has been a change in the phy type before OOB/SN for the
+		 * SATA finished start down the SAS link traning path. */
+		scic_sds_phy_start_sas_link_training(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
+ * - decode the event - sata phy detected returns us back to this state. -
+ * speed event detected causes a state transition to the wait for signature. -
+ * link failure events restart the starting state machine - any other events
+ * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any
+ * valid event notification SCI_FAILURE on any unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_SATA_PHY_DETECTED:
+		/*
+		 * The hardware reports multiple SATA PHY detected events
+		 * ignore the extras */
+		break;
+
+	case SCU_EVENT_SATA_15:
+	case SCU_EVENT_SATA_15_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy,
+			SCI_SAS_150_GB,
+			SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+			);
+		break;
+
+	case SCU_EVENT_SATA_30:
+	case SCU_EVENT_SATA_30_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy,
+			SCI_SAS_300_GB,
+			SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+			);
+		break;
+
+	case SCU_EVENT_SATA_60:
+	case SCU_EVENT_SATA_60_SSC:
+		scic_sds_phy_complete_link_training(
+			this_phy,
+			SCI_SAS_600_GB,
+			SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+			);
+		break;
+
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	case SCU_EVENT_SAS_PHY_DETECTED:
+		/*
+		 * There has been a change in the phy type before OOB/SN for the
+		 * SATA finished start down the SAS link traning path. */
+		scic_sds_phy_start_sas_link_training(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This struct scic_sds_phy object which has received an event.
+ * @event_code: This is the event code which the phy object is to decode.
+ *
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. -
+ * decode the event - sas phy detected event backs up the state machine to the
+ * await speed notification. - identify timeout is an un-expected event and the
+ * state machine is restarted. - link failure events restart the starting state
+ * machine - any other events log a warning message and set a failure status
+ * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any
+ * unexpected event notifation
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	u32 result = SCI_SUCCESS;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_SATA_PHY_DETECTED:
+		/* Backup the state machine */
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_starting_substate_machine(this_phy),
+			SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+			);
+		break;
+
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		scic_sds_phy_restart_starting_state(this_phy);
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 event_code);
+
+		result = SCI_FAILURE;
+		break;
+	}
+
+	return result;
+}
+
+
+/*
+ * *****************************************************************************
+ * *  SCIC SDS PHY FRAME_HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @phy: This is struct scic_sds_phy object which is being requested to decode the
+ *    frame data.
+ * @frame_index: This is the index of the unsolicited frame which was received
+ *    for this phy.
+ *
+ * This method decodes the unsolicited frame when the struct scic_sds_phy is in the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF
+ * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change
+ * starting substate to wait power. - else - log warning message of unexpected
+ * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler(
+	struct scic_sds_phy *this_phy,
+	u32 frame_index)
+{
+	enum sci_status result;
+	u32 *frame_words;
+	struct sci_sas_identify_address_frame *identify_frame;
+
+	result = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_phy_get_controller(this_phy)->uf_control),
+		frame_index,
+		(void **)&frame_words);
+
+	if (result != SCI_SUCCESS) {
+		return result;
+	}
+
+	frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]);
+	identify_frame = (struct sci_sas_identify_address_frame *)frame_words;
+
+	if (identify_frame->address_frame_type == 0) {
+		/*
+		 * Byte swap the rest of the frame so we can make
+		 * a copy of the buffer */
+		frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]);
+		frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]);
+		frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]);
+		frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]);
+		frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]);
+
+		memcpy(
+			&this_phy->phy_type.sas.identify_address_frame_buffer,
+			identify_frame,
+			sizeof(struct sci_sas_identify_address_frame)
+			);
+
+		if (identify_frame->protocols.u.bits.smp_target) {
+			/*
+			 * We got the IAF for an expander PHY go to the final state since
+			 * there are no power requirements for expander phys. */
+			sci_base_state_machine_change_state(
+				scic_sds_phy_get_starting_substate_machine(this_phy),
+				SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+				);
+		} else {
+			/* We got the IAF we can now go to the await spinup semaphore state */
+			sci_base_state_machine_change_state(
+				scic_sds_phy_get_starting_substate_machine(this_phy),
+				SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
+				);
+		}
+
+		result = SCI_SUCCESS;
+	} else
+		dev_warn(sciphy_to_dev(this_phy),
+			"%s: PHY starting substate machine received "
+			"unexpected frame id %x\n",
+			__func__,
+			frame_index);
+
+	/* Regardless of the result release this frame since we are done with it */
+	scic_sds_controller_release_frame(
+		scic_sds_phy_get_controller(this_phy), frame_index
+		);
+
+	return result;
+}
+
+/**
+ *
+ * @phy: This is struct scic_sds_phy object which is being requested to decode the
+ *    frame data.
+ * @frame_index: This is the index of the unsolicited frame which was received
+ *    for this phy.
+ *
+ * This method decodes the unsolicited frame when the struct scic_sds_phy is in the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If
+ * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS
+ * data buffer. - else - log warning message of unexpected unsolicted frame -
+ * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS
+ * data
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler(
+	struct scic_sds_phy *this_phy,
+	u32 frame_index)
+{
+	enum sci_status result;
+	u32 *frame_words;
+	struct sata_fis_header *fis_frame_header;
+	u32 *fis_frame_data;
+
+	result = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_phy_get_controller(this_phy)->uf_control),
+		frame_index,
+		(void **)&frame_words);
+
+	if (result != SCI_SUCCESS) {
+		return result;
+	}
+
+	fis_frame_header = (struct sata_fis_header *)frame_words;
+
+	if (
+		(fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
+		&& !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)
+		) {
+		scic_sds_unsolicited_frame_control_get_buffer(
+			&(scic_sds_phy_get_controller(this_phy)->uf_control),
+			frame_index,
+			(void **)&fis_frame_data
+			);
+
+		scic_sds_controller_copy_sata_response(
+			&this_phy->phy_type.sata.signature_fis_buffer,
+			frame_words,
+			fis_frame_data
+			);
+
+		/* We got the IAF we can now go to the await spinup semaphore state */
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_starting_substate_machine(this_phy),
+			SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+			);
+
+		result = SCI_SUCCESS;
+	} else
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: PHY starting substate machine received "
+			 "unexpected frame id %x\n",
+			 __func__,
+			 frame_index);
+
+	/* Regardless of the result release this frame since we are done with it */
+	scic_sds_controller_release_frame(
+		scic_sds_phy_get_controller(this_phy), frame_index
+		);
+
+	return result;
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY POWER_HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method is called by the struct scic_sds_controller when the phy object is
+ * granted power. - The notify enable spinups are turned on for this phy object
+ * - The phy state machine is transitioned to the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler(
+	struct scic_sds_phy *this_phy)
+{
+	u32 enable_spinup;
+
+	enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy);
+	enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);
+	SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup);
+
+	/* Change state to the final state this substate machine has run to completion */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_starting_substate_machine(this_phy),
+		SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method is called by the struct scic_sds_controller when the phy object is
+ * granted power. - The phy state machine is transitioned to the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler(
+	struct scic_sds_phy *this_phy)
+{
+	u32 scu_sas_pcfg_value;
+
+	/* Release the spinup hold state and reset the OOB state machine */
+	scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+	scu_sas_pcfg_value &=
+		~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));
+	scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+	/* Now restart the OOB operation */
+	scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+	scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+	/* Change state to the final state this substate machine has run to completion */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_starting_substate_machine(this_phy),
+		SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
+		);
+
+	return SCI_SUCCESS;
+}
+
+const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = {
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = {
+		.parent.start_handler    = scic_sds_phy_default_start_handler,
+		.parent.stop_handler     = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler    = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler           = scic_sds_phy_default_frame_handler,
+		.event_handler           = scic_sds_phy_default_event_handler,
+		.consume_power_handler   = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_ossp_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_iaf_uf_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sas_power_event_handler,
+		.consume_power_handler	 = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sata_power_event_handler,
+		.consume_power_handler	 = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sata_phy_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sata_speed_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
+		.event_handler		 = scic_sds_phy_starting_substate_await_sig_fis_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = {
+		.parent.start_handler	 = scic_sds_phy_default_start_handler,
+		.parent.stop_handler	 = scic_sds_phy_starting_substate_general_stop_handler,
+		.parent.reset_handler	 = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_default_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	}
+};
+
+/**
+ * scic_sds_phy_set_starting_substate_handlers() -
+ *
+ * This macro sets the starting substate handlers by state_id
+ */
+#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \
+	scic_sds_phy_set_state_handlers(\
+		(phy), \
+		&scic_sds_phy_starting_substate_handler_table[(state_id)] \
+		)
+
+/*
+ * ****************************************************************************
+ * *  PHY STARTING SUBSTATE METHODS
+ * **************************************************************************** */
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state
+ * handlers are put in place for the struct scic_sds_phy object. - The state is
+ * changed to the wait phy type event notification. none
+ */
+static void scic_sds_phy_starting_initial_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL);
+
+	/* This is just an temporary state go off to the starting state */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_starting_substate_machine(this_phy),
+		SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the
+ * struct scic_sds_phy object state handlers for this state. none
+ */
+static void scic_sds_phy_starting_await_ossp_en_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the
+ * struct scic_sds_phy object state handlers for this state. none
+ */
+static void scic_sds_phy_starting_await_sas_speed_en_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the
+ * struct scic_sds_phy object state handlers for this state. none
+ */
+static void scic_sds_phy_starting_await_iaf_uf_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the
+ * struct scic_sds_phy object state handlers for this state. - Add this phy object to
+ * the power control queue none
+ */
+static void scic_sds_phy_starting_await_sas_power_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
+		);
+
+	scic_sds_controller_power_control_queue_insert(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the
+ * struct scic_sds_phy object from the power control queue. none
+ */
+static void scic_sds_phy_starting_await_sas_power_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_controller_power_control_queue_remove(
+		scic_sds_phy_get_controller(this_phy), this_phy
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the
+ * struct scic_sds_phy object state handlers for this state. - Add this phy object to
+ * the power control queue none
+ */
+static void scic_sds_phy_starting_await_sata_power_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
+		);
+
+	scic_sds_controller_power_control_queue_insert(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the
+ * struct scic_sds_phy object from the power control queue. none
+ */
+static void scic_sds_phy_starting_await_sata_power_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_controller_power_control_queue_remove(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the
+ * struct scic_sds_phy object state handlers for this state. none
+ */
+static void scic_sds_phy_starting_await_sata_phy_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
+		);
+
+	isci_event_timer_start(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy->sata_timeout_timer,
+		SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer
+ * that was started on entry to await sata phy event notification none
+ */
+static void scic_sds_phy_starting_await_sata_phy_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	isci_event_timer_stop(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy->sata_timeout_timer
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the
+ * struct scic_sds_phy object state handlers for this state. none
+ */
+static void scic_sds_phy_starting_await_sata_speed_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+		);
+
+	isci_event_timer_start(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy->sata_timeout_timer,
+		SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer
+ * that was started on entry to await sata phy event notification none
+ */
+static void scic_sds_phy_starting_await_sata_speed_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	isci_event_timer_stop(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy->sata_timeout_timer
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the
+ * struct scic_sds_phy object state handlers for this state. - Start the SIGNATURE FIS
+ * timeout timer none
+ */
+static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(
+	struct sci_base_object *object)
+{
+	bool continue_to_ready_state;
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+		);
+
+	continue_to_ready_state = scic_sds_port_link_detected(
+		this_phy->owning_port,
+		this_phy
+		);
+
+	if (continue_to_ready_state) {
+		/*
+		 * Clear the PE suspend condition so we can actually receive SIG FIS
+		 * The hardware will not respond to the XRDY until the PE suspend
+		 * condition is cleared. */
+		scic_sds_phy_resume(this_phy);
+
+		isci_event_timer_start(
+			scic_sds_phy_get_controller(this_phy),
+			this_phy->sata_timeout_timer,
+			SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+			);
+	} else {
+		this_phy->is_in_link_training = false;
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE
+ * FIS timeout timer. none
+ */
+static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	isci_event_timer_stop(
+		scic_sds_phy_get_controller(this_phy),
+		this_phy->sata_timeout_timer
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy
+ * object state handlers for this state. - Change base state machine to the
+ * ready state. none
+ */
+static void scic_sds_phy_starting_final_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_starting_substate_handlers(
+		this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+		);
+
+	/*
+	 * State machine has run to completion so exit out and change
+	 * the base state machine to the ready state */
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(this_phy),
+		SCI_BASE_PHY_STATE_READY);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_phy_starting_substates[] = {
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = {
+		.enter_state = scic_sds_phy_starting_initial_substate_enter,
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = {
+		.enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter,
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = {
+		.enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter,
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = {
+		.enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter,
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = {
+		.enter_state = scic_sds_phy_starting_await_sas_power_substate_enter,
+		.exit_state  = scic_sds_phy_starting_await_sas_power_substate_exit,
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = {
+		.enter_state = scic_sds_phy_starting_await_sata_power_substate_enter,
+		.exit_state  = scic_sds_phy_starting_await_sata_power_substate_exit
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = {
+		.enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter,
+		.exit_state  = scic_sds_phy_starting_await_sata_phy_substate_exit
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = {
+		.enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter,
+		.exit_state  = scic_sds_phy_starting_await_sata_speed_substate_exit
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = {
+		.enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter,
+		.exit_state  = scic_sds_phy_starting_await_sig_fis_uf_substate_exit
+	},
+	[SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = {
+		.enter_state = scic_sds_phy_starting_final_substate_enter,
+	}
+};
+
+/*
+ * ***************************************************************************
+ * *  DEFAULT HANDLERS
+ * *************************************************************************** */
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This is the default method for phy a start request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_start_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	dev_warn(sciphy_to_dev(this_phy),
+		 "%s: SCIC Phy 0x%p requested to start from invalid "
+		 "state %d\n",
+		 __func__,
+		 this_phy,
+		 sci_base_state_machine_get_state(
+			 &this_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a
+ * struct scic_sds_phy object.
+ *
+ * This is the default method for phy a stop request.  It will report a warning
+ * and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_stop_handler(struct sci_base_phy *base_phy)
+{
+	struct scic_sds_phy *sci_phy;
+
+	sci_phy = (struct scic_sds_phy *)base_phy;
+
+	dev_dbg(sciphy_to_dev(sci_phy),
+		"%s: SCIC Phy 0x%p requested to stop from invalid state %d\n",
+		__func__,
+		sci_phy,
+		sci_base_state_machine_get_state(
+			&sci_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This is the default method for phy a reset request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_reset_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	dev_warn(sciphy_to_dev(this_phy),
+		 "%s: SCIC Phy 0x%p requested to reset from invalid state "
+		 "%d\n",
+		 __func__,
+		 this_phy,
+		 sci_base_state_machine_get_state(
+			 &this_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This is the default method for phy a destruct request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_destroy_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	/* / @todo Implement something for the default */
+	dev_warn(sciphy_to_dev(this_phy),
+		 "%s: SCIC Phy 0x%p requested to destroy from invalid "
+		 "state %d\n",
+		 __func__,
+		 this_phy,
+		 sci_base_state_machine_get_state(
+			 &this_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ * @frame_index: This is the frame index that was received from the SCU
+ *    hardware.
+ *
+ * This is the default method for a phy frame handling request.  It will report
+ * a warning, release the frame and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_frame_handler(
+	struct scic_sds_phy *this_phy,
+	u32 frame_index)
+{
+	dev_warn(sciphy_to_dev(this_phy),
+		 "%s: SCIC Phy 0x%p received unexpected frame data %d "
+		 "while in state %d\n",
+		 __func__,
+		 this_phy,
+		 frame_index,
+		 sci_base_state_machine_get_state(
+			 &this_phy->parent.state_machine));
+
+	scic_sds_controller_release_frame(
+		scic_sds_phy_get_controller(this_phy), frame_index);
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ * @event_code: This is the event code that was received from the SCU hardware.
+ *
+ * This is the default method for a phy event handler.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	dev_dbg(sciphy_to_dev(this_phy),
+		"%s: SCIC Phy 0x%p received unexpected event status %x "
+		"while in state %d\n",
+		__func__,
+		this_phy,
+		event_code,
+		sci_base_state_machine_get_state(
+			&this_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This is the default method for a phy consume power handler.  It will report
+ * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_phy_default_consume_power_handler(
+	struct scic_sds_phy *this_phy)
+{
+	dev_warn(sciphy_to_dev(this_phy),
+		 "%s: SCIC Phy 0x%p given unexpected permission to consume "
+		 "power while in state %d\n",
+		 __func__,
+		 this_phy,
+		 sci_base_state_machine_get_state(
+			 &this_phy->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/*
+ * ******************************************************************************
+ * * PHY STOPPED STATE HANDLERS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_phy from a stopped state and attempts to
+ * start it. - The phy state machine is transitioned to the
+ * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	/* Create the SIGNATURE FIS Timeout timer for this phy */
+	this_phy->sata_timeout_timer = isci_event_timer_create(
+		scic_sds_phy_get_controller(this_phy),
+		scic_sds_phy_sata_timeout, this_phy);
+
+	if (this_phy->sata_timeout_timer != NULL) {
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_base_state_machine(this_phy),
+			SCI_BASE_PHY_STATE_STARTING);
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_phy from a stopped state and destroys it. -
+ * This function takes no action. Shouldnt this function transition the
+ * struct sci_base_phy::state_machine to the SCI_BASE_PHY_STATE_FINAL? enum sci_status
+ * SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_stopped_state_destroy_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	/* @todo what do we actually need to do here? */
+	return SCI_SUCCESS;
+}
+
+/*
+ * ******************************************************************************
+ * * PHY STARTING STATE HANDLERS
+ * ****************************************************************************** */
+
+/* All of these state handlers are mapped to the starting sub-state machine */
+
+/*
+ * ******************************************************************************
+ * * PHY READY STATE HANDLERS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_phy from a ready state and attempts to stop
+ * it. - The phy state machine is transitioned to the
+ * SCI_BASE_PHY_STATE_STOPPED. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_ready_state_stop_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(this_phy),
+		SCI_BASE_PHY_STATE_STOPPED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_phy from a ready state and attempts to reset
+ * it. - The phy state machine is transitioned to the
+ * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_phy_ready_state_reset_handler(
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)phy;
+
+	sci_base_state_machine_change_state(
+		scic_sds_phy_get_base_state_machine(this_phy),
+		SCI_BASE_PHY_STATE_RESETTING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @phy: This is the struct scic_sds_phy object which has received the event.
+ *
+ * This method request the struct scic_sds_phy handle the received event.  The only
+ * event that we are interested in while in the ready state is the link failure
+ * event. - decoded event is a link failure - transition the struct scic_sds_phy back
+ * to the SCI_BASE_PHY_STATE_STARTING state. - any other event recived will
+ * report a warning message enum sci_status SCI_SUCCESS if the event received is a
+ * link failure SCI_FAILURE_INVALID_STATE for any other event received.
+ */
+static enum sci_status scic_sds_phy_ready_state_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	enum sci_status result = SCI_FAILURE;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_LINK_FAILURE:
+		/* Link failure change state back to the starting state */
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_base_state_machine(this_phy),
+			SCI_BASE_PHY_STATE_STARTING
+			);
+
+		result = SCI_SUCCESS;
+		break;
+
+	case SCU_EVENT_BROADCAST_CHANGE:
+		/* Broadcast change received. Notify the port. */
+		if (scic_sds_phy_get_port(this_phy) != NULL)
+			scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
+		else
+			this_phy->bcn_received_while_port_unassigned = true;
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%sP SCIC PHY 0x%p ready state machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 this_phy,
+			 event_code);
+
+		result = SCI_FAILURE_INVALID_STATE;
+		break;
+	}
+
+	return result;
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ *
+ * @this_phy: This is the struct scic_sds_phy object which is receiving the event.
+ * @event_code: This is the event code to be processed.
+ *
+ * This is the resetting state event handler. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_phy_resetting_state_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code)
+{
+	enum sci_status result = SCI_FAILURE;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_HARD_RESET_TRANSMITTED:
+		/* Link failure change state back to the starting state */
+		sci_base_state_machine_change_state(
+			scic_sds_phy_get_base_state_machine(this_phy),
+			SCI_BASE_PHY_STATE_STARTING
+			);
+
+		result = SCI_SUCCESS;
+		break;
+
+	default:
+		dev_warn(sciphy_to_dev(this_phy),
+			 "%s: SCIC PHY 0x%p resetting state machine received "
+			 "unexpected event_code %x\n",
+			 __func__,
+			 this_phy,
+			 event_code);
+
+		result = SCI_FAILURE_INVALID_STATE;
+		break;
+	}
+
+	return result;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = {
+	[SCI_BASE_PHY_STATE_INITIAL] = {
+		.parent.start_handler = scic_sds_phy_default_start_handler,
+		.parent.stop_handler  = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_default_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCI_BASE_PHY_STATE_STOPPED]  = {
+		.parent.start_handler = scic_sds_phy_stopped_state_start_handler,
+		.parent.stop_handler  = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_stopped_state_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_default_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCI_BASE_PHY_STATE_STARTING] = {
+		.parent.start_handler = scic_sds_phy_default_start_handler,
+		.parent.stop_handler  = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_default_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCI_BASE_PHY_STATE_READY] = {
+		.parent.start_handler = scic_sds_phy_default_start_handler,
+		.parent.stop_handler  = scic_sds_phy_ready_state_stop_handler,
+		.parent.reset_handler = scic_sds_phy_ready_state_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_ready_state_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCI_BASE_PHY_STATE_RESETTING] = {
+		.parent.start_handler = scic_sds_phy_default_start_handler,
+		.parent.stop_handler  = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_resetting_state_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	},
+	[SCI_BASE_PHY_STATE_FINAL] = {
+		.parent.start_handler = scic_sds_phy_default_start_handler,
+		.parent.stop_handler  = scic_sds_phy_default_stop_handler,
+		.parent.reset_handler = scic_sds_phy_default_reset_handler,
+		.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
+		.frame_handler		 = scic_sds_phy_default_frame_handler,
+		.event_handler		 = scic_sds_phy_default_event_handler,
+		.consume_power_handler	 = scic_sds_phy_default_consume_power_handler
+	}
+};
+
+/*
+ * ****************************************************************************
+ * *  PHY STATE PRIVATE METHODS
+ * **************************************************************************** */
+
+/**
+ *
+ * @this_phy: This is the struct scic_sds_phy object to stop.
+ *
+ * This method will stop the struct scic_sds_phy object. This does not reset the
+ * protocol engine it just suspends it and places it in a state where it will
+ * not cause the end device to power up. none
+ */
+static void scu_link_layer_stop_protocol_engine(
+	struct scic_sds_phy *this_phy)
+{
+	u32 scu_sas_pcfg_value;
+	u32 enable_spinup_value;
+
+	/* Suspend the protocol engine and place it in a sata spinup hold state */
+	scu_sas_pcfg_value  = SCU_SAS_PCFG_READ(this_phy);
+	scu_sas_pcfg_value |= (
+		SCU_SAS_PCFG_GEN_BIT(OOB_RESET)
+		| SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE)
+		| SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)
+		);
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+	/* Disable the notify enable spinup primitives */
+	enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy);
+	enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);
+	SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value);
+}
+
+/**
+ *
+ *
+ * This method will start the OOB/SN state machine for this struct scic_sds_phy object.
+ */
+static void scu_link_layer_start_oob(
+	struct scic_sds_phy *this_phy)
+{
+	u32 scu_sas_pcfg_value;
+
+	scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+	scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+	scu_sas_pcfg_value &=
+		~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
+
+	SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+}
+
+/**
+ *
+ *
+ * This method will transmit a hard reset request on the specified phy. The SCU
+ * hardware requires that we reset the OOB state machine and set the hard reset
+ * bit in the phy configuration register. We then must start OOB over with the
+ * hard reset bit set.
+ */
+static void scu_link_layer_tx_hard_reset(
+	struct scic_sds_phy *this_phy)
+{
+	u32 phy_configuration_value;
+
+	/*
+	 * SAS Phys must wait for the HARD_RESET_TX event notification to transition
+	 * to the starting state. */
+	phy_configuration_value = SCU_SAS_PCFG_READ(this_phy);
+	phy_configuration_value |=
+		(SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET));
+	SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
+
+	/* Now take the OOB state machine out of reset */
+	phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+	phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+	SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
+}
+
+/*
+ * ****************************************************************************
+ * *  PHY BASE STATE METHODS
+ * **************************************************************************** */
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state
+ * handlers for the phy object base state machine initial state. none
+ */
+static void scic_sds_phy_initial_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a
+ * struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state
+ * handlers for the phy object base state machine initial state. - The SCU
+ * hardware is requested to stop the protocol engine. none
+ */
+static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object)
+{
+	struct scic_sds_phy *sci_phy;
+
+	sci_phy = (struct scic_sds_phy *)object;
+
+	/*
+	 * @todo We need to get to the controller to place this PE in a
+	 * reset state
+	 */
+
+	scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STOPPED);
+
+	if (sci_phy->sata_timeout_timer != NULL) {
+		isci_event_timer_destroy(scic_sds_phy_get_controller(sci_phy),
+					 sci_phy->sata_timeout_timer);
+
+		sci_phy->sata_timeout_timer = NULL;
+	}
+
+	scu_link_layer_stop_protocol_engine(sci_phy);
+
+	if (sci_phy->parent.state_machine.previous_state_id !=
+			SCI_BASE_PHY_STATE_INITIAL)
+		scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy),
+					      scic_sds_phy_get_port(sci_phy),
+					      sci_phy);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state
+ * handlers for the phy object base state machine starting state. - The SCU
+ * hardware is requested to start OOB/SN on this protocl engine. - The phy
+ * starting substate machine is started. - If the previous state was the ready
+ * state then the struct scic_sds_controller is informed that the phy has gone link
+ * down. none
+ */
+static void scic_sds_phy_starting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING);
+
+	scu_link_layer_stop_protocol_engine(this_phy);
+	scu_link_layer_start_oob(this_phy);
+
+	/* We don't know what kind of phy we are going to be just yet */
+	this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+	this_phy->bcn_received_while_port_unassigned = false;
+
+	/* Change over to the starting substate machine to continue */
+	sci_base_state_machine_start(&this_phy->starting_substate_machine);
+
+	if (this_phy->parent.state_machine.previous_state_id
+	    == SCI_BASE_PHY_STATE_READY) {
+		scic_sds_controller_link_down(
+			scic_sds_phy_get_controller(this_phy),
+			scic_sds_phy_get_port(this_phy),
+			this_phy
+			);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state
+ * handlers for the phy object base state machine ready state. - The SCU
+ * hardware protocol engine is resumed. - The struct scic_sds_controller is informed
+ * that the phy object has gone link up. none
+ */
+static void scic_sds_phy_ready_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY);
+
+	scic_sds_controller_link_up(
+		scic_sds_phy_get_controller(this_phy),
+		scic_sds_phy_get_port(this_phy),
+		this_phy
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on exiting
+ * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware
+ * protocol engine represented by this struct scic_sds_phy object. none
+ */
+static void scic_sds_phy_ready_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_suspend(this_phy);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state
+ * handlers for the phy object base state machine resetting state. none
+ */
+static void scic_sds_phy_resetting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING);
+
+	/*
+	 * The phy is being reset, therefore deactivate it from the port.
+	 * In the resetting state we don't notify the user regarding
+	 * link up and link down notifications. */
+	scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, false);
+
+	if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+		scu_link_layer_tx_hard_reset(this_phy);
+	} else {
+		/*
+		 * The SCU does not need to have a descrete reset state so just go back to
+		 * the starting state. */
+		sci_base_state_machine_change_state(
+			&this_phy->parent.state_machine,
+			SCI_BASE_PHY_STATE_STARTING
+			);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object.
+ *
+ * This method will perform the actions required by the struct scic_sds_phy on
+ * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state
+ * handlers for the phy object base state machine final state. none
+ */
+static void scic_sds_phy_final_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_phy *this_phy;
+
+	this_phy = (struct scic_sds_phy *)object;
+
+	scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL);
+
+	/* Nothing to do here */
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_phy_state_table[] = {
+	[SCI_BASE_PHY_STATE_INITIAL] = {
+		.enter_state = scic_sds_phy_initial_state_enter,
+	},
+	[SCI_BASE_PHY_STATE_STOPPED] = {
+		.enter_state = scic_sds_phy_stopped_state_enter,
+	},
+	[SCI_BASE_PHY_STATE_STARTING] = {
+		.enter_state = scic_sds_phy_starting_state_enter,
+	},
+	[SCI_BASE_PHY_STATE_READY] = {
+		.enter_state = scic_sds_phy_ready_state_enter,
+		.exit_state = scic_sds_phy_ready_state_exit,
+	},
+	[SCI_BASE_PHY_STATE_RESETTING] = {
+		.enter_state = scic_sds_phy_resetting_state_enter,
+	},
+	[SCI_BASE_PHY_STATE_FINAL] = {
+		.enter_state = scic_sds_phy_final_state_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h
new file mode 100644
index 0000000..b611e33
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy.h
@@ -0,0 +1,476 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PHY_H_
+#define _SCIC_SDS_PHY_H_
+
+/**
+ * This file contains the structures, constants and prototypes for the
+ *    struct scic_sds_phy object.
+ *
+ *
+ */
+
+#include "intel_sata.h"
+#include "intel_sas.h"
+#include "sci_base_phy.h"
+#include "scu_registers.h"
+
+struct scic_sds_port;
+/**
+ *
+ *
+ * This is the timeout value for the SATA phy to wait for a SIGNATURE FIS
+ * before restarting the starting state machine.  Technically, the old parallel
+ * ATA specification required up to 30 seconds for a device to issue its
+ * signature FIS as a result of a soft reset.  Now we see that devices respond
+ * generally within 15 seconds, but we'll use 25 for now.
+ */
+#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT    25000
+
+/**
+ *
+ *
+ * This is the timeout for the SATA OOB/SN because the hardware does not
+ * recognize a hot plug after OOB signal but before the SN signals.  We need to
+ * make sure after a hotplug timeout if we have not received the speed event
+ * notification from the hardware that we restart the hardware OOB state
+ * machine.
+ */
+#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT  250
+
+/**
+ * enum SCIC_SDS_PHY_STARTING_SUBSTATES -
+ *
+ *
+ */
+enum SCIC_SDS_PHY_STARTING_SUBSTATES {
+	/**
+	 * Initial state
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
+
+	/**
+	 * Wait state for the hardware OSSP event type notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
+
+	/**
+	 * Wait state for the PHY speed notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
+
+	/**
+	 * Wait state for the IAF Unsolicited frame notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
+
+	/**
+	 * Wait state for the request to consume power
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
+
+	/**
+	 * Wait state for request to consume power
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
+
+	/**
+	 * Wait state for the SATA PHY notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
+
+	/**
+	 * Wait for the SATA PHY speed notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
+
+	/**
+	 * Wait state for the SIGNATURE FIS unsolicited frame notification
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
+
+	/**
+	 * Exit state for this state machine
+	 */
+	SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
+};
+
+struct scic_sds_port;
+struct scic_sds_controller;
+
+/**
+ * This enumeration provides a named phy type for the state machine
+ *
+ *
+ */
+enum SCIC_SDS_PHY_PROTOCOL {
+	/**
+	 * This is an unknown phy type since there is either nothing on the other
+	 * end or we have not detected the phy type as yet.
+	 */
+	SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
+
+	/**
+	 * This is a SAS PHY
+	 */
+	SCIC_SDS_PHY_PROTOCOL_SAS,
+
+	/**
+	 * This is a SATA PHY
+	 */
+	SCIC_SDS_PHY_PROTOCOL_SATA,
+
+	SCIC_SDS_MAX_PHY_PROTOCOLS
+};
+
+/**
+ * struct scic_sds_phy - This structure  contains or references all of the data
+ *    necessary to represent the core phy object and SCU harware protocol
+ *    engine.
+ *
+ *
+ */
+struct scic_sds_phy {
+	struct sci_base_phy parent;
+
+	/**
+	 * This field specifies the port object that owns/contains this phy.
+	 */
+	struct scic_sds_port *owning_port;
+
+	/**
+	 * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s,
+	 * or 6.0 Gb/s operation.
+	 */
+	enum sci_sas_link_rate max_negotiated_speed;
+
+	/**
+	 * This member specifies the protocol being utilized on this phy.  This
+	 * field contains a legitamite value once the PHY has link trained with
+	 * a remote phy.
+	 */
+	enum SCIC_SDS_PHY_PROTOCOL protocol;
+
+	/**
+	 * This field specifies the index with which this phy is associated (0-3).
+	 */
+	u8 phy_index;
+
+	/**
+	 * This member indicates if this particular PHY has received a BCN while
+	 * it had no port assignement.  This BCN will be reported once the phy is
+	 * assigned to a port.
+	 */
+	bool bcn_received_while_port_unassigned;
+
+	/**
+	 * This field indicates if this PHY is currently in the process of
+	 * link training (i.e. it has started OOB, but has yet to perform
+	 * IAF exchange/Signature FIS reception).
+	 */
+	bool is_in_link_training;
+
+	union {
+		struct {
+			struct sci_sas_identify_address_frame identify_address_frame_buffer;
+
+		} sas;
+
+		struct {
+			struct sata_fis_reg_d2h signature_fis_buffer;
+
+		} sata;
+
+	} phy_type;
+
+	/**
+	 * This field contains a reference to the timer utilized in detecting
+	 * when a signature FIS timeout has occurred.  The signature FIS is the
+	 * first FIS sent by an attached SATA device after OOB/SN.
+	 */
+	void *sata_timeout_timer;
+
+	const struct scic_sds_phy_state_handler *state_handlers;
+
+	struct sci_base_state_machine starting_substate_machine;
+
+	/**
+	 * This field is the pointer to the transport layer register for the SCU
+	 * hardware.
+	 */
+	struct scu_transport_layer_registers __iomem *transport_layer_registers;
+
+	/**
+	 * This field points to the link layer register set within the SCU.
+	 */
+	struct scu_link_layer_registers __iomem *link_layer_registers;
+
+};
+
+
+typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32);
+typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32);
+typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *);
+
+/**
+ * struct scic_sds_phy_state_handler -
+ *
+ *
+ */
+struct scic_sds_phy_state_handler {
+	/**
+	 * This is the struct sci_base_phy object state handlers.
+	 */
+	struct sci_base_phy_state_handler parent;
+
+	/**
+	 * The state handler for unsolicited frames received from the SCU hardware.
+	 */
+	scic_sds_phy_frame_handler_t frame_handler;
+
+	/**
+	 * The state handler for events received from the SCU hardware.
+	 */
+	scic_sds_phy_event_handler_t event_handler;
+
+	/**
+	 * The state handler for staggered spinup.
+	 */
+	scic_sds_phy_power_handler_t consume_power_handler;
+
+};
+
+extern const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[];
+extern const struct sci_base_state scic_sds_phy_state_table[];
+extern const struct sci_base_state scic_sds_phy_starting_substates[];
+extern const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[];
+
+
+/**
+ * scic_sds_phy_get_index() -
+ *
+ * This macro returns the phy index for the specified phy
+ */
+#define scic_sds_phy_get_index(phy) \
+	((phy)->phy_index)
+
+/**
+ * scic_sds_phy_get_controller() - This macro returns the controller for this
+ *    phy
+ *
+ *
+ */
+#define scic_sds_phy_get_controller(phy) \
+	(scic_sds_port_get_controller((phy)->owning_port))
+
+/**
+ * scic_sds_phy_get_base_state_machine() - This macro returns the state machine
+ *    for the base phy
+ *
+ *
+ */
+#define scic_sds_phy_get_base_state_machine(phy) \
+	(&(phy)->parent.state_machine)
+
+/**
+ * scic_sds_phy_get_starting_substate_machine() - This macro returns the
+ *    starting substate machine for this phy
+ *
+ *
+ */
+#define scic_sds_phy_get_starting_substate_machine(phy)	\
+	(&(phy)->starting_substate_machine)
+
+/**
+ * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for
+ *    this phy object
+ *
+ *
+ */
+#define scic_sds_phy_set_state_handlers(phy, handlers) \
+	((phy)->state_handlers = (handlers))
+
+/**
+ * scic_sds_phy_set_base_state_handlers() -
+ *
+ * This macro set the base state handlers for the phy object.
+ */
+#define scic_sds_phy_set_base_state_handlers(phy, state_id) \
+	scic_sds_phy_set_state_handlers(\
+		(phy), \
+		&scic_sds_phy_state_handler_table[(state_id)] \
+		)
+
+/**
+ * scic_sds_phy_is_ready() -
+ *
+ * This macro returns true if the current base state for this phy is
+ * SCI_BASE_PHY_STATE_READY
+ */
+#define scic_sds_phy_is_ready(phy) \
+	(\
+		SCI_BASE_PHY_STATE_READY \
+		== sci_base_state_machine_get_state(\
+			scic_sds_phy_get_base_state_machine(phy) \
+			) \
+	)
+
+/* --------------------------------------------------------------------------- */
+
+
+
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_phy_construct(
+	struct scic_sds_phy *this_phy,
+	struct scic_sds_port *owning_port,
+	u8 phy_index);
+
+struct scic_sds_port *scic_sds_phy_get_port(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_set_port(
+	struct scic_sds_phy *this_phy,
+	struct scic_sds_port *owning_port);
+
+enum sci_status scic_sds_phy_initialize(
+	struct scic_sds_phy *this_phy,
+	struct scu_transport_layer_registers __iomem *transport_layer_registers,
+	struct scu_link_layer_registers __iomem *link_layer_registers);
+
+enum sci_status scic_sds_phy_start(
+	struct scic_sds_phy *this_phy);
+
+enum sci_status scic_sds_phy_stop(
+	struct scic_sds_phy *this_phy);
+
+enum sci_status scic_sds_phy_reset(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_sata_timeout(
+	void *cookie);
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_phy_suspend(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_resume(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_setup_transport(
+	struct scic_sds_phy *this_phy,
+	u32 device_id);
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_phy_event_handler(
+	struct scic_sds_phy *this_phy,
+	u32 event_code);
+
+enum sci_status scic_sds_phy_frame_handler(
+	struct scic_sds_phy *this_phy,
+	u32 frame_index);
+
+enum sci_status scic_sds_phy_consume_power_handler(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_get_sas_address(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_address *sas_address);
+
+void scic_sds_phy_get_attached_sas_address(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_address *sas_address);
+
+void scic_sds_phy_get_protocols(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_identify_address_frame_protocols *protocols);
+
+void scic_sds_phy_get_attached_phy_protocols(
+	struct scic_sds_phy *this_phy,
+	struct sci_sas_identify_address_frame_protocols *protocols);
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS PHY Handler Methods
+ * ****************************************************************************- */
+
+enum sci_status scic_sds_phy_default_start_handler(
+	struct sci_base_phy *phy);
+
+enum sci_status scic_sds_phy_default_stop_handler(
+	struct sci_base_phy *phy);
+
+enum sci_status scic_sds_phy_default_reset_handler(
+	struct sci_base_phy *phy);
+
+enum sci_status scic_sds_phy_default_destroy_handler(
+	struct sci_base_phy *phy);
+
+enum sci_status scic_sds_phy_default_frame_handler(
+	struct scic_sds_phy *phy,
+	u32 frame_index);
+
+enum sci_status scic_sds_phy_default_event_handler(
+	struct scic_sds_phy *phy,
+	u32 evnet_code);
+
+enum sci_status scic_sds_phy_default_consume_power_handler(
+	struct scic_sds_phy *phy);
+
+#endif /* _SCIC_SDS_PHY_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h
new file mode 100644
index 0000000..ddbb236
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PHY_REGISTERS_H_
+#define _SCIC_SDS_PHY_REGISTERS_H_
+
+/**
+ * This file contains the macros used by the phy object to read/write to the
+ *    SCU link layer registers.
+ *
+ *
+ */
+
+#include "scic_sds_controller.h"
+
+/* **************************************************************************
+ * * SCU TRANSPORT LAYER REGISTER OPERATIONS
+ * ************************************************************************** */
+
+/**
+ * Macro to read the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_read(phy, reg) \
+	scu_register_read( \
+		scic_sds_phy_get_controller(phy), \
+		(phy)->transport_layer_registers->reg \
+		)
+
+/**
+ * Macro to write the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_write(phy, reg, value) \
+	scu_register_write( \
+		scic_sds_phy_get_controller(phy), \
+		(phy)->transport_layer_registers->reg, \
+		(value) \
+		)
+
+/* **************************************************************************
+ * * Transport Layer registers controlled by the phy object
+ * ************************************************************************** */
+
+/* This macro reads the Transport layer control register */
+#define SCU_TLCR_READ(phy) \
+	scu_transport_layer_read(phy, control)
+
+/* This macro writes the Transport layer control register */
+#define SCU_TLCR_WRITE(phy, value) \
+	scu_transport_layer_write(phy, control, value)
+
+/* This macro reads the Transport layer address translation register */
+#define SCU_TLADTR_READ(phy) \
+	scu_transport_layer_read(phy, address_translation)
+
+/* This macro writes the Transport layer address translation register */
+#define SCU_TLADTR_WRITE(phy) \
+	scu_transport_layer_write(phy, address_translation, value)
+
+/* This macro writes the STP Transport Layer Direct Attached RNi register */
+#define SCU_STPTLDARNI_WRITE(phy, index) \
+	scu_transport_layer_write(phy, stp_rni, index)
+
+/* This macro reads the STP Transport Layer Direct Attached RNi register */
+#define SCU_STPTLDARNI_READ(phy) \
+	scu_transport_layer_read(phy, stp_rni)
+
+/*
+ * *****************************************************************************
+ * * SCU LINK LAYER REGISTER OPERATIONS
+ * ***************************************************************************** */
+
+/**
+ * scu_link_layer_register_read() -
+ *
+ * THis macro requests the SCU register write for the specified link layer
+ * register.
+ */
+#define scu_link_layer_register_read(phy, reg) \
+	scu_register_read(\
+		scic_sds_phy_get_controller(phy), \
+		(phy)->link_layer_registers->reg \
+		)
+
+/**
+ * scu_link_layer_register_write() -
+ *
+ * This macro requests the SCU register read for the specified link layer
+ * register.
+ */
+#define scu_link_layer_register_write(phy, reg, value) \
+	scu_register_write(\
+		scic_sds_phy_get_controller(phy), \
+		(phy)->link_layer_registers->reg, \
+		(value)	\
+		)
+
+/*
+ * *****************************************************************************
+ * * SCU LINK LAYER REGISTERS
+ * ***************************************************************************** */
+
+/* / This macro reads from the SAS Identify Frame PHY Identifier register */
+#define SCU_SAS_TIPID_READ(phy)	\
+	scu_link_layer_register_read(phy, identify_frame_phy_id)
+
+/* / This macro writes to the SAS Identify Frame PHY Identifier register */
+#define SCU_SAS_TIPID_WRITE(phy, value)	\
+	scu_link_layer_register_write(phy, identify_frame_phy_id, value)
+
+/* / This macro reads from the SAS Identification register */
+#define SCU_SAS_TIID_READ(phy) \
+	scu_link_layer_register_read(phy, transmit_identification)
+
+/* / This macro writes to the SAS Identification register */
+#define SCU_SAS_TIID_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, transmit_identification, value)
+
+/* / This macro reads the SAS Device Name High register */
+#define SCU_SAS_TIDNH_READ(phy)	\
+	scu_link_layer_register_read(phy, sas_device_name_high)
+
+/* / This macro writes the SAS Device Name High register */
+#define SCU_SAS_TIDNH_WRITE(phy, value)	\
+	scu_link_layer_register_write(phy, sas_device_name_high, value)
+
+/* / This macro reads the SAS Device Name Low register */
+#define SCU_SAS_TIDNL_READ(phy)	\
+	scu_link_layer_register_read(phy, sas_device_name_low)
+
+/* / This macro writes the SAS Device Name Low register */
+#define SCU_SAS_TIDNL_WRITE(phy, value)	\
+	scu_link_layer_register_write(phy, sas_device_name_low, value)
+
+/* / This macro reads the Source SAS Address High register */
+#define SCU_SAS_TISSAH_READ(phy) \
+	scu_link_layer_register_read(phy, source_sas_address_high)
+
+/* / This macro writes the Source SAS Address High register */
+#define SCU_SAS_TISSAH_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, source_sas_address_high, value)
+
+/* / This macro reads the Source SAS Address Low register */
+#define SCU_SAS_TISSAL_READ(phy) \
+	scu_link_layer_register_read(phy, source_sas_address_low)
+
+/* / This macro writes the Source SAS Address Low register */
+#define SCU_SAS_TISSAL_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, source_sas_address_low, value)
+
+/* / This macro reads the PHY Configuration register */
+#define SCU_SAS_PCFG_READ(phy) \
+	scu_link_layer_register_read(phy, phy_configuration);
+
+/* / This macro writes the PHY Configuration register */
+#define SCU_SAS_PCFG_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, phy_configuration, value)
+
+/* / This macro reads the PHY Enable Spinup register */
+#define SCU_SAS_ENSPINUP_READ(phy) \
+	scu_link_layer_register_read(phy, notify_enable_spinup_control)
+
+/* / This macro writes the PHY Enable Spinup register */
+#define SCU_SAS_ENSPINUP_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, notify_enable_spinup_control, value)
+
+/* This macro reads the CLKSM register */
+#define SCU_SAS_CLKSM_READ(phy) \
+	scu_link_layer_register_read(phy, clock_skew_management)
+
+/* This macro writes the CLKSM register */
+#define SCU_SAS_CLKSM_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, clock_skew_management, value)
+
+/* / This macro reads the PHY Capacity register */
+#define SCU_SAS_PHYCAP_READ(phy) \
+	scu_link_layer_register_read(phy, phy_capabilities)
+
+/* / This macro writes the PHY Capacity register */
+#define SCU_SAS_PHYCAP_WRITE(phy, value) \
+	scu_link_layer_register_write(phy, phy_capabilities, value)
+
+/* / This macro reads the Recieved PHY Capacity register */
+#define SCU_SAS_RECPHYCAP_READ(phy) \
+	scu_link_layer_register_read(phy, receive_phycap)
+
+/* / This macro reads the link layer control register */
+#define SCU_SAS_LLCTL_READ(phy)	\
+	scu_link_layer_register_read(phy, link_layer_control);
+
+/* / This macro writes the link layer control register */
+#define SCU_SAS_LLCTL_WRITE(phy, value)	\
+	scu_link_layer_register_write(phy, link_layer_control, value);
+
+#endif /* _SCIC_SDS_PHY_REGISTERS_H_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 03/10] isci/core: port
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 01/10] isci/core: controller Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 02/10] isci/core: phy Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 04/10] isci/core: remote device Dan Williams
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Port state machines and port configuration agent.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/sci_base_port.h             |  203 +
 drivers/scsi/isci/core/scic_port.h                 |  195 +
 drivers/scsi/isci/core/scic_sds_port.c             | 2915 ++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_port.h             |  499 +++
 .../isci/core/scic_sds_port_configuration_agent.c  |  863 ++++++
 .../isci/core/scic_sds_port_configuration_agent.h  |  108 +
 drivers/scsi/isci/core/scic_sds_port_registers.h   |  147 +
 7 files changed, 4930 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_port.h
 create mode 100644 drivers/scsi/isci/core/scic_port.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_port.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_port_registers.h

diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h
new file mode 100644
index 0000000..4e2031d
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_port.h
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_PORT_H_
+#define _SCI_BASE_PORT_H_
+
+#include "sci_base_state_machine.h"
+#include "sci_object.h"
+
+/**
+ * enum sci_base_port_states - This enumeration depicts all the states for the
+ *    common port state machine.
+ *
+ *
+ */
+enum sci_base_port_states {
+	/**
+	 * This state indicates that the port has successfully been stopped.
+	 * In this state no new IO operations are permitted.
+	 * This state is entered from the STOPPING state.
+	 */
+	SCI_BASE_PORT_STATE_STOPPED,
+
+	/**
+	 * This state indicates that the port is in the process of stopping.
+	 * In this state no new IO operations are permitted, but existing IO
+	 * operations are allowed to complete.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_PORT_STATE_STOPPING,
+
+	/**
+	 * This state indicates the port is now ready.  Thus, the user is
+	 * able to perform IO operations on this port.
+	 * This state is entered from the STARTING state.
+	 */
+	SCI_BASE_PORT_STATE_READY,
+
+	/**
+	 * This state indicates the port is in the process of performing a hard
+	 * reset.  Thus, the user is unable to perform IO operations on this
+	 * port.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_PORT_STATE_RESETTING,
+
+	/**
+	 * This state indicates the port has failed a reset request.  This state
+	 * is entered when a port reset request times out.
+	 * This state is entered from the RESETTING state.
+	 */
+	SCI_BASE_PORT_STATE_FAILED,
+
+	SCI_BASE_PORT_MAX_STATES
+
+};
+
+/**
+ * struct sci_base_port - The base port object abstracts the fields common to
+ *    all SCI port objects.
+ *
+ *
+ */
+struct sci_base_port {
+	/**
+	 * The field specifies that the parent object for the base controller
+	 * is the base object itself.
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This field contains the information for the base port state machine.
+	 */
+	struct sci_base_state_machine state_machine;
+};
+
+struct sci_base_phy;
+
+typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)(
+	struct sci_base_port *
+	);
+
+typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)(
+	struct sci_base_port *,
+	struct sci_base_phy *
+	);
+
+typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)(
+	struct sci_base_port *,
+	u32 timeout
+	);
+
+/**
+ * struct sci_base_port_state_handler - This structure contains all of the
+ *    state handler methods common to base port state machines.  Handler
+ *    methods provide the ability to change the behavior for user requests or
+ *    transitions depending on the state the machine is in.
+ *
+ *
+ */
+struct sci_base_port_state_handler {
+	/**
+	 * The start_handler specifies the method invoked when a user attempts to
+	 * start a port.
+	 */
+	SCI_BASE_PORT_HANDLER_T start_handler;
+
+	/**
+	 * The stop_handler specifies the method invoked when a user attempts to
+	 * stop a port.
+	 */
+	SCI_BASE_PORT_HANDLER_T stop_handler;
+
+	/**
+	 * The destruct_handler specifies the method invoked when attempting to
+	 * destruct a port.
+	 */
+	SCI_BASE_PORT_HANDLER_T destruct_handler;
+
+	/**
+	 * The reset_handler specifies the method invoked when a user attempts to
+	 * hard reset a port.
+	 */
+	SCI_BASE_PORT_RESET_HANDLER_T reset_handler;
+
+	/**
+	 * The add_phy_handler specifies the method invoked when a user attempts to
+	 * add another phy into the port.
+	 */
+	SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler;
+
+	/**
+	 * The remove_phy_handler specifies the method invoked when a user
+	 * attempts to remove a phy from the port.
+	 */
+	SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler;
+
+};
+
+/**
+ * sci_base_port_construct() - Construct the base port object
+ * @this_port: This parameter specifies the base port to be constructed.
+ * @state_table: This parameter specifies the table of state definitions to be
+ *    utilized for the domain state machine.
+ *
+ */
+void sci_base_port_construct(
+	struct sci_base_port *this_port,
+	const struct sci_base_state *state_table);
+
+#endif /* _SCI_BASE_PORT_H_ */
diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h
new file mode 100644
index 0000000..8222443
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_port.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_PORT_H_
+#define _SCIC_PORT_H_
+
+/**
+ * This file contains all of the interface methods that can be called by an SCI
+ *    Core user on a SAS or SATA port.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+#include "intel_sas.h"
+
+struct scic_sds_port;
+
+enum SCIC_PORT_NOT_READY_REASON_CODE {
+	SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
+	SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
+	SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
+	SCIC_PORT_NOT_READY_RECONFIGURING,
+
+	SCIC_PORT_NOT_READY_REASON_CODE_MAX
+};
+
+/**
+ * struct scic_port_end_point_properties - This structure defines the
+ *    properties that can be retrieved for each end-point local or remote
+ *    (attached) port in the controller.
+ *
+ *
+ */
+struct scic_port_end_point_properties {
+	/**
+	 * This field indicates the SAS address for the associated end
+	 * point in the port.
+	 */
+	struct sci_sas_address sas_address;
+
+	/**
+	 * This field indicates the protocols supported by the associated
+	 * end-point in the port.
+	 */
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+};
+
+/**
+ * struct scic_port_properties - This structure defines the properties that can
+ *    be retrieved for each port in the controller.
+ *
+ *
+ */
+struct scic_port_properties {
+	/**
+	 * This field specifies the logical index of the port (0 relative).
+	 */
+	u32 index;
+
+	/**
+	 * This field indicates the local end-point properties for port.
+	 */
+	struct scic_port_end_point_properties local;
+
+	/**
+	 * This field indicates the remote (attached) end-point properties
+	 * for the port.
+	 */
+	struct scic_port_end_point_properties remote;
+
+	/**
+	 * This field specifies the phys contained inside the port.
+	 */
+	u32 phy_mask;
+
+};
+
+/**
+ * scic_port_get_properties() - This method simply returns the properties
+ *    regarding the port, such as: physical index, protocols, sas address, etc.
+ * @port: this parameter specifies the port for which to retrieve the physical
+ *    index.
+ * @properties: This parameter specifies the properties structure into which to
+ *    copy the requested information.
+ *
+ * Indicate if the user specified a valid port. SCI_SUCCESS This value is
+ * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
+ * value is returned if the specified port is not valid.  When this value is
+ * returned, no data is copied to the properties output parameter.
+ */
+enum sci_status scic_port_get_properties(
+	struct scic_sds_port *port,
+	struct scic_port_properties *properties);
+
+/**
+ * scic_port_stop() - This method will make the port no longer ready for
+ *    operation.  After invoking this method IO operation is not possible.
+ * @port: This parameter specifies the port to be stopped.
+ *
+ * Indicate if the port was successfully stopped. SCI_SUCCESS This value is
+ * returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE
+ * This value is returned if the port is already stopped or in the process of
+ * stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied
+ * port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a
+ * stop operation can't be completed due to the state of port.
+ */
+enum sci_status scic_port_stop(
+	struct scic_sds_port *port);
+
+/**
+ * scic_port_hard_reset() - This method will request the SCI implementation to
+ *    perform a HARD RESET on the SAS Port.  If/When the HARD RESET completes
+ *    the SCI user will be notified via an SCI OS callback indicating a direct
+ *    attached device was found.
+ * @port: a handle corresponding to the SAS port to be hard reset.
+ * @reset_timeout: This parameter specifies the number of milliseconds in which
+ *    the port reset operation should complete.
+ *
+ * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for
+ * each phy in the SAS Port at completion of the hard reset sequence. Return a
+ * status indicating whether the hard reset started successfully. SCI_SUCCESS
+ * This value is returned if the hard reset operation started successfully.
+ */
+enum sci_status scic_port_hard_reset(
+	struct scic_sds_port *port,
+	u32 reset_timeout);
+
+/**
+ * scic_port_enable_broadcast_change_notification() - This API method enables
+ *    the broadcast change notification from underneath hardware.
+ * @port: The port upon which broadcast change notifications (BCN) are to be
+ *    enabled.
+ *
+ */
+void scic_port_enable_broadcast_change_notification(
+	struct scic_sds_port *port);
+
+
+#endif  /* _SCIC_PORT_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c
new file mode 100644
index 0000000..a41fe42
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port.c
@@ -0,0 +1,2915 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_sas.h"
+#include "sci_base_port.h"
+#include "scic_controller.h"
+#include "scic_phy.h"
+#include "scic_port.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_phy_registers.h"
+#include "scic_sds_port.h"
+#include "scic_sds_port_registers.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_remote_node_context.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "scic_sds_controller_registers.h"
+
+
+static void scic_sds_port_invalid_link_up(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+static void scic_sds_port_timeout_handler(
+	void *port);
+#define SCIC_SDS_PORT_MIN_TIMER_COUNT  (SCI_MAX_PORTS)
+#define SCIC_SDS_PORT_MAX_TIMER_COUNT  (SCI_MAX_PORTS)
+
+#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT  (1000)
+#define SCU_DUMMY_INDEX    (0xFFFF)
+
+void sci_base_port_construct(
+	struct sci_base_port *base_port,
+	const struct sci_base_state *state_table)
+{
+	base_port->parent.private = NULL;
+	sci_base_state_machine_construct(
+		&base_port->state_machine,
+		&base_port->parent,
+		state_table,
+		SCI_BASE_PORT_STATE_STOPPED
+		);
+
+	sci_base_state_machine_start(
+		&base_port->state_machine
+		);
+}
+
+/**
+ *
+ * @this_port: This is the port object to which the phy is being assigned.
+ * @phy_index: This is the phy index that is being assigned to the port.
+ *
+ * This method will return a true value if the specified phy can be assigned to
+ * this port The following is a list of phys for each port that are allowed: -
+ * Port 0 - 3 2 1 0 - Port 1 -     1 - Port 2 - 3 2 - Port 3 - 3 This method
+ * doesn't preclude all configurations.  It merely ensures that a phy is part
+ * of the allowable set of phy identifiers for that port.  For example, one
+ * could assign phy 3 to port 0 and no other phys.  Please refer to
+ * scic_sds_port_is_phy_mask_valid() for information regarding whether the
+ * phy_mask for a port can be supported. bool true if this is a valid phy
+ * assignment for the port false if this is not a valid phy assignment for the
+ * port
+ */
+bool scic_sds_port_is_valid_phy_assignment(
+	struct scic_sds_port *this_port,
+	u32 phy_index)
+{
+	/* Initialize to invalid value. */
+	u32 existing_phy_index = SCI_MAX_PHYS;
+	u32 index;
+
+	if ((this_port->physical_port_index == 1) && (phy_index != 1)) {
+		return false;
+	}
+
+	if (this_port->physical_port_index == 3 && phy_index != 3) {
+		return false;
+	}
+
+	if (
+		(this_port->physical_port_index == 2)
+		&& ((phy_index == 0) || (phy_index == 1))
+		) {
+		return false;
+	}
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if ((this_port->phy_table[index] != NULL)
+		    && (index != phy_index)) {
+			existing_phy_index = index;
+		}
+	}
+
+	/*
+	 * Ensure that all of the phys in the port are capable of
+	 * operating at the same maximum link rate. */
+	if (
+		(existing_phy_index < SCI_MAX_PHYS)
+		&& (this_port->owning_controller->user_parameters.sds1.phys[
+			    phy_index].max_speed_generation !=
+		    this_port->owning_controller->user_parameters.sds1.phys[
+			    existing_phy_index].max_speed_generation)
+		)
+		return false;
+
+	return true;
+}
+
+/**
+ * This method requests a list (mask) of the phys contained in the supplied SAS
+ *    port.
+ * @this_port: a handle corresponding to the SAS port for which to return the
+ *    phy mask.
+ *
+ * Return a bit mask indicating which phys are a part of this port. Each bit
+ * corresponds to a phy identifier (e.g. bit 0 = phy id 0).
+ */
+u32 scic_sds_port_get_phys(struct scic_sds_port *this_port)
+{
+	u32 index;
+	u32 mask;
+
+	mask = 0;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->phy_table[index] != NULL) {
+			mask |= (1 << index);
+		}
+	}
+
+	return mask;
+}
+
+/**
+ *
+ * @this_port: This is the port object for which to determine if the phy mask
+ *    can be supported.
+ *
+ * This method will return a true value if the port's phy mask can be supported
+ * by the SCU. The following is a list of valid PHY mask configurations for
+ * each port: - Port 0 - [[3  2] 1] 0 - Port 1 -        [1] - Port 2 - [[3] 2]
+ * - Port 3 -  [3] This method returns a boolean indication specifying if the
+ * phy mask can be supported. true if this is a valid phy assignment for the
+ * port false if this is not a valid phy assignment for the port
+ */
+bool scic_sds_port_is_phy_mask_valid(
+	struct scic_sds_port *this_port,
+	u32 phy_mask)
+{
+	if (this_port->physical_port_index == 0) {
+		if (((phy_mask & 0x0F) == 0x0F)
+		    || ((phy_mask & 0x03) == 0x03)
+		    || ((phy_mask & 0x01) == 0x01)
+		    || (phy_mask == 0))
+			return true;
+	} else if (this_port->physical_port_index == 1) {
+		if (((phy_mask & 0x02) == 0x02)
+		    || (phy_mask == 0))
+			return true;
+	} else if (this_port->physical_port_index == 2) {
+		if (((phy_mask & 0x0C) == 0x0C)
+		    || ((phy_mask & 0x04) == 0x04)
+		    || (phy_mask == 0))
+			return true;
+	} else if (this_port->physical_port_index == 3) {
+		if (((phy_mask & 0x08) == 0x08)
+		    || (phy_mask == 0))
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ *
+ * @this_port: This parameter specifies the port from which to return a
+ *    connected phy.
+ *
+ * This method retrieves a currently active (i.e. connected) phy contained in
+ * the port.  Currently, the lowest order phy that is connected is returned.
+ * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is
+ * returned if there are no currently active (i.e. connected to a remote end
+ * point) phys contained in the port. All other values specify a struct scic_sds_phy
+ * object that is active in the port.
+ */
+static struct scic_sds_phy *scic_sds_port_get_a_connected_phy(
+	struct scic_sds_port *this_port
+	) {
+	u32 index;
+	struct scic_sds_phy *phy;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		/*
+		 * Ensure that the phy is both part of the port and currently
+		 * connected to the remote end-point. */
+		phy = this_port->phy_table[index];
+		if (
+			(phy != NULL)
+			&& scic_sds_port_active_phy(this_port, phy)
+			) {
+			return phy;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * scic_sds_port_set_phy() -
+ * @out]: port The port object to which the phy assignement is being made.
+ * @out]: phy The phy which is being assigned to the port.
+ *
+ * This method attempts to make the assignment of the phy to the port. If
+ * successful the phy is assigned to the ports phy table. bool true if the phy
+ * assignment can be made. false if the phy assignement can not be made. This
+ * is a functional test that only fails if the phy is currently assigned to a
+ * different port.
+ */
+enum sci_status scic_sds_port_set_phy(
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	/*
+	 * Check to see if we can add this phy to a port
+	 * that means that the phy is not part of a port and that the port does
+	 * not already have a phy assinged to the phy index. */
+	if (
+		(port->phy_table[phy->phy_index] == NULL)
+		&& (scic_sds_phy_get_port(phy) == NULL)
+		&& scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)
+		) {
+		/*
+		 * Phy is being added in the stopped state so we are in MPC mode
+		 * make logical port index = physical port index */
+		port->logical_port_index = port->physical_port_index;
+		port->phy_table[phy->phy_index] = phy;
+		scic_sds_phy_set_port(phy, port);
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE;
+}
+
+/**
+ * scic_sds_port_clear_phy() -
+ * @out]: port The port from which the phy is being cleared.
+ * @out]: phy The phy being cleared from the port.
+ *
+ * This method will clear the phy assigned to this port.  This method fails if
+ * this phy is not currently assinged to this port. bool true if the phy is
+ * removed from the port. false if this phy is not assined to this port.
+ */
+enum sci_status scic_sds_port_clear_phy(
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	/* Make sure that this phy is part of this port */
+	if (
+		(port->phy_table[phy->phy_index] == phy)
+		&& (scic_sds_phy_get_port(phy) == port)
+		) {
+		/* Yep it is assigned to this port so remove it */
+		scic_sds_phy_set_port(
+			phy,
+			&scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS]
+			);
+
+		port->phy_table[phy->phy_index] = NULL;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE;
+}
+
+/**
+ * scic_sds_port_add_phy() -
+ * @this_port: This parameter specifies the port in which the phy will be added.
+ * @the_phy: This parameter is the phy which is to be added to the port.
+ *
+ * This method will add a PHY to the selected port. This method returns an
+ * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status
+ * is failre to add the phy to the port.
+ */
+enum sci_status scic_sds_port_add_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	return this_port->state_handlers->parent.add_phy_handler(
+		       &this_port->parent, &the_phy->parent);
+}
+
+
+/**
+ * scic_sds_port_remove_phy() -
+ * @this_port: This parameter specifies the port in which the phy will be added.
+ * @the_phy: This parameter is the phy which is to be added to the port.
+ *
+ * This method will remove the PHY from the selected PORT. This method returns
+ * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other
+ * status is failre to add the phy to the port.
+ */
+enum sci_status scic_sds_port_remove_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	return this_port->state_handlers->parent.remove_phy_handler(
+		       &this_port->parent, &the_phy->parent);
+}
+
+/**
+ * This method requests the SAS address for the supplied SAS port from the SCI
+ *    implementation.
+ * @this_port: a handle corresponding to the SAS port for which to return the
+ *    SAS address.
+ * @sas_address: This parameter specifies a pointer to a SAS address structure
+ *    into which the core will copy the SAS address for the port.
+ *
+ */
+void scic_sds_port_get_sas_address(
+	struct scic_sds_port *this_port,
+	struct sci_sas_address *sas_address)
+{
+	u32 index;
+
+	sas_address->high = 0;
+	sas_address->low  = 0;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->phy_table[index] != NULL) {
+			scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address);
+		}
+	}
+}
+
+/**
+ * This method will indicate which protocols are supported by this port.
+ * @this_port: a handle corresponding to the SAS port for which to return the
+ *    supported protocols.
+ * @protocols: This parameter specifies a pointer to an IAF protocol field
+ *    structure into which the core will copy the protocol values for the port.
+ *     The values are returned as part of a bit mask in order to allow for
+ *    multi-protocol support.
+ *
+ */
+static void scic_sds_port_get_protocols(
+	struct scic_sds_port *this_port,
+	struct sci_sas_identify_address_frame_protocols *protocols)
+{
+	u8 index;
+
+	protocols->u.all = 0;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->phy_table[index] != NULL) {
+			scic_sds_phy_get_protocols(this_port->phy_table[index], protocols);
+		}
+	}
+}
+
+/**
+ * This method requests the SAS address for the device directly attached to
+ *    this SAS port.
+ * @this_port: a handle corresponding to the SAS port for which to return the
+ *    SAS address.
+ * @sas_address: This parameter specifies a pointer to a SAS address structure
+ *    into which the core will copy the SAS address for the device directly
+ *    attached to the port.
+ *
+ */
+void scic_sds_port_get_attached_sas_address(
+	struct scic_sds_port *this_port,
+	struct sci_sas_address *sas_address)
+{
+	struct sci_sas_identify_address_frame_protocols protocols;
+	struct scic_sds_phy *phy;
+
+	/*
+	 * Ensure that the phy is both part of the port and currently
+	 * connected to the remote end-point. */
+	phy = scic_sds_port_get_a_connected_phy(this_port);
+	if (phy != NULL) {
+		scic_sds_phy_get_attached_phy_protocols(phy, &protocols);
+
+		if (!protocols.u.bits.stp_target) {
+			scic_sds_phy_get_attached_sas_address(phy, sas_address);
+		} else {
+			scic_sds_phy_get_sas_address(phy, sas_address);
+			sas_address->low += phy->phy_index;
+		}
+	} else {
+		sas_address->high = 0;
+		sas_address->low  = 0;
+	}
+}
+
+/**
+ * This method will indicate which protocols are supported by this remote
+ *    device.
+ * @this_port: a handle corresponding to the SAS port for which to return the
+ *    supported protocols.
+ * @protocols: This parameter specifies a pointer to an IAF protocol field
+ *    structure into which the core will copy the protocol values for the port.
+ *     The values are returned as part of a bit mask in order to allow for
+ *    multi-protocol support.
+ *
+ */
+void scic_sds_port_get_attached_protocols(
+	struct scic_sds_port *this_port,
+	struct sci_sas_identify_address_frame_protocols *protocols)
+{
+	struct scic_sds_phy *phy;
+
+	/*
+	 * Ensure that the phy is both part of the port and currently
+	 * connected to the remote end-point. */
+	phy = scic_sds_port_get_a_connected_phy(this_port);
+	if (phy != NULL)
+		scic_sds_phy_get_attached_phy_protocols(phy, protocols);
+	else
+		protocols->u.all = 0;
+}
+
+/**
+ * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround
+ *
+ * @sci_port: logical port on which we need to create the remote node context
+ * @rni: remote node index for this remote node context.
+ *
+ * This routine will construct a dummy remote node context data structure
+ * This structure will be posted to the hardware to work around a scheduler
+ * error in the hardware.
+ */
+void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni)
+{
+	union scu_remote_node_context *rnc;
+
+	rnc = &sci_port->owning_controller->remote_node_context_table[rni];
+
+	memset(rnc, 0, sizeof(union scu_remote_node_context));
+
+	rnc->ssp.remote_sas_address_hi = 0;
+	rnc->ssp.remote_sas_address_lo = 0;
+
+	rnc->ssp.remote_node_index = rni;
+	rnc->ssp.remote_node_port_width = 1;
+	rnc->ssp.logical_port_index = sci_port->physical_port_index;
+
+	rnc->ssp.nexus_loss_timer_enable = false;
+	rnc->ssp.check_bit = false;
+	rnc->ssp.is_valid = true;
+	rnc->ssp.is_remote_node_context = true;
+	rnc->ssp.function_number = 0;
+	rnc->ssp.arbitration_wait_time = 0;
+}
+
+/**
+ * scic_sds_port_construct_dummy_task() - create dummy task for si workaround
+ * @sci_port The logical port on which we need to create the
+ *            remote node context.
+ *            context.
+ * @tci The remote node index for this remote node context.
+ *
+ * This routine will construct a dummy task context data structure.  This
+ * structure will be posted to the hardwre to work around a scheduler error
+ * in the hardware.
+ *
+ */
+void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci)
+{
+	struct scu_task_context *task_context;
+
+	task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci);
+
+	memset(task_context, 0, sizeof(struct scu_task_context));
+
+	task_context->abort = 0;
+	task_context->priority = 0;
+	task_context->initiator_request = 1;
+	task_context->connection_rate = 1;
+	task_context->protocol_engine_index = 0;
+	task_context->logical_port_index = sci_port->physical_port_index;
+	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
+	task_context->task_index = scic_sds_io_tag_get_index(tci);
+	task_context->valid = SCU_TASK_CONTEXT_VALID;
+	task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+	task_context->remote_node_index = sci_port->reserved_rni;
+	task_context->command_code = 0;
+
+	task_context->link_layer_control = 0;
+	task_context->do_not_dma_ssp_good_response = 1;
+	task_context->strict_ordering = 0;
+	task_context->control_frame = 0;
+	task_context->timeout_enable = 0;
+	task_context->block_guard_enable = 0;
+
+	task_context->address_modifier = 0;
+
+	task_context->task_phase = 0x01;
+}
+
+void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port)
+{
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+
+	if (sci_port->reserved_tci != SCU_DUMMY_INDEX)
+		scic_controller_free_io_tag(scic, sci_port->reserved_tci);
+
+	if (sci_port->reserved_rni != SCU_DUMMY_INDEX)
+		scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes,
+								     1, sci_port->reserved_rni);
+
+	sci_port->reserved_rni = SCU_DUMMY_INDEX;
+	sci_port->reserved_tci = SCU_DUMMY_INDEX;
+}
+
+void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index,
+			     struct scic_sds_controller *scic)
+{
+	u32 index;
+
+	sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table);
+
+	sci_base_state_machine_construct(
+		scic_sds_port_get_ready_substate_machine(sci_port),
+		&sci_port->parent.parent,
+		scic_sds_port_ready_substate_table,
+		SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+		);
+
+	sci_port->logical_port_index  = SCIC_SDS_DUMMY_PORT;
+	sci_port->physical_port_index = port_index;
+	sci_port->active_phy_mask     = 0;
+
+	sci_port->owning_controller = scic;
+
+	sci_port->started_request_count = 0;
+	sci_port->assigned_device_count = 0;
+
+	sci_port->reserved_rni = SCU_DUMMY_INDEX;
+	sci_port->reserved_tci = SCU_DUMMY_INDEX;
+
+	sci_port->timer_handle = NULL;
+
+	sci_port->port_task_scheduler_registers = NULL;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++)
+		sci_port->phy_table[index] = NULL;
+}
+
+/**
+ * This method performs initialization of the supplied port. Initialization
+ *    includes: - state machine initialization - member variable initialization
+ *    - configuring the phy_mask
+ * @this_port:
+ * @transport_layer_registers:
+ * @port_task_scheduler_registers:
+ * @port_configuration_regsiter:
+ *
+ * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned
+ * if the phy being added to the port
+ */
+enum sci_status scic_sds_port_initialize(
+	struct scic_sds_port *this_port,
+	void __iomem *port_task_scheduler_registers,
+	void __iomem *port_configuration_regsiter,
+	void __iomem *viit_registers)
+{
+	this_port->port_task_scheduler_registers  = port_task_scheduler_registers;
+	this_port->port_pe_configuration_register = port_configuration_regsiter;
+	this_port->viit_registers                 = viit_registers;
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_port: This is the struct scic_sds_port object for which has a phy that has
+ *    gone link up.
+ * @the_phy: This is the struct scic_sds_phy object that has gone link up.
+ * @do_notify_user: This parameter specifies whether to inform the user (via
+ *    scic_cb_port_link_up()) as to the fact that a new phy as become ready.
+ *
+ * This method is the a general link up handler for the struct scic_sds_port object.
+ * This function will determine if this struct scic_sds_phy can be assigned to this
+ * struct scic_sds_port object. If the struct scic_sds_phy object can is not a valid PHY for
+ * this port then the function will notify the SCIC_USER. A PHY can only be
+ * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
+ * the same port. none
+ */
+void scic_sds_port_general_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy,
+	bool do_notify_user)
+{
+	struct sci_sas_address port_sas_address;
+	struct sci_sas_address phy_sas_address;
+
+	scic_sds_port_get_attached_sas_address(this_port, &port_sas_address);
+	scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address);
+
+	/*
+	 * If the SAS address of the new phy matches the SAS address of
+	 * other phys in the port OR this is the first phy in the port,
+	 * then activate the phy and allow it to be used for operations
+	 * in this port. */
+	if (
+		(
+			(phy_sas_address.high == port_sas_address.high)
+			&& (phy_sas_address.low  == port_sas_address.low)
+		)
+		|| (this_port->active_phy_mask == 0)
+		) {
+		scic_sds_port_activate_phy(this_port, the_phy, do_notify_user);
+
+		if (this_port->parent.state_machine.current_state_id
+		    == SCI_BASE_PORT_STATE_RESETTING) {
+			sci_base_state_machine_change_state(
+				&this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY
+				);
+		}
+	} else {
+		scic_sds_port_invalid_link_up(this_port, the_phy);
+	}
+}
+
+enum sci_status scic_port_stop(struct scic_sds_port *port)
+{
+	return port->state_handlers->parent.stop_handler(&port->parent);
+}
+
+enum sci_status scic_port_get_properties(
+	struct scic_sds_port *port,
+	struct scic_port_properties *prop)
+{
+	if ((port == NULL) ||
+	    (port->logical_port_index == SCIC_SDS_DUMMY_PORT))
+		return SCI_FAILURE_INVALID_PORT;
+
+	prop->index    = port->logical_port_index;
+	prop->phy_mask = scic_sds_port_get_phys(port);
+	scic_sds_port_get_sas_address(port, &prop->local.sas_address);
+	scic_sds_port_get_protocols(port, &prop->local.protocols);
+	scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address);
+	scic_sds_port_get_attached_protocols(port, &prop->remote.protocols);
+
+	return SCI_SUCCESS;
+}
+
+
+enum sci_status scic_port_hard_reset(
+	struct scic_sds_port *port,
+	u32 reset_timeout)
+{
+	return port->state_handlers->parent.reset_handler(
+		       &port->parent, reset_timeout);
+}
+
+/**
+ * This method assigns the direct attached device ID for this port.
+ *
+ * @param[in] this_port The port for which the direct attached device id is to
+ *       be assigned.
+ * @param[in] device_id The direct attached device ID to assign to the port.
+ *       This will be the RNi for the device
+ */
+void scic_sds_port_setup_transports(
+	struct scic_sds_port *this_port,
+	u32 device_id)
+{
+	u8 index;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->active_phy_mask & (1 << index))
+			scic_sds_phy_setup_transport(this_port->phy_table[index], device_id);
+	}
+}
+
+/**
+ *
+ * @this_port: This is the port on which the phy should be enabled.
+ * @the_phy: This is the specific phy which to enable.
+ * @do_notify_user: This parameter specifies whether to inform the user (via
+ *    scic_cb_port_link_up()) as to the fact that a new phy as become ready.
+ *
+ * This method will activate the phy in the port. Activation includes: - adding
+ * the phy to the port - enabling the Protocol Engine in the silicon. -
+ * notifying the user that the link is up. none
+ */
+void scic_sds_port_activate_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy,
+	bool do_notify_user)
+{
+	struct scic_sds_controller *controller;
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+	controller = scic_sds_port_get_controller(this_port);
+	scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
+
+	/* If this is sata port then the phy has already been resumed */
+	if (!protocols.u.bits.stp_target) {
+		scic_sds_phy_resume(the_phy);
+	}
+
+	this_port->active_phy_mask |= 1 << the_phy->phy_index;
+
+	scic_sds_controller_clear_invalid_phy(controller, the_phy);
+
+	if (do_notify_user == true)
+		isci_event_port_link_up(this_port->owning_controller,
+					this_port,
+					the_phy);
+}
+
+/**
+ *
+ * @this_port: This is the port on which the phy should be deactivated.
+ * @the_phy: This is the specific phy that is no longer active in the port.
+ * @do_notify_user: This parameter specifies whether to inform the user (via
+ *    isci_event_port_link_down()) as to the fact that a new phy as become
+ *    ready.
+ *
+ * This method will deactivate the supplied phy in the port. none
+ */
+void scic_sds_port_deactivate_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy,
+	bool do_notify_user)
+{
+	this_port->active_phy_mask &= ~(1 << the_phy->phy_index);
+
+	the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
+
+	/* Re-assign the phy back to the LP as if it were a narrow port */
+	SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index);
+
+	if (do_notify_user == true)
+		isci_event_port_link_down(this_port->owning_controller,
+					  this_port,
+					  the_phy);
+}
+
+/**
+ *
+ * @this_port: This is the port on which the phy should be disabled.
+ * @the_phy: This is the specific phy which to disabled.
+ *
+ * This method will disable the phy and report that the phy is not valid for
+ * this port object. None
+ */
+static void scic_sds_port_invalid_link_up(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	struct scic_sds_controller *controller = scic_sds_port_get_controller(this_port);
+
+	/*
+	 * Check to see if we have alreay reported this link as bad and if not go
+	 * ahead and tell the SCI_USER that we have discovered an invalid link. */
+	if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) {
+		scic_sds_controller_set_invalid_phy(controller, the_phy);
+
+		isci_event_port_invalid_link_up(controller, this_port, the_phy);
+	}
+}
+
+/**
+ * This method returns false if the port only has a single phy object assigned.
+ *     If there are no phys or more than one phy then the method will return
+ *    true.
+ * @this_port: The port for which the wide port condition is to be checked.
+ *
+ * bool true Is returned if this is a wide ported port. false Is returned if
+ * this is a narrow port.
+ */
+static bool scic_sds_port_is_wide(struct scic_sds_port *this_port)
+{
+	u32 index;
+	u32 phy_count = 0;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->phy_table[index] != NULL) {
+			phy_count++;
+		}
+	}
+
+	return phy_count != 1;
+}
+
+/**
+ * This method is called by the PHY object when the link is detected. if the
+ *    port wants the PHY to continue on to the link up state then the port
+ *    layer must return true.  If the port object returns false the phy object
+ *    must halt its attempt to go link up.
+ * @this_port: The port associated with the phy object.
+ * @the_phy: The phy object that is trying to go link up.
+ *
+ * true if the phy object can continue to the link up condition. true Is
+ * returned if this phy can continue to the ready state. false Is returned if
+ * can not continue on to the ready state. This notification is in place for
+ * wide ports and direct attached phys.  Since there are no wide ported SATA
+ * devices this could become an invalid port configuration.
+ */
+bool scic_sds_port_link_detected(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+	scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
+
+	if (
+		(this_port->logical_port_index != SCIC_SDS_DUMMY_PORT)
+		&& (protocols.u.bits.stp_target)
+		&& scic_sds_port_is_wide(this_port)
+		) {
+		scic_sds_port_invalid_link_up(this_port, the_phy);
+
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * This method is the entry point for the phy to inform the port that it is now
+ *    in a ready state
+ * @this_port:
+ *
+ *
+ */
+void scic_sds_port_link_up(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	the_phy->is_in_link_training = false;
+
+	this_port->state_handlers->link_up_handler(this_port, the_phy);
+}
+
+/**
+ * This method is the entry point for the phy to inform the port that it is no
+ *    longer in a ready state
+ * @this_port:
+ *
+ *
+ */
+void scic_sds_port_link_down(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	this_port->state_handlers->link_down_handler(this_port, the_phy);
+}
+
+/**
+ * This method is called to start an IO request on this port.
+ * @this_port:
+ * @the_device:
+ * @the_io_request:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_port_start_io(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *the_device,
+	struct scic_sds_request *the_io_request)
+{
+	return this_port->state_handlers->start_io_handler(
+		       this_port, the_device, the_io_request);
+}
+
+/**
+ * This method is called to complete an IO request to the port.
+ * @this_port:
+ * @the_device:
+ * @the_io_request:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_port_complete_io(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *the_device,
+	struct scic_sds_request *the_io_request)
+{
+	return this_port->state_handlers->complete_io_handler(
+		       this_port, the_device, the_io_request);
+}
+
+/**
+ * This method is provided to timeout requests for port operations. Mostly its
+ *    for the port reset operation.
+ *
+ *
+ */
+static void scic_sds_port_timeout_handler(void *port)
+{
+	struct scic_sds_port *this_port = port;
+	u32 current_state;
+
+	current_state = sci_base_state_machine_get_state(
+		&this_port->parent.state_machine);
+
+	if (current_state == SCI_BASE_PORT_STATE_RESETTING) {
+		/*
+		 * if the port is still in the resetting state then the timeout fired
+		 * before the reset completed. */
+		sci_base_state_machine_change_state(
+			&this_port->parent.state_machine,
+			SCI_BASE_PORT_STATE_FAILED
+			);
+	} else if (current_state == SCI_BASE_PORT_STATE_STOPPED) {
+		/*
+		 * if the port is stopped then the start request failed
+		 * In this case stay in the stopped state. */
+		dev_err(sciport_to_dev(this_port),
+			"%s: SCIC Port 0x%p failed to stop before tiemout.\n",
+			__func__,
+			this_port);
+	} else if (current_state == SCI_BASE_PORT_STATE_STOPPING) {
+		/* if the port is still stopping then the stop has not completed */
+		isci_event_port_stop_complete(
+			scic_sds_port_get_controller(this_port),
+			port,
+			SCI_FAILURE_TIMEOUT
+			);
+	} else {
+		/*
+		 * The port is in the ready state and we have a timer reporting a timeout
+		 * this should not happen. */
+		dev_err(sciport_to_dev(this_port),
+			"%s: SCIC Port 0x%p is processing a timeout operation "
+			"in state %d.\n",
+			__func__,
+			this_port,
+			current_state);
+	}
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ * This function updates the hardwares VIIT entry for this port.
+ *
+ *
+ */
+void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port)
+{
+	struct sci_sas_address sas_address;
+
+	scic_sds_port_get_sas_address(this_port, &sas_address);
+
+	scu_port_viit_register_write(
+		this_port, initiator_sas_address_hi, sas_address.high);
+
+	scu_port_viit_register_write(
+		this_port, initiator_sas_address_lo, sas_address.low);
+
+	/* This value get cleared just in case its not already cleared */
+	scu_port_viit_register_write(
+		this_port, reserved, 0);
+
+	/* We are required to update the status register last */
+	scu_port_viit_register_write(
+		this_port, status, (
+			SCU_VIIT_ENTRY_ID_VIIT
+			| SCU_VIIT_IPPT_INITIATOR
+			| ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT)
+			| SCU_VIIT_STATUS_ALL_VALID
+			)
+		);
+}
+
+/**
+ * This method returns the maximum allowed speed for data transfers on this
+ *    port.  This maximum allowed speed evaluates to the maximum speed of the
+ *    slowest phy in the port.
+ * @this_port: This parameter specifies the port for which to retrieve the
+ *    maximum allowed speed.
+ *
+ * This method returns the maximum negotiated speed of the slowest phy in the
+ * port.
+ */
+enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
+	struct scic_sds_port *this_port)
+{
+	u16 index             = 0;
+	enum sci_sas_link_rate max_allowed_speed = SCI_SAS_600_GB;
+	struct scic_sds_phy *phy               = NULL;
+
+	/*
+	 * Loop through all of the phys in this port and find the phy with the
+	 * lowest maximum link rate. */
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		phy = this_port->phy_table[index];
+		if (
+			(phy != NULL)
+			&& (scic_sds_port_active_phy(this_port, phy) == true)
+			&& (phy->max_negotiated_speed < max_allowed_speed)
+			)
+			max_allowed_speed = phy->max_negotiated_speed;
+	}
+
+	return max_allowed_speed;
+}
+
+
+/**
+ * This method passes the event to core user.
+ * @this_port: The port that a BCN happens.
+ * @this_phy: The phy that receives BCN.
+ *
+ */
+void scic_sds_port_broadcast_change_received(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *this_phy)
+{
+	/* notify the user. */
+	isci_event_port_bc_change_primitive_received(
+		this_port->owning_controller, this_port, this_phy
+		);
+}
+
+
+/**
+ * This API methhod enables the broadcast change notification from underneath
+ *    hardware.
+ * @this_port: The port that a BCN had been disabled from.
+ *
+ */
+void scic_port_enable_broadcast_change_notification(
+	struct scic_sds_port *port)
+{
+	struct scic_sds_phy *phy;
+	u32 register_value;
+	u8 index;
+
+	/* Loop through all of the phys to enable BCN. */
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		phy = port->phy_table[index];
+		if (phy != NULL) {
+			register_value = SCU_SAS_LLCTL_READ(phy);
+
+			/* clear the bit by writing 1. */
+			SCU_SAS_LLCTL_WRITE(phy, register_value);
+		}
+	}
+}
+
+/*
+ * ****************************************************************************
+ * *  READY SUBSTATE HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method is the general ready state stop handler for the struct scic_sds_port
+ * object.  This function will transition the ready substate machine to its
+ * final state. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_ready_substate_stop_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	sci_base_state_machine_change_state(
+		&this_port->parent.state_machine,
+		SCI_BASE_PORT_STATE_STOPPING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @device: This is the struct sci_base_remote_device object which is not used in this
+ *    function.
+ * @io_request: This is the struct sci_base_request object which is not used in this
+ *    function.
+ *
+ * This method is the general ready substate complete io handler for the
+ * struct scic_sds_port object.  This function decrments the outstanding request count
+ * for this port object. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_ready_substate_complete_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	scic_sds_port_decrement_request_count(this_port);
+
+	return SCI_SUCCESS;
+}
+
+static enum sci_status scic_sds_port_ready_substate_add_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+	enum sci_status status;
+
+	status = scic_sds_port_set_phy(this_port, this_phy);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_port_general_link_up_handler(this_port, this_phy, true);
+
+		this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
+
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+			);
+	}
+
+	return status;
+}
+
+
+static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+	enum sci_status status;
+
+	status = scic_sds_port_clear_phy(this_port, this_phy);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_port_deactivate_phy(this_port, this_phy, true);
+
+		this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
+
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+			);
+	}
+
+	return status;
+}
+
+/*
+ * ****************************************************************************
+ * *  READY SUBSTATE WAITING HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @this_port: This is the struct scic_sds_port object that which has a phy that has
+ *    gone link up.
+ * @the_phy: This is the struct scic_sds_phy object that has gone link up.
+ *
+ * This method is the ready waiting substate link up handler for the
+ * struct scic_sds_port object.  This methos will report the link up condition for
+ * this port and will transition to the ready operational substate. none
+ */
+static void scic_sds_port_ready_waiting_substate_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	/*
+	 * Since this is the first phy going link up for the port we can just enable
+	 * it and continue. */
+	scic_sds_port_activate_phy(this_port, the_phy, true);
+
+	sci_base_state_machine_change_state(
+		&this_port->ready_substate_machine,
+		SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+		);
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @device: This is the struct sci_base_remote_device object which is not used in this
+ *    request.
+ * @io_request: This is the struct sci_base_request object which is not used in this
+ *    function.
+ *
+ * This method is the ready waiting substate start io handler for the
+ * struct scic_sds_port object. The port object can not accept new requests so the
+ * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/*
+ * ****************************************************************************
+ * *  READY SUBSTATE OPERATIONAL HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @timeout: This is the timeout for the reset request to complete.
+ *
+ * This method will casue the port to reset. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_ready_operational_substate_reset_handler(
+	struct sci_base_port *port,
+	u32 timeout)
+{
+	enum sci_status status = SCI_FAILURE_INVALID_PHY;
+	u32 phy_index;
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *selected_phy = NULL;
+
+
+	/* Select a phy on which we can send the hard reset request. */
+	for (
+		phy_index = 0;
+		(phy_index < SCI_MAX_PHYS)
+		&& (selected_phy == NULL);
+		phy_index++
+		) {
+		selected_phy = this_port->phy_table[phy_index];
+
+		if (
+			(selected_phy != NULL)
+			&& !scic_sds_port_active_phy(this_port, selected_phy)
+			) {
+			/* We found a phy but it is not ready select different phy */
+			selected_phy = NULL;
+		}
+	}
+
+	/* If we have a phy then go ahead and start the reset procedure */
+	if (selected_phy != NULL) {
+		status = scic_sds_phy_reset(selected_phy);
+
+		if (status == SCI_SUCCESS) {
+			isci_event_timer_start(
+				scic_sds_port_get_controller(this_port),
+				this_port->timer_handle,
+				timeout
+				);
+
+			this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
+
+			sci_base_state_machine_change_state(
+				&this_port->parent.state_machine,
+				SCI_BASE_PORT_STATE_RESETTING
+				);
+		}
+	}
+
+	return status;
+}
+
+/**
+ * scic_sds_port_ready_operational_substate_link_up_handler() -
+ * @this_port: This is the struct scic_sds_port object that which has a phy that has
+ *    gone link up.
+ * @the_phy: This is the struct scic_sds_phy object that has gone link up.
+ *
+ * This method is the ready operational substate link up handler for the
+ * struct scic_sds_port object. This function notifies the SCI User that the phy has
+ * gone link up. none
+ */
+static void scic_sds_port_ready_operational_substate_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	scic_sds_port_general_link_up_handler(this_port, the_phy, true);
+}
+
+/**
+ * scic_sds_port_ready_operational_substate_link_down_handler() -
+ * @this_port: This is the struct scic_sds_port object that which has a phy that has
+ *    gone link down.
+ * @the_phy: This is the struct scic_sds_phy object that has gone link down.
+ *
+ * This method is the ready operational substate link down handler for the
+ * struct scic_sds_port object. This function notifies the SCI User that the phy has
+ * gone link down and if this is the last phy in the port the port will change
+ * state to the ready waiting substate. none
+ */
+static void scic_sds_port_ready_operational_substate_link_down_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy)
+{
+	scic_sds_port_deactivate_phy(this_port, the_phy, true);
+
+	/*
+	 * If there are no active phys left in the port, then transition
+	 * the port to the WAITING state until such time as a phy goes
+	 * link up. */
+	if (this_port->active_phy_mask == 0) {
+		sci_base_state_machine_change_state(
+			scic_sds_port_get_ready_substate_machine(this_port),
+			SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+			);
+	}
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @device: This is the struct sci_base_remote_device object which is not used in this
+ *    function.
+ * @io_request: This is the struct sci_base_request object which is not used in this
+ *    function.
+ *
+ * This method is the ready operational substate start io handler for the
+ * struct scic_sds_port object.  This function incremetns the outstanding request
+ * count for this port object. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	scic_sds_port_increment_request_count(this_port);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * ****************************************************************************
+ * *  READY SUBSTATE OPERATIONAL HANDLERS
+ * **************************************************************************** */
+
+/**
+ * scic_sds_port_ready_configuring_substate_add_phy_handler() -
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port add phy request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+	enum sci_status status;
+
+	status = scic_sds_port_set_phy(this_port, this_phy);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_port_general_link_up_handler(this_port, this_phy, true);
+
+		/*
+		 * Re-enter the configuring state since this may be the last phy in
+		 * the port. */
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+			);
+	}
+
+	return status;
+}
+
+/**
+ * scic_sds_port_ready_configuring_substate_remove_phy_handler() -
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port remove phy request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+	enum sci_status status;
+
+	status = scic_sds_port_clear_phy(this_port, this_phy);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_port_deactivate_phy(this_port, this_phy, true);
+
+		/*
+		 * Re-enter the configuring state since this may be the last phy in
+		 * the port. */
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+			);
+	}
+
+	return status;
+}
+
+/**
+ * scic_sds_port_ready_configuring_substate_complete_io_handler() -
+ * @port: This is the port that is being requested to complete the io request.
+ * @device: This is the device on which the io is completing.
+ *
+ * This method will decrement the outstanding request count for this port. If
+ * the request count goes to 0 then the port can be reprogrammed with its new
+ * phy data.
+ */
+static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	scic_sds_port_decrement_request_count(port);
+
+	if (port->started_request_count == 0) {
+		sci_base_state_machine_change_state(
+			&port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+			);
+	}
+
+	return SCI_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_port_state_handler
+scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
+{
+	/* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_ready_substate_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_ready_substate_add_phy_handler,
+			scic_sds_port_default_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_ready_waiting_substate_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_ready_waiting_substate_start_io_handler,
+		scic_sds_port_ready_substate_complete_io_handler,
+	},
+	/* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_ready_substate_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_ready_operational_substate_reset_handler,
+			scic_sds_port_ready_substate_add_phy_handler,
+			scic_sds_port_ready_substate_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_ready_operational_substate_link_up_handler,
+		scic_sds_port_ready_operational_substate_link_down_handler,
+		scic_sds_port_ready_operational_substate_start_io_handler,
+		scic_sds_port_ready_substate_complete_io_handler
+	},
+	/* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_ready_substate_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_ready_configuring_substate_add_phy_handler,
+			scic_sds_port_ready_configuring_substate_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_default_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_ready_configuring_substate_complete_io_handler
+	}
+};
+
+
+/**
+ * scic_sds_port_set_ready_state_handlers() -
+ *
+ * This macro sets the port ready substate handlers.
+ */
+#define scic_sds_port_set_ready_state_handlers(port, state_id) \
+	scic_sds_port_set_state_handlers(\
+		port, &scic_sds_port_ready_substate_handler_table[(state_id)] \
+		)
+
+/*
+ * ******************************************************************************
+ * *  PORT STATE PRIVATE METHODS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @this_port: This is the struct scic_sds_port object to suspend.
+ *
+ * This method will susped the port task scheduler for this port object. none
+ */
+static void scic_sds_port_suspend_port_task_scheduler(
+	struct scic_sds_port *this_port)
+{
+	u32 pts_control_value;
+
+	pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+	pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
+
+	scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ * scic_sds_port_post_dummy_request() - post dummy/workaround request
+ * @sci_port: port to post task
+ *
+ * Prevent the hardware scheduler from posting new requests to the front
+ * of the scheduler queue causing a starvation problem for currently
+ * ongoing requests.
+ *
+ */
+void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port)
+{
+	u32 command;
+	struct scu_task_context *task_context;
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+	u16 tci = sci_port->reserved_tci;
+
+	task_context = scic_sds_controller_get_task_context_buffer(scic, tci);
+
+	task_context->abort = 0;
+
+	command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+		  sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
+		  tci;
+
+	scic_sds_controller_post_request(scic, command);
+}
+
+/**
+ * This routine will abort the dummy request.  This will alow the hardware to
+ * power down parts of the silicon to save power.
+ *
+ * @sci_port: The port on which the task must be aborted.
+ *
+ */
+void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port)
+{
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+	u16 tci = sci_port->reserved_tci;
+	struct scu_task_context *tc;
+	u32 command;
+
+	tc = scic_sds_controller_get_task_context_buffer(scic, tci);
+
+	tc->abort = 1;
+
+	command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT |
+		  sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
+		  tci;
+
+	scic_sds_controller_post_request(scic, command);
+}
+
+/**
+ *
+ * @this_port: This is the struct scic_sds_port object to resume.
+ *
+ * This method will resume the port task scheduler for this port object. none
+ */
+static void scic_sds_port_resume_port_task_scheduler(
+	struct scic_sds_port *this_port)
+{
+	u32 pts_control_value;
+
+	pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+	pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
+
+	scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/*
+ * ******************************************************************************
+ * *  PORT READY SUBSTATE METHODS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the
+ * port for any ready phys.  If there is at least one phy in a ready state then
+ * the port transitions to the ready operational substate. none
+ */
+static void scic_sds_port_ready_substate_waiting_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_ready_state_handlers(
+		this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+		);
+
+	scic_sds_port_suspend_port_task_scheduler(this_port);
+
+	this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
+
+	if (this_port->active_phy_mask != 0) {
+		/* At least one of the phys on the port is ready */
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+			);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets
+ * the state handlers for the port object, notifies the SCI User that the port
+ * is ready, and resumes port operations. none
+ */
+static void scic_sds_port_ready_substate_operational_enter(
+	struct sci_base_object *object)
+{
+	u32 index;
+	struct scic_sds_port *this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_ready_state_handlers(
+		this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+		);
+
+	isci_event_port_ready(
+		scic_sds_port_get_controller(this_port), this_port
+		);
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (this_port->phy_table[index] != NULL) {
+			scic_sds_port_write_phy_assignment(
+				this_port, this_port->phy_table[index]
+				);
+		}
+	}
+
+	scic_sds_port_update_viit_entry(this_port);
+
+	scic_sds_port_resume_port_task_scheduler(this_port);
+
+	/* Post the dummy task for the port so the hardware can schedule
+	 * io correctly
+	 */
+	scic_sds_port_post_dummy_request(this_port);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
+ * the port not ready and suspends the port task scheduler. none
+ */
+static void scic_sds_port_ready_substate_operational_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)object;
+
+/*
+ * Kill the dummy task for this port if it has not yet posted
+ * the hardware will treat this as a NOP and just return abort
+ * complete.
+ */
+	scic_sds_port_abort_dummy_request(this_port);
+
+	isci_event_port_not_ready(
+		scic_sds_port_get_controller(this_port),
+		this_port,
+		this_port->not_ready_reason
+		);
+}
+
+/*
+ * ******************************************************************************
+ * *  PORT READY CONFIGURING METHODS
+ * ****************************************************************************** */
+
+/**
+ * scic_sds_port_ready_substate_configuring_enter() -
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
+ * the port not ready and suspends the port task scheduler. none
+ */
+static void scic_sds_port_ready_substate_configuring_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_ready_state_handlers(
+		this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+		);
+
+	if (this_port->active_phy_mask == 0) {
+		isci_event_port_not_ready(
+			scic_sds_port_get_controller(this_port),
+			this_port,
+			SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+			);
+	} else if (this_port->started_request_count == 0) {
+		sci_base_state_machine_change_state(
+			&this_port->ready_substate_machine,
+			SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+			);
+	}
+}
+
+static void scic_sds_port_ready_substate_configuring_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_suspend_port_task_scheduler(this_port);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_port_ready_substate_table[] = {
+	[SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = {
+		.enter_state = scic_sds_port_ready_substate_waiting_enter,
+	},
+	[SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = {
+		.enter_state = scic_sds_port_ready_substate_operational_enter,
+		.exit_state  = scic_sds_port_ready_substate_operational_exit
+	},
+	[SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = {
+		.enter_state = scic_sds_port_ready_substate_configuring_enter,
+		.exit_state  = scic_sds_port_ready_substate_configuring_exit
+	},
+};
+
+/*
+ * ***************************************************************************
+ * *  DEFAULT HANDLERS
+ * *************************************************************************** */
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for port a start request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_start_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to start while in invalid "
+		 "state %d\n",
+		 __func__,
+		 port,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port stop request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_default_stop_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to stop while in invalid "
+		 "state %d\n",
+		 __func__,
+		 port,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port destruct request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_destruct_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to destruct while in invalid "
+		 "state %d\n",
+		 __func__,
+		 port,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @timeout: This is the timeout for the reset request to complete.
+ *
+ * This is the default method for a port reset request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_reset_handler(
+	struct sci_base_port *port,
+	u32 timeout)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to reset while in invalid "
+		 "state %d\n",
+		 __func__,
+		 port,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port add phy request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_default_add_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to add phy 0x%p while in "
+		 "invalid state %d\n",
+		 __func__,
+		 port,
+		 phy,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port remove phy request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_remove_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
+
+	dev_warn(sciport_to_dev(sci_port),
+		 "%s: SCIC Port 0x%p requested to remove phy 0x%p while in "
+		 "invalid state %d\n",
+		 __func__,
+		 port,
+		 phy,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port unsolicited frame request.  It will
+ * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even
+ * possible to receive an unsolicited frame directed to a port object?  It
+ * seems possible if we implementing virtual functions but until then?
+ */
+enum sci_status scic_sds_port_default_frame_handler(
+	struct scic_sds_port *port,
+	u32 frame_index)
+{
+	dev_warn(sciport_to_dev(port),
+		 "%s: SCIC Port 0x%p requested to process frame %d while in "
+		 "invalid state %d\n",
+		 __func__,
+		 port,
+		 frame_index,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(port)));
+
+	scic_sds_controller_release_frame(
+		scic_sds_port_get_controller(port), frame_index
+		);
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port event request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_event_handler(
+	struct scic_sds_port *port,
+	u32 event_code)
+{
+	dev_warn(sciport_to_dev(port),
+		 "%s: SCIC Port 0x%p requested to process event 0x%x while "
+		 "in invalid state %d\n",
+		 __func__,
+		 port,
+		 event_code,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(
+				 (struct scic_sds_port *)port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port link up notification.  It will report
+ * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+void scic_sds_port_default_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy)
+{
+	dev_warn(sciport_to_dev(this_port),
+		 "%s: SCIC Port 0x%p received link_up notification from phy "
+		 "0x%p while in invalid state %d\n",
+		 __func__,
+		 this_port,
+		 phy,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(this_port)));
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port link down notification.  It will
+ * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+void scic_sds_port_default_link_down_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy)
+{
+	dev_warn(sciport_to_dev(this_port),
+		 "%s: SCIC Port 0x%p received link down notification from "
+		 "phy 0x%p while in invalid state %d\n",
+		 __func__,
+		 this_port,
+		 phy,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(this_port)));
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port start io request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_port_default_start_io_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	dev_warn(sciport_to_dev(this_port),
+		 "%s: SCIC Port 0x%p requested to start io request 0x%p "
+		 "while in invalid state %d\n",
+		 __func__,
+		 this_port,
+		 io_request,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(this_port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This is the default method for a port complete io request.  It will report a
+ * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_port_default_complete_io_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	dev_warn(sciport_to_dev(this_port),
+		 "%s: SCIC Port 0x%p requested to complete io request 0x%p "
+		 "while in invalid state %d\n",
+		 __func__,
+		 this_port,
+		 io_request,
+		 sci_base_state_machine_get_state(
+			 scic_sds_port_get_base_state_machine(this_port)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/*
+ * ****************************************************************************
+ * * GENERAL STATE HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @port: This is the struct scic_sds_port object on which the io request count will
+ *    be decremented.
+ * @device: This is the struct scic_sds_remote_device object to which the io request
+ *    is being directed.  This parameter is not required to complete this
+ *    operation.
+ * @io_request: This is the request that is being completed on this port
+ *    object.  This parameter is not required to complete this operation.
+ *
+ * This is a general complete io request handler for the struct scic_sds_port object.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_general_complete_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	scic_sds_port_decrement_request_count(this_port);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * ****************************************************************************
+ * * STOPPED STATE HANDLERS
+ * **************************************************************************** */
+
+/**
+ * scic_sds_port_stopped_state_start_handler() - stop a port from "started"
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method takes the struct scic_sds_port from a stopped state and attempts to
+ * start it.  To start a port it must have no assiged devices and it must have
+ * at least one phy assigned to it.  If those conditions are met then the port
+ * can transition to the ready state. enum sci_status
+ * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This struct scic_sds_port object could
+ * not be started because the port configuration is not valid. SCI_SUCCESS the
+ * start request is successful and the struct scic_sds_port object has transitioned to
+ * the SCI_BASE_PORT_STATE_READY.
+ */
+static enum sci_status scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port)
+{
+	struct scic_sds_port *sci_port = container_of(base_port, typeof(*sci_port), parent);
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+	enum sci_status status = SCI_SUCCESS;
+	u32 phy_mask;
+
+	if (sci_port->assigned_device_count > 0) {
+		/*
+		 * / @todo This is a start failure operation because there are still
+		 * /       devices assigned to this port.  There must be no devices
+		 * /       assigned to a port on a start operation. */
+		return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+	}
+
+	sci_port->timer_handle = isci_event_timer_create(scic,
+							 scic_sds_port_timeout_handler,
+							 sci_port);
+
+	if (!sci_port->timer_handle)
+		return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+
+	if (sci_port->reserved_rni == SCU_DUMMY_INDEX) {
+		u16 rni = scic_sds_remote_node_table_allocate_remote_node(&scic->available_remote_nodes, 1);
+
+		if (rni != SCU_DUMMY_INDEX)
+			scic_sds_port_construct_dummy_rnc(sci_port, rni);
+		else
+			status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+		sci_port->reserved_rni = rni;
+	}
+
+	if (sci_port->reserved_tci == SCU_DUMMY_INDEX) {
+		/* Allocate a TCI and remove the sequence nibble */
+		u16 tci = scic_controller_allocate_io_tag(scic);
+
+		if (tci != SCU_DUMMY_INDEX)
+			scic_sds_port_construct_dummy_task(sci_port, tci);
+		else
+			status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+		sci_port->reserved_tci = tci;
+	}
+
+	if (status == SCI_SUCCESS) {
+		phy_mask = scic_sds_port_get_phys(sci_port);
+
+		/*
+		 * There are one or more phys assigned to this port.  Make sure
+		 * the port's phy mask is in fact legal and supported by the
+		 * silicon.
+		 */
+		if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) {
+			sci_base_state_machine_change_state(
+				scic_sds_port_get_base_state_machine(sci_port),
+				SCI_BASE_PORT_STATE_READY);
+
+			return SCI_SUCCESS;
+		} else
+			status = SCI_FAILURE;
+	}
+
+	if (status != SCI_SUCCESS)
+		scic_sds_port_destroy_dummy_resources(sci_port);
+
+	return status;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method takes the struct scic_sds_port that is in a stopped state and handles a
+ * stop request.  This function takes no action. enum sci_status SCI_SUCCESS the
+ * stop request is successful as the struct scic_sds_port object is already stopped.
+ */
+static enum sci_status scic_sds_port_stopped_state_stop_handler(
+	struct sci_base_port *port)
+{
+	/* We are already stopped so there is nothing to do here */
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method takes the struct scic_sds_port that is in a stopped state and handles
+ * the destruct request.  The stopped state is the only state in which the
+ * struct scic_sds_port can be destroyed.  This function causes the port object to
+ * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_stopped_state_destruct_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	sci_base_state_machine_stop(&this_port->parent.state_machine);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_port that is in a stopped state and handles
+ * the add phy request.  In MPC mode the only time a phy can be added to a port
+ * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
+ * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
+ * be added to the port. SCI_SUCCESS if the phy is added to the port.
+ */
+static enum sci_status scic_sds_port_stopped_state_add_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+	struct sci_sas_address port_sas_address;
+
+	/* Read the port assigned SAS Address if there is one */
+	scic_sds_port_get_sas_address(this_port, &port_sas_address);
+
+	if (port_sas_address.high != 0 && port_sas_address.low != 0) {
+		struct sci_sas_address phy_sas_address;
+
+		/*
+		 * Make sure that the PHY SAS Address matches the SAS Address
+		 * for this port. */
+		scic_sds_phy_get_sas_address(this_phy, &phy_sas_address);
+
+		if (
+			(port_sas_address.high != phy_sas_address.high)
+			|| (port_sas_address.low  != phy_sas_address.low)
+			) {
+			return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+		}
+	}
+
+	return scic_sds_port_set_phy(this_port, this_phy);
+}
+
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
+ *    object.
+ *
+ * This method takes the struct scic_sds_port that is in a stopped state and handles
+ * the remove phy request.  In MPC mode the only time a phy can be removed from
+ * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
+ * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
+ * be added to the port. SCI_SUCCESS if the phy is added to the port.
+ */
+static enum sci_status scic_sds_port_stopped_state_remove_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+	struct scic_sds_phy *this_phy  = (struct scic_sds_phy *)phy;
+
+	return scic_sds_port_clear_phy(this_port, this_phy);
+}
+
+/*
+ * ****************************************************************************
+ * *  READY STATE HANDLERS
+ * **************************************************************************** */
+
+/*
+ * ****************************************************************************
+ * *  RESETTING STATE HANDLERS
+ * **************************************************************************** */
+
+/*
+ * ****************************************************************************
+ * *  STOPPING STATE HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @port: This is the struct scic_sds_port object on which the io request count will
+ *    be decremented.
+ * @device: This is the struct scic_sds_remote_device object to which the io request
+ *    is being directed.  This parameter is not required to complete this
+ *    operation.
+ * @io_request: This is the request that is being completed on this port
+ *    object.  This parameter is not required to complete this operation.
+ *
+ * This method takes the struct scic_sds_port that is in a stopping state and handles
+ * the complete io request. Should the request count reach 0 then the port
+ * object will transition to the stopped state. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_stopping_state_complete_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	scic_sds_port_decrement_request_count(this_port);
+
+	if (this_port->started_request_count == 0) {
+		sci_base_state_machine_change_state(
+			scic_sds_port_get_base_state_machine(this_port),
+			SCI_BASE_PORT_STATE_STOPPED
+			);
+	}
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * ****************************************************************************
+ * *  RESETTING STATE HANDLERS
+ * **************************************************************************** */
+
+/**
+ *
+ * @port: This is the port object which is being requested to stop.
+ *
+ * This method will stop a failed port.  This causes a transition to the
+ * stopping state. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_port_reset_state_stop_handler(
+	struct sci_base_port *port)
+{
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	sci_base_state_machine_change_state(
+		&this_port->parent.state_machine,
+		SCI_BASE_PORT_STATE_STOPPING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method will transition a failed port to its ready state.  The port
+ * failed because a hard reset request timed out but at some time later one or
+ * more phys in the port became ready. enum sci_status SCI_SUCCESS
+ */
+static void scic_sds_port_reset_state_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy)
+{
+	/*
+	 * / @todo We should make sure that the phy that has gone link up is the same
+	 * /       one on which we sent the reset.  It is possible that the phy on
+	 * /       which we sent the reset is not the one that has gone link up and we
+	 * /       want to make sure that phy being reset comes back.  Consider the
+	 * /       case where a reset is sent but before the hardware processes the
+	 * /       reset it get a link up on the port because of a hot plug event.
+	 * /       because of the reset request this phy will go link down almost
+	 * /       immediately. */
+
+	/*
+	 * In the resetting state we don't notify the user regarding
+	 * link up and link down notifications. */
+	scic_sds_port_general_link_up_handler(this_port, phy, false);
+}
+
+/**
+ *
+ * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
+ *    object.
+ *
+ * This method process link down notifications that occur during a port reset
+ * operation. Link downs can occur during the reset operation. enum sci_status
+ * SCI_SUCCESS
+ */
+static void scic_sds_port_reset_state_link_down_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy)
+{
+	/*
+	 * In the resetting state we don't notify the user regarding
+	 * link up and link down notifications. */
+	scic_sds_port_deactivate_phy(this_port, phy, false);
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_port_state_handler
+scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] =
+{
+	/* SCI_BASE_PORT_STATE_STOPPED */
+	{
+		{
+			scic_sds_port_stopped_state_start_handler,
+			scic_sds_port_stopped_state_stop_handler,
+			scic_sds_port_stopped_state_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_stopped_state_add_phy_handler,
+			scic_sds_port_stopped_state_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_default_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_default_complete_io_handler
+	},
+	/* SCI_BASE_PORT_STATE_STOPPING */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_default_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_default_add_phy_handler,
+			scic_sds_port_default_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_default_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_stopping_state_complete_io_handler
+	},
+	/* SCI_BASE_PORT_STATE_READY */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_default_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_default_add_phy_handler,
+			scic_sds_port_default_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_default_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_general_complete_io_handler
+	},
+	/* SCI_BASE_PORT_STATE_RESETTING */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_reset_state_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_default_add_phy_handler,
+			scic_sds_port_default_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_reset_state_link_up_handler,
+		scic_sds_port_reset_state_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_general_complete_io_handler
+	},
+	/* SCI_BASE_PORT_STATE_FAILED */
+	{
+		{
+			scic_sds_port_default_start_handler,
+			scic_sds_port_default_stop_handler,
+			scic_sds_port_default_destruct_handler,
+			scic_sds_port_default_reset_handler,
+			scic_sds_port_default_add_phy_handler,
+			scic_sds_port_default_remove_phy_handler
+		},
+		scic_sds_port_default_frame_handler,
+		scic_sds_port_default_event_handler,
+		scic_sds_port_default_link_up_handler,
+		scic_sds_port_default_link_down_handler,
+		scic_sds_port_default_start_io_handler,
+		scic_sds_port_general_complete_io_handler
+	}
+};
+
+/*
+ * ******************************************************************************
+ * *  PORT STATE PRIVATE METHODS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @this_port: This is the port object which to suspend.
+ *
+ * This method will enable the SCU Port Task Scheduler for this port object but
+ * will leave the port task scheduler in a suspended state. none
+ */
+static void scic_sds_port_enable_port_task_scheduler(
+	struct scic_sds_port *this_port)
+{
+	u32 pts_control_value;
+
+	pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+	pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
+
+	scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ *
+ * @this_port: This is the port object which to resume.
+ *
+ * This method will disable the SCU port task scheduler for this port object.
+ * none
+ */
+static void scic_sds_port_disable_port_task_scheduler(
+	struct scic_sds_port *this_port)
+{
+	u32 pts_control_value;
+
+	pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+	pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE)
+			       | SCU_PTSxCR_GEN_BIT(SUSPEND));
+
+	scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port)
+{
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+	u8 phys_index = sci_port->physical_port_index;
+	union scu_remote_node_context *rnc;
+	u16 rni = sci_port->reserved_rni;
+	u32 command;
+
+	rnc = &scic->remote_node_context_table[rni];
+	rnc->ssp.is_valid = true;
+
+	command = SCU_CONTEXT_COMMAND_POST_RNC_32 |
+		  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
+
+	scic_sds_controller_post_request(scic, command);
+
+	/* ensure hardware has seen the post rnc command and give it
+	 * ample time to act before sending the suspend
+	 */
+	SMU_ISR_READ(scic); /* flush */
+	udelay(10);
+
+	command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX |
+		  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
+
+	scic_sds_controller_post_request(scic, command);
+}
+
+void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port)
+{
+	struct scic_sds_controller *scic = sci_port->owning_controller;
+	u8 phys_index = sci_port->physical_port_index;
+	union scu_remote_node_context *rnc;
+	u16 rni = sci_port->reserved_rni;
+	u32 command;
+
+	rnc = &scic->remote_node_context_table[rni];
+
+	rnc->ssp.is_valid = false;
+
+	/* ensure the preceding tc abort request has reached the
+	 * controller and give it ample time to act before posting the rnc
+	 * invalidate
+	 */
+	SMU_ISR_READ(scic); /* flush */
+	udelay(10);
+
+	command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE |
+		  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
+
+	scic_sds_controller_post_request(scic, command);
+}
+
+/*
+ * ******************************************************************************
+ * *  PORT STATE METHODS
+ * ****************************************************************************** */
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped
+ * state handlers for the struct scic_sds_port object and disables the port task
+ * scheduler in the hardware. none
+ */
+static void scic_sds_port_stopped_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_base_state_handlers(
+		this_port, SCI_BASE_PORT_STATE_STOPPED
+		);
+
+	if (
+		SCI_BASE_PORT_STATE_STOPPING
+		== this_port->parent.state_machine.previous_state_id
+		) {
+		/*
+		 * If we enter this state becasuse of a request to stop
+		 * the port then we want to disable the hardwares port
+		 * task scheduler. */
+		scic_sds_port_disable_port_task_scheduler(this_port);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware
+ * port task scheduler. none
+ */
+static void scic_sds_port_stopped_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	/* Enable and suspend the port task scheduler */
+	scic_sds_port_enable_port_task_scheduler(this_port);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state
+ * handlers for the struct scic_sds_port object, reports the port object as not ready
+ * and starts the ready substate machine. none
+ */
+static void scic_sds_port_ready_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	/* Put the ready state handlers in place though they will not be there long */
+	scic_sds_port_set_base_state_handlers(
+		this_port, SCI_BASE_PORT_STATE_READY
+		);
+
+	if (
+		SCI_BASE_PORT_STATE_RESETTING
+		== this_port->parent.state_machine.previous_state_id
+		) {
+		isci_event_port_hard_reset_complete(
+			scic_sds_port_get_controller(this_port),
+			this_port,
+			SCI_SUCCESS
+			);
+	} else {
+		/* Notify the caller that the port is not yet ready */
+		isci_event_port_not_ready(
+			scic_sds_port_get_controller(this_port),
+			this_port,
+			SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
+			);
+	}
+
+	/* Post and suspend the dummy remote node context for this port. */
+	scic_sds_port_post_dummy_remote_node(this_port);
+
+	/* Start the ready substate machine */
+	sci_base_state_machine_start(
+		scic_sds_port_get_ready_substate_machine(this_port)
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCI_BASE_STATE_READY. This function does nothing. none
+ */
+static void scic_sds_port_ready_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	sci_base_state_machine_stop(&this_port->ready_substate_machine);
+
+	scic_sds_port_invalidate_dummy_remote_node(this_port);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting
+ * state handlers for the struct scic_sds_port object. none
+ */
+static void scic_sds_port_resetting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_base_state_handlers(
+		this_port, SCI_BASE_PORT_STATE_RESETTING
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none
+ */
+static void scic_sds_port_resetting_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	isci_event_timer_stop(
+		scic_sds_port_get_controller(this_port),
+		this_port->timer_handle
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
+ * state handlers for the struct scic_sds_port object. none
+ */
+static void scic_sds_port_stopping_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_base_state_handlers(
+		this_port, SCI_BASE_PORT_STATE_STOPPING
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none
+ */
+static void scic_sds_port_stopping_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	isci_event_timer_stop(
+		scic_sds_port_get_controller(this_port),
+		this_port->timer_handle
+		);
+
+	scic_sds_port_destroy_dummy_resources(this_port);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
+ *
+ * This method will perform the actions required by the struct scic_sds_port on
+ * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
+ * state handlers for the struct scic_sds_port object. none
+ */
+static void scic_sds_port_failed_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_port *this_port;
+
+	this_port = (struct scic_sds_port *)object;
+
+	scic_sds_port_set_base_state_handlers(
+		this_port,
+		SCI_BASE_PORT_STATE_FAILED
+		);
+
+	isci_event_port_hard_reset_complete(
+		scic_sds_port_get_controller(this_port),
+		this_port,
+		SCI_FAILURE_TIMEOUT
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_port_state_table[] = {
+	[SCI_BASE_PORT_STATE_STOPPED] = {
+		.enter_state = scic_sds_port_stopped_state_enter,
+		.exit_state  = scic_sds_port_stopped_state_exit
+	},
+	[SCI_BASE_PORT_STATE_STOPPING] = {
+		.enter_state = scic_sds_port_stopping_state_enter,
+		.exit_state  = scic_sds_port_stopping_state_exit
+	},
+	[SCI_BASE_PORT_STATE_READY] = {
+		.enter_state = scic_sds_port_ready_state_enter,
+		.exit_state  = scic_sds_port_ready_state_exit
+	},
+	[SCI_BASE_PORT_STATE_RESETTING] = {
+		.enter_state = scic_sds_port_resetting_state_enter,
+		.exit_state  = scic_sds_port_resetting_state_exit
+	},
+	[SCI_BASE_PORT_STATE_FAILED] = {
+		.enter_state = scic_sds_port_failed_state_enter,
+	}
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h
new file mode 100644
index 0000000..c98caef
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port.h
@@ -0,0 +1,499 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PORT_H_
+#define _SCIC_SDS_PORT_H_
+
+/**
+ * This file contains the structures, constants and prototypes for the
+ *    struct scic_sds_port object.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include "sci_controller_constants.h"
+#include "intel_sas.h"
+#include "sci_base_port.h"
+#include "sci_base_phy.h"
+#include "scu_registers.h"
+
+#define SCIC_SDS_DUMMY_PORT   0xFF
+
+/**
+ * This constant defines the value utilized by SCI Components to indicate
+ * an invalid handle.
+ */
+#define SCI_INVALID_HANDLE 0x0
+
+/**
+ * enum SCIC_SDS_PORT_READY_SUBSTATES -
+ *
+ * This enumeration depicts all of the states for the core port ready substate
+ * machine.
+ */
+enum SCIC_SDS_PORT_READY_SUBSTATES {
+	/**
+	 * The substate where the port is started and ready but has no active phys.
+	 */
+	SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
+
+	/**
+	 * The substate where the port is started and ready and there is at least one
+	 * phy operational.
+	 */
+	SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
+
+	/**
+	 * The substate where the port is started and there was an add/remove phy
+	 * event.  This state is only used in Automatic Port Configuration Mode (APC)
+	 */
+	SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
+
+	SCIC_SDS_PORT_READY_MAX_SUBSTATES
+};
+
+struct scic_sds_controller;
+struct scic_sds_phy;
+struct scic_sds_remote_device;
+struct scic_sds_request;
+
+/**
+ * struct scic_sds_port -
+ *
+ * The core port object provides the the abstraction for an SCU port.
+ */
+struct scic_sds_port {
+	/**
+	 * This field is the oommon base port object.
+	 */
+	struct sci_base_port parent;
+
+	/**
+	 * This field is the port index that is reported to the SCI USER.  This allows
+	 * the actual hardware physical port to change without the SCI USER getting a
+	 * different answer for the get port index.
+	 */
+	u8 logical_port_index;
+
+	/**
+	 * This field is the port index used to program the SCU hardware.
+	 */
+	u8 physical_port_index;
+
+	/**
+	 * This field contains the active phy mask for the port.  This mask is used in
+	 * conjunction with the phy state to determine which phy to select for some
+	 * port operations.
+	 */
+	u8 active_phy_mask;
+
+	u16 reserved_rni;
+	u16 reserved_tci;
+
+	/**
+	 * This field contains the count of the io requests started on this port
+	 * object.  It is used to control controller shutdown.
+	 */
+	u32 started_request_count;
+
+	/**
+	 * This field contains the number of devices assigned to this port.  It is
+	 * used to control port start requests.
+	 */
+	u32 assigned_device_count;
+
+	/**
+	 * This field contains the reason for the port not going ready.  It is
+	 * assigned in the state handlers and used in the state transition.
+	 */
+	u32 not_ready_reason;
+
+	/**
+	 * This field is the table of phys assigned to the port.
+	 */
+	struct scic_sds_phy *phy_table[SCI_MAX_PHYS];
+
+	/**
+	 * This field is a pointer back to the controller that owns this port object.
+	 */
+	struct scic_sds_controller *owning_controller;
+
+	/**
+	 * This field contains the port start/stop timer handle.
+	 */
+	void *timer_handle;
+
+	/**
+	 * This field points to the current set of state handlers for this port
+	 * object.  These state handlers are assigned at each enter state of the state
+	 * machine.
+	 */
+	struct scic_sds_port_state_handler *state_handlers;
+
+	/**
+	 * This field is the ready substate machine for the port.
+	 */
+	struct sci_base_state_machine ready_substate_machine;
+
+	/* / Memory mapped hardware register space */
+
+	/**
+	 * This field is the pointer to the port task scheduler registers for the SCU
+	 * hardware.
+	 */
+	struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers;
+
+	/**
+	 * This field is identical for all port objects and points to the port task
+	 * scheduler group PE configuration registers.  It is used to assign PEs to a
+	 * port.
+	 */
+	SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register;
+
+	/**
+	 * This field is the VIIT register space for ths port object.
+	 */
+	struct scu_viit_entry __iomem *viit_registers;
+
+};
+
+
+typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32);
+
+typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32);
+
+typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *);
+
+typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)(
+	struct scic_sds_port *,
+	struct scic_sds_remote_device *,
+	struct scic_sds_request *);
+
+struct scic_sds_port_state_handler {
+	struct sci_base_port_state_handler parent;
+
+	SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler;
+	SCIC_SDS_PORT_EVENT_HANDLER_T event_handler;
+
+	SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler;
+	SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler;
+
+	SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler;
+	SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler;
+
+};
+
+extern const struct sci_base_state scic_sds_port_state_table[];
+extern const struct sci_base_state scic_sds_port_ready_substate_table[];
+
+extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[];
+extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[];
+
+/**
+ * scic_sds_port_get_controller() -
+ *
+ * Helper macro to get the owning controller of this port
+ */
+#define scic_sds_port_get_controller(this_port)	\
+	((this_port)->owning_controller)
+
+/**
+ * scic_sds_port_get_base_state_machine() -
+ *
+ * Helper macro to get the base state machine for this port
+ */
+#define scic_sds_port_get_base_state_machine(this_port)	\
+	(&(this_port)->parent.state_machine)
+
+/**
+ * scic_sds_port_set_base_state_handlers() -
+ *
+ * This macro will change the state handlers to those of the specified state id
+ */
+#define scic_sds_port_set_base_state_handlers(this_port, state_id) \
+	scic_sds_port_set_state_handlers(\
+		(this_port), &scic_sds_port_state_handler_table[(state_id)])
+
+/**
+ * scic_sds_port_get_ready_substate_machine() -
+ *
+ * Helper macro to get the ready substate machine for this port
+ */
+#define scic_sds_port_get_ready_substate_machine(this_port) \
+	(&(this_port)->ready_substate_machine)
+
+/**
+ * scic_sds_port_set_state_handlers() -
+ *
+ * Helper macro to set the port object state handlers
+ */
+#define scic_sds_port_set_state_handlers(this_port, handlers) \
+	((this_port)->state_handlers = (handlers))
+
+/**
+ * scic_sds_port_get_index() -
+ *
+ * This macro returns the physical port index for this port object
+ */
+#define scic_sds_port_get_index(this_port) \
+	((this_port)->physical_port_index)
+
+
+static inline void scic_sds_port_increment_request_count(struct scic_sds_port *sci_port)
+{
+	sci_port->started_request_count++;
+}
+
+static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port)
+{
+	if (WARN_ONCE(sci_port->started_request_count == 0,
+		       "%s: tried to decrement started_request_count past 0!?",
+			__func__))
+		/* pass */;
+	else
+		sci_port->started_request_count--;
+}
+
+/**
+ * scic_sds_port_write_phy_assignment() -
+ *
+ * Helper macro to write the phys port assignment
+ */
+#define scic_sds_port_write_phy_assignment(port, phy) \
+	SCU_PCSPExCR_WRITE(\
+		(port),	\
+		(phy)->phy_index, \
+		(port)->physical_port_index \
+		)
+
+/**
+ * scic_sds_port_read_phy_assignment() -
+ *
+ * Helper macro to read the phys port assignment
+ */
+#define scic_sds_port_read_phy_assignment(port, phy) \
+	SCU_PCSPExCR_READ(\
+		(port),	\
+		(phy)->phy_index \
+		)
+
+#define scic_sds_port_active_phy(port, phy) \
+	(((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
+
+/* --------------------------------------------------------------------------- */
+
+
+
+
+/* --------------------------------------------------------------------------- */
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_port_construct(
+	struct scic_sds_port *this_port,
+	u8 port_index,
+	struct scic_sds_controller *owning_controller);
+
+enum sci_status scic_sds_port_initialize(
+	struct scic_sds_port *this_port,
+	void __iomem *port_task_scheduler_registers,
+	void __iomem *port_configuration_regsiter,
+	void __iomem *viit_registers);
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_port_add_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy);
+
+enum sci_status scic_sds_port_remove_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy);
+
+void scic_sds_port_setup_transports(
+	struct scic_sds_port *this_port,
+	u32 device_id);
+
+void scic_sds_port_activate_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy,
+	bool do_notify_user);
+
+void scic_sds_port_deactivate_phy(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy,
+	bool do_notify_user);
+
+
+
+void scic_sds_port_general_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *the_phy,
+	bool do_notify_user);
+
+bool scic_sds_port_link_detected(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+
+void scic_sds_port_link_up(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+
+void scic_sds_port_link_down(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+
+/* --------------------------------------------------------------------------- */
+
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_port_start_io(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *the_device,
+	struct scic_sds_request *the_io_request);
+
+enum sci_status scic_sds_port_complete_io(
+	struct scic_sds_port *this_port,
+	struct scic_sds_remote_device *the_device,
+	struct scic_sds_request *the_io_request);
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_port_update_viit_entry(
+	struct scic_sds_port *this_port);
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_port_default_start_handler(
+	struct sci_base_port *port);
+
+
+enum sci_status scic_sds_port_default_destruct_handler(
+	struct sci_base_port *port);
+
+enum sci_status scic_sds_port_default_reset_handler(
+	struct sci_base_port *port,
+	u32 timeout);
+
+
+enum sci_status scic_sds_port_default_remove_phy_handler(
+	struct sci_base_port *port,
+	struct sci_base_phy *phy);
+
+enum sci_status scic_sds_port_default_frame_handler(
+	struct scic_sds_port *port,
+	u32 frame_index);
+
+enum sci_status scic_sds_port_default_event_handler(
+	struct scic_sds_port *port,
+	u32 event_code);
+
+void scic_sds_port_default_link_up_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+
+void scic_sds_port_default_link_down_handler(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *phy);
+
+enum sci_status scic_sds_port_default_start_io_handler(
+	struct scic_sds_port *port,
+	struct scic_sds_remote_device *device,
+	struct scic_sds_request *io_request);
+
+
+enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
+	struct scic_sds_port *this_port);
+
+void scic_sds_port_broadcast_change_received(
+	struct scic_sds_port *this_port,
+	struct scic_sds_phy *this_phy);
+
+bool scic_sds_port_is_valid_phy_assignment(
+	struct scic_sds_port *this_port,
+	u32 phy_index);
+
+bool scic_sds_port_is_phy_mask_valid(
+	struct scic_sds_port *this_port,
+	u32 phy_mask);
+
+u32 scic_sds_port_get_phys(
+	struct scic_sds_port *this_port);
+
+void scic_sds_port_get_sas_address(
+	struct scic_sds_port *this_port,
+	struct sci_sas_address *sas_address);
+
+void scic_sds_port_get_attached_sas_address(
+	struct scic_sds_port *this_port,
+	struct sci_sas_address *sas_address);
+
+void scic_sds_port_get_attached_protocols(
+	struct scic_sds_port *this_port,
+	struct sci_sas_identify_address_frame_protocols *protocols);
+
+enum sci_status scic_sds_port_set_phy(
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+enum sci_status scic_sds_port_clear_phy(
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+
+
+#endif /* _SCIC_SDS_PORT_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
new file mode 100644
index 0000000..e26a4e6
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
@@ -0,0 +1,863 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains the implementation for the public and protected methods
+ *    for the port configuration agent.
+ *
+ *
+ */
+
+#include "sci_environment.h"
+#include "scic_controller.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port_configuration_agent.h"
+
+#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT    (10)
+#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT    (10)
+#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION  (100)
+
+enum SCIC_SDS_APC_ACTIVITY {
+	SCIC_SDS_APC_SKIP_PHY,
+	SCIC_SDS_APC_ADD_PHY,
+	SCIC_SDS_APC_START_TIMER,
+
+	SCIC_SDS_APC_ACTIVITY_MAX
+};
+
+/*
+ * ******************************************************************************
+ * General port configuration agent routines
+ * ****************************************************************************** */
+
+/**
+ *
+ * @address_one: A SAS Address to be compared.
+ * @address_two: A SAS Address to be compared.
+ *
+ * Compare the two SAS Address and if SAS Address One is greater than SAS
+ * Address Two then return > 0 else if SAS Address One is less than SAS Address
+ * Two return < 0 Otherwise they are the same return 0 A signed value of x > 0
+ * > y where x is returned for Address One > Address Two y is returned for
+ * Address One < Address Two 0 is returned ofr Address One = Address Two
+ */
+static s32 sci_sas_address_compare(
+	struct sci_sas_address address_one,
+	struct sci_sas_address address_two)
+{
+	if (address_one.high > address_two.high) {
+		return 1;
+	} else if (address_one.high < address_two.high) {
+		return -1;
+	} else if (address_one.low > address_two.low) {
+		return 1;
+	} else if (address_one.low < address_two.low) {
+		return -1;
+	}
+
+	/* The two SAS Address must be identical */
+	return 0;
+}
+
+/**
+ *
+ * @controller: The controller object used for the port search.
+ * @phy: The phy object to match.
+ *
+ * This routine will find a matching port for the phy.  This means that the
+ * port and phy both have the same broadcast sas address and same received sas
+ * address. The port address or the NULL if there is no matching
+ * port. port address if the port can be found to match the phy.
+ * NULL if there is no matching port for the phy.
+ */
+static struct scic_sds_port *scic_sds_port_configuration_agent_find_port(
+	struct scic_sds_controller *controller,
+	struct scic_sds_phy *phy)
+{
+	u8 port_index;
+	struct scic_sds_port *port_handle;
+	struct sci_sas_address port_sas_address;
+	struct sci_sas_address port_attached_device_address;
+	struct sci_sas_address phy_sas_address;
+	struct sci_sas_address phy_attached_device_address;
+
+	/*
+	 * Since this phy can be a member of a wide port check to see if one or
+	 * more phys match the sent and received SAS address as this phy in which
+	 * case it should participate in the same port. */
+	scic_sds_phy_get_sas_address(phy, &phy_sas_address);
+	scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address);
+
+	for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
+		if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) {
+			struct scic_sds_port *port = (struct scic_sds_port *)port_handle;
+
+			scic_sds_port_get_sas_address(port, &port_sas_address);
+			scic_sds_port_get_attached_sas_address(port, &port_attached_device_address);
+
+			if (
+				(sci_sas_address_compare(port_sas_address, phy_sas_address) == 0)
+				&& (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)
+				) {
+				return port;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ *
+ * @controller: This is the controller object that contains the port agent
+ * @port_agent: This is the port configruation agent for the controller.
+ *
+ * This routine will validate the port configuration is correct for the SCU
+ * hardware.  The SCU hardware allows for port configurations as follows. LP0
+ * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2,
+ * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for
+ * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION
+ * the port configuration is not valid for this port configuration agent.
+ */
+static enum sci_status scic_sds_port_configuration_agent_validate_ports(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent)
+{
+	struct sci_sas_address first_address;
+	struct sci_sas_address second_address;
+
+	/*
+	 * Sanity check the max ranges for all the phys the max index
+	 * is always equal to the port range index */
+	if (
+		(port_agent->phy_valid_port_range[0].max_index != 0)
+		|| (port_agent->phy_valid_port_range[1].max_index != 1)
+		|| (port_agent->phy_valid_port_range[2].max_index != 2)
+		|| (port_agent->phy_valid_port_range[3].max_index != 3)
+		) {
+		return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+	}
+
+	/*
+	 * This is a request to configure a single x4 port or at least attempt
+	 * to make all the phys into a single port */
+	if (
+		(port_agent->phy_valid_port_range[0].min_index == 0)
+		&& (port_agent->phy_valid_port_range[1].min_index == 0)
+		&& (port_agent->phy_valid_port_range[2].min_index == 0)
+		&& (port_agent->phy_valid_port_range[3].min_index == 0)
+		) {
+		return SCI_SUCCESS;
+	}
+
+	/*
+	 * This is a degenerate case where phy 1 and phy 2 are assigned
+	 * to the same port this is explicitly disallowed by the hardware
+	 * unless they are part of the same x4 port and this condition was
+	 * already checked above. */
+	if (port_agent->phy_valid_port_range[2].min_index == 1) {
+		return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+	}
+
+	/*
+	 * PE0 and PE3 can never have the same SAS Address unless they
+	 * are part of the same x4 wide port and we have already checked
+	 * for this condition. */
+	scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
+	scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
+
+	if (sci_sas_address_compare(first_address, second_address) == 0) {
+		return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+	}
+
+	/*
+	 * PE0 and PE1 are configured into a 2x1 ports make sure that the
+	 * SAS Address for PE0 and PE2 are different since they can not be
+	 * part of the same port. */
+	if (
+		(port_agent->phy_valid_port_range[0].min_index == 0)
+		&& (port_agent->phy_valid_port_range[1].min_index == 1)
+		) {
+		scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
+		scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address);
+
+		if (sci_sas_address_compare(first_address, second_address) == 0) {
+			return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+		}
+	}
+
+	/*
+	 * PE2 and PE3 are configured into a 2x1 ports make sure that the
+	 * SAS Address for PE1 and PE3 are different since they can not be
+	 * part of the same port. */
+	if (
+		(port_agent->phy_valid_port_range[2].min_index == 2)
+		&& (port_agent->phy_valid_port_range[3].min_index == 3)
+		) {
+		scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address);
+		scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
+
+		if (sci_sas_address_compare(first_address, second_address) == 0) {
+			return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+		}
+	}
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * ******************************************************************************
+ * Manual port configuration agent routines
+ * ****************************************************************************** */
+
+/**
+ *
+ *
+ * This routine will verify that all of the phys in the same port are using the
+ * same SAS address.
+ */
+static enum sci_status scic_sds_mpc_agent_validate_phy_configuration(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent)
+{
+	u32 phy_mask;
+	u32 assigned_phy_mask;
+	struct sci_sas_address sas_address;
+	struct sci_sas_address phy_assigned_address;
+	u8 port_index;
+	u8 phy_index;
+
+	assigned_phy_mask = 0;
+	sas_address.high = 0;
+	sas_address.low = 0;
+
+	for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
+		phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask;
+
+		if (phy_mask != 0) {
+			/*
+			 * Make sure that one or more of the phys were not already assinged to
+			 * a different port. */
+			if ((phy_mask & ~assigned_phy_mask) == 0) {
+				return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+			}
+
+			/* Find the starting phy index for this round through the loop */
+			for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
+				if ((1 << phy_index) & phy_mask) {
+					scic_sds_phy_get_sas_address(
+						&controller->phy_table[phy_index], &sas_address
+						);
+
+					/*
+					 * The phy_index can be used as the starting point for the
+					 * port range since the hardware starts all logical ports
+					 * the same as the PE index. */
+					port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+					port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+
+					if (phy_index != port_index) {
+						return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+					}
+
+					break;
+				}
+			}
+
+			/*
+			 * See how many additional phys are being added to this logical port.
+			 * Note: We have not moved the current phy_index so we will actually
+			 *       compare the startting phy with itself.
+			 *       This is expected and required to add the phy to the port. */
+			while (phy_index < SCI_MAX_PHYS) {
+				if ((1 << phy_index) & phy_mask) {
+					scic_sds_phy_get_sas_address(
+						&controller->phy_table[phy_index], &phy_assigned_address
+						);
+
+					if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
+						/*
+						 * The phy mask specified that this phy is part of the same port
+						 * as the starting phy and it is not so fail this configuration */
+						return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+					}
+
+					port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+					port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+
+					scic_sds_port_add_phy(
+						&controller->port_table[port_index],
+						&controller->phy_table[phy_index]
+						);
+
+					assigned_phy_mask |= (1 << phy_index);
+				}
+
+				phy_index++;
+			}
+		}
+	}
+
+	return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
+}
+
+/**
+ *
+ *
+ * This timer routine is used to allow the SCI User to rediscover or change
+ * device objects before a new series of link up notifications because a link
+ * down has allowed a better port configuration.
+ */
+static void scic_sds_mpc_agent_timeout_handler(
+	void *object)
+{
+	u8 index;
+	struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
+	struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent;
+	u16 configure_phy_mask;
+
+	port_agent->timer_pending = false;
+
+	/* Find the mask of phys that are reported read but as yet unconfigured into a port */
+	configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		if (configure_phy_mask & (1 << index)) {
+			port_agent->link_up_handler(
+				controller,
+				port_agent,
+				scic_sds_phy_get_port(&controller->phy_table[index]),
+				&controller->phy_table[index]
+				);
+		}
+	}
+}
+
+/**
+ *
+ * @controller: This is the controller object that receives the link up
+ *    notification.
+ * @port: This is the port object associated with the phy.  If the is no
+ *    associated port this is an NULL.
+ * @phy: This is the phy object which has gone ready.
+ *
+ * This method handles the manual port configuration link up notifications.
+ * Since all ports and phys are associate at initialization time we just turn
+ * around and notifiy the port object that there is a link up.  If this PHY is
+ * not associated with a port there is no action taken. Is it possible to get a
+ * link up notification from a phy that has no assocoated port?
+ */
+static void scic_sds_mpc_agent_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	/*
+	 * If the port has an invalid handle then the phy was not assigned to
+	 * a port.  This is because the phy was not given the same SAS Address
+	 * as the other PHYs in the port. */
+	if (port != NULL) {
+		port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
+
+		scic_sds_port_link_up(port, phy);
+
+		if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) {
+			port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy));
+		}
+	}
+}
+
+/**
+ *
+ * @controller: This is the controller object that receives the link down
+ *    notification.
+ * @port: This is the port object associated with the phy.  If the is no
+ *    associated port this is an NULL.  The port is an invalid
+ *    handle only if the phy was never port of this port.  This happens when
+ *    the phy is not broadcasting the same SAS address as the other phys in the
+ *    assigned port.
+ * @phy: This is the phy object which has gone link down.
+ *
+ * This method handles the manual port configuration link down notifications.
+ * Since all ports and phys are associated at initialization time we just turn
+ * around and notifiy the port object of the link down event.  If this PHY is
+ * not associated with a port there is no action taken. Is it possible to get a
+ * link down notification from a phy that has no assocoated port?
+ */
+static void scic_sds_mpc_agent_link_down(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	if (port != NULL) {
+		/*
+		 * If we can form a new port from the remainder of the phys then we want
+		 * to start the timer to allow the SCI User to cleanup old devices and
+		 * rediscover the port before rebuilding the port with the phys that
+		 * remain in the ready state. */
+		port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
+		port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy));
+
+		/*
+		 * Check to see if there are more phys waiting to be configured into a port.
+		 * If there are allow the SCI User to tear down this port, if necessary, and
+		 * then reconstruc the port after the timeout. */
+		if (
+			(port_agent->phy_configured_mask == 0x0000)
+			&& (port_agent->phy_ready_mask != 0x0000)
+			&& !port_agent->timer_pending
+			) {
+			port_agent->timer_pending = true;
+
+			isci_event_timer_start(
+				controller,
+				port_agent->timer,
+				SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT
+				);
+		}
+
+		scic_sds_port_link_down(port, phy);
+	}
+}
+
+/*
+ * ******************************************************************************
+ * Automatic port configuration agent routines
+ * ****************************************************************************** */
+
+/**
+ *
+ *
+ * This routine will verify that the phys are assigned a valid SAS address for
+ * automatic port configuration mode.
+ */
+static enum sci_status scic_sds_apc_agent_validate_phy_configuration(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent)
+{
+	u8 phy_index;
+	u8 port_index;
+	struct sci_sas_address sas_address;
+	struct sci_sas_address phy_assigned_address;
+
+	phy_index = 0;
+
+	while (phy_index < SCI_MAX_PHYS) {
+		port_index = phy_index;
+
+		/* Get the assigned SAS Address for the first PHY on the controller. */
+		scic_sds_phy_get_sas_address(
+			&controller->phy_table[phy_index], &sas_address
+			);
+
+		while (++phy_index < SCI_MAX_PHYS) {
+			scic_sds_phy_get_sas_address(
+				&controller->phy_table[phy_index], &phy_assigned_address
+				);
+
+			/* Verify each of the SAS address are all the same for every PHY */
+			if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
+				port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+			} else {
+				port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
+				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+				break;
+			}
+		}
+	}
+
+	return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
+}
+
+/**
+ *
+ * @controller: This is the controller that to which the port agent is assigned.
+ * @port_agent: This is the port agent that is requesting the timer start
+ *    operation.
+ * @phy: This is the phy that has caused the timer operation to be scheduled.
+ *
+ * This routine will restart the automatic port configuration timeout timer for
+ * the next time period.  This could be caused by either a link down event or a
+ * link up event where we can not yet tell to which port a phy belongs.
+ */
+static void scic_sds_apc_agent_start_timer(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_phy *phy,
+	u32 timeout)
+{
+	if (port_agent->timer_pending) {
+		isci_event_timer_stop(controller, port_agent->timer);
+	}
+
+	port_agent->timer_pending = true;
+
+	isci_event_timer_start(controller, port_agent->timer, timeout);
+}
+
+/**
+ *
+ * @controller: This is the controller object that receives the link up
+ *    notification.
+ * @phy: This is the phy object which has gone link up.
+ *
+ * This method handles the automatic port configuration for link up
+ * notifications.
+ */
+static void scic_sds_apc_agent_configure_ports(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_phy *phy,
+	bool start_timer)
+{
+	u8 port_index;
+	enum sci_status status;
+	struct scic_sds_port *port;
+	struct scic_sds_port *port_handle;
+	enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY;
+
+	port = scic_sds_port_configuration_agent_find_port(controller, phy);
+
+	if (port != NULL) {
+		if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index))
+			apc_activity = SCIC_SDS_APC_ADD_PHY;
+		else
+			apc_activity = SCIC_SDS_APC_SKIP_PHY;
+	} else {
+		/*
+		 * There is no matching Port for this PHY so lets search through the
+		 * Ports and see if we can add the PHY to its own port or maybe start
+		 * the timer and wait to see if a wider port can be made.
+		 *
+		 * Note the break when we reach the condition of the port id == phy id */
+		for (
+			port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index;
+			port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index;
+			port_index++
+			) {
+			scic_controller_get_port_handle(controller, port_index, &port_handle);
+
+			port = (struct scic_sds_port *)port_handle;
+
+			/* First we must make sure that this PHY can be added to this Port. */
+			if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) {
+				/*
+				 * Port contains a PHY with a greater PHY ID than the current
+				 * PHY that has gone link up.  This phy can not be part of any
+				 * port so skip it and move on. */
+				if (port->active_phy_mask > (1 << phy->phy_index)) {
+					apc_activity = SCIC_SDS_APC_SKIP_PHY;
+					break;
+				}
+
+				/*
+				 * We have reached the end of our Port list and have not found
+				 * any reason why we should not either add the PHY to the port
+				 * or wait for more phys to become active. */
+				if (port->physical_port_index == phy->phy_index) {
+					/*
+					 * The Port either has no active PHYs.
+					 * Consider that if the port had any active PHYs we would have
+					 * or active PHYs with
+					 * a lower PHY Id than this PHY. */
+					if (apc_activity != SCIC_SDS_APC_START_TIMER) {
+						apc_activity = SCIC_SDS_APC_ADD_PHY;
+					}
+
+					break;
+				}
+
+				/*
+				 * The current Port has no active PHYs and this PHY could be part
+				 * of this Port.  Since we dont know as yet setup to start the
+				 * timer and see if there is a better configuration. */
+				if (port->active_phy_mask == 0) {
+					apc_activity = SCIC_SDS_APC_START_TIMER;
+				}
+			} else if (port->active_phy_mask != 0) {
+				/*
+				 * The Port has an active phy and the current Phy can not
+				 * participate in this port so skip the PHY and see if
+				 * there is a better configuration. */
+				apc_activity = SCIC_SDS_APC_SKIP_PHY;
+			}
+		}
+	}
+
+	/*
+	 * Check to see if the start timer operations should instead map to an
+	 * add phy operation.  This is caused because we have been waiting to
+	 * add a phy to a port but could not becuase the automatic port
+	 * configuration engine had a choice of possible ports for the phy.
+	 * Since we have gone through a timeout we are going to restrict the
+	 * choice to the smallest possible port. */
+	if (
+		(start_timer == false)
+		&& (apc_activity == SCIC_SDS_APC_START_TIMER)
+		) {
+		apc_activity = SCIC_SDS_APC_ADD_PHY;
+	}
+
+	switch (apc_activity) {
+	case SCIC_SDS_APC_ADD_PHY:
+		status = scic_sds_port_add_phy(port, phy);
+
+		if (status == SCI_SUCCESS) {
+			port_agent->phy_configured_mask |= (1 << phy->phy_index);
+		}
+		break;
+
+	case SCIC_SDS_APC_START_TIMER:
+		scic_sds_apc_agent_start_timer(
+			controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION
+			);
+		break;
+
+	case SCIC_SDS_APC_SKIP_PHY:
+	default:
+		/* do nothing the PHY can not be made part of a port at this time. */
+		break;
+	}
+}
+
+/**
+ * scic_sds_apc_agent_link_up - handle apc link up events
+ * @scic: This is the controller object that receives the link up
+ *    notification.
+ * @sci_port: This is the port object associated with the phy.  If the is no
+ *    associated port this is an NULL.
+ * @sci_phy: This is the phy object which has gone link up.
+ *
+ * This method handles the automatic port configuration for link up
+ * notifications. Is it possible to get a link down notification from a phy
+ * that has no assocoated port?
+ */
+static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic,
+				       struct scic_sds_port_configuration_agent *port_agent,
+				       struct scic_sds_port *sci_port,
+				       struct scic_sds_phy *sci_phy)
+{
+	u8 phy_index  = sci_phy->phy_index;
+
+	if (!sci_port) {
+		/* the phy is not the part of this port */
+		port_agent->phy_ready_mask |= 1 << phy_index;
+		scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true);
+	} else {
+		/* the phy is already the part of the port */
+		u32 port_state = sci_port->parent.state_machine.current_state_id;
+
+		/* if the PORT'S state is resetting then the link up is from
+		 * port hard reset in this case, we need to tell the port
+		 * that link up is recieved
+		 */
+		BUG_ON(port_state != SCI_BASE_PORT_STATE_RESETTING);
+		port_agent->phy_ready_mask |= 1 << phy_index;
+		scic_sds_port_link_up(sci_port, sci_phy);
+	}
+}
+
+/**
+ *
+ * @controller: This is the controller object that receives the link down
+ *    notification.
+ * @port: This is the port object associated with the phy.  If the is no
+ *    associated port this is an NULL.
+ * @phy: This is the phy object which has gone link down.
+ *
+ * This method handles the automatic port configuration link down
+ * notifications. not associated with a port there is no action taken. Is it
+ * possible to get a link down notification from a phy that has no assocoated
+ * port?
+ */
+static void scic_sds_apc_agent_link_down(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
+
+	if (port != NULL) {
+		if (port_agent->phy_configured_mask & (1 << phy->phy_index)) {
+			enum sci_status status;
+
+			status = scic_sds_port_remove_phy(port, phy);
+
+			if (status == SCI_SUCCESS) {
+				port_agent->phy_configured_mask &= ~(1 << phy->phy_index);
+			}
+		}
+	}
+}
+
+/**
+ *
+ *
+ * This routine will try to configure the phys into ports when the timer fires.
+ */
+static void scic_sds_apc_agent_timeout_handler(
+	void *object)
+{
+	u32 index;
+	struct scic_sds_port_configuration_agent *port_agent;
+	struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
+	u16 configure_phy_mask;
+
+	port_agent = scic_sds_controller_get_port_configuration_agent(controller);
+
+	port_agent->timer_pending = false;
+
+	configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+
+	if (configure_phy_mask != 0x00) {
+		for (index = 0; index < SCI_MAX_PHYS; index++) {
+			if (configure_phy_mask & (1 << index)) {
+				scic_sds_apc_agent_configure_ports(
+					controller, port_agent, &controller->phy_table[index], false
+					);
+			}
+		}
+	}
+}
+
+/*
+ * ******************************************************************************
+ * Public port configuration agent routines
+ * ****************************************************************************** */
+
+/**
+ *
+ *
+ * This method will construct the port configuration agent for operation. This
+ * call is universal for both manual port configuration and automatic port
+ * configuration modes.
+ */
+void scic_sds_port_configuration_agent_construct(
+	struct scic_sds_port_configuration_agent *port_agent)
+{
+	u32 index;
+
+	port_agent->phy_configured_mask = 0x00;
+	port_agent->phy_ready_mask = 0x00;
+
+	port_agent->link_up_handler = NULL;
+	port_agent->link_down_handler = NULL;
+
+	port_agent->timer_pending = false;
+	port_agent->timer = NULL;
+
+	for (index = 0; index < SCI_MAX_PORTS; index++) {
+		port_agent->phy_valid_port_range[index].min_index = 0;
+		port_agent->phy_valid_port_range[index].max_index = 0;
+	}
+}
+
+/**
+ *
+ * @controller: This is the controller object for which the port agent is being
+ *    initialized.
+ *
+ * This method will construct the port configuration agent for this controller.
+ */
+enum sci_status scic_sds_port_configuration_agent_initialize(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent)
+{
+	enum sci_status status = SCI_SUCCESS;
+	enum SCIC_PORT_CONFIGURATION_MODE mode;
+
+	mode = scic_sds_controller_get_port_configuration_mode(controller);
+
+	if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
+		status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
+
+		port_agent->link_up_handler = scic_sds_mpc_agent_link_up;
+		port_agent->link_down_handler = scic_sds_mpc_agent_link_down;
+
+		port_agent->timer = isci_event_timer_create(
+			controller,
+			scic_sds_mpc_agent_timeout_handler,
+			controller
+			);
+	} else {
+		status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent);
+
+		port_agent->link_up_handler = scic_sds_apc_agent_link_up;
+		port_agent->link_down_handler = scic_sds_apc_agent_link_down;
+
+		port_agent->timer = isci_event_timer_create(
+			controller,
+			scic_sds_apc_agent_timeout_handler,
+			controller
+			);
+	}
+
+	/* Make sure we have actually gotten a timer */
+	if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) {
+		dev_err(scic_to_dev(controller),
+			"%s: Controller 0x%p automatic port configuration "
+			"agent could not get timer.\n",
+			__func__,
+			controller);
+
+		status = SCI_FAILURE;
+	}
+
+	return status;
+}
diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
new file mode 100644
index 0000000..4146735
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
+#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
+
+/**
+ * This file contains the structures, constants and prototypes used for the
+ *    core controller automatic port configuration engine.
+ *
+ *
+ */
+
+#include "scic_sds_port.h"
+#include "scic_sds_phy.h"
+
+struct scic_sds_controller;
+struct scic_sds_port_configuration_agent;
+struct scic_sds_port;
+struct scic_sds_phy;
+
+typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)(
+	struct scic_sds_controller *,
+	struct scic_sds_port_configuration_agent *,
+	struct scic_sds_port *,
+	struct scic_sds_phy *
+	);
+
+struct SCIC_SDS_PORT_RANGE {
+	u8 min_index;
+	u8 max_index;
+};
+
+struct scic_sds_port_configuration_agent {
+	u16 phy_configured_mask;
+	u16 phy_ready_mask;
+
+	struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS];
+
+	bool timer_pending;
+
+	SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler;
+	SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler;
+
+	void *timer;
+
+};
+
+void scic_sds_port_configuration_agent_construct(
+	struct scic_sds_port_configuration_agent *port_agent);
+
+enum sci_status scic_sds_port_configuration_agent_initialize(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port_configuration_agent *port_agent);
+
+#endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h
new file mode 100644
index 0000000..dbe82d8
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port_registers.h
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PORT_REGISTERS_H_
+#define _SCIC_SDS_PORT_REGISTERS_H_
+
+/**
+ * This file contains a set of macros that assist in reading the SCU hardware
+ *    registers.
+ *
+ *
+ */
+
+/**
+ * scu_port_task_scheduler_read() -
+ *
+ * Macro to read the port task scheduler register associated with this port
+ * object
+ */
+#define scu_port_task_scheduler_read(port, reg)	\
+	scu_register_read(\
+		scic_sds_port_get_controller(port), \
+		(port)->port_task_scheduler_registers->reg \
+		)
+
+/**
+ * scu_port_task_scheduler_write() -
+ *
+ * Macro to write the port task scheduler register associated with this port
+ * object
+ */
+#define scu_port_task_scheduler_write(port, reg, value)	\
+	scu_register_write(\
+		scic_sds_port_get_controller(port), \
+		(port)->port_task_scheduler_registers->reg, \
+		(value)	\
+		)
+
+#define scu_port_viit_register_write(port, reg, value) \
+	scu_register_write(\
+		scic_sds_port_get_controller(port), \
+		(port)->viit_registers->reg, \
+		(value)	\
+		)
+
+/*
+ * ****************************************************************************
+ * * Port Task Scheduler registers controlled by the port object
+ * **************************************************************************** */
+
+/**
+ * SCU_PTSxCR_READ() -
+ *
+ * Macro to read the port task scheduler control register
+ */
+#define SCU_PTSxCR_READ(port) \
+	scu_port_task_scheduler_read(port, control)
+
+/**
+ * SCU_PTSxCR_WRITE() -
+ *
+ * Macro to write the port task scheduler control regsister
+ */
+#define SCU_PTSxCR_WRITE(port, value) \
+	scu_port_task_scheduler_write(port, control, value)
+
+/*
+ * ****************************************************************************
+ * * Port PE Configuration registers
+ * **************************************************************************** */
+
+/**
+ * SCU_PCSPExCR_WRITE() -
+ *
+ * Macro to write the PE Port Configuration Register
+ */
+#define SCU_PCSPExCR_WRITE(port, phy_id, value)	\
+	scu_register_write(\
+		scic_sds_port_get_controller(port), \
+		(port)->port_pe_configuration_register[phy_id],	\
+		(value)	\
+		)
+
+/**
+ * SCU_PCSPExCR_READ() -
+ *
+ * Macro to read the PE Port Configuration Regsiter
+ */
+#define SCU_PCSPExCR_READ(port, phy_id)	\
+	scu_register_read(\
+		scic_sds_port_get_controller(port), \
+		(port)->port_pe_configuration_register[phy_id] \
+		)
+
+#endif /* _SCIC_SDS_PORT_REGISTERS_H_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 04/10] isci/core: remote device
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (2 preceding siblings ...)
  2011-03-10 10:54 ` [RFC PATCH 03/10] isci/core: port Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 05/10] isci/core: remote node context Dan Williams
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Software representation of SSP, SMP, STP and direct attached SATA
devices.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/sci_base_remote_device.h    |  274 +++
 drivers/scsi/isci/core/scic_remote_device.h        |  294 +++
 drivers/scsi/isci/core/scic_sds_remote_device.c    | 2079 ++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_remote_device.h    |  570 +++++
 .../scsi/isci/core/scic_sds_smp_remote_device.c    |  325 +++
 .../scsi/isci/core/scic_sds_stp_remote_device.c    |  908 +++++++++
 6 files changed, 4450 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_remote_device.h
 create mode 100644 drivers/scsi/isci/core/scic_remote_device.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_remote_device.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_remote_device.c

diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h
new file mode 100644
index 0000000..45414ce
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_remote_device.h
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_REMOTE_DEVICE_H_
+#define _SCI_BASE_REMOTE_DEVICE_H_
+
+/**
+ * This file contains all of the structures, constants, and methods common to
+ *    all remote device object definitions.
+ *
+ *
+ */
+
+#include "sci_base_state_machine.h"
+
+struct sci_base_request;
+
+/**
+ * enum sci_base_remote_device_states - This enumeration depicts all the states
+ *    for the common remote device state machine.
+ *
+ *
+ */
+enum sci_base_remote_device_states {
+	/**
+	 * Simply the initial state for the base remote device state machine.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
+
+	/**
+	 * This state indicates that the remote device has successfully been
+	 * stopped.  In this state no new IO operations are permitted.
+	 * This state is entered from the INITIAL state.
+	 * This state is entered from the STOPPING state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
+
+	/**
+	 * This state indicates the the remote device is in the process of
+	 * becoming ready (i.e. starting).  In this state no new IO operations
+	 * are permitted.
+	 * This state is entered from the STOPPED state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
+
+	/**
+	 * This state indicates the remote device is now ready.  Thus, the user
+	 * is able to perform IO operations on the remote device.
+	 * This state is entered from the STARTING state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_READY,
+
+	/**
+	 * This state indicates that the remote device is in the process of
+	 * stopping.  In this state no new IO operations are permitted, but
+	 * existing IO operations are allowed to complete.
+	 * This state is entered from the READY state.
+	 * This state is entered from the FAILED state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
+
+	/**
+	 * This state indicates that the remote device has failed.
+	 * In this state no new IO operations are permitted.
+	 * This state is entered from the INITIALIZING state.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
+
+	/**
+	 * This state indicates the device is being reset.
+	 * In this state no new IO operations are permitted.
+	 * This state is entered from the READY state.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
+
+	/**
+	 * Simply the final state for the base remote device state machine.
+	 */
+	SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
+};
+
+/**
+ * struct sci_base_remote_device - The base remote device object abstracts the
+ *    fields common to all SCI remote device objects.
+ *
+ *
+ */
+struct sci_base_remote_device {
+	/**
+	 * The field specifies that the parent object for the base remote
+	 * device is the base object itself.
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This field contains the information for the base remote device state
+	 * machine.
+	 */
+	struct sci_base_state_machine state_machine;
+};
+
+
+typedef enum sci_status (*sci_base_remote_device_handler_t)(
+	struct sci_base_remote_device *
+	);
+
+typedef enum sci_status (*sci_base_remote_device_request_handler_t)(
+	struct sci_base_remote_device *,
+	struct sci_base_request *
+	);
+
+typedef enum sci_status (*sci_base_remote_device_high_priority_request_complete_handler_t)(
+	struct sci_base_remote_device *,
+	struct sci_base_request *,
+	void *,
+	enum sci_io_status
+	);
+
+/**
+ * struct sci_base_remote_device_state_handler - This structure contains all of
+ *    the state handler methods common to base remote device state machines.
+ *    Handler methods provide the ability to change the behavior for user
+ *    requests or transitions depending on the state the machine is in.
+ *
+ *
+ */
+struct sci_base_remote_device_state_handler {
+	/**
+	 * The start_handler specifies the method invoked when a user attempts to
+	 * start a remote device.
+	 */
+	sci_base_remote_device_handler_t start_handler;
+
+	/**
+	 * The stop_handler specifies the method invoked when a user attempts to
+	 * stop a remote device.
+	 */
+	sci_base_remote_device_handler_t stop_handler;
+
+	/**
+	 * The fail_handler specifies the method invoked when a remote device
+	 * failure has occurred.  A failure may be due to an inability to
+	 * initialize/configure the device.
+	 */
+	sci_base_remote_device_handler_t fail_handler;
+
+	/**
+	 * The destruct_handler specifies the method invoked when attempting to
+	 * destruct a remote device.
+	 */
+	sci_base_remote_device_handler_t destruct_handler;
+
+	/**
+	 * The reset handler specifies the method invloked when requesting to reset a
+	 * remote device.
+	 */
+	sci_base_remote_device_handler_t reset_handler;
+
+	/**
+	 * The reset complete handler specifies the method invloked when reporting
+	 * that a reset has completed to the remote device.
+	 */
+	sci_base_remote_device_handler_t reset_complete_handler;
+
+	/**
+	 * The start_io_handler specifies the method invoked when a user
+	 * attempts to start an IO request for a remote device.
+	 */
+	sci_base_remote_device_request_handler_t start_io_handler;
+
+	/**
+	 * The complete_io_handler specifies the method invoked when a user
+	 * attempts to complete an IO request for a remote device.
+	 */
+	sci_base_remote_device_request_handler_t complete_io_handler;
+
+	/**
+	 * The continue_io_handler specifies the method invoked when a user
+	 * attempts to continue an IO request for a remote device.
+	 */
+	sci_base_remote_device_request_handler_t continue_io_handler;
+
+	/**
+	 * The start_task_handler specifies the method invoked when a user
+	 * attempts to start a task management request for a remote device.
+	 */
+	sci_base_remote_device_request_handler_t start_task_handler;
+
+	/**
+	 * The complete_task_handler specifies the method invoked when a user
+	 * attempts to complete a task management request for a remote device.
+	 */
+	sci_base_remote_device_request_handler_t complete_task_handler;
+
+};
+
+/**
+ * sci_base_remote_device_construct() - Construct the base remote device
+ * @this_remote_device: This parameter specifies the base remote device to be
+ *    constructed.
+ * @state_table: This parameter specifies the table of state definitions to be
+ *    utilized for the remote device state machine.
+ *
+ */
+static inline void sci_base_remote_device_construct(
+	struct sci_base_remote_device *base_dev,
+	const struct sci_base_state *state_table)
+{
+	base_dev->parent.private = NULL;
+	sci_base_state_machine_construct(
+		&base_dev->state_machine,
+		&base_dev->parent,
+		state_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+		);
+
+	sci_base_state_machine_start(
+		&base_dev->state_machine
+		);
+}
+#endif /* _SCI_BASE_REMOTE_DEVICE_H_ */
diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h
new file mode 100644
index 0000000..1401844
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_remote_device.h
@@ -0,0 +1,294 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_REMOTE_DEVICE_H_
+#define _SCIC_REMOTE_DEVICE_H_
+
+/**
+ * This file contains all of the interface methods that can be called by an
+ *    SCIC user on the device object.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+#include "intel_sas.h"
+
+struct scic_sds_port;
+struct scic_sds_remote_device;
+
+/**
+ *
+ *
+ *
+ */
+enum scic_remote_device_not_ready_reason_code {
+	SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED,
+	SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED,
+	SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED,
+	SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED,
+	SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED,
+
+	SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX
+
+};
+
+/**
+ * scic_remote_device_get_object_size() - This method simply returns the
+ *    maximum memory space needed to store a remote device object.
+ *
+ * a positive integer value indicating the size (in bytes) of the remote device
+ * object.
+ */
+u32 scic_remote_device_get_object_size(
+	void);
+
+struct scic_sds_port;
+struct scic_sds_remote_device;
+/**
+ * scic_remote_device_construct() - This method will perform the construction
+ *    common to all remote device objects.
+ * @sci_port: SAS/SATA port through which this device is accessed.
+ * @sci_dev: remote device to construct
+ *
+ * It isn't necessary to call scic_remote_device_destruct() for device objects
+ * that have only called this method for construction. Once subsequent
+ * construction methods have been invoked (e.g.
+ * scic_remote_device_da_construct()), then destruction should occur. none
+ */
+void scic_remote_device_construct(struct scic_sds_port *sci_port,
+				  struct scic_sds_remote_device *sci_dev);
+
+/**
+ * scic_remote_device_da_construct() - This method will construct a
+ *    SCIC_REMOTE_DEVICE object for a direct attached (da) device.  The
+ *    information (e.g. IAF, Signature FIS, etc.) necessary to build the device
+ *    is known to the SCI Core since it is contained in the scic_phy object.
+ * @remote_device: This parameter specifies the remote device to be destructed.
+ *
+ * The user must have previously called scic_remote_device_construct() Remote
+ * device objects are a limited resource.  As such, they must be protected.
+ * Thus calls to construct and destruct are mutually exclusive and
+ * non-reentrant. Indicate if the remote device was successfully constructed.
+ * SCI_SUCCESS Returned if the device was successfully constructed.
+ * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
+ * constructed.  If it's an additional phy for the target, then call
+ * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
+ * if the supplied parameters necessitate creation of a remote device for which
+ * the protocol is not supported by the underlying controller hardware.
+ * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
+ * controller associated with the supplied parameters is unable to support
+ * additional remote devices.
+ */
+enum sci_status scic_remote_device_da_construct(
+	struct scic_sds_remote_device *remote_device);
+
+/**
+ * scic_remote_device_ea_construct() - This method will construct an
+ *    SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an
+ *    SMP Discover Response.
+ * @remote_device: This parameter specifies the remote device to be destructed.
+ * @discover_response: This parameter specifies the SMP Discovery Response to
+ *    be used in device creation.
+ *
+ * The user must have previously called scic_remote_device_construct() Remote
+ * device objects are a limited resource.  As such, they must be protected.
+ * Thus calls to construct and destruct are mutually exclusive and
+ * non-reentrant. Indicate if the remote device was successfully constructed.
+ * SCI_SUCCESS Returned if the device was successfully constructed.
+ * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
+ * constructed.  If it's an additional phy for the target, then call
+ * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
+ * if the supplied parameters necessitate creation of a remote device for which
+ * the protocol is not supported by the underlying controller hardware.
+ * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
+ * controller associated with the supplied parameters is unable to support
+ * additional remote devices.
+ */
+enum sci_status scic_remote_device_ea_construct(
+	struct scic_sds_remote_device *remote_device,
+	struct smp_response_discover *discover_response);
+
+/**
+ * scic_remote_device_destruct() - This method is utilized to free up a core's
+ *    remote device object.
+ * @remote_device: This parameter specifies the remote device to be destructed.
+ *
+ * Remote device objects are a limited resource.  As such, they must be
+ * protected.  Thus calls to construct and destruct are mutually exclusive and
+ * non-reentrant. The return value shall indicate if the device was
+ * successfully destructed or if some failure occurred. enum sci_status This value
+ * is returned if the device is successfully destructed.
+ * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied
+ * device isn't valid (e.g. it's already been destoryed, the handle isn't
+ * valid, etc.).
+ */
+enum sci_status scic_remote_device_destruct(
+	struct scic_sds_remote_device *remote_device);
+
+
+
+
+
+/**
+ * scic_remote_device_start() - This method will start the supplied remote
+ *    device.  This method enables normal IO requests to flow through to the
+ *    remote device.
+ * @remote_device: This parameter specifies the device to be started.
+ * @timeout: This parameter specifies the number of milliseconds in which the
+ *    start operation should complete.
+ *
+ * An indication of whether the device was successfully started. SCI_SUCCESS
+ * This value is returned if the device was successfully started.
+ * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start
+ * the device when there have been no phys added to it.
+ */
+enum sci_status scic_remote_device_start(
+	struct scic_sds_remote_device *remote_device,
+	u32 timeout);
+
+/**
+ * scic_remote_device_stop() - This method will stop both transmission and
+ *    reception of link activity for the supplied remote device.  This method
+ *    disables normal IO requests from flowing through to the remote device.
+ * @remote_device: This parameter specifies the device to be stopped.
+ * @timeout: This parameter specifies the number of milliseconds in which the
+ *    stop operation should complete.
+ *
+ * An indication of whether the device was successfully stopped. SCI_SUCCESS
+ * This value is returned if the transmission and reception for the device was
+ * successfully stopped.
+ */
+enum sci_status scic_remote_device_stop(
+	struct scic_sds_remote_device *remote_device,
+	u32 timeout);
+
+/**
+ * scic_remote_device_reset() - This method will reset the device making it
+ *    ready for operation. This method must be called anytime the device is
+ *    reset either through a SMP phy control or a port hard reset request.
+ * @remote_device: This parameter specifies the device to be reset.
+ *
+ * This method does not actually cause the device hardware to be reset. This
+ * method resets the software object so that it will be operational after a
+ * device hardware reset completes. An indication of whether the device reset
+ * was accepted. SCI_SUCCESS This value is returned if the device reset is
+ * started.
+ */
+enum sci_status scic_remote_device_reset(
+	struct scic_sds_remote_device *remote_device);
+
+/**
+ * scic_remote_device_reset_complete() - This method informs the device object
+ *    that the reset operation is complete and the device can resume operation
+ *    again.
+ * @remote_device: This parameter specifies the device which is to be informed
+ *    of the reset complete operation.
+ *
+ * An indication that the device is resuming operation. SCI_SUCCESS the device
+ * is resuming operation.
+ */
+enum sci_status scic_remote_device_reset_complete(
+	struct scic_sds_remote_device *remote_device);
+
+
+
+/**
+ * scic_remote_device_get_connection_rate() - This method simply returns the
+ *    link rate at which communications to the remote device occur.
+ * @remote_device: This parameter specifies the device for which to get the
+ *    connection rate.
+ *
+ * Return the link rate at which we transfer for the supplied remote device.
+ */
+enum sci_sas_link_rate scic_remote_device_get_connection_rate(
+	struct scic_sds_remote_device *remote_device);
+
+/**
+ * scic_remote_device_get_protocols() - This method will indicate which
+ *    protocols are supported by this remote device.
+ * @remote_device: This parameter specifies the device for which to return the
+ *    protocol.
+ * @protocols: This parameter specifies the output values, from the remote
+ *    device object, which indicate the protocols supported by the supplied
+ *    remote_device.
+ *
+ * The type of protocols supported by this device.  The values are returned as
+ * part of a bit mask in order to allow for multi-protocol support.
+ */
+void scic_remote_device_get_protocols(
+	struct scic_sds_remote_device *remote_device,
+	struct smp_discover_response_protocols *protocols);
+
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * scic_remote_device_is_atapi() -
+ * @this_device: The device whose type is to be decided.
+ *
+ * This method first decide whether a device is a stp target, then decode the
+ * signature fis of a DA STP device to tell whether it is a standard end disk
+ * or an ATAPI device. bool Indicate a device is ATAPI device or not.
+ */
+bool scic_remote_device_is_atapi(
+	struct scic_sds_remote_device *device_handle);
+#else /* !defined(DISABLE_ATAPI) */
+#define scic_remote_device_is_atapi(device_handle) false
+#endif /* !defined(DISABLE_ATAPI) */
+
+
+#endif  /* _SCIC_REMOTE_DEVICE_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c
new file mode 100644
index 0000000..0ac6ca0
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_device.c
@@ -0,0 +1,2079 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_sas.h"
+#include "scic_controller.h"
+#include "scic_phy.h"
+#include "scic_port.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_remote_node_context.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_event_codes.h"
+
+
+#define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT  (1000)
+
+/*
+ * *****************************************************************************
+ * *  CORE REMOTE DEVICE PRIVATE METHODS
+ * ***************************************************************************** */
+
+/*
+ * *****************************************************************************
+ * *  CORE REMOTE DEVICE PUBLIC METHODS
+ * ***************************************************************************** */
+
+u32 scic_remote_device_get_object_size(void)
+{
+	return sizeof(struct scic_sds_remote_device)
+	       + sizeof(struct scic_sds_remote_node_context);
+}
+
+/* --------------------------------------------------------------------------- */
+
+void scic_remote_device_construct(struct scic_sds_port *sci_port,
+				  struct scic_sds_remote_device *sci_dev)
+{
+	sci_dev->owning_port = sci_port;
+	sci_dev->started_request_count = 0;
+	sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1];
+
+	sci_base_remote_device_construct(
+		&sci_dev->parent,
+		scic_sds_remote_device_state_table
+		);
+
+	scic_sds_remote_node_context_construct(
+		sci_dev,
+		sci_dev->rnc,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+		);
+
+	sci_object_set_association(sci_dev->rnc, sci_dev);
+}
+
+
+enum sci_status scic_remote_device_da_construct(
+	struct scic_sds_remote_device *sci_dev)
+{
+	enum sci_status status;
+	u16 remote_node_index;
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+	/*
+	 * This information is request to determine how many remote node context
+	 * entries will be needed to store the remote node.
+	 */
+	scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols);
+	sci_dev->target_protocols.u.all = protocols.u.all;
+	sci_dev->is_direct_attached = true;
+#if !defined(DISABLE_ATAPI)
+	sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev);
+#endif
+
+	status = scic_sds_controller_allocate_remote_node_context(
+		sci_dev->owning_port->owning_controller,
+		sci_dev,
+		&remote_node_index);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_remote_node_context_set_remote_node_index(
+			sci_dev->rnc, remote_node_index);
+
+		scic_sds_port_get_attached_sas_address(
+			sci_dev->owning_port, &sci_dev->device_address);
+
+		if (sci_dev->target_protocols.u.bits.attached_ssp_target) {
+			sci_dev->has_ready_substate_machine = false;
+		} else if (sci_dev->target_protocols.u.bits.attached_stp_target) {
+			sci_dev->has_ready_substate_machine = true;
+
+			sci_base_state_machine_construct(
+				&sci_dev->ready_substate_machine,
+				&sci_dev->parent.parent,
+				scic_sds_stp_remote_device_ready_substate_table,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
+		} else if (sci_dev->target_protocols.u.bits.attached_smp_target) {
+			sci_dev->has_ready_substate_machine = true;
+
+			/* add the SMP ready substate machine construction here */
+			sci_base_state_machine_construct(
+				&sci_dev->ready_substate_machine,
+				&sci_dev->parent.parent,
+				scic_sds_smp_remote_device_ready_substate_table,
+				SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
+		}
+
+		sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(
+			sci_dev->owning_port);
+
+		/* / @todo Should I assign the port width by reading all of the phys on the port? */
+		sci_dev->device_port_width = 1;
+	}
+
+	return status;
+}
+
+
+static void scic_sds_remote_device_get_info_from_smp_discover_response(
+	struct scic_sds_remote_device *this_device,
+	struct smp_response_discover *discover_response)
+{
+	/* decode discover_response to set sas_address to this_device. */
+	this_device->device_address.high =
+		discover_response->attached_sas_address.high;
+
+	this_device->device_address.low =
+		discover_response->attached_sas_address.low;
+
+	this_device->target_protocols.u.all = discover_response->protocols.u.all;
+}
+
+
+enum sci_status scic_remote_device_ea_construct(
+	struct scic_sds_remote_device *sci_dev,
+	struct smp_response_discover *discover_response)
+{
+	enum sci_status status;
+	struct scic_sds_controller *the_controller;
+
+	the_controller = scic_sds_port_get_controller(sci_dev->owning_port);
+
+	scic_sds_remote_device_get_info_from_smp_discover_response(
+		sci_dev, discover_response);
+
+	status = scic_sds_controller_allocate_remote_node_context(
+		the_controller, sci_dev, &sci_dev->rnc->remote_node_index);
+
+	if (status == SCI_SUCCESS) {
+		if (sci_dev->target_protocols.u.bits.attached_ssp_target) {
+			sci_dev->has_ready_substate_machine = false;
+		} else if (sci_dev->target_protocols.u.bits.attached_smp_target) {
+			sci_dev->has_ready_substate_machine = true;
+
+			/* add the SMP ready substate machine construction here */
+			sci_base_state_machine_construct(
+				&sci_dev->ready_substate_machine,
+				&sci_dev->parent.parent,
+				scic_sds_smp_remote_device_ready_substate_table,
+				SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
+		} else if (sci_dev->target_protocols.u.bits.attached_stp_target) {
+			sci_dev->has_ready_substate_machine = true;
+
+			sci_base_state_machine_construct(
+				&sci_dev->ready_substate_machine,
+				&sci_dev->parent.parent,
+				scic_sds_stp_remote_device_ready_substate_table,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
+		}
+
+		/*
+		 * For SAS-2 the physical link rate is actually a logical link
+		 * rate that incorporates multiplexing.  The SCU doesn't
+		 * incorporate multiplexing and for the purposes of the
+		 * connection the logical link rate is that same as the
+		 * physical.  Furthermore, the SAS-2 and SAS-1.1 fields overlay
+		 * one another, so this code works for both situations. */
+		sci_dev->connection_rate = min_t(u16,
+			scic_sds_port_get_max_allowed_speed(sci_dev->owning_port),
+			discover_response->u2.sas1_1.negotiated_physical_link_rate
+			);
+
+		/* / @todo Should I assign the port width by reading all of the phys on the port? */
+		sci_dev->device_port_width = 1;
+	}
+
+	return status;
+}
+
+enum sci_status scic_remote_device_destruct(
+	struct scic_sds_remote_device *sci_dev)
+{
+	return sci_dev->state_handlers->parent.destruct_handler(&sci_dev->parent);
+}
+
+
+enum sci_status scic_remote_device_start(
+	struct scic_sds_remote_device *sci_dev,
+	u32 timeout)
+{
+	return sci_dev->state_handlers->parent.start_handler(&sci_dev->parent);
+}
+
+
+enum sci_status scic_remote_device_stop(
+	struct scic_sds_remote_device *sci_dev,
+	u32 timeout)
+{
+	return sci_dev->state_handlers->parent.stop_handler(&sci_dev->parent);
+}
+
+
+enum sci_status scic_remote_device_reset(
+	struct scic_sds_remote_device *sci_dev)
+{
+	return sci_dev->state_handlers->parent.reset_handler(&sci_dev->parent);
+}
+
+
+enum sci_status scic_remote_device_reset_complete(
+	struct scic_sds_remote_device *sci_dev)
+{
+	return sci_dev->state_handlers->parent.reset_complete_handler(&sci_dev->parent);
+}
+
+
+enum sci_sas_link_rate scic_remote_device_get_connection_rate(
+	struct scic_sds_remote_device *sci_dev)
+{
+	return sci_dev->connection_rate;
+}
+
+
+void scic_remote_device_get_protocols(
+	struct scic_sds_remote_device *sci_dev,
+	struct smp_discover_response_protocols *pr)
+{
+	pr->u.all = sci_dev->target_protocols.u.all;
+}
+
+#if !defined(DISABLE_ATAPI)
+bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev)
+{
+	return sci_dev->is_atapi;
+}
+#endif
+
+
+/*
+ * *****************************************************************************
+ * *  SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS
+ * ***************************************************************************** */
+
+/**
+ *
+ *
+ * Remote device timer requirements
+ */
+#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0)
+#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES)
+
+
+/**
+ *
+ * @this_device: The remote device for which the suspend is being requested.
+ *
+ * This method invokes the remote device suspend state handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_suspend(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type)
+{
+	return this_device->state_handlers->suspend_handler(this_device, suspend_type);
+}
+
+/**
+ *
+ * @this_device: The remote device for which the resume is being requested.
+ *
+ * This method invokes the remote device resume state handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_resume(
+	struct scic_sds_remote_device *this_device)
+{
+	return this_device->state_handlers->resume_handler(this_device);
+}
+
+/**
+ *
+ * @this_device: The remote device for which the event handling is being
+ *    requested.
+ * @frame_index: This is the frame index that is being processed.
+ *
+ * This method invokes the frame handler for the remote device state machine
+ * enum sci_status
+ */
+enum sci_status scic_sds_remote_device_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	return this_device->state_handlers->frame_handler(this_device, frame_index);
+}
+
+/**
+ *
+ * @this_device: The remote device for which the event handling is being
+ *    requested.
+ * @event_code: This is the event code that is to be processed.
+ *
+ * This method invokes the remote device event handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code)
+{
+	return this_device->state_handlers->event_handler(this_device, event_code);
+}
+
+/**
+ *
+ * @controller: The controller that is starting the io request.
+ * @this_device: The remote device for which the start io handling is being
+ *    requested.
+ * @io_request: The io request that is being started.
+ *
+ * This method invokes the remote device start io handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_start_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request)
+{
+	return this_device->state_handlers->parent.start_io_handler(
+		       &this_device->parent, &io_request->parent);
+}
+
+/**
+ *
+ * @controller: The controller that is completing the io request.
+ * @this_device: The remote device for which the complete io handling is being
+ *    requested.
+ * @io_request: The io request that is being completed.
+ *
+ * This method invokes the remote device complete io handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_complete_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request)
+{
+	return this_device->state_handlers->parent.complete_io_handler(
+		       &this_device->parent, &io_request->parent);
+}
+
+/**
+ *
+ * @controller: The controller that is starting the task request.
+ * @this_device: The remote device for which the start task handling is being
+ *    requested.
+ * @io_request: The task request that is being started.
+ *
+ * This method invokes the remote device start task handler. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_start_task(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request)
+{
+	return this_device->state_handlers->parent.start_task_handler(
+		       &this_device->parent, &io_request->parent);
+}
+
+/**
+ *
+ * @controller: The controller that is completing the task request.
+ * @this_device: The remote device for which the complete task handling is
+ *    being requested.
+ * @io_request: The task request that is being completed.
+ *
+ * This method invokes the remote device complete task handler. enum sci_status
+ */
+
+/**
+ *
+ * @this_device:
+ * @request:
+ *
+ * This method takes the request and bulids an appropriate SCU context for the
+ * request and then requests the controller to post the request. none
+ */
+void scic_sds_remote_device_post_request(
+	struct scic_sds_remote_device *this_device,
+	u32 request)
+{
+	u32 context;
+
+	context = scic_sds_remote_device_build_command_context(this_device, request);
+
+	scic_sds_controller_post_request(
+		scic_sds_remote_device_get_controller(this_device),
+		context
+		);
+}
+
+#if !defined(DISABLE_ATAPI)
+/**
+ *
+ * @this_device: The device to be checked.
+ *
+ * This method check the signature fis of a stp device to decide whether a
+ * device is atapi or not. true if a device is atapi device. False if a device
+ * is not atapi.
+ */
+bool scic_sds_remote_device_is_atapi(
+	struct scic_sds_remote_device *this_device)
+{
+	if (!this_device->target_protocols.u.bits.attached_stp_target)
+		return false;
+	else if (this_device->is_direct_attached) {
+		struct scic_sds_phy *phy;
+		struct scic_sata_phy_properties properties;
+		struct sata_fis_reg_d2h *signature_fis;
+		phy = scic_sds_port_get_a_connected_phy(this_device->owning_port);
+		scic_sata_phy_get_properties(phy, &properties);
+
+		/* decode the signature fis. */
+		signature_fis = &(properties.signature_fis);
+
+		if ((signature_fis->sector_count  == 0x01)
+		    && (signature_fis->lba_low       == 0x01)
+		    && (signature_fis->lba_mid       == 0x14)
+		    && (signature_fis->lba_high      == 0xEB)
+		    && ((signature_fis->device & 0x5F) == 0x00)
+		    ) {
+			/* An ATA device supporting the PACKET command set. */
+			return true;
+		} else
+			return false;
+	} else {
+		/* Expander supported ATAPI device is not currently supported. */
+		return false;
+	}
+}
+#endif
+
+/**
+ *
+ * @user_parameter: This is cast to a remote device object.
+ *
+ * This method is called once the remote node context is ready to be freed.
+ * The remote device can now report that its stop operation is complete. none
+ */
+static void scic_sds_cb_remote_device_rnc_destruct_complete(
+	void *user_parameter)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)user_parameter;
+
+	BUG_ON(this_device->started_request_count != 0);
+
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+		);
+}
+
+/**
+ *
+ * @user_parameter: This is cast to a remote device object.
+ *
+ * This method is called once the remote node context has transisitioned to a
+ * ready state.  This is the indication that the remote device object can also
+ * transition to ready. none
+ */
+static void scic_sds_remote_device_resume_complete_handler(
+	void *user_parameter)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)user_parameter;
+
+	if (
+		sci_base_state_machine_get_state(&this_device->parent.state_machine)
+		!= SCI_BASE_REMOTE_DEVICE_STATE_READY
+		) {
+		sci_base_state_machine_change_state(
+			&this_device->parent.state_machine,
+			SCI_BASE_REMOTE_DEVICE_STATE_READY
+			);
+	}
+}
+
+/**
+ *
+ * @device: This parameter specifies the device for which the request is being
+ *    started.
+ * @request: This parameter specifies the request being started.
+ * @status: This parameter specifies the current start operation status.
+ *
+ * This method will perform the STP request start processing common to IO
+ * requests and task requests of all types. none
+ */
+void scic_sds_remote_device_start_request(
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *the_request,
+	enum sci_status status)
+{
+	/* We still have a fault in starting the io complete it on the port */
+	if (status == SCI_SUCCESS)
+		scic_sds_remote_device_increment_request_count(this_device);
+	else{
+		this_device->owning_port->state_handlers->complete_io_handler(
+			this_device->owning_port, this_device, the_request
+			);
+	}
+}
+
+
+/**
+ *
+ * @request: This parameter specifies the request being continued.
+ *
+ * This method will continue to post tc for a STP request. This method usually
+ * serves as a callback when RNC gets resumed during a task management
+ * sequence. none
+ */
+void scic_sds_remote_device_continue_request(void *dev)
+{
+	struct scic_sds_remote_device *sci_dev = dev;
+	struct scic_sds_request *sci_req = sci_dev->working_request;
+
+	/* we need to check if this request is still valid to continue. */
+	if (sci_req) {
+		struct scic_sds_controller *scic = sci_req->owning_controller;
+		u32 state = scic->parent.state_machine.current_state_id;
+		sci_base_controller_request_handler_t continue_io;
+
+		continue_io = scic_sds_controller_state_handler_table[state].base.continue_io;
+		continue_io(&scic->parent, &sci_req->target_device->parent,
+			    &sci_req->parent);
+	}
+}
+
+/**
+ *
+ * @user_parameter: This is cast to a remote device object.
+ *
+ * This method is called once the remote node context has reached a suspended
+ * state. The remote device can now report that its suspend operation is
+ * complete. none
+ */
+
+/**
+ * This method will terminate all of the IO requests in the controllers IO
+ *    request table that were targeted for this device.
+ * @this_device: This parameter specifies the remote device for which to
+ *    attempt to terminate all requests.
+ *
+ * This method returns an indication as to whether all requests were
+ * successfully terminated.  If a single request fails to be terminated, then
+ * this method will return the failure.
+ */
+static enum sci_status scic_sds_remote_device_terminate_requests(
+	struct scic_sds_remote_device *this_device)
+{
+	enum sci_status status           = SCI_SUCCESS;
+	enum sci_status terminate_status = SCI_SUCCESS;
+	struct scic_sds_request *the_request;
+	u32 index;
+	u32 request_count    = this_device->started_request_count;
+
+	for (index = 0;
+	     (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
+	     index++) {
+		the_request = this_device->owning_port->owning_controller->io_request_table[index];
+
+		if ((the_request != NULL) && (the_request->target_device == this_device)) {
+			terminate_status = scic_controller_terminate_request(
+				this_device->owning_port->owning_controller,
+				this_device,
+				the_request
+				);
+
+			if (terminate_status != SCI_SUCCESS)
+				status = terminate_status;
+
+			request_count--;
+		}
+	}
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  DEFAULT STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default start handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_start_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to start while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default stop handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status scic_sds_remote_device_default_stop_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to stop while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default fail handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_fail_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to fail while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default destruct handler.  It logs a warning and returns
+ * a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_destruct_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to destroy while in "
+		 "wrong state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default reset handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_reset_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to reset while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default reset complete handler.  It logs a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_reset_complete_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to complete reset while "
+		 "in wrong state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default suspend handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_suspend_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type)
+{
+	dev_warn(scirdev_to_dev(this_device),
+		 "%s: SCIC Remote Device 0x%p requested to suspend %d while "
+		 "in wrong state %d\n",
+		 __func__,
+		 this_device,
+		 suspend_type,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 this_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method is the default resume handler.  It logs a warning and returns a
+ * failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_resume_handler(
+	struct scic_sds_remote_device *this_device)
+{
+	dev_warn(scirdev_to_dev(this_device),
+		 "%s: SCIC Remote Device requested to resume while in "
+		 "wrong state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 this_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @event_code: The event code that the struct scic_sds_controller wants the device
+ *    object to process.
+ *
+ * This method is the default event handler.  It will call the RNC state
+ * machine handler for any RNC events otherwise it will log a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status  scic_sds_remote_device_core_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code,
+	bool is_ready_state)
+{
+	enum sci_status status;
+
+	switch (scu_get_event_type(event_code)) {
+	case SCU_EVENT_TYPE_RNC_OPS_MISC:
+	case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+	case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+		status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code);
+		break;
+	case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
+
+		if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) {
+			status = SCI_SUCCESS;
+
+			/* Suspend the associated RNC */
+			scic_sds_remote_node_context_suspend(this_device->rnc,
+							      SCI_SOFTWARE_SUSPENSION,
+							      NULL, NULL);
+
+			dev_dbg(scirdev_to_dev(this_device),
+				"%s: device: %p event code: %x: %s\n",
+				__func__, this_device, event_code,
+				(is_ready_state)
+				? "I_T_Nexus_Timeout event"
+				: "I_T_Nexus_Timeout event in wrong state");
+
+			break;
+		}
+	/* Else, fall through and treat as unhandled... */
+
+	default:
+		dev_dbg(scirdev_to_dev(this_device),
+			"%s: device: %p event code: %x: %s\n",
+			__func__, this_device, event_code,
+			(is_ready_state)
+			? "unexpected event"
+			: "unexpected event in wrong state");
+		status = SCI_FAILURE_INVALID_STATE;
+		break;
+	}
+
+	return status;
+}
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @event_code: The event code that the struct scic_sds_controller wants the device
+ *    object to process.
+ *
+ * This method is the default event handler.  It will call the RNC state
+ * machine handler for any RNC events otherwise it will log a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+static enum sci_status  scic_sds_remote_device_default_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code)
+{
+	return scic_sds_remote_device_core_event_handler(this_device,
+							  event_code,
+							  false);
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @frame_index: The frame index for which the struct scic_sds_controller wants this
+ *    device object to process.
+ *
+ * This method is the default unsolicited frame handler.  It logs a warning,
+ * releases the frame and returns a failure. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	dev_warn(scirdev_to_dev(this_device),
+		 "%s: SCIC Remote Device requested to handle frame %x "
+		 "while in wrong state %d\n",
+		 __func__,
+		 frame_index,
+		 sci_base_state_machine_get_state(
+			 &this_device->parent.state_machine));
+
+	/* Return the frame back to the controller */
+	scic_sds_controller_release_frame(
+		scic_sds_remote_device_get_controller(this_device), frame_index
+		);
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST
+ *    to start.
+ *
+ * This method is the default start io handler.  It logs a warning and returns
+ * a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_start_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to start io request %p "
+		 "while in wrong state %d\n",
+		 __func__,
+		 request,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 (struct scic_sds_remote_device *)device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST
+ *    to complete.
+ *
+ * This method is the default complete io handler.  It logs a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to complete io_request %p "
+		 "while in wrong state %d\n",
+		 __func__,
+		 request,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+				 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST
+ *    to continue.
+ *
+ * This method is the default continue io handler.  It logs a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_default_continue_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	struct scic_sds_remote_device *sds_device =
+		(struct scic_sds_remote_device *)device;
+
+	dev_warn(scirdev_to_dev(sds_device),
+		 "%s: SCIC Remote Device requested to continue io request %p "
+		 "while in wrong state %d\n",
+		 __func__,
+		 request,
+		 sci_base_state_machine_get_state(
+			 scic_sds_remote_device_get_base_state_machine(
+			 sds_device)));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST
+ *    to complete.
+ *
+ * This method is the default complete task handler.  It logs a warning and
+ * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+
+/*
+ * *****************************************************************************
+ * *  NORMAL STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is then cast into a
+ *    struct scic_sds_remote_device.
+ * @frame_index: The frame index for which the struct scic_sds_controller wants this
+ *    device object to process.
+ *
+ * This method is a general ssp frame handler.  In most cases the device object
+ * needs to route the unsolicited frame processing to the io request object.
+ * This method decodes the tag for the io request object and routes the
+ * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_remote_device_general_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	enum sci_status result;
+	struct sci_ssp_frame_header *frame_header;
+	struct scic_sds_request *io_request;
+
+	result = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_remote_device_get_controller(this_device)->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (SCI_SUCCESS == result) {
+		io_request = scic_sds_controller_get_io_request_from_tag(
+			scic_sds_remote_device_get_controller(this_device), frame_header->tag);
+
+		if ((io_request == NULL)
+		    || (io_request->target_device != this_device)) {
+			/*
+			 * We could not map this tag to a valid IO request
+			 * Just toss the frame and continue */
+			scic_sds_controller_release_frame(
+				scic_sds_remote_device_get_controller(this_device), frame_index
+				);
+		} else {
+			/* The IO request is now in charge of releasing the frame */
+			result = io_request->state_handlers->frame_handler(
+				io_request, frame_index);
+		}
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @[in]: this_device This is the device object that is receiving the event.
+ * @[in]: event_code The event code to process.
+ *
+ * This is a common method for handling events reported to the remote device
+ * from the controller object. enum sci_status
+ */
+enum sci_status scic_sds_remote_device_general_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code)
+{
+	return scic_sds_remote_device_core_event_handler(this_device,
+							  event_code,
+							  true);
+}
+
+/*
+ * *****************************************************************************
+ * *  STOPPED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device:
+ *
+ * This method takes the struct scic_sds_remote_device from a stopped state and
+ * attempts to start it.   The RNC buffer for the device is constructed and the
+ * device state machine is transitioned to the
+ * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is
+ * an RNC buffer available to construct the remote device.
+ * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in
+ * which to construct the remote device.
+ */
+static enum sci_status scic_sds_remote_device_stopped_state_start_handler(
+	struct sci_base_remote_device *device)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	status = scic_sds_remote_node_context_resume(
+		this_device->rnc,
+		scic_sds_remote_device_resume_complete_handler,
+		this_device
+		);
+
+	if (status == SCI_SUCCESS) {
+		sci_base_state_machine_change_state(
+			scic_sds_remote_device_get_base_state_machine(this_device),
+			SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+			);
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_device: The struct sci_base_remote_device which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method will stop a struct scic_sds_remote_device that is already in a stopped
+ * state.  This is not considered an error since the device is already stopped.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_device_stopped_state_stop_handler(
+	struct sci_base_remote_device *this_device)
+{
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_device: The struct sci_base_remote_device which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method will destruct a struct scic_sds_remote_device that is in a stopped
+ * state.  This is the only state from which a destruct request will succeed.
+ * The RNi for this struct scic_sds_remote_device is returned to the free pool and the
+ * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	scic_sds_controller_free_remote_node_context(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device,
+		this_device->rnc->remote_node_index
+		);
+
+	scic_sds_remote_node_context_set_remote_node_index(
+		this_device->rnc,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+		);
+
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * *  STARTING STATE HANDLERS
+ * ***************************************************************************** */
+
+static enum sci_status scic_sds_remote_device_starting_state_stop_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	/*
+	 * This device has not yet started so there had better be no IO requests
+	 */
+	BUG_ON(this_device->started_request_count != 0);
+
+	/*
+	 * Destroy the remote node context
+	 */
+	scic_sds_remote_node_context_destruct(
+		this_device->rnc,
+		scic_sds_cb_remote_device_rnc_destruct_complete,
+		this_device
+		);
+
+	/*
+	 * Transition to the stopping state and wait for the remote node to
+	 * complete being posted and invalidated.
+	 */
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * *  INITIALIZING STATE HANDLERS
+ * ***************************************************************************** */
+
+/* There is nothing to do here for SSP devices */
+
+/*
+ * *****************************************************************************
+ * *  READY STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @this_device: The struct scic_sds_remote_device object to be suspended.
+ *
+ * This method is the resume handler for the struct scic_sds_remote_device object. It
+ * will post an RNC resume to the SCU hardware. enum sci_status SCI_SUCCESS
+ */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device object which is cast to a
+ *    struct scic_sds_remote_device object.
+ *
+ * This method is the default stop handler for the struct scic_sds_remote_device ready
+ * substate machine. It will stop the current substate machine and transition
+ * the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status
+ * SCI_SUCCESS
+ */
+enum sci_status scic_sds_remote_device_ready_state_stop_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	enum sci_status status      = SCI_SUCCESS;
+
+	/* Request the parent state machine to transition to the stopping state */
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+		);
+
+	if (this_device->started_request_count == 0) {
+		scic_sds_remote_node_context_destruct(
+			this_device->rnc,
+			scic_sds_cb_remote_device_rnc_destruct_complete,
+			this_device
+			);
+	} else
+		status = scic_sds_remote_device_terminate_requests(this_device);
+
+	return status;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device object which is cast to a
+ *    struct scic_sds_remote_device object.
+ *
+ * This is the ready state device reset handler enum sci_status
+ */
+enum sci_status scic_sds_remote_device_ready_state_reset_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	/* Request the parent state machine to transition to the stopping state */
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device object which is cast to a
+ *    struct scic_sds_remote_device object.
+ *
+ * This is the default fail handler for the struct scic_sds_remote_device ready
+ * substate machine.  It will stop the current ready substate and transition
+ * the remote device object to the SCI_BASE_REMOTE_DEVICE_STATE_FAILED.
+ * enum sci_status SCI_SUCCESS
+ */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device for which the request is to be started.
+ * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that
+ *    is to be started.
+ *
+ * This method will attempt to start a task request for this device object. The
+ * remote device object will issue the start request for the task and if
+ * successful it will start the request for the port object then increment its
+ * own requet count. enum sci_status SCI_SUCCESS if the task request is started for
+ * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request
+ * object could not get the resources to start.
+ */
+static enum sci_status scic_sds_remote_device_ready_state_start_task_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status result;
+	struct scic_sds_remote_device *this_device  = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *task_request = (struct scic_sds_request *)request;
+
+	/* See if the port is in a state where we can start the IO request */
+	result = scic_sds_port_start_io(
+		scic_sds_remote_device_get_port(this_device), this_device, task_request);
+
+	if (result == SCI_SUCCESS) {
+		result = scic_sds_remote_node_context_start_task(
+			this_device->rnc, task_request
+			);
+
+		if (result == SCI_SUCCESS) {
+			result = scic_sds_request_start(task_request);
+		}
+
+		scic_sds_remote_device_start_request(this_device, task_request, result);
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device for which the request is to be started.
+ * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that
+ *    is to be started.
+ *
+ * This method will attempt to start an io request for this device object. The
+ * remote device object will issue the start request for the io and if
+ * successful it will start the request for the port object then increment its
+ * own requet count. enum sci_status SCI_SUCCESS if the io request is started for
+ * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request
+ * object could not get the resources to start.
+ */
+static enum sci_status scic_sds_remote_device_ready_state_start_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status result;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *io_request  = (struct scic_sds_request *)request;
+
+	/* See if the port is in a state where we can start the IO request */
+	result = scic_sds_port_start_io(
+		scic_sds_remote_device_get_port(this_device), this_device, io_request);
+
+	if (result == SCI_SUCCESS) {
+		result = scic_sds_remote_node_context_start_io(
+			this_device->rnc, io_request
+			);
+
+		if (result == SCI_SUCCESS) {
+			result = scic_sds_request_start(io_request);
+		}
+
+		scic_sds_remote_device_start_request(this_device, io_request, result);
+	}
+
+	return result;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is cast to a
+ *    struct scic_sds_remote_device for which the request is to be completed.
+ * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that
+ *    is to be completed.
+ *
+ * This method will complete the request for the remote device object.  The
+ * method will call the completion handler for the request object and if
+ * successful it will complete the request on the port object then decrement
+ * its own started_request_count. enum sci_status
+ */
+static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status result;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *the_request = (struct scic_sds_request *)request;
+
+	result = scic_sds_request_complete(the_request);
+
+	if (result == SCI_SUCCESS) {
+		/* See if the port is in a state where we can start the IO request */
+		result = scic_sds_port_complete_io(
+			scic_sds_remote_device_get_port(this_device), this_device, the_request);
+
+		if (result == SCI_SUCCESS) {
+			scic_sds_remote_device_decrement_request_count(this_device);
+		}
+	}
+
+	return result;
+}
+
+/*
+ * *****************************************************************************
+ * *  STOPPING STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @this_device: The struct sci_base_remote_device which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This method will stop a struct scic_sds_remote_device that is already in the
+ * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error
+ * since we allow a stop request on a device that is alreay stopping or
+ * stopped. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_device_stopping_state_stop_handler(
+	struct sci_base_remote_device *device)
+{
+	/*
+	 * All requests should have been terminated, but if there is an
+	 * attempt to stop a device already in the stopping state, then
+	 * try again to terminate. */
+	return scic_sds_remote_device_terminate_requests(
+		       (struct scic_sds_remote_device *)device);
+}
+
+
+/**
+ *
+ * @device: The device object for which the request is completing.
+ * @request: The task request that is being completed.
+ *
+ * This method completes requests for this struct scic_sds_remote_device while it is
+ * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the
+ * complete method for the request object and if that is successful the port
+ * object is called to complete the task request. Then the device object itself
+ * completes the task request. If struct scic_sds_remote_device started_request_count
+ * goes to 0 and the invalidate RNC request has completed the device object can
+ * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status
+ */
+static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status status = SCI_SUCCESS;
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	status = scic_sds_request_complete(this_request);
+	if (status == SCI_SUCCESS) {
+		status = scic_sds_port_complete_io(
+			scic_sds_remote_device_get_port(this_device),
+			this_device,
+			this_request
+			);
+
+		if (status == SCI_SUCCESS) {
+			scic_sds_remote_device_decrement_request_count(this_device);
+
+			if (scic_sds_remote_device_get_request_count(this_device) == 0) {
+				scic_sds_remote_node_context_destruct(
+					this_device->rnc,
+					scic_sds_cb_remote_device_rnc_destruct_complete,
+					this_device
+					);
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  RESETTING STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is to be cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ * This method will complete the reset operation when the device is in the
+ * resetting state. enum sci_status
+ */
+static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	sci_base_state_machine_change_state(
+		&this_device->parent.state_machine,
+		SCI_BASE_REMOTE_DEVICE_STATE_READY
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is to be cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ * This method will stop the remote device while in the resetting state.
+ * enum sci_status
+ */
+static enum sci_status scic_sds_remote_device_resetting_state_stop_handler(
+	struct sci_base_remote_device *device)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	sci_base_state_machine_change_state(
+		&this_device->parent.state_machine,
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @device: The device object for which the request is completing.
+ * @request: The task request that is being completed.
+ *
+ * This method completes requests for this struct scic_sds_remote_device while it is
+ * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the
+ * complete method for the request object and if that is successful the port
+ * object is called to complete the task request. Then the device object itself
+ * completes the task request. enum sci_status
+ */
+static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status status = SCI_SUCCESS;
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+
+	status = scic_sds_request_complete(this_request);
+
+	if (status == SCI_SUCCESS) {
+		status = scic_sds_port_complete_io(
+			scic_sds_remote_device_get_port(this_device), this_device, this_request);
+
+		if (status == SCI_SUCCESS) {
+			scic_sds_remote_device_decrement_request_count(this_device);
+		}
+	}
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  FAILED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: The struct sci_base_remote_device which is to be cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ * This method handles the remove request for a failed struct scic_sds_remote_device
+ * object. The method will transition the device object to the
+ * SCIC_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status SCI_SUCCESS
+ */
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = {
+	[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_default_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_default_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
+		.parent.start_handler		= scic_sds_remote_device_stopped_state_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_stopped_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_stopped_state_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_default_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_starting_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_ready_state_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_ready_state_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_ready_state_start_task_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_ready_state_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler,
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_stopping_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_stopping_state_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_stopping_state_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_default_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_default_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_resetting_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_resetting_state_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_resetting_state_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_resetting_state_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_default_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_default_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_default_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	}
+};
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
+ * immediatly transitions the remote device object to the stopped state. none
+ */
+static void scic_sds_remote_device_initial_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+		);
+
+	/* Initial state is a transitional state to the stopped state */
+	sci_base_state_machine_change_state(
+		scic_sds_remote_device_get_base_state_machine(this_device),
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
+ * sets the stopped state handlers and if this state is entered from the
+ * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the
+ * device stop is complete. none
+ */
+static void scic_sds_remote_device_stopped_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+		);
+
+	/*
+	 * If we are entering from the stopping state let the SCI User know that
+	 * the stop operation has completed. */
+	if (this_device->parent.state_machine.previous_state_id
+	    == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) {
+		isci_event_remote_device_stop_complete(
+			scic_sds_remote_device_get_controller(this_device),
+			this_device,
+			SCI_SUCCESS
+			);
+	}
+
+	scic_sds_controller_remote_device_stopped(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device
+	);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it
+ * sets the starting state handlers, sets the device not ready, and posts the
+ * remote node context to the hardware. none
+ */
+static void scic_sds_remote_device_starting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *the_controller;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	the_controller = scic_sds_remote_device_get_controller(this_device);
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+		);
+
+	isci_event_remote_device_not_ready(
+		the_controller,
+		this_device,
+		SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it
+ * reports that the device start is complete. none
+ */
+static void scic_sds_remote_device_starting_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	/*
+	 * / @todo Check the device object for the proper return code for this
+	 * /       callback */
+	isci_event_remote_device_start_complete(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device,
+		SCI_SUCCESS
+		);
+
+	scic_sds_controller_remote_device_started(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device
+	);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets
+ * the ready state handlers, and starts the ready substate machine. none
+ */
+static void scic_sds_remote_device_ready_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *the_controller;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	the_controller = scic_sds_remote_device_get_controller(this_device);
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_READY
+		);
+
+	the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++;
+
+	if (this_device->has_ready_substate_machine) {
+		sci_base_state_machine_start(&this_device->ready_substate_machine);
+	} else {
+		isci_event_remote_device_ready(the_controller, this_device);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does
+ * nothing. none
+ */
+static void scic_sds_remote_device_ready_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_controller *the_controller;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	the_controller = scic_sds_remote_device_get_controller(this_device);
+
+	if (this_device->has_ready_substate_machine) {
+		sci_base_state_machine_stop(&this_device->ready_substate_machine);
+	} else {
+		isci_event_remote_device_not_ready(
+			the_controller,
+			this_device,
+			SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED
+			);
+	}
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it
+ * sets the stopping state handlers and posts an RNC invalidate request to the
+ * SCU hardware. none
+ */
+static void scic_sds_remote_device_stopping_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it sets
+ * the stopping state handlers. none
+ */
+static void scic_sds_remote_device_failed_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
+ * sets the resetting state handlers. none
+ */
+static void scic_sds_remote_device_resetting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
+		);
+
+	scic_sds_remote_node_context_suspend(
+		this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
+ * does nothing. none
+ */
+static void scic_sds_remote_device_resetting_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object that is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets
+ * the final state handlers. none
+ */
+static void scic_sds_remote_device_final_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_remote_device_state_handler_table,
+		SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_remote_device_state_table[] = {
+	[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
+		.enter_state = scic_sds_remote_device_initial_state_enter,
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
+		.enter_state = scic_sds_remote_device_stopped_state_enter,
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
+		.enter_state = scic_sds_remote_device_starting_state_enter,
+		.exit_state  = scic_sds_remote_device_starting_state_exit
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
+		.enter_state = scic_sds_remote_device_ready_state_enter,
+		.exit_state  = scic_sds_remote_device_ready_state_exit
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
+		.enter_state = scic_sds_remote_device_stopping_state_enter,
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
+		.enter_state = scic_sds_remote_device_failed_state_enter,
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
+		.enter_state = scic_sds_remote_device_resetting_state_enter,
+		.exit_state  = scic_sds_remote_device_resetting_state_exit
+	},
+	[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
+		.enter_state = scic_sds_remote_device_final_state_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h
new file mode 100644
index 0000000..4841e45
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_device.h
@@ -0,0 +1,570 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_REMOTE_DEVICE_H_
+#define _SCIC_SDS_REMOTE_DEVICE_H_
+
+/**
+ * This file contains the structures, constants, and prototypes for the
+ *    struct scic_sds_remote_device object.
+ *
+ *
+ */
+
+#include "intel_sas.h"
+#include "sci_base_remote_device.h"
+#include "sci_base_request.h"
+#include "scu_remote_node_context.h"
+#include "scic_sds_remote_node_context.h"
+
+struct scic_sds_controller;
+struct scic_sds_port;
+struct scic_sds_request;
+struct scic_sds_remote_device_state_handler;
+
+/**
+ * enum scic_sds_ssp_remote_device_ready_substates -
+ *
+ * This is the enumeration of the ready substates for the
+ * struct scic_sds_remote_device.
+ */
+enum scic_sds_ssp_remote_device_ready_substates {
+	/**
+	 * This is the initial state for the remote device ready substate.
+	 */
+	SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL,
+
+	/**
+	 * This is the ready operational substate for the remote device.
+	 * This is the normal operational state for a remote device.
+	 */
+	SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
+
+	/**
+	 * This is the suspended state for the remote device. This is the state
+	 * that the device is placed in when a RNC suspend is received by
+	 * the SCU hardware.
+	 */
+	SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
+
+	/**
+	 * This is the final state that the device is placed in before a change
+	 * to the base state machine.
+	 */
+	SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL,
+
+	SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+/**
+ * enum scic_sds_stp_remote_device_ready_substates -
+ *
+ * This is the enumeration for the struct scic_sds_remote_device ready substates
+ * for the STP remote device.
+ */
+enum scic_sds_stp_remote_device_ready_substates {
+	/**
+	 * This is the idle substate for the stp remote device.  When there are no
+	 * active IO for the device it is is in this state.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+
+	/**
+	 * This is the command state for for the STP remote device.  This state is
+	 * entered when the device is processing a non-NCQ command.  The device object
+	 * will fail any new start IO requests until this command is complete.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+
+	/**
+	 * This is the NCQ state for the STP remote device.  This state is entered
+	 * when the device is processing an NCQ reuqest.  It will remain in this state
+	 * so long as there is one or more NCQ requests being processed.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
+
+	/**
+	 * This is the NCQ error state for the STP remote device.  This state is
+	 * entered when an SDB error FIS is received by the device object while in the
+	 * NCQ state.  The device object will only accept a READ LOG command while in
+	 * this state.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
+
+#if !defined(DISABLE_ATAPI)
+	/**
+	 * This is the ATAPI error state for the STP ATAPI remote device.  This state is
+	 * entered when ATAPI device sends error status FIS without data while the device
+	 * object is in CMD state. A suspension event is expected in this state. The device
+	 * object will resume right away.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
+#endif
+
+	/**
+	 * This is the READY substate indicates the device is waiting for the RESET task
+	 * coming to be recovered from certain hardware specific error.
+	 */
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
+};
+
+/**
+ * enum scic_sds_smp_remote_device_ready_substates -
+ *
+ * This is the enumeration of the ready substates for the SMP REMOTE DEVICE.
+ */
+enum scic_sds_smp_remote_device_ready_substates {
+	/**
+	 * This is the ready operational substate for the remote device.  This is the
+	 * normal operational state for a remote device.
+	 */
+	SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+
+	/**
+	 * This is the suspended state for the remote device.  This is the state that
+	 * the device is placed in when a RNC suspend is received by the SCU hardware.
+	 */
+	SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+};
+
+/**
+ * struct scic_sds_remote_device - This structure contains the data for an SCU
+ *    implementation of the SCU Core device data.
+ *
+ *
+ */
+struct scic_sds_remote_device {
+	/**
+	 * This field is the common base for all remote device objects.
+	 */
+	struct sci_base_remote_device parent;
+
+	/**
+	 * This field is the programmed device port width.  This value is written to
+	 * the RCN data structure to tell the SCU how many open connections this
+	 * device can have.
+	 */
+	u32 device_port_width;
+
+	/**
+	 * This field is the programmed connection rate for this remote device.  It is
+	 * used to program the TC with the maximum allowed connection rate.
+	 */
+	enum sci_sas_link_rate connection_rate;
+
+	/**
+	 * This field contains the allowed target protocols for this remote device.
+	 */
+	struct smp_discover_response_protocols target_protocols;
+
+	/**
+	 * This field contains the device SAS address.
+	 */
+	struct sci_sas_address device_address;
+
+	/**
+	 * This filed is assinged the value of true if the device is directly
+	 * attached to the port.
+	 */
+	bool is_direct_attached;
+
+#if !defined(DISABLE_ATAPI)
+	/**
+	 * This filed is assinged the value of true if the device is an ATAPI
+	 * device.
+	 */
+	bool is_atapi;
+#endif
+
+	/**
+	 * This filed contains a pointer back to the port to which this device
+	 * is assigned.
+	 */
+	struct scic_sds_port *owning_port;
+
+	/**
+	 * This field contains the SCU silicon remote node context specific
+	 * information.
+	 */
+	struct scic_sds_remote_node_context *rnc;
+
+	/**
+	 * This field contains the stated request count for the remote device.  The
+	 * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all
+	 * requests are complete and the rnc_posted value is false.
+	 */
+	u32 started_request_count;
+
+	/**
+	 * This field contains a pointer to the working request object.  It is only
+	 * used only for SATA requests since the unsolicited frames we get from the
+	 * hardware have no Tag value to look up the io request object.
+	 */
+	struct scic_sds_request *working_request;
+
+	/**
+	 * This field contains the reason for the remote device going not_ready.  It is
+	 * assigned in the state handlers and used in the state transition.
+	 */
+	u32 not_ready_reason;
+
+	/**
+	 * This field is true if this remote device has an initialzied ready substate
+	 * machine. SSP devices do not have a ready substate machine and STP devices
+	 * have a ready substate machine.
+	 */
+	bool has_ready_substate_machine;
+
+	/**
+	 * This field contains the state machine for the ready substate machine for
+	 * this struct scic_sds_remote_device object.
+	 */
+	struct sci_base_state_machine ready_substate_machine;
+
+	/**
+	 * This field maintains the set of state handlers for the remote device
+	 * object.  These are changed each time the remote device enters a new state.
+	 */
+	const struct scic_sds_remote_device_state_handler *state_handlers;
+};
+
+typedef enum sci_status (*scic_sds_remote_device_handler_t)(
+	struct scic_sds_remote_device *this_device);
+
+typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type);
+
+typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)(
+	struct scic_sds_remote_device *this_device);
+
+typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index);
+
+typedef enum sci_status (*scic_sds_remote_device_event_handler_t)(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code);
+
+typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)(
+	struct scic_sds_remote_device *this_device);
+
+/**
+ * struct scic_sds_remote_device_state_handler - This structure conains the
+ *    state handlers that are needed to process requests for the SCU remote
+ *    device objects.
+ *
+ *
+ */
+struct scic_sds_remote_device_state_handler {
+	struct sci_base_remote_device_state_handler parent;
+	scic_sds_remote_device_suspend_handler_t suspend_handler;
+	scic_sds_remote_device_resume_handler_t resume_handler;
+	scic_sds_remote_device_event_handler_t event_handler;
+	scic_sds_remote_device_frame_handler_t frame_handler;
+};
+
+extern const struct sci_base_state scic_sds_remote_device_state_table[];
+extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[];
+extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[];
+extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[];
+
+extern const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[];
+extern const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[];
+extern const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[];
+
+/**
+ * scic_sds_remote_device_increment_request_count() -
+ *
+ * This macro incrments the request count for this device
+ */
+#define scic_sds_remote_device_increment_request_count(this_device) \
+	((this_device)->started_request_count++)
+
+/**
+ * scic_sds_remote_device_decrement_request_count() -
+ *
+ * This macro decrements the request count for this device.  This count will
+ * never decrment past 0.
+ */
+#define scic_sds_remote_device_decrement_request_count(this_device) \
+	((this_device)->started_request_count > 0 ? \
+	 (this_device)->started_request_count-- : 0)
+
+/**
+ * scic_sds_remote_device_get_request_count() -
+ *
+ * This is a helper macro to return the current device request count.
+ */
+#define scic_sds_remote_device_get_request_count(this_device) \
+	((this_device)->started_request_count)
+
+/**
+ * scic_sds_remote_device_get_port() -
+ *
+ * This macro returns the owning port of this remote device obejct.
+ */
+#define scic_sds_remote_device_get_port(this_device) \
+	((this_device)->owning_port)
+
+/**
+ * scic_sds_remote_device_get_controller() -
+ *
+ * This macro returns the controller object that contains this device object
+ */
+#define scic_sds_remote_device_get_controller(this_device) \
+	scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device))
+
+/**
+ * scic_sds_remote_device_set_state_handlers() -
+ *
+ * This macro sets the remote device state handlers pointer and is set on entry
+ * to each device state.
+ */
+#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \
+	((this_device)->state_handlers = (handlers))
+
+/**
+ * scic_sds_remote_device_get_base_state_machine() -
+ *
+ * This macro returns the base sate machine object for the remote device.
+ */
+#define scic_sds_remote_device_get_base_state_machine(this_device) \
+	(&(this_device)->parent.state_machine)
+
+/**
+ * scic_sds_remote_device_get_ready_substate_machine() -
+ *
+ * This macro returns the remote device ready substate machine
+ */
+#define scic_sds_remote_device_get_ready_substate_machine(this_device) \
+	(&(this_device)->ready_substate_machine)
+
+/**
+ * scic_sds_remote_device_get_port() -
+ *
+ * This macro returns the owning port of this device
+ */
+#define scic_sds_remote_device_get_port(this_device) \
+	((this_device)->owning_port)
+
+/**
+ * scic_sds_remote_device_get_sequence() -
+ *
+ * This macro returns the remote device sequence value
+ */
+#define scic_sds_remote_device_get_sequence(this_device) \
+	(\
+		scic_sds_remote_device_get_controller(this_device)-> \
+		remote_device_sequence[(this_device)->rnc->remote_node_index] \
+	)
+
+/**
+ * scic_sds_remote_device_get_controller_peg() -
+ *
+ * This macro returns the controllers protocol engine group
+ */
+#define scic_sds_remote_device_get_controller_peg(this_device) \
+	(\
+		scic_sds_controller_get_protocol_engine_group(\
+			scic_sds_port_get_controller(\
+				scic_sds_remote_device_get_port(this_device) \
+				) \
+			) \
+	)
+
+/**
+ * scic_sds_remote_device_get_port_index() -
+ *
+ * This macro returns the port index for the devices owning port
+ */
+#define scic_sds_remote_device_get_port_index(this_device) \
+	(scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device)))
+
+/**
+ * scic_sds_remote_device_get_index() -
+ *
+ * This macro returns the remote node index for this device object
+ */
+#define scic_sds_remote_device_get_index(this_device) \
+	((this_device)->rnc->remote_node_index)
+
+/**
+ * scic_sds_remote_device_build_command_context() -
+ *
+ * This macro builds a remote device context for the SCU post request operation
+ */
+#define scic_sds_remote_device_build_command_context(device, command) \
+	((command) \
+	 | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \
+	 | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \
+	 | (scic_sds_remote_device_get_index((device)))	\
+	)
+
+/**
+ * scic_sds_remote_device_set_working_request() -
+ *
+ * This macro makes the working request assingment for the remote device
+ * object. To clear the working request use this macro with a NULL request
+ * object.
+ */
+#define scic_sds_remote_device_set_working_request(device, request) \
+	((device)->working_request = (request))
+
+enum sci_status scic_sds_remote_device_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index);
+
+enum sci_status scic_sds_remote_device_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code);
+
+enum sci_status scic_sds_remote_device_start_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request);
+
+enum sci_status scic_sds_remote_device_complete_io(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request);
+
+enum sci_status scic_sds_remote_device_resume(
+	struct scic_sds_remote_device *this_device);
+
+enum sci_status scic_sds_remote_device_suspend(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type);
+
+enum sci_status scic_sds_remote_device_start_task(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *io_request);
+
+void scic_sds_remote_device_post_request(
+	struct scic_sds_remote_device *this_device,
+	u32 request);
+
+#if !defined(DISABLE_ATAPI)
+bool scic_sds_remote_device_is_atapi(
+	struct scic_sds_remote_device *this_device);
+#else /* !defined(DISABLE_ATAPI) */
+#define scic_sds_remote_device_is_atapi(this_device) false
+#endif /* !defined(DISABLE_ATAPI) */
+
+void scic_sds_remote_device_start_request(
+	struct scic_sds_remote_device *this_device,
+	struct scic_sds_request *the_request,
+	enum sci_status status);
+
+void scic_sds_remote_device_continue_request(void *sci_dev);
+
+enum sci_status scic_sds_remote_device_default_start_handler(
+	struct sci_base_remote_device *this_device);
+
+enum sci_status scic_sds_remote_device_default_fail_handler(
+	struct sci_base_remote_device *this_device);
+
+enum sci_status scic_sds_remote_device_default_destruct_handler(
+	struct sci_base_remote_device *this_device);
+
+enum sci_status scic_sds_remote_device_default_reset_handler(
+	struct sci_base_remote_device *device);
+
+enum sci_status scic_sds_remote_device_default_reset_complete_handler(
+	struct sci_base_remote_device *device);
+
+enum sci_status scic_sds_remote_device_default_start_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request);
+
+enum sci_status scic_sds_remote_device_default_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request);
+
+enum sci_status scic_sds_remote_device_default_continue_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request);
+
+enum sci_status scic_sds_remote_device_default_suspend_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type);
+
+enum sci_status scic_sds_remote_device_default_resume_handler(
+	struct scic_sds_remote_device *this_device);
+
+
+enum sci_status scic_sds_remote_device_default_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index);
+
+enum sci_status scic_sds_remote_device_ready_state_stop_handler(
+	struct sci_base_remote_device *device);
+
+enum sci_status scic_sds_remote_device_ready_state_reset_handler(
+	struct sci_base_remote_device *device);
+
+enum sci_status scic_sds_remote_device_general_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index);
+
+enum sci_status scic_sds_remote_device_general_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code);
+
+enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler(
+	struct scic_sds_remote_device *this_device);
+
+#endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c
new file mode 100644
index 0000000..93e6ab8
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_event_codes.h"
+#include "scu_task_context.h"
+
+/*
+ * *****************************************************************************
+ * *  SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @[in]: device The device the io is sent to.
+ * @[in]: request The io to start.
+ *
+ * This method will handle the start io operation for a SMP device that is in
+ * the idle state. enum sci_status
+ */
+static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *io_request  = (struct scic_sds_request *)request;
+
+	/* Will the port allow the io request to start? */
+	status = this_device->owning_port->state_handlers->start_io_handler(
+		this_device->owning_port,
+		this_device,
+		io_request
+		);
+
+	if (status == SCI_SUCCESS) {
+		status =
+			scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
+
+		if (status == SCI_SUCCESS) {
+			status = scic_sds_request_start(io_request);
+		}
+
+		if (status == SCI_SUCCESS) {
+			this_device->working_request = io_request;
+
+			sci_base_state_machine_change_state(
+				&this_device->ready_substate_machine,
+				SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+				);
+		}
+
+		scic_sds_remote_device_start_request(this_device, io_request, status);
+	}
+
+	return status;
+}
+
+
+/*
+ * ******************************************************************************
+ * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
+ * ****************************************************************************** */
+/**
+ *
+ * @device: This is the device object that is receiving the IO.
+ * @request: The io to start.
+ *
+ * This device is already handling a command it can not accept new commands
+ * until this one is complete. enum sci_status
+ */
+static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * this is the complete_io_handler for smp device at ready cmd substate.
+ * @device: This is the device object that is receiving the IO.
+ * @request: The io to start.
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *this_device;
+	struct scic_sds_request *the_request;
+
+	this_device = (struct scic_sds_remote_device *)device;
+	the_request = (struct scic_sds_request *)request;
+
+	status = scic_sds_io_request_complete(the_request);
+
+	if (status == SCI_SUCCESS) {
+		status = scic_sds_port_complete_io(
+			this_device->owning_port, this_device, the_request);
+
+		if (status == SCI_SUCCESS) {
+			scic_sds_remote_device_decrement_request_count(this_device);
+			sci_base_state_machine_change_state(
+				&this_device->ready_substate_machine,
+				SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+				);
+		} else
+			dev_err(scirdev_to_dev(this_device),
+				"%s: SCIC SDS Remote Device 0x%p io request "
+				"0x%p could not be completd on the port 0x%p "
+				"failed with status %d.\n",
+				__func__,
+				this_device,
+				the_request,
+				this_device->owning_port,
+				status);
+	}
+
+	return status;
+}
+
+/**
+ * This is frame handler for smp device ready cmd substate.
+ * @this_device: This is the device object that is receiving the frame.
+ * @frame_index: The index for the frame received.
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	enum sci_status status;
+
+	/*
+	 * / The device does not process any UF received from the hardware while
+	 * / in this state.  All unsolicited frames are forwarded to the io request
+	 * / object. */
+	status = scic_sds_io_request_frame_handler(
+		this_device->working_request,
+		frame_index
+		);
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = {
+	[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	},
+	[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_default_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
+	}
+};
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method.
+ * This method sets the ready cmd substate handlers and reports the device as
+ * ready. none
+ */
+static void scic_sds_smp_remote_device_ready_idle_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_smp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+		);
+
+	isci_event_remote_device_ready(
+		scic_sds_remote_device_get_controller(this_device), this_device);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
+ * method sets the remote device objects ready cmd substate handlers, and
+ * notify core user that the device is not ready. none
+ */
+static void scic_sds_smp_remote_device_ready_cmd_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	BUG_ON(this_device->working_request == NULL);
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_smp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+		);
+
+	isci_event_remote_device_not_ready(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device,
+		SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED
+		);
+}
+
+/**
+ *
+ * @object: This is the struct sci_base_object which is cast into a
+ *    struct scic_sds_remote_device.
+ *
+ * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none
+ */
+static void scic_sds_smp_remote_device_ready_cmd_substate_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
+
+	this_device->working_request = NULL;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = {
+	[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
+		.enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
+	},
+	[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
+		.enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
+		.exit_state  = scic_sds_smp_remote_device_ready_cmd_substate_exit,
+	},
+};
diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c
new file mode 100644
index 0000000..9a615f0
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c
@@ -0,0 +1,908 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_ata.h"
+#include "intel_sata.h"
+#include "intel_sat.h"
+#include "sci_base_state.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_event_codes.h"
+
+/**
+ * This method will perform the STP request completion processing common to IO
+ *    requests and task requests of all types
+ * @device: This parameter specifies the device for which the request is being
+ *    completed.
+ * @request: This parameter specifies the request being completed.
+ *
+ * This method returns an indication as to whether the request processing
+ * completed successfully.
+ */
+static enum sci_status scic_sds_stp_remote_device_complete_request(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *the_request = (struct scic_sds_request *)request;
+	enum sci_status status;
+
+	status = scic_sds_io_request_complete(the_request);
+
+	if (status == SCI_SUCCESS) {
+		status = scic_sds_port_complete_io(
+			this_device->owning_port, this_device, the_request
+			);
+
+		if (status == SCI_SUCCESS) {
+			scic_sds_remote_device_decrement_request_count(this_device);
+			if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
+				/*
+				 * This request causes hardware error, device needs to be Lun Reset.
+				 * So here we force the state machine to IDLE state so the rest IOs
+				 * can reach RNC state handler, these IOs will be completed by RNC with
+				 * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */
+				sci_base_state_machine_change_state(
+					&this_device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
+					);
+			} else if (scic_sds_remote_device_get_request_count(this_device) == 0) {
+				sci_base_state_machine_change_state(
+					&this_device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+					);
+			}
+		}
+	}
+
+	if (status != SCI_SUCCESS)
+		dev_err(scirdev_to_dev(this_device),
+			"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
+			"could not complete\n",
+			__func__,
+			this_device->owning_port,
+			this_device,
+			the_request,
+			status);
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * This is the READY NCQ substate handler to start task management request. In
+ *    this routine, we suspend and resume the RNC.
+ * @device: The target device a task management request towards to.
+ * @request: The task request.
+ *
+ * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to
+ * let controller_start_task_handler know that the controller can't post TC for
+ * task request yet, instead, when RNC gets resumed, a controller_continue_task
+ * callback will be called.
+ */
+static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *this_device  = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	/* Will the port allow the io request to start? */
+	status = this_device->owning_port->state_handlers->start_io_handler(
+		this_device->owning_port,
+		this_device,
+		this_request
+		);
+
+	if (SCI_SUCCESS == status) {
+		status =
+			scic_sds_remote_node_context_start_task(this_device->rnc, this_request);
+
+		if (SCI_SUCCESS == status) {
+			status = this_request->state_handlers->parent.start_handler(request);
+		}
+
+		if (status == SCI_SUCCESS) {
+			/*
+			 * / @note If the remote device state is not IDLE this will replace
+			 * /       the request that probably resulted in the task management
+			 * /       request. */
+			this_device->working_request = this_request;
+
+			sci_base_state_machine_change_state(
+				&this_device->ready_substate_machine,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+				);
+
+			/*
+			 * The remote node context must cleanup the TCi to NCQ mapping table.
+			 * The only way to do this correctly is to either write to the TLCR
+			 * register or to invalidate and repost the RNC. In either case the
+			 * remote node context state machine will take the correct action when
+			 * the remote node context is suspended and later resumed. */
+			scic_sds_remote_node_context_suspend(
+				this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
+
+			scic_sds_remote_node_context_resume(
+				this_device->rnc,
+				scic_sds_remote_device_continue_request,
+				this_device);
+		}
+
+		scic_sds_remote_device_start_request(this_device, this_request, status);
+
+		/*
+		 * We need to let the controller start request handler know that it can't
+		 * post TC yet. We will provide a callback function to post TC when RNC gets
+		 * resumed. */
+		return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
+	}
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * This method will handle the start io operation for a sata device that is in
+ *    the command idle state. - Evalute the type of IO request to be started -
+ *    If its an NCQ request change to NCQ substate - If its any other command
+ *    change to the CMD substate
+ * @device:
+ * @request:
+ *
+ * If this is a softreset we may want to have a different substate.
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
+	struct sci_base_remote_device *base_device,
+	struct sci_base_request *base_request)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *device =
+		(struct scic_sds_remote_device *)&base_device->parent;
+	struct scic_sds_request *sds_request  =
+		(struct scic_sds_request *)&base_request->parent;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+
+	/* Will the port allow the io request to start? */
+	status = device->owning_port->state_handlers->start_io_handler(
+			device->owning_port,
+			device,
+			sds_request);
+
+	if (status == SCI_SUCCESS) {
+		status =
+			scic_sds_remote_node_context_start_io(device->rnc,
+							      sds_request);
+
+		if (status == SCI_SUCCESS)
+			status =
+				sds_request->state_handlers->
+					parent.start_handler(base_request);
+
+		if (status == SCI_SUCCESS) {
+			if (isci_sata_get_sat_protocol(isci_request) ==
+					SAT_PROTOCOL_FPDMA)
+				sci_base_state_machine_change_state(
+					&device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ);
+			else {
+				device->working_request = sds_request;
+
+				sci_base_state_machine_change_state(
+					&device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
+			}
+		}
+
+		scic_sds_remote_device_start_request(device,
+						     sds_request,
+						     status);
+	}
+
+	return status;
+}
+
+
+/**
+ *
+ * @[in]: device The device received event.
+ * @[in]: event_code The event code.
+ *
+ * This method will handle the event for a sata device that is in the idle
+ * state. We pick up suspension events to handle specifically to this state. We
+ * resume the RNC right away. enum sci_status
+ */
+static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	status = scic_sds_remote_device_general_event_handler(this_device, event_code);
+
+	if (status == SCI_SUCCESS) {
+		if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
+		    || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
+			status = scic_sds_remote_node_context_resume(
+				this_device->rnc, NULL, NULL);
+		}
+	}
+
+	return status;
+}
+
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
+	struct sci_base_remote_device *base_device,
+	struct sci_base_request *base_request)
+{
+	enum sci_status status;
+	struct scic_sds_remote_device *device =
+		(struct scic_sds_remote_device *)&base_device->parent;
+	struct scic_sds_request *sds_request  =
+		(struct scic_sds_request *)&base_request->parent;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+	if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) {
+		status = device->owning_port->state_handlers->start_io_handler(
+				device->owning_port,
+				device,
+				sds_request);
+
+		if (status == SCI_SUCCESS) {
+			status = scic_sds_remote_node_context_start_io(
+					device->rnc,
+					sds_request);
+
+			if (status == SCI_SUCCESS)
+				status = sds_request->state_handlers->
+					parent.start_handler(base_request);
+
+			scic_sds_remote_device_start_request(device,
+							     sds_request,
+							     status);
+		}
+	} else
+		status = SCI_FAILURE_INVALID_STATE;
+
+	return status;
+}
+
+
+/**
+ * This method will handle events received while the STP device is in the ready
+ *    command substate.
+ * @this_device: This is the device object that is receiving the event.
+ * @event_code: The event code to process.
+ *
+ * enum sci_status
+ */
+
+static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_remote_device_get_controller(this_device)->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
+		    (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
+			this_device->not_ready_reason =
+				SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
+
+			/*
+			 * / @todo Check sactive and complete associated IO
+			 * if any.
+			 */
+
+			sci_base_state_machine_change_state(
+				&this_device->ready_substate_machine,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+				);
+		} else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H &&
+			   (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
+
+			/*
+			 * Some devices return D2H FIS when an NCQ error is detected.
+			 * Treat this like an SDB error FIS ready reason.
+			 */
+			this_device->not_ready_reason =
+				SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
+
+			sci_base_state_machine_change_state(
+				&this_device->ready_substate_machine,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+				);
+		} else {
+			status = SCI_FAILURE;
+		}
+
+		scic_sds_controller_release_frame(
+			scic_sds_remote_device_get_controller(this_device), frame_index
+			);
+	}
+
+	return status;
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * This device is already handling a command it can not accept new commands
+ *    until this one is complete.
+ * @device:
+ * @request:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 suspend_type)
+{
+	enum sci_status status;
+
+	status = scic_sds_remote_node_context_suspend(
+		this_device->rnc, suspend_type, NULL, NULL
+		);
+
+	return status;
+}
+
+static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 frame_index)
+{
+	enum sci_status status;
+
+	/*
+	 * / The device doe not process any UF received from the hardware while
+	 * / in this state.  All unsolicited frames are forwarded to the io request
+	 * / object. */
+	status = scic_sds_io_request_frame_handler(
+		this_device->working_request,
+		frame_index
+		);
+
+	return status;
+}
+
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
+ * ***************************************************************************** */
+static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
+}
+
+
+
+/**
+ * This method will perform the STP request (both io or task) completion
+ *    processing for await reset state.
+ * @device: This parameter specifies the device for which the request is being
+ *    completed.
+ * @request: This parameter specifies the request being completed.
+ *
+ * This method returns an indication as to whether the request processing
+ * completed successfully.
+ */
+static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
+	struct sci_base_remote_device *device,
+	struct sci_base_request *request)
+{
+	struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
+	struct scic_sds_request *the_request = (struct scic_sds_request *)request;
+	enum sci_status status;
+
+	status = scic_sds_io_request_complete(the_request);
+
+	if (status == SCI_SUCCESS) {
+		status = scic_sds_port_complete_io(
+			this_device->owning_port, this_device, the_request
+			);
+
+		if (status == SCI_SUCCESS)
+			scic_sds_remote_device_decrement_request_count(this_device);
+	}
+
+	if (status != SCI_SUCCESS)
+		dev_err(scirdev_to_dev(this_device),
+			"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
+			"could not complete\n",
+			__func__,
+			this_device->owning_port,
+			this_device,
+			the_request,
+			status);
+
+	return status;
+}
+
+#if !defined(DISABLE_ATAPI)
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @[in]: device The device received event.
+ * @[in]: event_code The event code.
+ *
+ * This method will handle the event for a ATAPI device that is in the ATAPI
+ * ERROR state. We pick up suspension events to handle specifically to this
+ * state. We resume the RNC right away. We then complete the outstanding IO to
+ * this device. enum sci_status
+ */
+enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler(
+	struct scic_sds_remote_device *this_device,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	status = scic_sds_remote_device_general_event_handler(this_device, event_code);
+
+	if (status == SCI_SUCCESS) {
+		if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
+		    || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
+			status = scic_sds_remote_node_context_resume(
+				this_device->rnc,
+				this_device->working_request->state_handlers->parent.complete_handler,
+				(void *)this_device->working_request
+				);
+		}
+	}
+
+	return status;
+}
+#endif /* !defined(DISABLE_ATAPI) */
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = {
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_remote_device_default_complete_request_handler,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_stp_remote_device_ready_idle_substate_event_handler,
+		.frame_handler			= scic_sds_remote_device_default_frame_handler
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_stp_remote_device_complete_request,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_stp_remote_device_complete_request,
+		.suspend_handler		= scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_stp_remote_device_complete_request,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_stp_remote_device_complete_request,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_stp_remote_device_complete_request,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_stp_remote_device_complete_request,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	},
+#if !defined(DISABLE_ATAPI)
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_remote_device_default_start_request_handler,
+		.parent.complete_io_handler	= scic_sds_stp_remote_device_complete_request,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_stp_remote_device_complete_request,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	},
+#endif
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
+		.parent.start_handler		= scic_sds_remote_device_default_start_handler,
+		.parent.stop_handler		= scic_sds_remote_device_ready_state_stop_handler,
+		.parent.fail_handler		= scic_sds_remote_device_default_fail_handler,
+		.parent.destruct_handler	= scic_sds_remote_device_default_destruct_handler,
+		.parent.reset_handler		= scic_sds_remote_device_ready_state_reset_handler,
+		.parent.reset_complete_handler	= scic_sds_remote_device_default_reset_complete_handler,
+		.parent.start_io_handler	= scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
+		.parent.complete_io_handler	= scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
+		.parent.continue_io_handler	= scic_sds_remote_device_default_continue_request_handler,
+		.parent.start_task_handler	= scic_sds_stp_remote_device_ready_substate_start_request_handler,
+		.parent.complete_task_handler	= scic_sds_stp_remote_device_complete_request,
+		.suspend_handler		= scic_sds_remote_device_default_suspend_handler,
+		.resume_handler			= scic_sds_remote_device_default_resume_handler,
+		.event_handler			= scic_sds_remote_device_general_event_handler,
+		.frame_handler			= scic_sds_remote_device_general_frame_handler
+	}
+};
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
+ * ***************************************************************************** */
+
+static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
+	void *user_cookie)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)user_cookie;
+
+	/*
+	 * For NCQ operation we do not issue a
+	 * scic_cb_remote_device_not_ready().  As a result, avoid sending
+	 * the ready notification. */
+	if (this_device->ready_substate_machine.previous_state_id
+	    != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) {
+		isci_event_remote_device_ready(
+			scic_sds_remote_device_get_controller(this_device), this_device
+			);
+	}
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY IDLE SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+static void scic_sds_stp_remote_device_ready_idle_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+		);
+
+	this_device->working_request = NULL;
+
+	if (scic_sds_remote_node_context_is_ready(this_device->rnc)) {
+		/*
+		 * Since the RNC is ready, it's alright to finish completion
+		 * processing (e.g. signal the remote device is ready). */
+		scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
+			this_device
+			);
+	} else {
+		scic_sds_remote_node_context_resume(
+			this_device->rnc,
+			scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
+			this_device
+			);
+	}
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY CMD SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+static void scic_sds_stp_remote_device_ready_cmd_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	BUG_ON(this_device->working_request == NULL);
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+		);
+
+	isci_event_remote_device_not_ready(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device,
+		SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED
+		);
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY NCQ SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+static void scic_sds_stp_remote_device_ready_ncq_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
+		);
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY NCQ ERROR SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ *
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+		);
+
+	if (this_device->not_ready_reason ==
+	    SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) {
+		isci_event_remote_device_not_ready(
+			scic_sds_remote_device_get_controller(this_device),
+			this_device,
+			this_device->not_ready_reason
+			);
+	}
+}
+
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ * The enter routine to READY AWAIT RESET substate.
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
+		);
+}
+
+#if !defined(DISABLE_ATAPI)
+/*
+ * *****************************************************************************
+ * *  STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE
+ * ***************************************************************************** */
+
+/**
+ * The enter routine to READY ATAPI ERROR substate.
+ * @device: This is the SCI base object which is cast into a
+ *    struct scic_sds_remote_device object.
+ *
+ */
+void scic_sds_stp_remote_device_ready_atapi_error_substate_enter(
+	struct sci_base_object *device)
+{
+	struct scic_sds_remote_device *this_device;
+
+	this_device = (struct scic_sds_remote_device *)device;
+
+	SET_STATE_HANDLER(
+		this_device,
+		scic_sds_stp_remote_device_ready_substate_handler_table,
+		SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+		);
+}
+#endif /* !defined(DISABLE_ATAPI) */
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = {
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
+		.enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
+		.enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
+		.enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter,
+	},
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
+		.enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
+	},
+#if !defined(DISABLE_ATAPI)
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = {
+		.enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter,
+	},
+#endif
+	[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
+		.enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter,
+	},
+};


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 05/10] isci/core: remote node context
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (3 preceding siblings ...)
  2011-03-10 10:54 ` [RFC PATCH 04/10] isci/core: remote device Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 06/10] isci/core: stp Dan Williams
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

A remote node context is a descriptor that represents an end device.  An
SSP device consumes 1 descriptor while an STP target consumes 3.  There
are 256 remote node context descriptor that can be active at any given
point in time.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 .../scsi/isci/core/scic_sds_remote_node_context.c  | 1247 ++++++++++++++++++++
 .../scsi/isci/core/scic_sds_remote_node_context.h  |  323 +++++
 .../scsi/isci/core/scic_sds_remote_node_table.c    |  600 ++++++++++
 .../scsi/isci/core/scic_sds_remote_node_table.h    |  195 +++
 drivers/scsi/isci/core/scu_remote_node_context.h   |  229 ++++
 5 files changed, 2594 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.h
 create mode 100644 drivers/scsi/isci/core/scu_remote_node_context.h

diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c
new file mode 100644
index 0000000..253b2d8
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c
@@ -0,0 +1,1247 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "sci_base_state_machine.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_remote_node_context.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_event_codes.h"
+#include "scu_task_context.h"
+
+void scic_sds_remote_node_context_construct(
+	struct scic_sds_remote_device *device,
+	struct scic_sds_remote_node_context *rnc,
+	u16 remote_node_index)
+{
+	memset(rnc, 0, sizeof(struct scic_sds_remote_node_context));
+
+	rnc->remote_node_index = remote_node_index;
+	rnc->device            = device;
+	rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+	sci_base_state_machine_construct(
+		&rnc->state_machine,
+		&rnc->parent,
+		scic_sds_remote_node_context_state_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+		);
+
+	sci_base_state_machine_start(&rnc->state_machine);
+}
+
+/**
+ *
+ * @this_rnc: The RNC for which the is posted request is being made.
+ *
+ * This method will return true if the RNC is not in the initial state.  In all
+ * other states the RNC is considered active and this will return true. The
+ * destroy request of the state machine drives the RNC back to the initial
+ * state.  If the state machine changes then this routine will also have to be
+ * changed. bool true if the state machine is not in the initial state false if
+ * the state machine is in the initial state
+ */
+
+/**
+ *
+ * @this_rnc: The state of the remote node context object to check.
+ *
+ * This method will return true if the remote node context is in a READY state
+ * otherwise it will return false bool true if the remote node context is in
+ * the ready state. false if the remote node context is not in the ready state.
+ */
+bool scic_sds_remote_node_context_is_ready(
+	struct scic_sds_remote_node_context *this_rnc)
+{
+	u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
+
+	if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) {
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ *
+ * @this_device: The remote device to use to construct the RNC buffer.
+ * @rnc: The buffer into which the remote device data will be copied.
+ *
+ * This method will construct the RNC buffer for this remote device object. none
+ */
+void scic_sds_remote_node_context_construct_buffer(
+	struct scic_sds_remote_node_context *this_rnc)
+{
+	union scu_remote_node_context *rnc;
+	struct scic_sds_controller *the_controller;
+
+	the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
+
+	rnc = scic_sds_controller_get_remote_node_context_buffer(
+		the_controller, this_rnc->remote_node_index);
+
+	memset(
+		rnc,
+		0x00,
+		sizeof(union scu_remote_node_context)
+		* scic_sds_remote_device_node_count(this_rnc->device)
+		);
+
+	rnc->ssp.remote_node_index = this_rnc->remote_node_index;
+	rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
+	rnc->ssp.logical_port_index =
+		scic_sds_remote_device_get_port_index(this_rnc->device);
+
+	rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
+	rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
+
+	rnc->ssp.nexus_loss_timer_enable = true;
+	rnc->ssp.check_bit               = false;
+	rnc->ssp.is_valid                = false;
+	rnc->ssp.is_remote_node_context  = true;
+	rnc->ssp.function_number         = 0;
+
+	rnc->ssp.arbitration_wait_time = 0;
+
+
+	if (
+		this_rnc->device->target_protocols.u.bits.attached_sata_device
+		|| this_rnc->device->target_protocols.u.bits.attached_stp_target
+		) {
+		rnc->ssp.connection_occupancy_timeout =
+			the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
+		rnc->ssp.connection_inactivity_timeout =
+			the_controller->user_parameters.sds1.stp_inactivity_timeout;
+	} else {
+		rnc->ssp.connection_occupancy_timeout  =
+			the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
+		rnc->ssp.connection_inactivity_timeout =
+			the_controller->user_parameters.sds1.ssp_inactivity_timeout;
+	}
+
+	rnc->ssp.initial_arbitration_wait_time = 0;
+
+	/* Open Address Frame Parameters */
+	rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
+	rnc->ssp.oaf_features = 0;
+	rnc->ssp.oaf_source_zone_group = 0;
+	rnc->ssp.oaf_more_compatibility_features = 0;
+}
+
+/**
+ *
+ * @this_rnc:
+ * @the_callback:
+ * @callback_parameter:
+ *
+ * This method will setup the remote node context object so it will transition
+ * to its ready state.  If the remote node context is already setup to
+ * transition to its final state then this function does nothing. none
+ */
+static void scic_sds_remote_node_context_setup_to_resume(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
+		this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
+		this_rnc->user_callback     = the_callback;
+		this_rnc->user_cookie       = callback_parameter;
+	}
+}
+
+/**
+ *
+ * @this_rnc:
+ * @the_callback:
+ * @callback_parameter:
+ *
+ * This method will setup the remote node context object so it will transistion
+ * to its final state. none
+ */
+static void scic_sds_remote_node_context_setup_to_destory(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
+	this_rnc->user_callback     = the_callback;
+	this_rnc->user_cookie       = callback_parameter;
+}
+
+/**
+ *
+ * @this_rnc:
+ * @the_callback:
+ *
+ * This method will continue to resume a remote node context.  This is used in
+ * the states where a resume is requested while a resume is in progress.
+ */
+static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
+		this_rnc->user_callback = the_callback;
+		this_rnc->user_cookie   = callback_parameter;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_default_destruct_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to stop while "
+		 "in unexpected state %d\n",
+		 __func__,
+		 this_rnc,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	/*
+	 * We have decided that the destruct request on the remote node context can not fail
+	 * since it is either in the initial/destroyed state or is can be destroyed. */
+	return SCI_SUCCESS;
+}
+
+static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 suspend_type,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to suspend "
+		 "while in wrong state %d\n",
+		 __func__,
+		 this_rnc,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+static enum sci_status scic_sds_remote_node_context_default_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to resume "
+		 "while in wrong state %d\n",
+		 __func__,
+		 this_rnc,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+static enum sci_status scic_sds_remote_node_context_default_start_io_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to start io "
+		 "0x%p while in wrong state %d\n",
+		 __func__,
+		 this_rnc,
+		 the_request,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
+}
+
+static enum sci_status scic_sds_remote_node_context_default_start_task_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to start "
+		 "task 0x%p while in wrong state %d\n",
+		 __func__,
+		 this_rnc,
+		 the_request,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	return SCI_FAILURE;
+}
+
+static enum sci_status scic_sds_remote_node_context_default_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	dev_warn(scirdev_to_dev(this_rnc->device),
+		 "%s: SCIC Remote Node Context 0x%p requested to process "
+		 "event 0x%x while in wrong state %d\n",
+		 __func__,
+		 this_rnc,
+		 event_code,
+		 sci_base_state_machine_get_state(&this_rnc->state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ *
+ * @this_rnc: The rnc for which the task request is targeted.
+ * @the_request: The request which is going to be started.
+ *
+ * This method determines if the task request can be started by the SCU
+ * hardware. When the RNC is in the ready state any task can be started.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_node_context_success_start_task_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_rnc:
+ * @the_callback:
+ * @callback_parameter:
+ *
+ * This method handles destruct calls from the various state handlers.  The
+ * remote node context can be requested to destroy from any state. If there was
+ * a user callback it is always replaced with the request to destroy user
+ * callback. enum sci_status
+ */
+static enum sci_status scic_sds_remote_node_context_general_destruct_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	scic_sds_remote_node_context_setup_to_destory(
+		this_rnc, the_callback, callback_parameter
+		);
+
+	sci_base_state_machine_change_state(
+		&this_rnc->state_machine,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+		scic_sds_remote_node_context_setup_to_resume(
+			this_rnc, the_callback, callback_parameter
+			);
+
+		scic_sds_remote_node_context_construct_buffer(this_rnc);
+
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+			);
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_posting_state_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	switch (scu_get_event_code(event_code)) {
+	case SCU_EVENT_POST_RNC_COMPLETE:
+		status = SCI_SUCCESS;
+
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+			);
+		break;
+
+	default:
+		status = SCI_FAILURE;
+		dev_warn(scirdev_to_dev(this_rnc->device),
+			 "%s: SCIC Remote Node Context 0x%p requested to "
+			 "process unexpected event 0x%x while in posting "
+			 "state\n",
+			 __func__,
+			 this_rnc,
+			 event_code);
+		break;
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	scic_sds_remote_node_context_setup_to_destory(
+		this_rnc, the_callback, callback_parameter
+		);
+
+	return SCI_SUCCESS;
+}
+
+static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
+		status = SCI_SUCCESS;
+
+		if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
+			sci_base_state_machine_change_state(
+				&this_rnc->state_machine,
+				SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+				);
+		} else {
+			sci_base_state_machine_change_state(
+				&this_rnc->state_machine,
+				SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+				);
+		}
+	} else {
+		switch (scu_get_event_type(event_code)) {
+		case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+		case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+			/*
+			 * We really dont care if the hardware is going to suspend
+			 * the device since it's being invalidated anyway */
+			dev_dbg(scirdev_to_dev(this_rnc->device),
+				"%s: SCIC Remote Node Context 0x%p was "
+				"suspeneded by hardware while being "
+				"invalidated.\n",
+				__func__,
+				this_rnc);
+			status = SCI_SUCCESS;
+			break;
+
+		default:
+			dev_warn(scirdev_to_dev(this_rnc->device),
+				 "%s: SCIC Remote Node Context 0x%p "
+				 "requested to process event 0x%x while "
+				 "in state %d.\n",
+				 __func__,
+				 this_rnc,
+				 event_code,
+				 sci_base_state_machine_get_state(
+					 &this_rnc->state_machine));
+			status = SCI_FAILURE;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+
+static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
+		status = SCI_SUCCESS;
+
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+			);
+	} else {
+		switch (scu_get_event_type(event_code)) {
+		case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+		case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+			/*
+			 * We really dont care if the hardware is going to suspend
+			 * the device since it's being resumed anyway */
+			dev_dbg(scirdev_to_dev(this_rnc->device),
+				"%s: SCIC Remote Node Context 0x%p was "
+				"suspeneded by hardware while being resumed.\n",
+				__func__,
+				this_rnc);
+			status = SCI_SUCCESS;
+			break;
+
+		default:
+			dev_warn(scirdev_to_dev(this_rnc->device),
+				 "%s: SCIC Remote Node Context 0x%p requested "
+				 "to process event 0x%x while in state %d.\n",
+				 __func__,
+				 this_rnc,
+				 event_code,
+				 sci_base_state_machine_get_state(
+					 &this_rnc->state_machine));
+			status = SCI_FAILURE;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ *
+ * @this_rnc: The remote node context object being suspended.
+ * @the_callback: The callback when the suspension is complete.
+ * @callback_parameter: The parameter that is to be passed into the callback.
+ *
+ * This method will handle the suspend requests from the ready state.
+ * SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 suspend_type,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	this_rnc->user_callback   = the_callback;
+	this_rnc->user_cookie     = callback_parameter;
+	this_rnc->suspension_code = suspend_type;
+
+	if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
+		scic_sds_remote_device_post_request(
+			this_rnc->device,
+			SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
+			);
+	}
+
+	sci_base_state_machine_change_state(
+		&this_rnc->state_machine,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_rnc: The rnc for which the io request is targeted.
+ * @the_request: The request which is going to be started.
+ *
+ * This method determines if the io request can be started by the SCU hardware.
+ * When the RNC is in the ready state any io request can be started. enum sci_status
+ * SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	return SCI_SUCCESS;
+}
+
+
+static enum sci_status scic_sds_remote_node_context_ready_state_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	switch (scu_get_event_type(event_code)) {
+	case SCU_EVENT_TL_RNC_SUSPEND_TX:
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+			);
+
+		this_rnc->suspension_code = scu_get_event_specifier(event_code);
+		status = SCI_SUCCESS;
+		break;
+
+	case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+			);
+
+		this_rnc->suspension_code = scu_get_event_specifier(event_code);
+		status = SCI_SUCCESS;
+		break;
+
+	default:
+		dev_warn(scirdev_to_dev(this_rnc->device),
+			"%s: SCIC Remote Node Context 0x%p requested to "
+			"process event 0x%x while in state %d.\n",
+			__func__,
+			this_rnc,
+			event_code,
+			sci_base_state_machine_get_state(
+				&this_rnc->state_machine));
+
+		status = SCI_FAILURE;
+		break;
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	enum sci_status status;
+	struct smp_discover_response_protocols protocols;
+
+	scic_sds_remote_node_context_setup_to_resume(
+		this_rnc, the_callback, callback_parameter
+		);
+
+	/* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
+
+	scic_remote_device_get_protocols(this_rnc->device, &protocols);
+
+	if (
+		(protocols.u.bits.attached_ssp_target == 1)
+		|| (protocols.u.bits.attached_smp_target == 1)
+		) {
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+			);
+
+		status = SCI_SUCCESS;
+	} else if (protocols.u.bits.attached_stp_target == 1) {
+		if (this_rnc->device->is_direct_attached) {
+			/* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
+			sci_base_state_machine_change_state(
+				&this_rnc->state_machine,
+				SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+				);
+		} else {
+			sci_base_state_machine_change_state(
+				&this_rnc->state_machine,
+				SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+				);
+		}
+
+		status = SCI_SUCCESS;
+	} else {
+		status = SCI_FAILURE;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_rnc: The remote node context which is to receive the task request.
+ * @the_request: The task request to be transmitted to to the remote target
+ *    device.
+ *
+ * This method will report a success or failure attempt to start a new task
+ * request to the hardware.  Since all task requests are sent on the high
+ * priority queue they can be sent when the RCN is in a TX suspend state.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
+
+	return SCI_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	scic_sds_remote_node_context_setup_to_resume(
+		this_rnc, the_callback, callback_parameter
+		);
+
+	sci_base_state_machine_change_state(
+		&this_rnc->state_machine,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+		);
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ *
+ *
+ *
+ */
+static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter)
+{
+	scic_sds_remote_node_context_setup_to_resume(
+		this_rnc, the_callback, callback_parameter
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_rnc: The remote node context which is to receive the task request.
+ * @the_request: The task request to be transmitted to to the remote target
+ *    device.
+ *
+ * This method will report a success or failure attempt to start a new task
+ * request to the hardware.  Since all task requests are sent on the high
+ * priority queue they can be sent when the RCN is in a TX suspend state.
+ * enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request)
+{
+	return SCI_SUCCESS;
+}
+
+static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	switch (scu_get_event_type(event_code)) {
+	case SCU_EVENT_TL_RNC_SUSPEND_TX:
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+			);
+
+		this_rnc->suspension_code = scu_get_event_specifier(event_code);
+		status = SCI_SUCCESS;
+		break;
+
+	case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
+		sci_base_state_machine_change_state(
+			&this_rnc->state_machine,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+			);
+
+		this_rnc->suspension_code = scu_get_event_specifier(event_code);
+		status = SCI_SUCCESS;
+		break;
+
+	default:
+		dev_warn(scirdev_to_dev(this_rnc->device),
+			 "%s: SCIC Remote Node Context 0x%p requested to "
+			 "process event 0x%x while in state %d.\n",
+			 __func__,
+			 this_rnc,
+			 event_code,
+			 sci_base_state_machine_get_state(
+				 &this_rnc->state_machine));
+
+		status = SCI_FAILURE;
+		break;
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_remote_node_context_handlers
+scic_sds_remote_node_context_state_handler_table[
+	SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
+{
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */
+	{
+		scic_sds_remote_node_context_default_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_initial_state_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_default_start_task_handler,
+		scic_sds_remote_node_context_default_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_continue_to_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_default_start_task_handler,
+		scic_sds_remote_node_context_posting_state_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */
+	{
+		scic_sds_remote_node_context_invalidating_state_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_continue_to_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_default_start_task_handler,
+		scic_sds_remote_node_context_invalidating_state_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_continue_to_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_success_start_task_handler,
+		scic_sds_remote_node_context_resuming_state_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_ready_state_suspend_handler,
+		scic_sds_remote_node_context_default_resume_handler,
+		scic_sds_remote_node_context_ready_state_start_io_handler,
+		scic_sds_remote_node_context_success_start_task_handler,
+		scic_sds_remote_node_context_ready_state_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_tx_suspended_state_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_suspended_start_task_handler,
+		scic_sds_remote_node_context_default_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_suspended_start_task_handler,
+		scic_sds_remote_node_context_default_event_handler
+	},
+	/* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */
+	{
+		scic_sds_remote_node_context_general_destruct_handler,
+		scic_sds_remote_node_context_default_suspend_handler,
+		scic_sds_remote_node_context_await_suspension_state_resume_handler,
+		scic_sds_remote_node_context_default_start_io_handler,
+		scic_sds_remote_node_context_await_suspension_state_start_task_handler,
+		scic_sds_remote_node_context_await_suspension_state_event_handler
+	}
+};
+
+/*
+ * *****************************************************************************
+ * * REMOTE NODE CONTEXT PRIVATE METHODS
+ * ***************************************************************************** */
+
+/**
+ *
+ *
+ * This method just calls the user callback function and then resets the
+ * callback.
+ */
+static void scic_sds_remote_node_context_notify_user(
+	struct scic_sds_remote_node_context *rnc)
+{
+	if (rnc->user_callback != NULL) {
+		(*rnc->user_callback)(rnc->user_cookie);
+
+		rnc->user_callback = NULL;
+		rnc->user_cookie = NULL;
+	}
+}
+
+/**
+ *
+ *
+ * This method will continue the remote node context state machine by
+ * requesting to resume the remote node context state machine from its current
+ * state.
+ */
+static void scic_sds_remote_node_context_continue_state_transitions(
+	struct scic_sds_remote_node_context *rnc)
+{
+	if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
+		rnc->state_handlers->resume_handler(
+			rnc, rnc->user_callback, rnc->user_cookie
+			);
+	}
+}
+
+/**
+ *
+ * @this_rnc: The remote node context object that is to be validated.
+ *
+ * This method will mark the rnc buffer as being valid and post the request to
+ * the hardware. none
+ */
+static void scic_sds_remote_node_context_validate_context_buffer(
+	struct scic_sds_remote_node_context *this_rnc)
+{
+	union scu_remote_node_context *rnc_buffer;
+
+	rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
+		scic_sds_remote_device_get_controller(this_rnc->device),
+		this_rnc->remote_node_index
+		);
+
+	rnc_buffer->ssp.is_valid = true;
+
+	if (
+		!this_rnc->device->is_direct_attached
+		&& this_rnc->device->target_protocols.u.bits.attached_stp_target
+		) {
+		scic_sds_remote_device_post_request(
+			this_rnc->device,
+			SCU_CONTEXT_COMMAND_POST_RNC_96
+			);
+	} else {
+		scic_sds_remote_device_post_request(
+			this_rnc->device,
+			SCU_CONTEXT_COMMAND_POST_RNC_32
+			);
+
+		if (this_rnc->device->is_direct_attached) {
+			scic_sds_port_setup_transports(
+				this_rnc->device->owning_port,
+				this_rnc->remote_node_index
+				);
+		}
+	}
+}
+
+/**
+ *
+ * @this_rnc: The remote node context object that is to be invalidated.
+ *
+ * This method will update the RNC buffer and post the invalidate request. none
+ */
+static void scic_sds_remote_node_context_invalidate_context_buffer(
+	struct scic_sds_remote_node_context *this_rnc)
+{
+	union scu_remote_node_context *rnc_buffer;
+
+	rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
+		scic_sds_remote_device_get_controller(this_rnc->device),
+		this_rnc->remote_node_index
+		);
+
+	rnc_buffer->ssp.is_valid = false;
+
+	scic_sds_remote_device_post_request(
+		this_rnc->device,
+		SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
+		);
+}
+
+/*
+ * *****************************************************************************
+ * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
+ * ***************************************************************************** */
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_initial_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+		);
+
+	/*
+	 * Check to see if we have gotten back to the initial state because someone
+	 * requested to destroy the remote node context object. */
+	if (
+		rnc->state_machine.previous_state_id
+		== SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+		) {
+		rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+		scic_sds_remote_node_context_notify_user(rnc);
+	}
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_posting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *this_rnc;
+
+	this_rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		this_rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+		);
+
+	scic_sds_remote_node_context_validate_context_buffer(this_rnc);
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_invalidating_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+		);
+
+	scic_sds_remote_node_context_invalidate_context_buffer(rnc);
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_resuming_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+	struct smp_discover_response_protocols protocols;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+		);
+
+	/*
+	 * For direct attached SATA devices we need to clear the TLCR
+	 * NCQ to TCi tag mapping on the phy and in cases where we
+	 * resume because of a target reset we also need to update
+	 * the STPTLDARNI register with the RNi of the device
+	 */
+	scic_remote_device_get_protocols(rnc->device, &protocols);
+
+	if ((protocols.u.bits.attached_stp_target == 1) &&
+	    (rnc->device->is_direct_attached)) {
+		scic_sds_port_setup_transports(
+			rnc->device->owning_port, rnc->remote_node_index);
+	}
+
+	scic_sds_remote_device_post_request(
+		rnc->device,
+		SCU_CONTEXT_COMMAND_POST_RNC_RESUME
+		);
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_ready_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+		);
+
+	rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+	if (rnc->user_callback != NULL) {
+		scic_sds_remote_node_context_notify_user(rnc);
+	}
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_tx_suspended_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+		);
+
+	scic_sds_remote_node_context_continue_state_transitions(rnc);
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+		);
+
+	scic_sds_remote_node_context_continue_state_transitions(rnc);
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_remote_node_context_await_suspension_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_remote_node_context *rnc;
+
+	rnc = (struct scic_sds_remote_node_context *)object;
+
+	SET_STATE_HANDLER(
+		rnc,
+		scic_sds_remote_node_context_state_handler_table,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_remote_node_context_state_table[] = {
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
+		.enter_state = scic_sds_remote_node_context_initial_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
+		.enter_state = scic_sds_remote_node_context_posting_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
+		.enter_state = scic_sds_remote_node_context_invalidating_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
+		.enter_state = scic_sds_remote_node_context_resuming_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
+		.enter_state = scic_sds_remote_node_context_ready_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
+		.enter_state = scic_sds_remote_node_context_tx_suspended_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
+		.enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter,
+	},
+	[SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
+		.enter_state = scic_sds_remote_node_context_await_suspension_state_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h
new file mode 100644
index 0000000..86c6d75
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
+#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
+
+/**
+ * This file contains the structures, constants, and prototypes associated with
+ *    the remote node context in the silicon.  It exists to model and manage
+ *    the remote node context in the silicon.
+ *
+ *
+ */
+
+#include "sci_base_state.h"
+#include "sci_base_state_machine.h"
+
+/**
+ *
+ *
+ * This constant represents an invalid remote device id, it is used to program
+ * the STPDARNI register so the driver knows when it has received a SIGNATURE
+ * FIS from the SCU.
+ */
+#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX    0x0FFF
+
+#define SCU_HARDWARE_SUSPENSION  (0)
+#define SCI_SOFTWARE_SUSPENSION  (1)
+
+struct scic_sds_request;
+struct scic_sds_remote_device;
+struct scic_sds_remote_node_context;
+
+typedef void (*scics_sds_remote_node_context_callback)(void *);
+
+typedef enum sci_status (*scic_sds_remote_node_context_operation)(
+	struct scic_sds_remote_node_context *this_rnc,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter
+	);
+
+typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 suspension_type,
+	scics_sds_remote_node_context_callback the_callback,
+	void *callback_parameter
+	);
+
+typedef enum sci_status (*scic_sds_remote_node_context_io_request)(
+	struct scic_sds_remote_node_context *this_rnc,
+	struct scic_sds_request *the_request
+	);
+
+typedef enum sci_status (*scic_sds_remote_node_context_event_handler)(
+	struct scic_sds_remote_node_context *this_rnc,
+	u32 event_code
+	);
+
+struct scic_sds_remote_node_context_handlers {
+	/**
+	 * This handle is invoked to stop the RNC.  The callback is invoked when after
+	 * the hardware notification that the RNC has been invalidated.
+	 */
+	scic_sds_remote_node_context_operation destruct_handler;
+
+	/**
+	 * This handler is invoked when there is a request to suspend  the RNC.  The
+	 * callback is invoked after the hardware notification that the remote node is
+	 * suspended.
+	 */
+	scic_sds_remote_node_context_suspend_operation suspend_handler;
+
+	/**
+	 * This handler is invoked when there is a request to resume the RNC.  The
+	 * callback is invoked when after the RNC has reached the ready state.
+	 */
+	scic_sds_remote_node_context_operation resume_handler;
+
+	/**
+	 * This handler is invoked when there is a request to start an io request
+	 * operation.
+	 */
+	scic_sds_remote_node_context_io_request start_io_handler;
+
+	/**
+	 * This handler is invoked when there is a request to start a task request
+	 * operation.
+	 */
+	scic_sds_remote_node_context_io_request start_task_handler;
+
+	/**
+	 * This handler is invoked where there is an RNC event that must be processed.
+	 */
+	scic_sds_remote_node_context_event_handler event_handler;
+
+};
+
+/**
+ * This is the enumeration of the remote node context states.
+ */
+enum scis_sds_remote_node_context_states {
+	/**
+	 * This state is the initial state for a remote node context.  On a resume
+	 * request the remote node context will transition to the posting state.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
+
+	/**
+	 * This is a transition state that posts the RNi to the hardware. Once the RNC
+	 * is posted the remote node context will be made ready.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
+
+	/**
+	 * This is a transition state that will post an RNC invalidate to the
+	 * hardware.  Once the invalidate is complete the remote node context will
+	 * transition to the posting state.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
+
+	/**
+	 * This is a transition state that will post an RNC resume to the hardare.
+	 * Once the event notification of resume complete is received the remote node
+	 * context will transition to the ready state.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
+
+	/**
+	 * This is the state that the remote node context must be in to accept io
+	 * request operations.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
+
+	/**
+	 * This is the state that the remote node context transitions to when it gets
+	 * a TX suspend notification from the hardware.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
+
+	/**
+	 * This is the state that the remote node context transitions to when it gets
+	 * a TX RX suspend notification from the hardware.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
+
+	/**
+	 * This state is a wait state for the remote node context that waits for a
+	 * suspend notification from the hardware.  This state is entered when either
+	 * there is a request to supend the remote node context or when there is a TC
+	 * completion where the remote node will be suspended by the hardware.
+	 */
+	SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
+
+	SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES
+
+};
+
+/**
+ *
+ *
+ * This enumeration is used to define the end destination state for the remote
+ * node context.
+ */
+enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE {
+	SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED,
+	SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY,
+	SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
+};
+
+/**
+ * struct scic_sds_remote_node_context - This structure contains the data
+ *    associated with the remote node context object.  The remote node context
+ *    (RNC) object models the the remote device information necessary to manage
+ *    the silicon RNC.
+ */
+struct scic_sds_remote_node_context {
+	/*
+	 * parent object
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This pointer simply points to the remote device object containing
+	 * this RNC.
+	 *
+	 * @todo Consider making the device pointer the associated object of the
+	 *       the parent object.
+	 */
+	struct scic_sds_remote_device *device;
+
+	/**
+	 * This field indicates the remote node index (RNI) associated with
+	 * this RNC.
+	 */
+	u16 remote_node_index;
+
+	/**
+	 * This field is the recored suspension code or the reason for the remote node
+	 * context suspension.
+	 */
+	u32 suspension_code;
+
+	/**
+	 * This field is true if the remote node context is resuming from its current
+	 * state.  This can cause an automatic resume on receiving a suspension
+	 * notification.
+	 */
+	enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state;
+
+	/**
+	 * This field contains the callback function that the user requested to be
+	 * called when the requested state transition is complete.
+	 */
+	scics_sds_remote_node_context_callback user_callback;
+
+	/**
+	 * This field contains the parameter that is called when the user requested
+	 * state transition is completed.
+	 */
+	void *user_cookie;
+
+	/**
+	 * This field contains the data for the object's state machine.
+	 */
+	struct sci_base_state_machine state_machine;
+
+	struct scic_sds_remote_node_context_handlers *state_handlers;
+};
+
+extern const struct sci_base_state scic_sds_remote_node_context_state_table[];
+
+extern struct scic_sds_remote_node_context_handlers
+	scic_sds_remote_node_context_state_handler_table[
+	SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES];
+
+void scic_sds_remote_node_context_construct(
+	struct scic_sds_remote_device *device,
+	struct scic_sds_remote_node_context *rnc,
+	u16 remote_node_index);
+
+void scic_sds_remote_node_context_construct_buffer(
+	struct scic_sds_remote_node_context *rnc);
+
+bool scic_sds_remote_node_context_is_ready(
+	struct scic_sds_remote_node_context *this_rnc);
+
+#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \
+	((rnc)->remote_node_index = (rni))
+
+#define scic_sds_remote_node_context_get_remote_node_index(rcn)	\
+	((rnc)->remote_node_index)
+
+#define scic_sds_remote_node_context_event_handler(rnc, event_code) \
+	((rnc)->state_handlers->event_handler(rnc, event_code))
+
+#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \
+	((rnc)->state_handlers->resume_handler(rnc, callback, parameter))
+
+#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \
+	((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter))
+
+#define scic_sds_remote_node_context_destruct(rnc, callback, parameter)	\
+	((rnc)->state_handlers->destruct_handler(rnc, callback, parameter))
+
+#define scic_sds_remote_node_context_start_io(rnc, request) \
+	((rnc)->state_handlers->start_io_handler(rnc, request))
+
+#define scic_sds_remote_node_context_start_task(rnc, task) \
+	((rnc)->state_handlers->start_task_handler(rnc, task))
+
+#endif  /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.c b/drivers/scsi/isci/core/scic_sds_remote_node_table.c
new file mode 100644
index 0000000..77919a2
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.c
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE
+ *    public, protected, and private methods.
+ *
+ *
+ */
+#include "sci_util.h"
+#include "sci_environment.h"
+#include "scic_sds_remote_node_table.h"
+#include "scic_sds_remote_node_context.h"
+
+/**
+ *
+ * @remote_node_table: This is the remote node index table from which the
+ *    selection will be made.
+ * @group_table_index: This is the index to the group table from which to
+ *    search for an available selection.
+ *
+ * This routine will find the bit position in absolute bit terms of the next 32
+ * + bit position.  If there are available bits in the first u32 then it is
+ * just bit position. u32 This is the absolute bit position for an available
+ * group.
+ */
+static u32 scic_sds_remote_node_table_get_group_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_table_index)
+{
+	u32 dword_index;
+	u32 *group_table;
+	u32 bit_index;
+
+	group_table = remote_node_table->remote_node_groups[group_table_index];
+
+	for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) {
+		if (group_table[dword_index] != 0) {
+			for (bit_index = 0; bit_index < 32; bit_index++) {
+				if ((group_table[dword_index] & (1 << bit_index)) != 0) {
+					return (dword_index * 32) + bit_index;
+				}
+			}
+		}
+	}
+
+	return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
+}
+
+/**
+ *
+ * @out]: remote_node_table This the remote node table in which to clear the
+ *    selector.
+ * @set_index: This is the remote node selector in which the change will be
+ *    made.
+ * @group_index: This is the bit index in the table to be modified.
+ *
+ * This method will clear the group index entry in the specified group index
+ * table. none
+ */
+static void scic_sds_remote_node_table_clear_group_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_table_index,
+	u32 group_index)
+{
+	u32 dword_index;
+	u32 bit_index;
+	u32 *group_table;
+
+	BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
+	BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
+
+	dword_index = group_index / 32;
+	bit_index   = group_index % 32;
+	group_table = remote_node_table->remote_node_groups[group_table_index];
+
+	group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
+}
+
+/**
+ *
+ * @out]: remote_node_table This the remote node table in which to set the
+ *    selector.
+ * @group_table_index: This is the remote node selector in which the change
+ *    will be made.
+ * @group_index: This is the bit position in the table to be modified.
+ *
+ * This method will set the group index bit entry in the specified gropu index
+ * table. none
+ */
+static void scic_sds_remote_node_table_set_group_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_table_index,
+	u32 group_index)
+{
+	u32 dword_index;
+	u32 bit_index;
+	u32 *group_table;
+
+	BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
+	BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
+
+	dword_index = group_index / 32;
+	bit_index   = group_index % 32;
+	group_table = remote_node_table->remote_node_groups[group_table_index];
+
+	group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
+}
+
+/**
+ *
+ * @out]: remote_node_table This is the remote node table in which to modify
+ *    the remote node availability.
+ * @remote_node_index: This is the remote node index that is being returned to
+ *    the table.
+ *
+ * This method will set the remote to available in the remote node allocation
+ * table. none
+ */
+static void scic_sds_remote_node_table_set_node_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_index)
+{
+	u32 dword_location;
+	u32 dword_remainder;
+	u32 slot_normalized;
+	u32 slot_position;
+
+	BUG_ON(
+		(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+		<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
+		);
+
+	dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
+	dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
+	slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
+	slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
+
+	remote_node_table->available_remote_nodes[dword_location] |=
+		1 << (slot_normalized + slot_position);
+}
+
+/**
+ *
+ * @out]: remote_node_table This is the remote node table from which to clear
+ *    the available remote node bit.
+ * @remote_node_index: This is the remote node index which is to be cleared
+ *    from the table.
+ *
+ * This method clears the remote node index from the table of available remote
+ * nodes. none
+ */
+static void scic_sds_remote_node_table_clear_node_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_index)
+{
+	u32 dword_location;
+	u32 dword_remainder;
+	u32 slot_position;
+	u32 slot_normalized;
+
+	BUG_ON(
+		(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+		<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
+		);
+
+	dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
+	dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
+	slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
+	slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
+
+	remote_node_table->available_remote_nodes[dword_location] &=
+		~(1 << (slot_normalized + slot_position));
+}
+
+/**
+ *
+ * @out]: remote_node_table The remote node table from which the slot will be
+ *    cleared.
+ * @group_index: The index for the slot that is to be cleared.
+ *
+ * This method clears the entire table slot at the specified slot index. none
+ */
+static void scic_sds_remote_node_table_clear_group(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_index)
+{
+	u32 dword_location;
+	u32 dword_remainder;
+	u32 dword_value;
+
+	BUG_ON(
+		(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+		<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
+		);
+
+	dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+	dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+	dword_value = remote_node_table->available_remote_nodes[dword_location];
+	dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+	remote_node_table->available_remote_nodes[dword_location] = dword_value;
+}
+
+/**
+ *
+ * @remote_node_table:
+ *
+ * THis method sets an entire remote node group in the remote node table.
+ */
+static void scic_sds_remote_node_table_set_group(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_index)
+{
+	u32 dword_location;
+	u32 dword_remainder;
+	u32 dword_value;
+
+	BUG_ON(
+		(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+		<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
+		);
+
+	dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+	dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+	dword_value = remote_node_table->available_remote_nodes[dword_location];
+	dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+	remote_node_table->available_remote_nodes[dword_location] = dword_value;
+}
+
+/**
+ *
+ * @remote_node_table: This is the remote node table that for which the group
+ *    value is to be returned.
+ * @group_index: This is the group index to use to find the group value.
+ *
+ * This method will return the group value for the specified group index. The
+ * bit values at the specified remote node group index.
+ */
+static u8 scic_sds_remote_node_table_get_group_value(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_index)
+{
+	u32 dword_location;
+	u32 dword_remainder;
+	u32 dword_value;
+
+	dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+	dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+	dword_value = remote_node_table->available_remote_nodes[dword_location];
+	dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+	dword_value = dword_value >> (dword_remainder * 4);
+
+	return (u8)dword_value;
+}
+
+/**
+ *
+ * @out]: remote_node_table The remote that which is to be initialized.
+ * @remote_node_entries: The number of entries to put in the table.
+ *
+ * This method will initialize the remote node table for use. none
+ */
+void scic_sds_remote_node_table_initialize(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_entries)
+{
+	u32 index;
+
+	/*
+	 * Initialize the raw data we could improve the speed by only initializing
+	 * those entries that we are actually going to be used */
+	memset(
+		remote_node_table->available_remote_nodes,
+		0x00,
+		sizeof(remote_node_table->available_remote_nodes)
+		);
+
+	memset(
+		remote_node_table->remote_node_groups,
+		0x00,
+		sizeof(remote_node_table->remote_node_groups)
+		);
+
+	/* Initialize the available remote node sets */
+	remote_node_table->available_nodes_array_size = (u16)
+							(remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+							+ ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
+
+
+	/* Initialize each full DWORD to a FULL SET of remote nodes */
+	for (index = 0; index < remote_node_entries; index++) {
+		scic_sds_remote_node_table_set_node_index(remote_node_table, index);
+	}
+
+	remote_node_table->group_array_size = (u16)
+					      (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
+					      + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
+
+	for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) {
+		/*
+		 * These are all guaranteed to be full slot values so fill them in the
+		 * available sets of 3 remote nodes */
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
+	}
+
+	/* Now fill in any remainders that we may find */
+	if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) {
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
+	} else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) {
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
+	}
+}
+
+/**
+ *
+ * @out]: remote_node_table The remote node table from which to allocate a
+ *    remote node.
+ * @table_index: The group index that is to be used for the search.
+ *
+ * This method will allocate a single RNi from the remote node table.  The
+ * table index will determine from which remote node group table to search.
+ * This search may fail and another group node table can be specified.  The
+ * function is designed to allow a serach of the available single remote node
+ * group up to the triple remote node group.  If an entry is found in the
+ * specified table the remote node is removed and the remote node groups are
+ * updated. The RNi value or an invalid remote node context if an RNi can not
+ * be found.
+ */
+static u16 scic_sds_remote_node_table_allocate_single_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_table_index)
+{
+	u8 index;
+	u8 group_value;
+	u32 group_index;
+	u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+	group_index = scic_sds_remote_node_table_get_group_index(
+		remote_node_table, group_table_index);
+
+	/* We could not find an available slot in the table selector 0 */
+	if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
+		group_value = scic_sds_remote_node_table_get_group_value(
+			remote_node_table, group_index);
+
+		for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) {
+			if (((1 << index) & group_value) != 0) {
+				/* We have selected a bit now clear it */
+				remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT
+							  + index);
+
+				scic_sds_remote_node_table_clear_group_index(
+					remote_node_table, group_table_index, group_index
+					);
+
+				scic_sds_remote_node_table_clear_node_index(
+					remote_node_table, remote_node_index
+					);
+
+				if (group_table_index > 0) {
+					scic_sds_remote_node_table_set_group_index(
+						remote_node_table, group_table_index - 1, group_index
+						);
+				}
+
+				break;
+			}
+		}
+	}
+
+	return remote_node_index;
+}
+
+/**
+ *
+ * @remote_node_table: This is the remote node table from which to allocate the
+ *    remote node entries.
+ * @group_table_index: THis is the group table index which must equal two (2)
+ *    for this operation.
+ *
+ * This method will allocate three consecutive remote node context entries. If
+ * there are no remaining triple entries the function will return a failure.
+ * The remote node index that represents three consecutive remote node entries
+ * or an invalid remote node context if none can be found.
+ */
+static u16 scic_sds_remote_node_table_allocate_triple_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u32 group_table_index)
+{
+	u32 group_index;
+	u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+	group_index = scic_sds_remote_node_table_get_group_index(
+		remote_node_table, group_table_index);
+
+	if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
+		remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT;
+
+		scic_sds_remote_node_table_clear_group_index(
+			remote_node_table, group_table_index, group_index
+			);
+
+		scic_sds_remote_node_table_clear_group(
+			remote_node_table, group_index
+			);
+	}
+
+	return remote_node_index;
+}
+
+/**
+ *
+ * @remote_node_table: This is the remote node table from which the remote node
+ *    allocation is to take place.
+ * @remote_node_count: This is ther remote node count which is one of
+ *    SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
+ *
+ * This method will allocate a remote node that mataches the remote node count
+ * specified by the caller.  Valid values for remote node count is
+ * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is
+ * the remote node index that is returned or an invalid remote node context.
+ */
+u16 scic_sds_remote_node_table_allocate_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_count)
+{
+	u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+	if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
+		remote_node_index =
+			scic_sds_remote_node_table_allocate_single_remote_node(
+				remote_node_table, 0);
+
+		if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+			remote_node_index =
+				scic_sds_remote_node_table_allocate_single_remote_node(
+					remote_node_table, 1);
+		}
+
+		if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+			remote_node_index =
+				scic_sds_remote_node_table_allocate_single_remote_node(
+					remote_node_table, 2);
+		}
+	} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
+		remote_node_index =
+			scic_sds_remote_node_table_allocate_triple_remote_node(
+				remote_node_table, 2);
+	}
+
+	return remote_node_index;
+}
+
+/**
+ *
+ * @remote_node_table:
+ *
+ * This method will free a single remote node index back to the remote node
+ * table.  This routine will update the remote node groups
+ */
+static void scic_sds_remote_node_table_release_single_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u16 remote_node_index)
+{
+	u32 group_index;
+	u8 group_value;
+
+	group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
+
+	group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
+
+	/*
+	 * Assert that we are not trying to add an entry to a slot that is already
+	 * full. */
+	BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
+
+	if (group_value == 0x00) {
+		/*
+		 * There are no entries in this slot so it must be added to the single
+		 * slot table. */
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
+	} else if ((group_value & (group_value - 1)) == 0) {
+		/*
+		 * There is only one entry in this slot so it must be moved from the
+		 * single slot table to the dual slot table */
+		scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
+	} else {
+		/*
+		 * There are two entries in the slot so it must be moved from the dual
+		 * slot table to the tripple slot table. */
+		scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
+		scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
+	}
+
+	scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
+}
+
+/**
+ *
+ * @remote_node_table: This is the remote node table to which the remote node
+ *    index is to be freed.
+ *
+ * This method will release a group of three consecutive remote nodes back to
+ * the free remote nodes.
+ */
+static void scic_sds_remote_node_table_release_triple_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u16 remote_node_index)
+{
+	u32 group_index;
+
+	group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
+
+	scic_sds_remote_node_table_set_group_index(
+		remote_node_table, 2, group_index
+		);
+
+	scic_sds_remote_node_table_set_group(remote_node_table, group_index);
+}
+
+/**
+ *
+ * @remote_node_table: The remote node table to which the remote node index is
+ *    to be freed.
+ * @remote_node_count: This is the count of consecutive remote nodes that are
+ *    to be freed.
+ *
+ * This method will release the remote node index back into the remote node
+ * table free pool.
+ */
+void scic_sds_remote_node_table_release_remote_node_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_count,
+	u16 remote_node_index)
+{
+	if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
+		scic_sds_remote_node_table_release_single_remote_node(
+			remote_node_table, remote_node_index);
+	} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
+		scic_sds_remote_node_table_release_triple_remote_node(
+			remote_node_table, remote_node_index);
+	}
+}
+
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.h b/drivers/scsi/isci/core/scic_sds_remote_node_table.h
new file mode 100644
index 0000000..9c02a6c
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_
+#define _SCIC_SDS_REMOTE_NODE_TABLE_H_
+
+/**
+ * This file contains the structures, constants and prototypes used for the
+ *    remote node table.
+ *
+ *
+ */
+
+#include "sci_controller_constants.h"
+
+/**
+ *
+ *
+ * Remote node sets are sets of remote node index in the remtoe node table The
+ * SCU hardware requires that STP remote node entries take three consecutive
+ * remote node index so the table is arranged in sets of three. The bits are
+ * used as 0111 0111 to make a byte and the bits define the set of three remote
+ * nodes to use as a sequence.
+ */
+#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2
+
+/**
+ *
+ *
+ * Since the remote node table is organized as DWORDS take the remote node sets
+ * in bytes and represent them in DWORDs. The lowest ordered bits are the ones
+ * used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111
+ * 0111 0111 0111 // if only a single WORD is in use in the DWORD.
+ */
+#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \
+	(sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
+/**
+ *
+ *
+ * This is a count of the numeber of remote nodes that can be represented in a
+ * byte
+ */
+#define SCIC_SDS_REMOTE_NODES_PER_BYTE	\
+	(SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
+
+/**
+ *
+ *
+ * This is a count of the number of remote nodes that can be represented in a
+ * DWROD
+ */
+#define SCIC_SDS_REMOTE_NODES_PER_DWORD	\
+	(sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE)
+
+/**
+ *
+ *
+ * This is the number of bits in a remote node group
+ */
+#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP   4
+
+#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX      (0xFFFFFFFF)
+#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE    (0x07)
+#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE   (0x00)
+
+/**
+ *
+ *
+ * Expander attached sata remote node count
+ */
+#define SCU_STP_REMOTE_NODE_COUNT        3
+
+/**
+ *
+ *
+ * Expander or direct attached ssp remote node count
+ */
+#define SCU_SSP_REMOTE_NODE_COUNT        1
+
+/**
+ *
+ *
+ * Direct attached STP remote node count
+ */
+#define SCU_SATA_REMOTE_NODE_COUNT       1
+
+/**
+ * struct scic_remote_node_table -
+ *
+ *
+ */
+struct scic_remote_node_table {
+	/**
+	 * This field contains the array size in dwords
+	 */
+	u16 available_nodes_array_size;
+
+	/**
+	 * This field contains the array size of the
+	 */
+	u16 group_array_size;
+
+	/**
+	 * This field is the array of available remote node entries in bits.
+	 * Because of the way STP remote node data is allocated on the SCU hardware
+	 * the remote nodes must occupy three consecutive remote node context
+	 * entries.  For ease of allocation and de-allocation we have broken the
+	 * sets of three into a single nibble.  When the STP RNi is allocated all
+	 * of the bits in the nibble are cleared.  This math results in a table size
+	 * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte.
+	 */
+	u32 available_remote_nodes[
+		(SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+		+ ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)];
+
+	/**
+	 * This field is the nibble selector for the above table.  There are three
+	 * possible selectors each for fast lookup when trying to find one, two or
+	 * three remote node entries.
+	 */
+	u32 remote_node_groups[
+		SCU_STP_REMOTE_NODE_COUNT][
+		(SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT))
+		+ ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)];
+
+};
+
+/* --------------------------------------------------------------------------- */
+
+void scic_sds_remote_node_table_initialize(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_entries);
+
+u16 scic_sds_remote_node_table_allocate_remote_node(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_count);
+
+void scic_sds_remote_node_table_release_remote_node_index(
+	struct scic_remote_node_table *remote_node_table,
+	u32 remote_node_count,
+	u16 remote_node_index);
+
+#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */
diff --git a/drivers/scsi/isci/core/scu_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h
new file mode 100644
index 0000000..33745ad
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_remote_node_context.h
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__
+#define __SCU_REMOTE_NODE_CONTEXT_HEADER__
+
+/**
+ * This file contains the structures and constatns used by the SCU hardware to
+ *    describe a remote node context.
+ *
+ *
+ */
+
+/**
+ * struct ssp_remote_node_context - This structure contains the SCU hardware
+ *    definition for an SSP remote node.
+ *
+ *
+ */
+struct ssp_remote_node_context {
+	/* WORD 0 */
+
+	/**
+	 * This field is the remote node index assigned for this remote node. All
+	 * remote nodes must have a unique remote node index. The value of the remote
+	 * node index can not exceed the maximum number of remote nodes reported in
+	 * the SCU device context capacity register.
+	 */
+	u32 remote_node_index:12;
+	u32 reserved0_1:4;
+
+	/**
+	 * This field tells the SCU hardware how many simultaneous connections that
+	 * this remote node will support.
+	 */
+	u32 remote_node_port_width:4;
+
+	/**
+	 * This field tells the SCU hardware which logical port to associate with this
+	 * remote node.
+	 */
+	u32 logical_port_index:3;
+	u32 reserved0_2:5;
+
+	/**
+	 * This field will enable the I_T nexus loss timer for this remote node.
+	 */
+	u32 nexus_loss_timer_enable:1;
+
+	/**
+	 * This field is the for driver debug only and is not used.
+	 */
+	u32 check_bit:1;
+
+	/**
+	 * This field must be set to true when the hardware DMAs the remote node
+	 * context to the hardware SRAM.  When the remote node is being invalidated
+	 * this field must be set to false.
+	 */
+	u32 is_valid:1;
+
+	/**
+	 * This field must be set to true.
+	 */
+	u32 is_remote_node_context:1;
+
+	/* WORD 1 - 2 */
+
+	/**
+	 * This is the low word of the remote device SAS Address
+	 */
+	u32 remote_sas_address_lo;
+
+	/**
+	 * This field is the high word of the remote device SAS Address
+	 */
+	u32 remote_sas_address_hi;
+
+	/* WORD 3 */
+	/**
+	 * This field reprensets the function number assigned to this remote device.
+	 * This value must match the virtual function number that is being used to
+	 * communicate to the device.
+	 */
+	u32 function_number:8;
+	u32 reserved3_1:8;
+
+	/**
+	 * This field provides the driver a way to cheat on the arbitration wait time
+	 * for this remote node.
+	 */
+	u32 arbitration_wait_time:16;
+
+	/* WORD 4 */
+	/**
+	 * This field tells the SCU hardware how long this device may occupy the
+	 * connection before it must be closed.
+	 */
+	u32 connection_occupancy_timeout:16;
+
+	/**
+	 * This field tells the SCU hardware how long to maintain a connection when
+	 * there are no frames being transmitted on the link.
+	 */
+	u32 connection_inactivity_timeout:16;
+
+	/* WORD  5 */
+	/**
+	 * This field allows the driver to cheat on the arbitration wait time for this
+	 * remote node.
+	 */
+	u32 initial_arbitration_wait_time:16;
+
+	/**
+	 * This field is tells the hardware what to program for the connection rate in
+	 * the open address frame.  See the SAS spec for valid values.
+	 */
+	u32 oaf_connection_rate:4;
+
+	/**
+	 * This field tells the SCU hardware what to program for the features in the
+	 * open address frame.  See the SAS spec for valid values.
+	 */
+	u32 oaf_features:4;
+
+	/**
+	 * This field tells the SCU hardware what to use for the source zone group in
+	 * the open address frame.  See the SAS spec for more details on zoning.
+	 */
+	u32 oaf_source_zone_group:8;
+
+	/* WORD 6 */
+	/**
+	 * This field tells the SCU hardware what to use as the more capibilities in
+	 * the open address frame. See the SAS Spec for details.
+	 */
+	u32 oaf_more_compatibility_features;
+
+	/* WORD 7 */
+	u32 reserved7;
+
+};
+
+/**
+ * struct stp_remote_node_context - This structure contains the SCU hardware
+ *    definition for a STP remote node.
+ *
+ * STP Targets are not yet supported so this definition is a placeholder until
+ * we do support them.
+ */
+struct stp_remote_node_context {
+	/**
+	 * Placeholder data for the STP remote node.
+	 */
+	u32 data[8];
+
+};
+
+/**
+ * This union combines the SAS and SATA remote node definitions.
+ *
+ * union scu_remote_node_context
+ */
+union scu_remote_node_context {
+	/**
+	 * SSP Remote Node
+	 */
+	struct ssp_remote_node_context ssp;
+
+	/**
+	 * STP Remote Node
+	 */
+	struct stp_remote_node_context stp;
+
+};
+
+#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 06/10] isci/core: stp
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (4 preceding siblings ...)
  2011-03-10 10:54 ` [RFC PATCH 05/10] isci/core: remote node context Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:54 ` [RFC PATCH 07/10] isci/core: request (general, ssp and smp) Dan Williams
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

stp request support and state machines.  pio and exceptions handled in
software, fpdma and udma handled in hardware.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 .../scsi/isci/core/scic_sds_stp_packet_request.c   |  834 +++++++++
 .../scsi/isci/core/scic_sds_stp_packet_request.h   |  153 ++
 drivers/scsi/isci/core/scic_sds_stp_pio_request.h  |  116 +
 drivers/scsi/isci/core/scic_sds_stp_request.c      | 1941 ++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_stp_request.h      |  221 ++
 5 files changed, 3265 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_pio_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.h

diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c
new file mode 100644
index 0000000..97dc9bf
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c
@@ -0,0 +1,834 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+#if !defined(DISABLE_ATAPI)
+
+#include "intel_ata.h"
+#include "intel_sas.h"
+#include "intel_sata.h"
+#include "intel_sat.h"
+#include "sati_translator_sequence.h"
+#include "sci_base_state.h"
+#include "scic_controller.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_stp_packet_request.h"
+#include "scic_user_callback.h"
+#include "sci_util.h"
+#include "scu_completion_codes.h"
+#include "scu_task_context.h"
+
+
+/**
+ * This method will fill in the SCU Task Context for a PACKET fis. And
+ *    construct the request STARTED sub-state machine for Packet Protocol IO.
+ * @this_request: This parameter specifies the stp packet request object being
+ *    constructed.
+ *
+ */
+enum sci_status scic_sds_stp_packet_request_construct(
+	struct scic_sds_request *this_request)
+{
+	struct sata_fis_reg_h2d *h2d_fis =
+		scic_stp_io_request_get_h2d_reg_address(
+			this_request
+			);
+
+	/*
+	 * Work around, we currently only support PACKET DMA protocol, so we
+	 * need to make change to Packet Fis features field. */
+	h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
+
+	scic_sds_stp_non_ncq_request_construct(this_request);
+
+	/* Build the Packet Fis task context structure */
+	scu_stp_raw_request_construct_task_context(
+		(struct scic_sds_stp_request *)this_request,
+		this_request->task_context_buffer
+		);
+
+	sci_base_state_machine_construct(
+		&this_request->started_substate_machine,
+		&this_request->parent.parent,
+		scic_sds_stp_packet_request_started_substate_table,
+		SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+/**
+ * This method will fill in the SCU Task Context for a Packet request command
+ *    phase in PACKET DMA DATA (IN/OUT) type. The following important settings
+ *    are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA.  This simply
+ *    indicates that a normal request type (i.e. non-raw frame) is being
+ *    utilized to perform task management. -# control_frame == 1.  This ensures
+ *    that the proper endianess is set so that the bytes are transmitted in the
+ *    right order for a smp request frame.
+ * @this_request: This parameter specifies the smp request object being
+ *    constructed.
+ * @task_context: The task_context to be reconstruct for packet request command
+ *    phase.
+ *
+ */
+void scu_stp_packet_request_command_phase_construct_task_context(
+	struct scic_sds_request *this_request,
+	struct scu_task_context *task_context)
+{
+	void *atapi_cdb;
+	u32 atapi_cdb_length;
+	struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request;
+
+	/*
+	 * reference: SSTL 1.13.4.2
+	 * task_type, sata_direction */
+	if (scic_cb_io_request_get_data_direction(this_request->user_request)
+	     == SCI_IO_REQUEST_DATA_OUT) {
+		task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
+		task_context->sata_direction = 0;
+	} else {  /* todo: for NO_DATA command, we need to send out raw frame. */
+		task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
+		task_context->sata_direction = 1;
+	}
+
+	/* sata header */
+	memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
+	task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+	/*
+	 * Copy in the command IU with CDB so that the commandIU address doesn't
+	 * change. */
+	memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
+
+	atapi_cdb =
+		scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
+
+	atapi_cdb_length =
+		scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
+
+	memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
+
+	atapi_cdb_length =
+		max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
+
+	task_context->ssp_command_iu_length =
+		((atapi_cdb_length % 4) == 0) ?
+		(atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
+
+	/* task phase is set to TX_CMD */
+	task_context->task_phase = 0x1;
+
+	/* retry counter */
+	task_context->stp_retry_count = 0;
+
+	if (scic_cb_request_is_initial_construction(this_request->user_request)) {
+		/* data transfer size. */
+		task_context->transfer_length_bytes =
+			scic_cb_io_request_get_transfer_length(this_request->user_request);
+
+		/* setup sgl */
+		scic_sds_request_build_sgl(this_request);
+	} else {
+		/* data transfer size, need to be 4 bytes aligned. */
+		task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
+
+		scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
+	}
+}
+
+/**
+ * This method will fill in the SCU Task Context for a DATA fis containing CDB
+ *    in Raw Frame type. The TC for previous Packet fis was already there, we
+ *    only need to change the H2D fis content.
+ * @this_request: This parameter specifies the smp request object being
+ *    constructed.
+ * @task_context: The task_context to be reconstruct for packet request command
+ *    phase.
+ *
+ */
+void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+	struct scic_sds_request *this_request,
+	struct scu_task_context *task_context)
+{
+	void *atapi_cdb =
+		scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
+
+	u32 atapi_cdb_length =
+		scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
+
+	memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
+	memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
+
+	memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
+	task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+	/*
+	 * Note the data send out has to be 4 bytes aligned. Or else out hardware will
+	 * patch non-zero bytes and cause the target device unhappy. */
+	task_context->transfer_length_bytes = 12;
+}
+
+
+/*
+ * *@brief This methods decode the D2H status FIS and retrieve the sense data,
+ *          then pass the sense data to user request.
+ *
+ ***@param[in] this_request The request receive D2H status FIS.
+ ***@param[in] status_fis The D2H status fis to be processed.
+ *
+ */
+enum sci_status scic_sds_stp_packet_request_process_status_fis(
+	struct scic_sds_request *this_request,
+	struct sata_fis_reg_d2h *status_fis)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	/* TODO: Process the error status fis, retrieve sense data. */
+	if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
+		status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+	return status;
+}
+
+/*
+ * *@brief This methods builds sgl for internal REQUEST SENSE stp packet
+ *          command using this request response buffer, only one sge is
+ *          needed.
+ *
+ ***@param[in] this_request The request receive request sense data.
+ *
+ */
+void scic_sds_stp_packet_internal_request_sense_build_sgl(
+	struct scic_sds_request *sds_request)
+{
+	void *sge;
+	struct scu_sgl_element_pair *scu_sgl_list   = NULL;
+	struct scu_task_context *task_context;
+	dma_addr_t dma_addr;
+
+	struct sci_ssp_response_iu *rsp_iu =
+		(struct sci_ssp_response_iu *)sds_request->response_buffer;
+
+	sge =  (void *)&rsp_iu->data[0];
+
+	task_context =
+		(struct scu_task_context *)sds_request->task_context_buffer;
+	scu_sgl_list = &task_context->sgl_pair_ab;
+
+	dma_addr = scic_io_request_get_dma_addr(sds_request, sge);
+
+	scu_sgl_list->A.address_upper = upper_32_bits(dma_addr);
+	scu_sgl_list->A.address_lower = lower_32_bits(dma_addr);
+	scu_sgl_list->A.length = task_context->transfer_length_bytes;
+	scu_sgl_list->A.address_modifier = 0;
+
+	SCU_SGL_ZERO(scu_sgl_list->B);
+}
+
+/**
+ * This method processes the completions transport layer (TL) status to
+ *    determine if the Packet FIS was sent successfully. If the Packet FIS was
+ *    sent successfully, then the state for the Packet request transits to
+ *    waiting for a PIO SETUP frame.
+ * @this_request: This parameter specifies the request for which the TC
+ *    completion was received.
+ * @completion_code: This parameter indicates the completion status information
+ *    for the TC.
+ *
+ * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
+ * this method always returns success.
+ */
+enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return status;
+}
+
+
+/**
+ * This method processes an unsolicited frame while the Packet request is
+ *    waiting for a PIO SETUP FIS.  It will release the unsolicited frame, and
+ *    transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+ *    state.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the pio setup frame was handled
+ * successfully or not. SCI_SUCCESS Currently this value is always returned and
+ * indicates successful processing of the TC response.
+ */
+enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+	struct scic_sds_stp_request *this_request;
+
+	this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP);
+
+		/*
+		 * Get from the frame buffer the PIO Setup Data, although we don't need
+		 * any info from this pio setup fis. */
+		scic_sds_unsolicited_frame_control_get_buffer(
+			&(this_request->parent.owning_controller->uf_control),
+			frame_index,
+			(void **)&frame_buffer
+			);
+
+		/*
+		 * Get the data from the PIO Setup
+		 * The SCU Hardware returns first word in the frame_header and the rest
+		 * of the data is in the frame buffer so we need to back up one dword */
+		this_request->type.packet.device_preferred_cdb_length =
+			(u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count;
+
+		/* Frame has been decoded return it to the controller */
+		scic_sds_controller_release_frame(
+			this_request->parent.owning_controller, frame_index
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.started_substate_machine,
+			SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+			);
+	} else
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC IO Request 0x%p could not get frame header "
+			"for frame index %d, status %x\n",
+			__func__, this_request, frame_index, status);
+
+	return status;
+}
+
+
+/**
+ * This method processes the completions transport layer (TL) status to
+ *    determine if the PACKET command data FIS was sent successfully. If
+ *    successfully, then the state for the packet request transits to COMPLETE
+ *    state. If not successfuly, the request transits to
+ *    COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
+ * @this_request: This parameter specifies the request for which the TC
+ *    completion was received.
+ * @completion_code: This parameter indicates the completion status information
+ *    for the TC.
+ *
+ * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
+ * this method always returns success.
+ */
+enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	enum sci_status status = SCI_SUCCESS;
+	u8 sat_packet_protocol =
+		scic_cb_request_get_sat_protocol(this_request->user_request);
+
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
+		     || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
+		     )
+			sci_base_state_machine_change_state(
+				&this_request->parent.state_machine,
+				SCI_BASE_REQUEST_STATE_COMPLETED
+				);
+		else
+			sci_base_state_machine_change_state(
+				&this_request->started_substate_machine,
+				SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+				);
+		break;
+
+	case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
+		if (scic_io_request_get_number_of_bytes_transferred(this_request) <
+		    scic_cb_io_request_get_transfer_length(this_request->user_request)) {
+			scic_sds_request_set_status(
+				this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
+				);
+
+			sci_base_state_machine_change_state(
+				&this_request->parent.state_machine,
+				SCI_BASE_REQUEST_STATE_COMPLETED
+				);
+
+			status = this_request->sci_status;
+		}
+		break;
+
+	case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
+		/* In this case, there is no UF coming after. compelte the IO now. */
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+
+		break;
+
+	default:
+		if (this_request->sci_status != SCI_SUCCESS) {  /* The io status was set already. This means an UF for the status
+								 * fis was received already.
+								 */
+
+			/*
+			 * A device suspension event is expected, we need to have the device
+			 * coming out of suspension, then complete the IO. */
+			sci_base_state_machine_change_state(
+				&this_request->started_substate_machine,
+				SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+				);
+
+			/* change the device state to ATAPI_ERROR. */
+			sci_base_state_machine_change_state(
+				&this_request->target_device->ready_substate_machine,
+				SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+				);
+
+			status = this_request->sci_status;
+		} else {  /* If receiving any non-sucess TC status, no UF received yet, then an UF for
+			   * the status fis is coming after.
+			   */
+			scic_sds_request_set_status(
+				this_request,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+
+			sci_base_state_machine_change_state(
+				&this_request->started_substate_machine,
+				SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+				);
+		}
+		break;
+	}
+
+	return status;
+}
+
+
+/**
+ * This method processes an unsolicited frame.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the UF frame was handled
+ * successfully or not. SCI_SUCCESS Currently this value is always returned and
+ * indicates successful processing of the TC response.
+ */
+enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+	struct scic_sds_stp_request *this_request;
+
+	this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H);
+
+		/*
+		 * Get from the frame buffer the PIO Setup Data, although we don't need
+		 * any info from this pio setup fis. */
+		scic_sds_unsolicited_frame_control_get_buffer(
+			&(this_request->parent.owning_controller->uf_control),
+			frame_index,
+			(void **)&frame_buffer
+			);
+
+		scic_sds_controller_copy_sata_response(
+			&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
+			);
+
+		/* Frame has been decoded return it to the controller */
+		scic_sds_controller_release_frame(
+			this_request->parent.owning_controller, frame_index
+			);
+	}
+
+	return status;
+}
+
+/**
+ * This method processes an unsolicited frame while the packet request is
+ *    expecting TC completion. It will process the FIS and construct sense data.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the UF frame was handled
+ * successfully or not. SCI_SUCCESS Currently this value is always returned and
+ * indicates successful processing of the TC response.
+ */
+enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	enum sci_status status =
+		scic_sds_stp_packet_request_command_phase_common_frame_handler(
+			request, frame_index);
+
+	if (status == SCI_SUCCESS) {
+		/* The command has completed with error status from target device. */
+		status = scic_sds_stp_packet_request_process_status_fis(
+			request, &this_request->d2h_reg_fis);
+
+		if (status != SCI_SUCCESS) {
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				status
+				);
+		} else
+			scic_sds_request_set_status(
+				&this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+				);
+	}
+
+	return status;
+}
+
+
+/**
+ * This method processes an unsolicited frame while the packet request is
+ *    expecting TC completion. It will process the FIS and construct sense data.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the UF frame was handled
+ * successfully or not. SCI_SUCCESS Currently this value is always returned and
+ * indicates successful processing of the TC response.
+ */
+enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status =
+		scic_sds_stp_packet_request_command_phase_common_frame_handler(
+			request, frame_index);
+
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	if (status == SCI_SUCCESS) {
+		/* The command has completed with error status from target device. */
+		status = scic_sds_stp_packet_request_process_status_fis(
+			request, &this_request->d2h_reg_fis);
+
+		if (status != SCI_SUCCESS) {
+			scic_sds_request_set_status(
+				request,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				status
+				);
+		} else
+			scic_sds_request_set_status(
+				request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+				);
+
+		/*
+		 * Always complete the NON_DATA command right away, no need to delay completion
+		 * even an error status fis came from target device. */
+		sci_base_state_machine_change_state(
+			&request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+	}
+
+	return status;
+}
+
+enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	return this_request->sci_status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = {
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler
+		.tc_completion_handler   = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler
+		.tc_completion_handler   = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler
+	},
+};
+
+void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_packet_request_started_substate_handler_table,
+		SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+		);
+
+	scic_sds_remote_device_set_working_request(
+		this_request->target_device, this_request
+		);
+}
+
+void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_packet_request_started_substate_handler_table,
+		SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
+		);
+}
+
+void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+	u8 sat_packet_protocol =
+		scic_cb_request_get_sat_protocol(this_request->user_request);
+
+	struct scu_task_context *task_context;
+	enum sci_status status;
+
+	/*
+	 * Recycle the TC and reconstruct it for sending out data fis containing
+	 * CDB. */
+	task_context = scic_sds_controller_get_task_context_buffer(
+		this_request->owning_controller, this_request->io_tag);
+
+	if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
+		scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+			this_request, task_context);
+	else
+		scu_stp_packet_request_command_phase_construct_task_context(
+			this_request, task_context);
+
+	/* send the new TC out. */
+	status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
+		&this_request->owning_controller->parent,
+		&this_request->target_device->parent,
+		&this_request->parent
+		);
+
+	if (status == SCI_SUCCESS)
+		SET_STATE_HANDLER(
+			this_request,
+			scic_sds_stp_packet_request_started_substate_handler_table,
+			SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+			);
+}
+
+void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_packet_request_started_substate_handler_table,
+		SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+		);
+}
+
+void scic_sds_stp_packet_request_started_completion_delay_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_packet_request_started_substate_handler_table,
+		SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+		);
+}
+
+
+/* --------------------------------------------------------------------------- */
+const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = {
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
+		.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
+		.enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
+	},
+	[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
+		.enter_state scic_sds_stp_packet_request_started_completion_delay_enter,
+	}
+};
+
+#endif /* !defined(DISABLE_ATAPI) */
diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h
new file mode 100644
index 0000000..2a7aec9
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_
+#define _SCIC_SDS_STP_PACKET_REQUEST_H_
+
+#include "intel_sas.h"
+#include "scic_sds_stp_request.h"
+
+/**
+ * This file contains the structures and constants for PACKET protocol requests.
+ *
+ *
+ */
+
+
+/**
+ *
+ *
+ * This is the enumeration of the SATA PIO DATA IN started substate machine.
+ */
+enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES {
+	/**
+	 * While in this state the IO request object is waiting for the TC completion
+	 * notification for the H2D Register FIS
+	 */
+	SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+
+	/**
+	 * While in this state the IO request object is waiting for either a PIO Setup.
+	 */
+	SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
+
+	/**
+	 * While in this state the IO request object is waiting for TC completion for
+	 * the Packet DMA DATA fis or Raw Frame.
+	 */
+	SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+
+	/**
+	 * The non-data IO transit to this state in this state after receiving TC
+	 * completion. While in this state IO request object is waiting for D2H status
+	 * frame as UF.
+	 */
+	SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
+
+	/**
+	 * The IO transit to this state in this state if the previous TC completion status
+	 * is not success and the atapi device is suspended due to target device failed the IO.
+	 * While in this state IO request object is waiting for device coming out of the
+	 * suspension state then complete the IO.
+	 */
+	SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
+};
+
+
+
+#if !defined(DISABLE_ATAPI)
+extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[];
+extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[];
+#endif /* !defined(DISABLE_ATAPI) */
+
+#if !defined(DISABLE_ATAPI)
+enum sci_status scic_sds_stp_packet_request_construct(
+	struct scic_sds_request *this_request);
+#else  /* !defined(DISABLE_ATAPI) */
+#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE
+#endif /* !defined(DISABLE_ATAPI) */
+
+#if !defined(DISABLE_ATAPI)
+void scu_stp_packet_request_command_phase_construct_task_context(
+	struct scic_sds_request *this_request,
+	struct scu_task_context *task_context);
+#else  /* !defined(DISABLE_ATAPI) */
+#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc)
+#endif /* !defined(DISABLE_ATAPI) */
+
+#if !defined(DISABLE_ATAPI)
+void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+	struct scic_sds_request *this_request,
+	struct scu_task_context *task_context);
+#else  /* !defined(DISABLE_ATAPI) */
+#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc)
+#endif /* !defined(DISABLE_ATAPI) */
+
+#if !defined(DISABLE_ATAPI)
+enum sci_status scic_sds_stp_packet_request_process_status_fis(
+	struct scic_sds_request *this_request,
+	struct sata_fis_reg_d2h *status_fis);
+#else  /* !defined(DISABLE_ATAPI) */
+#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE
+#endif /* !defined(DISABLE_ATAPI) */
+
+#if !defined(DISABLE_ATAPI)
+void scic_sds_stp_packet_internal_request_sense_build_sgl(
+	struct scic_sds_request *this_request);
+#else  /* !defined(DISABLE_ATAPI) */
+#define scic_sds_stp_packet_internal_request_sense_build_sgl(request)
+#endif /* !defined(DISABLE_ATAPI) */
+
+#endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h
new file mode 100644
index 0000000..64bf40a
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_
+#define _SCIC_SDS_SATA_PIO_REQUEST_H_
+
+#include "sci_base_state.h"
+#include "scic_sds_request.h"
+#include "scu_task_context.h"
+
+/**
+ * This file contains the structures and constants for SATA PIO requests.
+ *
+ *
+ */
+
+
+/**
+ *
+ *
+ * This is the enumeration of the SATA PIO DATA IN started substate machine.
+ */
+enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES {
+	/**
+	 * While in this state the IO request object is waiting for the TC completion
+	 * notification for the H2D Register FIS
+	 */
+	SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
+
+	/**
+	 * While in this state the IO request object is waiting for either a PIO Setup
+	 * FIS or a D2H register FIS.  The type of frame received is based on the
+	 * result of the prior frame and line conditions.
+	 */
+	SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
+
+	/**
+	 * While in this state the IO request object is waiting for a DATA frame from
+	 * the device.
+	 */
+	SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
+
+	/**
+	 * While in this state the IO request object is waiting to transmit the next data
+	 * frame to the device.
+	 */
+	SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
+};
+
+
+/* --------------------------------------------------------------------------- */
+
+extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[];
+
+extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[];
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_stp_request;
+
+struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(
+	struct scic_sds_stp_request *this_request);
+
+#endif   /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c
new file mode 100644
index 0000000..8da309f
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_request.c
@@ -0,0 +1,1941 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_ata.h"
+#include "intel_sata.h"
+#include "intel_sat.h"
+#include "sci_base_state.h"
+#include "sci_base_state_machine.h"
+#include "scic_io_request.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_stp_pio_request.h"
+#include "scic_sds_stp_request.h"
+#include "scic_sds_unsolicited_frame_control.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_completion_codes.h"
+#include "scu_event_codes.h"
+#include "scu_task_context.h"
+
+/**
+ * scic_sds_stp_request_get_h2d_reg_buffer() -
+ *
+ * This macro returns the address of the stp h2d reg fis buffer in the io
+ * request memory
+ */
+#define scic_sds_stp_request_get_h2d_reg_buffer(memory)	\
+	((struct sata_fis_reg_h2d *)(\
+		 ((char *)(memory)) + sizeof(struct scic_sds_stp_request) \
+		 ))
+
+/**
+ * scic_sds_stp_request_get_response_buffer() -
+ *
+ * This macro returns the address of the ssp response iu buffer in the io
+ * request memory
+ */
+#define scic_sds_stp_request_get_response_buffer(memory) \
+	((struct sata_fis_reg_d2h *)(\
+		 ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \
+		 + sizeof(struct sata_fis_reg_h2d) \
+		 ))
+
+/**
+ * scic_sds_stp_request_get_task_context_buffer() -
+ *
+ * This macro returns the address of the task context buffer in the io request
+ * memory
+ */
+#define scic_sds_stp_request_get_task_context_buffer(memory) \
+	((struct scu_task_context *)(\
+		 ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \
+		 + sizeof(struct sci_ssp_response_iu) \
+		 ))
+
+/**
+ * scic_sds_stp_request_get_sgl_element_buffer() -
+ *
+ * This macro returns the address of the sgl elment pairs in the io request
+ * memory buffer
+ */
+#define scic_sds_stp_request_get_sgl_element_buffer(memory) \
+	((struct scu_sgl_element_pair *)(\
+		 ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \
+		 + sizeof(struct scu_task_context) \
+		 ))
+
+/**
+ *
+ *
+ * This method return the memory space required for STP PIO requests. u32
+ */
+u32 scic_sds_stp_request_get_object_size(void)
+{
+	return sizeof(struct scic_sds_stp_request)
+	       + sizeof(struct sata_fis_reg_h2d)
+	       + sizeof(struct sata_fis_reg_d2h)
+	       + sizeof(struct scu_task_context)
+	       + SMP_CACHE_BYTES
+	       + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS;
+}
+
+void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req)
+{
+	struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent);
+
+	sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req);
+	sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req);
+	sci_req->sgl_element_pair_buffer = scic_sds_stp_request_get_sgl_element_buffer(stp_req);
+	sci_req->sgl_element_pair_buffer = PTR_ALIGN(sci_req->sgl_element_pair_buffer,
+						     sizeof(struct scu_sgl_element_pair));
+
+	if (sci_req->was_tag_assigned_by_user == false) {
+		sci_req->task_context_buffer =
+			scic_sds_stp_request_get_task_context_buffer(stp_req);
+		sci_req->task_context_buffer = PTR_ALIGN(sci_req->task_context_buffer,
+							 SMP_CACHE_BYTES);
+	}
+}
+
+/**
+ * This method is will fill in the SCU Task Context for any type of SATA
+ *    request.  This is called from the various SATA constructors.
+ * @this_request: The general IO request object which is to be used in
+ *    constructing the SCU task context.
+ * @task_context: The buffer pointer for the SCU task context which is being
+ *    constructed.
+ *
+ * The general io request construction is complete. The buffer assignment for
+ * the command buffer is complete. none Revisit task context construction to
+ * determine what is common for SSP/SMP/STP task context structures.
+ */
+static void scu_sata_reqeust_construct_task_context(
+	struct scic_sds_request *sds_request,
+	struct scu_task_context *task_context)
+{
+	dma_addr_t dma_addr;
+	struct scic_sds_controller *controller;
+	struct scic_sds_remote_device *target_device;
+	struct scic_sds_port *target_port;
+
+	controller = scic_sds_request_get_controller(sds_request);
+	target_device = scic_sds_request_get_device(sds_request);
+	target_port = scic_sds_request_get_port(sds_request);
+
+	/* Fill in the TC with the its required data */
+	task_context->abort = 0;
+	task_context->priority = SCU_TASK_PRIORITY_NORMAL;
+	task_context->initiator_request = 1;
+	task_context->connection_rate =
+		scic_remote_device_get_connection_rate(target_device);
+	task_context->protocol_engine_index =
+		scic_sds_controller_get_protocol_engine_group(controller);
+	task_context->logical_port_index =
+		scic_sds_port_get_index(target_port);
+	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP;
+	task_context->valid = SCU_TASK_CONTEXT_VALID;
+	task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+	task_context->remote_node_index =
+		scic_sds_remote_device_get_index(sds_request->target_device);
+	task_context->command_code = 0;
+
+	task_context->link_layer_control = 0;
+	task_context->do_not_dma_ssp_good_response = 1;
+	task_context->strict_ordering = 0;
+	task_context->control_frame = 0;
+	task_context->timeout_enable = 0;
+	task_context->block_guard_enable = 0;
+
+	task_context->address_modifier = 0;
+	task_context->task_phase = 0x01;
+
+	task_context->ssp_command_iu_length =
+		(sizeof(struct sata_fis_reg_h2d) - sizeof(u32)) / sizeof(u32);
+
+	/* Set the first word of the H2D REG FIS */
+	task_context->type.words[0] = *(u32 *)sds_request->command_buffer;
+
+	if (sds_request->was_tag_assigned_by_user) {
+		/*
+		 * Build the task context now since we have already read
+		 * the data
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
+			 scic_sds_io_tag_get_index(sds_request->io_tag));
+	} else {
+		/*
+		 * Build the task context now since we have already read
+		 * the data.
+		 * I/O tag index is not assigned because we have to wait
+		 * until we get a TCi.
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
+	}
+
+	/*
+	 * Copy the physical address for the command buffer to the SCU Task
+	 * Context. We must offset the command buffer by 4 bytes because the
+	 * first 4 bytes are transfered in the body of the TC.
+	 */
+	dma_addr =
+		scic_io_request_get_dma_addr(sds_request,
+						(char *)sds_request->
+							command_buffer +
+							sizeof(u32));
+
+	task_context->command_iu_upper = upper_32_bits(dma_addr);
+	task_context->command_iu_lower = lower_32_bits(dma_addr);
+
+	/* SATA Requests do not have a response buffer */
+	task_context->response_iu_upper = 0;
+	task_context->response_iu_lower = 0;
+}
+
+/**
+ *
+ * @this_request:
+ *
+ * This method will perform any general sata request construction. What part of
+ * SATA IO request construction is general? none
+ */
+void scic_sds_stp_non_ncq_request_construct(
+	struct scic_sds_request *this_request)
+{
+	this_request->has_started_substate_machine = true;
+}
+
+/**
+ *
+ * @sci_req: This parameter specifies the request to be constructed as an
+ *    optimized request.
+ * @optimized_task_type: This parameter specifies whether the request is to be
+ *    an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A
+ *    value of 1 indicates NCQ.
+ *
+ * This method will perform request construction common to all types of STP
+ * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method
+ * returns an indication as to whether the construction was successful.
+ */
+static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req,
+						     u8 optimized_task_type,
+						     u32 len,
+						     enum dma_data_direction dir)
+{
+	struct scu_task_context *task_context = sci_req->task_context_buffer;
+
+	/* Build the STP task context structure */
+	scu_sata_reqeust_construct_task_context(sci_req, task_context);
+
+	/* Copy over the SGL elements */
+	scic_sds_request_build_sgl(sci_req);
+
+	/* Copy over the number of bytes to be transfered */
+	task_context->transfer_length_bytes = len;
+
+	if (dir == DMA_TO_DEVICE) {
+		/*
+		 * The difference between the DMA IN and DMA OUT request task type
+		 * values are consistent with the difference between FPDMA READ
+		 * and FPDMA WRITE values.  Add the supplied task type parameter
+		 * to this difference to set the task type properly for this
+		 * DATA OUT (WRITE) case. */
+		task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT
+								 - SCU_TASK_TYPE_DMA_IN);
+	} else {
+		/*
+		 * For the DATA IN (READ) case, simply save the supplied
+		 * optimized task type. */
+		task_context->task_type = optimized_task_type;
+	}
+}
+
+/**
+ *
+ * @sci_req: This parameter specifies the request to be constructed.
+ *
+ * This method will construct the STP UDMA request and its associated TC data.
+ * This method returns an indication as to whether the construction was
+ * successful. SCI_SUCCESS Currently this method always returns this value.
+ */
+enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req,
+						    u32 len,
+						    enum dma_data_direction dir)
+{
+	scic_sds_stp_non_ncq_request_construct(sci_req);
+
+	scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN,
+						 len, dir);
+
+	sci_base_state_machine_construct(
+		&sci_req->started_substate_machine,
+		&sci_req->parent.parent,
+		scic_sds_stp_request_started_udma_substate_table,
+		SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @sci_req: This parameter specifies the request to be constructed.
+ *
+ * This method will construct the STP UDMA request and its associated TC data.
+ * This method returns an indication as to whether the construction was
+ * successful. SCI_SUCCESS Currently this method always returns this value.
+ */
+enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req,
+						   u32 len,
+						   enum dma_data_direction dir)
+{
+	scic_sds_stp_optimized_request_construct(sci_req,
+						 SCU_TASK_TYPE_FPDMAQ_READ,
+						 len, dir);
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_request: This parameter specifies the STP request object for which to
+ *    construct a RAW command frame task context.
+ * @task_context: This parameter specifies the SCU specific task context buffer
+ *    to construct.
+ *
+ * This method performs the operations common to all SATA/STP requests
+ * utilizing the raw frame method. none
+ */
+void scu_stp_raw_request_construct_task_context(
+	struct scic_sds_stp_request *this_request,
+	struct scu_task_context *task_context)
+{
+	scu_sata_reqeust_construct_task_context(&this_request->parent, task_context);
+
+	task_context->control_frame         = 0;
+	task_context->priority              = SCU_TASK_PRIORITY_NORMAL;
+	task_context->task_type             = SCU_TASK_TYPE_SATA_RAW_FRAME;
+	task_context->type.stp.fis_type     = SATA_FIS_TYPE_REGH2D;
+	task_context->transfer_length_bytes = sizeof(struct sata_fis_reg_h2d) - sizeof(u32);
+}
+
+/**
+ *
+ * @this_request: This parameter specifies the core request object to
+ *    construction into an STP/SATA non-data request.
+ *
+ * This method will construct the STP Non-data request and its associated TC
+ * data.  A non-data request essentially behaves like a 0 length read request
+ * in the SCU. This method currently always returns SCI_SUCCESS
+ */
+enum sci_status scic_sds_stp_non_data_request_construct(
+	struct scic_sds_request *this_request)
+{
+	scic_sds_stp_non_ncq_request_construct(this_request);
+
+	/* Build the STP task context structure */
+	scu_stp_raw_request_construct_task_context(
+		(struct scic_sds_stp_request *)this_request,
+		this_request->task_context_buffer
+		);
+
+	sci_base_state_machine_construct(
+		&this_request->started_substate_machine,
+		&this_request->parent.parent,
+		scic_sds_stp_request_started_non_data_substate_table,
+		SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+enum sci_status scic_sds_stp_soft_reset_request_construct(
+	struct scic_sds_request *this_request)
+{
+	scic_sds_stp_non_ncq_request_construct(this_request);
+
+	/* Build the STP task context structure */
+	scu_stp_raw_request_construct_task_context(
+		(struct scic_sds_stp_request *)this_request,
+		this_request->task_context_buffer
+		);
+
+	sci_base_state_machine_construct(
+		&this_request->started_substate_machine,
+		&this_request->parent.parent,
+		scic_sds_stp_request_started_soft_reset_substate_table,
+		SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+void scic_stp_io_request_set_ncq_tag(
+	struct scic_sds_request *req,
+	u16 ncq_tag)
+{
+	/**
+	 * @note This could be made to return an error to the user if the user
+	 *       attempts to set the NCQ tag in the wrong state.
+	 */
+	req->task_context_buffer->type.stp.ncq_tag = ncq_tag;
+}
+
+
+void *scic_stp_io_request_get_h2d_reg_address(
+	struct scic_sds_request *req)
+{
+	return req->command_buffer;
+}
+
+
+void *scic_stp_io_request_get_d2h_reg_address(
+	struct scic_sds_request *req)
+{
+	return &((struct scic_sds_stp_request *)req)->d2h_reg_fis;
+}
+
+/**
+ *
+ * @this_request:
+ *
+ * Get the next SGL element from the request. - Check on which SGL element pair
+ * we are working - if working on SLG pair element A - advance to element B -
+ * else - check to see if there are more SGL element pairs for this IO request
+ * - if there are more SGL element pairs - advance to the next pair and return
+ * element A struct scu_sgl_element*
+ */
+struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req)
+{
+	struct scu_sgl_element *current_sgl;
+	struct scic_sds_request *sci_req = &stp_req->parent;
+	struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current;
+
+	if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
+		if (pio_sgl->sgl_pair->B.address_lower == 0 &&
+		    pio_sgl->sgl_pair->B.address_upper == 0) {
+			current_sgl = NULL;
+		} else {
+			pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B;
+			current_sgl = &pio_sgl->sgl_pair->B;
+		}
+	} else {
+		if (pio_sgl->sgl_pair->next_pair_lower == 0 &&
+		    pio_sgl->sgl_pair->next_pair_upper == 0) {
+			current_sgl = NULL;
+		} else {
+			u64 phys_addr;
+
+			phys_addr = pio_sgl->sgl_pair->next_pair_upper;
+			phys_addr <<= 32;
+			phys_addr |= pio_sgl->sgl_pair->next_pair_lower;
+
+			pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr);
+			pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A;
+			current_sgl = &pio_sgl->sgl_pair->A;
+		}
+	}
+
+	return current_sgl;
+}
+
+/**
+ *
+ * @scic_io_request: The core request object which is cast to a SATA PIO
+ *    request object.
+ *
+ * This method will construct the SATA PIO request. This method returns an
+ * indication as to whether the construction was successful. SCI_SUCCESS
+ * Currently this method always returns this value.
+ */
+enum sci_status scic_sds_stp_pio_request_construct(
+	struct scic_sds_request *scic_io_request,
+	u8 sat_protocol,
+	bool copy_rx_frame)
+{
+	struct scic_sds_stp_request *this_request;
+
+	this_request = (struct scic_sds_stp_request *)scic_io_request;
+
+	scic_sds_stp_non_ncq_request_construct(&this_request->parent);
+
+	scu_stp_raw_request_construct_task_context(
+		this_request, this_request->parent.task_context_buffer
+		);
+
+	this_request->type.pio.current_transfer_bytes = 0;
+	this_request->type.pio.ending_error = 0;
+	this_request->type.pio.ending_status = 0;
+
+	this_request->type.pio.request_current.sgl_offset = 0;
+	this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
+	this_request->type.pio.sat_protocol = sat_protocol;
+
+	if (copy_rx_frame) {
+		scic_sds_request_build_sgl(&this_request->parent);
+		/*
+		 * Since the IO request copy of the TC contains the same data as
+		 * the actual TC this pointer is vaild for either. */
+		this_request->type.pio.request_current.sgl_pair =
+			&this_request->parent.task_context_buffer->sgl_pair_ab;
+	} else {
+		/* The user does not want the data copied to the SGL buffer location */
+		this_request->type.pio.request_current.sgl_pair = NULL;
+	}
+
+	sci_base_state_machine_construct(
+		&this_request->parent.started_substate_machine,
+		&this_request->parent.parent.parent,
+		scic_sds_stp_request_started_pio_substate_table,
+		SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_request:
+ * @completion_code:
+ *
+ * This method processes a TC completion.  The expected TC completion is for
+ * the transmission of the H2D register FIS containing the SATA/STP non-data
+ * request. This method always successfully processes the TC completion.
+ * SCI_SUCCESS This value is always returned.
+ */
+static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @request: This parameter specifies the request for which a frame has been
+ *    received.
+ * @frame_index: This parameter specifies the index of the frame that has been
+ *    received.
+ *
+ * This method processes frames received from the target while waiting for a
+ * device to host register FIS.  If a non-register FIS is received during this
+ * time, it is treated as a protocol violation from an IO perspective. Indicate
+ * if the received frame was processed successfully.
+ */
+static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		switch (frame_header->fis_type) {
+		case SATA_FIS_TYPE_REGD2H:
+			scic_sds_unsolicited_frame_control_get_buffer(
+				&(this_request->parent.owning_controller->uf_control),
+				frame_index,
+				(void **)&frame_buffer
+				);
+
+			scic_sds_controller_copy_sata_response(
+				&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
+				);
+
+			/* The command has completed with error */
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+			break;
+
+		default:
+			dev_warn(scic_to_dev(request->owning_controller),
+				 "%s: IO Request:0x%p Frame Id:%d protocol "
+				 "violation occurred\n",
+				 __func__, this_request, frame_index);
+
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_UNEXP_FIS,
+				SCI_FAILURE_PROTOCOL_VIOLATION
+				);
+			break;
+		}
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+
+		/* Frame has been decoded return it to the controller */
+		scic_sds_controller_release_frame(
+			this_request->parent.owning_controller, frame_index
+			);
+	} else
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC IO Request 0x%p could not get frame header "
+			"for frame index %d, status %x\n",
+			__func__, this_request, frame_index, status);
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_request_non_data_await_d2h_frame_handler,
+	}
+};
+
+static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_non_data_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
+		);
+
+	scic_sds_remote_device_set_working_request(
+		this_request->target_device, this_request
+		);
+}
+
+static void scic_sds_stp_request_started_non_data_await_d2h_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_non_data_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter,
+	},
+};
+
+#define SCU_MAX_FRAME_BUFFER_SIZE  0x400  /* 1K is the maximum SCU frame data payload */
+
+/**
+ *
+ * @this_request:
+ * @length:
+ *
+ * This function will transmit DATA_FIS from (current sgl + offset) for input
+ * parameter length. current sgl and offset is alreay stored in the IO request
+ * enum sci_status
+ */
+
+static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame(
+	struct scic_sds_request *this_request,
+	u32 length)
+{
+	struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request;
+	sci_base_controller_request_handler_t continue_io;
+	struct scu_sgl_element *current_sgl;
+	struct scic_sds_controller *scic;
+	u32 state;
+
+	/*
+	 * Recycle the TC and reconstruct it for sending out DATA FIS containing
+	 * for the data from current_sgl+offset for the input length */
+	struct scu_task_context *task_context = scic_sds_controller_get_task_context_buffer(
+		this_request->owning_controller,
+		this_request->io_tag
+		);
+
+	if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
+		current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
+	else
+		current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
+
+	/* update the TC */
+	task_context->command_iu_upper = current_sgl->address_upper;
+	task_context->command_iu_lower = current_sgl->address_lower;
+	task_context->transfer_length_bytes = length;
+	task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+	/* send the new TC out. */
+	scic = this_request->owning_controller;
+	state = scic->parent.state_machine.current_state_id;
+	continue_io = scic_sds_controller_state_handler_table[state].base.continue_io;
+	return continue_io(&scic->parent, &this_request->target_device->parent,
+			   &this_request->parent);
+}
+
+/**
+ *
+ * @this_request:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(
+	struct scic_sds_request *this_sds_request)
+{
+
+	struct scu_sgl_element *current_sgl;
+	u32 sgl_offset;
+	u32 remaining_bytes_in_current_sgl = 0;
+	enum sci_status status = SCI_SUCCESS;
+
+	struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_sds_request;
+
+	sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset;
+
+	if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
+		current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
+		remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset;
+	} else {
+		current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
+		remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset;
+	}
+
+
+	if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0) {
+		if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) {
+			/* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */
+			status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, remaining_bytes_in_current_sgl);
+			if (status == SCI_SUCCESS) {
+				this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl;
+
+				/* update the current sgl, sgl_offset and save for future */
+				current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request);
+				sgl_offset = 0;
+			}
+		} else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) {
+			/* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */
+			scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes);
+
+			if (status == SCI_SUCCESS) {
+				/* Sgl offset will be adjusted and saved for future */
+				sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes;
+				current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes;
+				this_sds_stp_request->type.pio.pio_transfer_bytes = 0;
+			}
+		}
+	}
+
+	if (status == SCI_SUCCESS) {
+		this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @stp_request: The request that is used for the SGL processing.
+ * @data_buffer: The buffer of data to be copied.
+ * @length: The length of the data transfer.
+ *
+ * Copy the data from the buffer for the length specified to the IO reqeust SGL
+ * specified data region. enum sci_status
+ */
+static enum sci_status
+scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req,
+						  u8 *data_buf, u32 len)
+{
+	struct scic_sds_request *sci_req;
+	struct isci_request *ireq;
+	u8 *src_addr;
+	int copy_len;
+	struct sas_task *task;
+	struct scatterlist *sg;
+	void *kaddr;
+	int total_len = len;
+
+	sci_req = &stp_req->parent;
+	ireq = scic_sds_request_get_user_request(sci_req);
+	task = isci_request_access_task(ireq);
+	src_addr = data_buf;
+
+	if (task->num_scatter > 0) {
+		sg = task->scatter;
+
+		while (total_len > 0) {
+			struct page *page = sg_page(sg);
+
+			copy_len = min_t(int, total_len, sg_dma_len(sg));
+			kaddr = kmap_atomic(page, KM_IRQ0);
+			memcpy(kaddr + sg->offset, src_addr, copy_len);
+			kunmap_atomic(kaddr, KM_IRQ0);
+			total_len -= copy_len;
+			src_addr += copy_len;
+			sg = sg_next(sg);
+		}
+	} else {
+		BUG_ON(task->total_xfer_len < total_len);
+		memcpy(task->scatter, src_addr, total_len);
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_request: The PIO DATA IN request that is to receive the data.
+ * @data_buffer: The buffer to copy from.
+ *
+ * Copy the data buffer to the io request data region. enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_data_in_copy_data(
+	struct scic_sds_stp_request *this_request,
+	u8 *data_buffer)
+{
+	enum sci_status status;
+
+	/*
+	 * If there is less than 1K remaining in the transfer request
+	 * copy just the data for the transfer */
+	if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) {
+		status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
+			this_request, data_buffer, this_request->type.pio.pio_transfer_bytes);
+
+		if (status == SCI_SUCCESS)
+			this_request->type.pio.pio_transfer_bytes = 0;
+	} else {
+		/* We are transfering the whole frame so copy */
+		status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
+			this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE);
+
+		if (status == SCI_SUCCESS)
+			this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_request:
+ * @completion_code:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @this_request:
+ * @frame_index:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+	struct scic_sds_stp_request *this_request;
+
+	this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		switch (frame_header->fis_type) {
+		case SATA_FIS_TYPE_PIO_SETUP:
+			/* Get from the frame buffer the PIO Setup Data */
+			scic_sds_unsolicited_frame_control_get_buffer(
+				&(this_request->parent.owning_controller->uf_control),
+				frame_index,
+				(void **)&frame_buffer
+				);
+
+			/*
+			 * Get the data from the PIO Setup
+			 * The SCU Hardware returns first word in the frame_header and the rest
+			 * of the data is in the frame buffer so we need to back up one dword */
+			this_request->type.pio.pio_transfer_bytes =
+				(u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count;
+			this_request->type.pio.ending_status =
+				(u8)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->ending_status;
+
+			scic_sds_controller_copy_sata_response(
+				&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
+				);
+
+			this_request->d2h_reg_fis.status =
+				this_request->type.pio.ending_status;
+
+			/* The next state is dependent on whether the request was PIO Data-in or Data out */
+			if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) {
+				sci_base_state_machine_change_state(
+					&this_request->parent.started_substate_machine,
+					SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
+					);
+			} else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) {
+				/* Transmit data */
+				status = scic_sds_stp_request_pio_data_out_transmit_data(request);
+				if (status == SCI_SUCCESS) {
+					sci_base_state_machine_change_state(
+						&this_request->parent.started_substate_machine,
+						SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
+						);
+				}
+			}
+			break;
+
+		case SATA_FIS_TYPE_SETDEVBITS:
+			sci_base_state_machine_change_state(
+				&this_request->parent.started_substate_machine,
+				SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+				);
+			break;
+
+		case SATA_FIS_TYPE_REGD2H:
+			if ((frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) {
+				scic_sds_unsolicited_frame_control_get_buffer(
+					&(this_request->parent.owning_controller->uf_control),
+					frame_index,
+					(void **)&frame_buffer
+					);
+
+				scic_sds_controller_copy_sata_response(
+					&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer);
+
+				scic_sds_request_set_status(
+					&this_request->parent,
+					SCU_TASK_DONE_CHECK_RESPONSE,
+					SCI_FAILURE_IO_RESPONSE_VALID
+					);
+
+				sci_base_state_machine_change_state(
+					&this_request->parent.parent.state_machine,
+					SCI_BASE_REQUEST_STATE_COMPLETED
+					);
+			} else {
+				/*
+				 * Now why is the drive sending a D2H Register FIS when it is still busy?
+				 * Do nothing since we are still in the right state. */
+				dev_dbg(scic_to_dev(request->owning_controller),
+					"%s: SCIC PIO Request 0x%p received "
+					"D2H Register FIS with BSY status "
+					"0x%x\n",
+					__func__,
+					this_request,
+					frame_header->status);
+			}
+			break;
+
+		default:
+			break;
+		}
+
+		/* Frame is decoded return it to the controller */
+		scic_sds_controller_release_frame(
+			this_request->parent.owning_controller,
+			frame_index
+			);
+	} else
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC IO Request 0x%p could not get frame header "
+			"for frame index %d, status %x\n",
+			__func__, this_request, frame_index, status);
+
+	return status;
+}
+
+/**
+ *
+ * @this_request:
+ * @frame_index:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	struct sata_fis_data *frame_buffer;
+	struct scic_sds_stp_request *this_request;
+
+	this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		if (frame_header->fis_type == SATA_FIS_TYPE_DATA) {
+			if (this_request->type.pio.request_current.sgl_pair == NULL) {
+				this_request->parent.saved_rx_frame_index = frame_index;
+				this_request->type.pio.pio_transfer_bytes = 0;
+			} else {
+				status = scic_sds_unsolicited_frame_control_get_buffer(
+					&(this_request->parent.owning_controller->uf_control),
+					frame_index,
+					(void **)&frame_buffer
+					);
+
+				status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (u8 *)frame_buffer);
+
+				/* Frame is decoded return it to the controller */
+				scic_sds_controller_release_frame(
+					this_request->parent.owning_controller,
+					frame_index
+					);
+			}
+
+			/*
+			 * Check for the end of the transfer, are there more bytes remaining
+			 * for this data transfer */
+			if (
+				(status == SCI_SUCCESS)
+				&& (this_request->type.pio.pio_transfer_bytes == 0)
+				) {
+				if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) {
+					scic_sds_request_set_status(
+						&this_request->parent,
+						SCU_TASK_DONE_CHECK_RESPONSE,
+						SCI_FAILURE_IO_RESPONSE_VALID
+						);
+
+					sci_base_state_machine_change_state(
+						&this_request->parent.parent.state_machine,
+						SCI_BASE_REQUEST_STATE_COMPLETED
+						);
+				} else {
+					sci_base_state_machine_change_state(
+						&this_request->parent.started_substate_machine,
+						SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+						);
+				}
+			}
+		} else {
+			dev_err(scic_to_dev(request->owning_controller),
+				"%s: SCIC PIO Request 0x%p received frame %d "
+				"with fis type 0x%02x when expecting a data "
+				"fis.\n",
+				__func__,
+				this_request,
+				frame_index,
+				frame_header->fis_type);
+
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_GOOD,
+				SCI_FAILURE_IO_REQUIRES_SCSI_ABORT
+				);
+
+			sci_base_state_machine_change_state(
+				&this_request->parent.parent.state_machine,
+				SCI_BASE_REQUEST_STATE_COMPLETED
+				);
+
+			/* Frame is decoded return it to the controller */
+			scic_sds_controller_release_frame(
+				this_request->parent.owning_controller,
+				frame_index
+				);
+		}
+	} else
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC IO Request 0x%p could not get frame header "
+			"for frame index %d, status %x\n",
+			__func__, this_request, frame_index, status);
+
+	return status;
+}
+
+
+/**
+ *
+ * @this_request:
+ * @completion_code:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler(
+
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	enum sci_status status                     = SCI_SUCCESS;
+	bool all_frames_transferred     = false;
+
+	struct scic_sds_stp_request *this_scic_sds_stp_request = (struct scic_sds_stp_request *)this_request;
+
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		/* Transmit data */
+		if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0) {
+			status = scic_sds_stp_request_pio_data_out_transmit_data(this_request);
+			if (status == SCI_SUCCESS) {
+				if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
+					all_frames_transferred = true;
+			}
+		} else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) {
+			/*
+			 * this will happen if the all data is written at the
+			 * first time after the pio setup fis is received
+			 */
+			all_frames_transferred  = true;
+		}
+
+		/* all data transferred. */
+		if (all_frames_transferred) {
+			/*
+			 * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE
+			 * and wait for PIO_SETUP fis / or D2H REg fis. */
+			sci_base_state_machine_change_state(
+				&this_request->started_substate_machine,
+				SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+				);
+		}
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return status;
+}
+
+/**
+ *
+ * @request: This is the request which is receiving the event.
+ * @event_code: This is the event code that the request on which the request is
+ *    expected to take action.
+ *
+ * This method will handle any link layer events while waiting for the data
+ * frame. enum sci_status SCI_SUCCESS SCI_FAILURE
+ */
+static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler(
+	struct scic_sds_request *request,
+	u32 event_code)
+{
+	enum sci_status status;
+
+	switch (scu_get_event_specifier(event_code)) {
+	case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT:
+		/*
+		 * We are waiting for data and the SCU has R_ERR the data frame.
+		 * Go back to waiting for the D2H Register FIS */
+		sci_base_state_machine_change_state(
+			&request->started_substate_machine,
+			SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+			);
+
+		status = SCI_SUCCESS;
+		break;
+
+	default:
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC PIO Request 0x%p received unexpected "
+			"event 0x%08x\n",
+			__func__, request, event_code);
+
+		/* / @todo Should we fail the PIO request when we get an unexpected event? */
+		status = SCI_FAILURE;
+		break;
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_request_pio_await_frame_frame_handler
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_stp_request_pio_data_in_await_data_event_handler,
+		.frame_handler           = scic_sds_stp_request_pio_data_in_await_data_frame_handler
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	}
+};
+
+static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_pio_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
+		);
+
+	scic_sds_remote_device_set_working_request(
+		this_request->target_device, this_request);
+}
+
+static void scic_sds_stp_request_started_pio_await_frame_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_pio_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+		);
+}
+
+static void scic_sds_stp_request_started_pio_data_in_await_data_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_pio_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
+		);
+}
+
+static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_pio_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_pio_await_frame_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter,
+	}
+};
+
+static void scic_sds_stp_request_udma_complete_request(
+	struct scic_sds_request *this_request,
+	u32 scu_status,
+	enum sci_status sci_status)
+{
+	scic_sds_request_set_status(
+		this_request, scu_status, sci_status
+		);
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+}
+
+/**
+ *
+ * @this_request:
+ * @frame_index:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_udma_general_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&this_request->owning_controller->uf_control,
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (
+		(status == SCI_SUCCESS)
+		&& (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
+		) {
+		scic_sds_unsolicited_frame_control_get_buffer(
+			&this_request->owning_controller->uf_control,
+			frame_index,
+			(void **)&frame_buffer
+			);
+
+		scic_sds_controller_copy_sata_response(
+			&((struct scic_sds_stp_request *)this_request)->d2h_reg_fis,
+			(u32 *)frame_header,
+			frame_buffer
+			);
+	}
+
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index);
+
+	return status;
+}
+
+/**
+ * This method process TC completions while in the state where we are waiting
+ *    for TC completions.
+ * @this_request:
+ * @completion_code:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler(
+	struct scic_sds_request *request,
+	u32 completion_code)
+{
+	enum sci_status status = SCI_SUCCESS;
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_stp_request_udma_complete_request(
+			&this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+		break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
+		/*
+		 * We must check ther response buffer to see if the D2H Register FIS was
+		 * received before we got the TC completion. */
+		if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) {
+			scic_sds_remote_device_suspend(
+				this_request->parent.target_device,
+				SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
+				);
+
+			scic_sds_stp_request_udma_complete_request(
+				&this_request->parent,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+		} else {
+			/*
+			 * If we have an error completion status for the TC then we can expect a
+			 * D2H register FIS from the device so we must change state to wait for it */
+			sci_base_state_machine_change_state(
+				&this_request->parent.started_substate_machine,
+				SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
+				);
+		}
+		break;
+
+	/*
+	 * / @todo Check to see if any of these completion status need to wait for
+	 * /       the device to host register fis. */
+	/* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
+		scic_sds_remote_device_suspend(
+			this_request->parent.target_device,
+			SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
+			);
+	/* Fall through to the default case */
+	default:
+		/* All other completion status cause the IO to be complete. */
+		scic_sds_stp_request_udma_complete_request(
+			&this_request->parent,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+		break;
+	}
+
+	return status;
+}
+
+static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	enum sci_status status;
+
+	/* Use the general frame handler to copy the resposne data */
+	status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index);
+
+	if (status == SCI_SUCCESS) {
+		scic_sds_stp_request_udma_complete_request(
+			this_request,
+			SCU_TASK_DONE_CHECK_RESPONSE,
+			SCI_FAILURE_IO_RESPONSE_VALID
+			);
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_request_udma_general_frame_handler,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler,
+	},
+};
+
+static void scic_sds_stp_request_started_udma_await_tc_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_udma_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+		);
+}
+
+/**
+ *
+ *
+ * This state is entered when there is an TC completion failure.  The hardware
+ * received an unexpected condition while processing the IO request and now
+ * will UF the D2H register FIS to complete the IO.
+ */
+static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_udma_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter,
+	},
+};
+
+/**
+ *
+ * @this_request:
+ * @completion_code:
+ *
+ * This method processes a TC completion.  The expected TC completion is for
+ * the transmission of the H2D register FIS containing the SATA/STP non-data
+ * request. This method always successfully processes the TC completion.
+ * SCI_SUCCESS This value is always returned.
+ */
+static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_request:
+ * @completion_code:
+ *
+ * This method processes a TC completion.  The expected TC completion is for
+ * the transmission of the H2D register FIS containing the SATA/STP non-data
+ * request. This method always successfully processes the TC completion.
+ * SCI_SUCCESS This value is always returned.
+ */
+static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @request: This parameter specifies the request for which a frame has been
+ *    received.
+ * @frame_index: This parameter specifies the index of the frame that has been
+ *    received.
+ *
+ * This method processes frames received from the target while waiting for a
+ * device to host register FIS.  If a non-register FIS is received during this
+ * time, it is treated as a protocol violation from an IO perspective. Indicate
+ * if the received frame was processed successfully.
+ */
+static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler(
+	struct scic_sds_request *request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sata_fis_header *frame_header;
+	u32 *frame_buffer;
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(this_request->parent.owning_controller->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (status == SCI_SUCCESS) {
+		switch (frame_header->fis_type) {
+		case SATA_FIS_TYPE_REGD2H:
+			scic_sds_unsolicited_frame_control_get_buffer(
+				&(this_request->parent.owning_controller->uf_control),
+				frame_index,
+				(void **)&frame_buffer
+				);
+
+			scic_sds_controller_copy_sata_response(
+				&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
+				);
+
+			/* The command has completed with error */
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+			break;
+
+		default:
+			dev_warn(scic_to_dev(request->owning_controller),
+				 "%s: IO Request:0x%p Frame Id:%d protocol "
+				 "violation occurred\n",
+				 __func__,
+				 this_request,
+				 frame_index);
+
+			scic_sds_request_set_status(
+				&this_request->parent,
+				SCU_TASK_DONE_UNEXP_FIS,
+				SCI_FAILURE_PROTOCOL_VIOLATION
+				);
+			break;
+		}
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+
+		/* Frame has been decoded return it to the controller */
+		scic_sds_controller_release_frame(
+			this_request->parent.owning_controller, frame_index
+			);
+	} else
+		dev_err(scic_to_dev(request->owning_controller),
+			"%s: SCIC IO Request 0x%p could not get frame header "
+			"for frame index %d, status %x\n",
+			__func__, this_request, frame_index, status);
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_stp_request_soft_reset_await_d2h_frame_handler,
+	},
+};
+
+static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_soft_reset_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
+		);
+
+	scic_sds_remote_device_set_working_request(
+		this_request->target_device, this_request
+		);
+}
+
+static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+	sci_base_controller_request_handler_t continue_io;
+	struct scu_task_context *task_context;
+	struct sata_fis_reg_h2d *h2d_fis;
+	struct scic_sds_controller *scic;
+	enum sci_status status;
+	u32 state;
+
+	/* Clear the SRST bit */
+	h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request);
+	h2d_fis->control = 0;
+
+	/* Clear the TC control bit */
+	task_context = scic_sds_controller_get_task_context_buffer(
+		this_request->owning_controller, this_request->io_tag);
+	task_context->control_frame = 0;
+
+	scic = this_request->owning_controller;
+	state = scic->parent.state_machine.current_state_id;
+	continue_io = scic_sds_controller_state_handler_table[state].base.continue_io;
+
+	status = continue_io(&scic->parent, &this_request->target_device->parent,
+			     &this_request->parent);
+
+	if (status == SCI_SUCCESS) {
+		SET_STATE_HANDLER(
+			this_request,
+			scic_sds_stp_request_started_soft_reset_substate_handler_table,
+			SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
+			);
+	}
+}
+
+static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_stp_request_started_soft_reset_substate_handler_table,
+		SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = {
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter,
+	},
+	[SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = {
+		.enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h
new file mode 100644
index 0000000..c950bb3
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_request.h
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_STP_REQUEST_T_
+#define _SCIC_SDS_STP_REQUEST_T_
+
+#include <linux/dma-mapping.h>
+#include "intel_sata.h"
+#include "scic_sds_request.h"
+
+/**
+ * This structure represents the additional information that is required to
+ *    handle SATA PIO requests.
+ *
+ *
+ */
+struct scic_sds_stp_request {
+	struct scic_sds_request parent;
+
+	struct sata_fis_reg_d2h d2h_reg_fis;
+
+	union {
+		u32 ncq;
+
+		u32 udma;
+
+		struct {
+			/**
+			 * Total transfer for the entire PIO request recorded at request constuction
+			 * time.
+			 *
+			 * @todo Should we just decrement this value for each byte of data transitted
+			 *       or received to elemenate the current_transfer_bytes field?
+			 */
+			u32 total_transfer_bytes;
+
+			/**
+			 * Total number of bytes received/transmitted in data frames since the start
+			 * of the IO request.  At the end of the IO request this should equal the
+			 * total_transfer_bytes.
+			 */
+			u32 current_transfer_bytes;
+
+			/**
+			 * The number of bytes requested in the in the PIO setup.
+			 */
+			u32 pio_transfer_bytes;
+
+			/**
+			 * PIO Setup ending status value to tell us if we need to wait for another FIS
+			 * or if the transfer is complete. On the receipt of a D2H FIS this will be
+			 * the status field of that FIS.
+			 */
+			u8 ending_status;
+
+			/**
+			 * On receipt of a D2H FIS this will be the ending error field if the
+			 * ending_status has the SATA_STATUS_ERR bit set.
+			 */
+			u8 ending_error;
+
+			/**
+			 * Protocol Type. This is filled in by core during IO Request construction type.
+			 */
+			u8 sat_protocol;
+
+			struct scic_sds_request_pio_sgl {
+				struct scu_sgl_element_pair *sgl_pair;
+				u8 sgl_set;
+				u32 sgl_offset;
+			} request_current;
+		} pio;
+
+		struct {
+			/**
+			 * The number of bytes requested in the PIO setup before CDB data frame.
+			 */
+			u32 device_preferred_cdb_length;
+		} packet;
+	} type;
+
+};
+
+/**
+ * enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts
+ *    the various sub-states associated with a SATA/STP UDMA protocol operation.
+ *
+ *
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES {
+	SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
+	SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
+};
+
+/**
+ * enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration
+ *    depicts the various sub-states associated with a SATA/STP non-data
+ *    protocol operation.
+ *
+ *
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES {
+	SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
+	SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
+};
+
+/**
+ * enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration
+ *    depicts the various sub-states associated with a SATA/STP soft reset
+ *    operation.
+ *
+ *
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES {
+	SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
+	SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
+	SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
+};
+
+extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[];
+
+extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[];
+
+extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[];
+
+extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[];
+
+extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[];
+
+extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[];
+
+/* --------------------------------------------------------------------------- */
+
+u32 scic_sds_stp_request_get_object_size(void);
+
+
+void scic_sds_stp_non_ncq_request_construct(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_stp_pio_request_construct(
+	struct scic_sds_request *scic_io_request,
+	u8 sat_protocol,
+	bool copy_rx_frame);
+
+enum sci_status scic_sds_stp_pio_request_construct_pass_through(
+	struct scic_sds_request *scic_io_request,
+	struct scic_stp_passthru_request_callbacks *passthru_cb);
+
+enum sci_status scic_sds_stp_udma_request_construct(
+	struct scic_sds_request *this_request,
+	u32 transfer_length,
+	enum dma_data_direction dir);
+
+enum sci_status scic_sds_stp_non_data_request_construct(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_stp_soft_reset_request_construct(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_stp_ncq_request_construct(
+	struct scic_sds_request *this_request,
+	u32 transfer_length,
+	enum dma_data_direction dir);
+
+void scu_stp_raw_request_construct_task_context(
+	struct scic_sds_stp_request *this_request,
+	struct scu_task_context *task_context);
+
+#endif /* _SCIC_SDS_STP_REQUEST_T_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 07/10] isci/core: request (general, ssp and smp)
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (5 preceding siblings ...)
  2011-03-10 10:54 ` [RFC PATCH 06/10] isci/core: stp Dan Williams
@ 2011-03-10 10:54 ` Dan Williams
  2011-03-10 10:55 ` [RFC PATCH 08/10] isci/core: unsolicited frame handling and registers Dan Williams
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:54 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

General request state machines as well as the sub-state machines for ssp
(hardware accelerated) and smp operation (not accelerated).

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/sci_base_request.h     |  195 ++
 drivers/scsi/isci/core/scic_io_request.h      |  511 ++++++
 drivers/scsi/isci/core/scic_sds_request.c     | 2174 +++++++++++++++++++++++++
 drivers/scsi/isci/core/scic_sds_request.h     |  469 +++++
 drivers/scsi/isci/core/scic_sds_smp_request.c |  669 ++++++++
 drivers/scsi/isci/core/scic_sds_smp_request.h |   69 +
 drivers/scsi/isci/core/scic_sds_ssp_request.c |  268 +++
 drivers/scsi/isci/core/scic_task_request.h    |  147 ++
 8 files changed, 4502 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_request.h
 create mode 100644 drivers/scsi/isci/core/scic_io_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_ssp_request.c
 create mode 100644 drivers/scsi/isci/core/scic_task_request.h

diff --git a/drivers/scsi/isci/core/sci_base_request.h b/drivers/scsi/isci/core/sci_base_request.h
new file mode 100644
index 0000000..d1b2195
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_request.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_REQUST_H_
+#define _SCI_BASE_REQUST_H_
+
+/**
+ * This file contains all of the constants, types, and method declarations for
+ *    the SCI base IO and task request objects.
+ *
+ *
+ */
+
+#include "sci_base_state_machine.h"
+
+/**
+ * enum sci_base_request_states - This enumeration depicts all the states for
+ *    the common request state machine.
+ *
+ *
+ */
+enum sci_base_request_states {
+	/**
+	 * Simply the initial state for the base request state machine.
+	 */
+	SCI_BASE_REQUEST_STATE_INITIAL,
+
+	/**
+	 * This state indicates that the request has been constructed. This state
+	 * is entered from the INITIAL state.
+	 */
+	SCI_BASE_REQUEST_STATE_CONSTRUCTED,
+
+	/**
+	 * This state indicates that the request has been started. This state is
+	 * entered from the CONSTRUCTED state.
+	 */
+	SCI_BASE_REQUEST_STATE_STARTED,
+
+	/**
+	 * This state indicates that the request has completed.
+	 * This state is entered from the STARTED state. This state is entered from
+	 * the ABORTING state.
+	 */
+	SCI_BASE_REQUEST_STATE_COMPLETED,
+
+	/**
+	 * This state indicates that the request is in the process of being
+	 * terminated/aborted.
+	 * This state is entered from the CONSTRUCTED state.
+	 * This state is entered from the STARTED state.
+	 */
+	SCI_BASE_REQUEST_STATE_ABORTING,
+
+	/**
+	 * Simply the final state for the base request state machine.
+	 */
+	SCI_BASE_REQUEST_STATE_FINAL,
+};
+
+/**
+ * struct sci_base_request - The base request object abstracts the fields
+ *    common to all SCI IO and task request objects.
+ *
+ *
+ */
+struct sci_base_request {
+	/**
+	 * The field specifies that the parent object for the base request is the
+	 * base object itself.
+	 */
+	struct sci_base_object parent;
+
+	/**
+	 * This field contains the information for the base request state machine.
+	 */
+	struct sci_base_state_machine state_machine;
+};
+
+typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)(
+	struct sci_base_request *this_request
+	);
+
+/**
+ * struct sci_base_request_state_handler - This structure contains all of the
+ *    state handler methods common to base IO and task request state machines.
+ *    Handler methods provide the ability to change the behavior for user
+ *    requests or transitions depending on the state the machine is in.
+ *
+ *
+ */
+struct sci_base_request_state_handler {
+	/**
+	 * The start_handler specifies the method invoked when a user attempts to
+	 * start a request.
+	 */
+	SCI_BASE_REQUEST_HANDLER_T start_handler;
+
+	/**
+	 * The abort_handler specifies the method invoked when a user attempts to
+	 * abort a request.
+	 */
+	SCI_BASE_REQUEST_HANDLER_T abort_handler;
+
+	/**
+	 * The complete_handler specifies the method invoked when a user attempts to
+	 * complete a request.
+	 */
+	SCI_BASE_REQUEST_HANDLER_T complete_handler;
+
+	/**
+	 * The destruct_handler specifies the method invoked when a user attempts to
+	 * destruct a request.
+	 */
+	SCI_BASE_REQUEST_HANDLER_T destruct_handler;
+
+};
+
+/**
+ * sci_base_request_construct() - Construct the base request.
+ * @this_request: This parameter specifies the base request to be constructed.
+ * @state_table: This parameter specifies the table of state definitions to be
+ *    utilized for the request state machine.
+ *
+ */
+static inline void sci_base_request_construct(
+	struct sci_base_request *base_req,
+	const struct sci_base_state *my_state_table)
+{
+	base_req->parent.private = NULL;
+	sci_base_state_machine_construct(
+		&base_req->state_machine,
+		&base_req->parent,
+		my_state_table,
+		SCI_BASE_REQUEST_STATE_INITIAL
+		);
+
+	sci_base_state_machine_start(
+		&base_req->state_machine
+		);
+}
+
+#endif /* _SCI_BASE_REQUST_H_ */
diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h
new file mode 100644
index 0000000..a52f33d
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_io_request.h
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_IO_REQUEST_H_
+#define _SCIC_IO_REQUEST_H_
+
+/**
+ * This file contains the structures and interface methods that can be
+ *    referenced and used by the SCI user for the SCI IO request object.
+ *
+ * Determine the failure situations and return values.
+ */
+
+
+#include "sci_status.h"
+#include "intel_sas.h"
+
+struct scic_sds_request;
+struct scic_sds_remote_device;
+struct scic_sds_controller;
+
+/**
+ * struct scic_io_parameters - This structure contains additional optional
+ *    parameters for SSP IO requests.  These parameters are utilized with the
+ *    scic_io_request_construct_advanced_ssp() method.
+ *
+ * Add Block-guard/DIF, TLR
+ */
+struct scic_io_parameters {
+	/**
+	 * This sub-structure contains SCSI specific features (for use with SSP
+	 * IO requests).
+	 */
+	struct {
+		/**
+		 * Data Integrity Format (DIF) is also known as protection information
+		 * or block-guard.  This sub-structure contains DIF specific feature
+		 * information for SSP IO requests.
+		 */
+		struct {
+			void *placeholder;
+		} dif;
+
+		/**
+		 * Transport Layer Retries (TLR) is an SSP protocol specific feature.
+		 * This sub-structure contains Transport Layer Retries (TLR) specific
+		 * feature information for SSP IO requests.
+		 */
+		struct {
+			void *placeholder;
+		} tlr;
+
+	} scsi;
+
+};
+
+/**
+ * struct scic_passthru_request_callbacks - This structure contains the pointer
+ *    to the callback functions for constructing the passthrough request common
+ *    to SSP, SMP and STP. This structure must be set by the win sci layer
+ *    before the passthrough build is called
+ *
+ *
+ */
+struct scic_passthru_request_callbacks {
+	/**
+	 * Function pointer to get the phy identifier for passthrough request.
+	 */
+	u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *);
+	/**
+	 * Function pointer to get the port identifier for passthrough request.
+	 */
+	u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *);
+	/**
+	 * Function pointer to get the connection rate for passthrough request.
+	 */
+	u32 (*scic_cb_passthru_get_connection_rate)(void *, void *);
+	/**
+	 * Function pointer to get the destination sas address for passthrough request.
+	 */
+	void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **);
+	/**
+	 * Function pointer to get the transfer length for passthrough request.
+	 */
+	u32 (*scic_cb_passthru_get_transfer_length)(void *);
+	/**
+	 * Function pointer to get the data direction for passthrough request.
+	 */
+	u32 (*scic_cb_passthru_get_data_direction)(void *);
+
+};
+
+/**
+ * struct scic_ssp_passthru_request_callbacks - This structure contains the
+ *    pointer to the callback functions for constructing the passthrough
+ *    request specific to SSP. This structure must be set by the win sci layer
+ *    before the passthrough build is called
+ *
+ *
+ */
+struct scic_ssp_passthru_request_callbacks {
+	/**
+	 * Common callbacks for all Passthru requests
+	 */
+	struct scic_passthru_request_callbacks common_callbacks;
+	/**
+	 * Function pointer to get the lun for passthrough request.
+	 */
+	void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **);
+	/**
+	 * Function pointer to get the cdb
+	 */
+	void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **);
+	/**
+	 * Function pointer to get the task attribute for passthrough request.
+	 */
+	u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *);
+};
+
+/**
+ * struct scic_stp_passthru_request_callbacks - This structure contains the
+ *    pointer to the callback functions for constructing the passthrough
+ *    request specific to STP. This structure must be set by the win sci layer
+ *    before the passthrough build is called
+ *
+ *
+ */
+struct scic_stp_passthru_request_callbacks {
+	/**
+	 * Common callbacks for all Passthru requests
+	 */
+	struct scic_passthru_request_callbacks common_callbacks;
+	/**
+	 * Function pointer to get the protocol for passthrough request.
+	 */
+	u8 (*scic_cb_stp_passthru_get_protocol)(void *);
+	/**
+	 * Function pointer to get the resgister fis
+	 */
+	void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **);
+	/**
+	 * Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_multiplecount)(void *);
+	/**
+	 * Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_extend)(void *);
+	/**
+	 * Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_ckcond)(void *);
+	/**
+	 * Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_tdir)(void *);
+	/**
+	 * Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_byteblock)(void *);
+	/**
+	 * Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+	 */
+	u8 (*scic_cb_stp_passthru_get_tlength)(void *);
+
+};
+
+/**
+ * struct scic_smp_passthru_request_callbacks - This structure contains the
+ *    pointer to the callback functions for constructing the passthrough
+ *    request specific to SMP. This structure must be set by the win sci layer
+ *    before the passthrough build is called
+ *
+ *
+ */
+struct scic_smp_passthru_request_callbacks {
+	/**
+	 * Common callbacks for all Passthru requests
+	 */
+	struct scic_passthru_request_callbacks common_callbacks;
+
+	/**
+	 * Function pointer to get the length of the smp request and its length
+	 */
+	u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **);
+	/**
+	 * Function pointer to get the frame type of the smp request
+	 */
+	u8 (*scic_cb_smp_passthru_get_frame_type)(void *);
+	/**
+	 * Function pointer to get the function in the the smp request
+	 */
+	u8 (*scic_cb_smp_passthru_get_function)(void *);
+
+	/**
+	 * Function pointer to get the "allocated response length" in the the smp request
+	 */
+	u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *);
+
+};
+
+/**
+ * This enumeration specifies the transport protocol utilized for the request.
+ *
+ *
+ */
+typedef enum {
+	/**
+	 * This enumeration constant indicates that no protocol has yet been
+	 * set.
+	 */
+	SCIC_NO_PROTOCOL,
+
+	/**
+	 * This enumeration constant indicates that the protocol utilized
+	 * is the Serial Management Protocol.
+	 */
+	SCIC_SMP_PROTOCOL,
+
+	/**
+	 * This enumeration constant indicates that the protocol utilized
+	 * is the Serial SCSI Protocol.
+	 */
+	SCIC_SSP_PROTOCOL,
+
+	/**
+	 * This enumeration constant indicates that the protocol utilized
+	 * is the Serial-ATA Tunneling Protocol.
+	 */
+	SCIC_STP_PROTOCOL
+
+} SCIC_TRANSPORT_PROTOCOL;
+
+
+/**
+ * scic_io_request_get_object_size() - This method simply returns the size
+ *    required to build an SCI based IO request object.
+ *
+ * Return the size of the SCI IO request object.
+ */
+u32 scic_io_request_get_object_size(
+	void);
+
+/**
+ * scic_io_request_construct() - This method is called by the SCI user to
+ *    construct all SCI Core IO requests.  Memory initialization and
+ *    functionality common to all IO request types is performed in this method.
+ * @scic_controller: the handle to the core controller object for which to
+ *    build an IO request.
+ * @scic_remote_device: the handle to the core remote device object for which
+ *    to build an IO request.
+ * @io_tag: This parameter specifies the IO tag to be associated with this
+ *    request.  If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
+ *    request is built internally.  The request will be copied into the actual
+ *    controller request memory when the IO tag is allocated internally during
+ *    the scic_controller_start_io() method.
+ * @user_io_request_object: This parameter specifies the user IO request to be
+ *    utilized during IO construction.  This IO pointer will become the
+ *    associated object for the core IO request object.
+ * @scic_io_request_memory: This parameter specifies the memory location to be
+ *    utilized when building the core request.
+ * @new_scic_io_request_handle: This parameter specifies a pointer to the
+ *    handle the core will expect in further interactions with the core IO
+ *    request object.
+ *
+ * The SCI core implementation will create an association between the user IO
+ * request object and the core IO request object. Indicate if the controller
+ * successfully built the IO request. SCI_SUCCESS This value is returned if the
+ * IO request was successfully built.
+ */
+enum sci_status scic_io_request_construct(
+	struct scic_sds_controller *scic_controller,
+	struct scic_sds_remote_device *scic_remote_device,
+	u16 io_tag,
+	void *user_io_request_object,
+	void *scic_io_request_memory,
+	struct scic_sds_request **new_scic_io_request_handle);
+
+/**
+ * scic_io_request_construct_basic_ssp() - This method is called by the SCI
+ *    user to build an SSP IO request.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ *
+ * - The user must have previously called scic_io_request_construct() on the
+ * supplied IO request. Indicate if the controller successfully built the IO
+ * request. SCI_SUCCESS This value is returned if the IO request was
+ * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
+ * if the remote_device does not support the SSP protocol.
+ * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
+ * properly set the association between the SCIC IO request and the user's IO
+ * request.  Please refer to the sci_object_set_association() routine for more
+ * information.
+ */
+enum sci_status scic_io_request_construct_basic_ssp(
+	struct scic_sds_request *scic_io_request);
+
+
+
+
+
+/**
+ * scic_io_request_construct_basic_sata() - This method is called by the SCI
+ *    Core user to build an STP IO request.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ *
+ * - The user must have previously called scic_io_request_construct() on the
+ * supplied IO request. Indicate if the controller successfully built the IO
+ * request. SCI_SUCCESS This value is returned if the IO request was
+ * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
+ * if the remote_device does not support the STP protocol.
+ * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
+ * properly set the association between the SCIC IO request and the user's IO
+ * request.  Please refer to the sci_object_set_association() routine for more
+ * information.
+ */
+enum sci_status scic_io_request_construct_basic_sata(
+	struct scic_sds_request *scic_io_request);
+
+
+
+
+/**
+ * scic_io_request_construct_smp() - This method is called by the SCI user to
+ *    build an SMP IO request.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ *
+ * - The user must have previously called scic_io_request_construct() on the
+ * supplied IO request. Indicate if the controller successfully built the IO
+ * request. SCI_SUCCESS This value is returned if the IO request was
+ * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
+ * if the remote_device does not support the SMP protocol.
+ * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
+ * properly set the association between the SCIC IO request and the user's IO
+ * request.  Please refer to the sci_object_set_association() routine for more
+ * information.
+ */
+enum sci_status scic_io_request_construct_smp(
+	struct scic_sds_request *scic_io_request);
+
+
+
+/**
+ * scic_request_get_controller_status() - This method returns the controller
+ *    specific IO/Task request status. These status values are unique to the
+ *    specific controller being managed by the SCIC.
+ * @io_request: the handle to the IO or task management request object for
+ *    which to retrieve the status.
+ *
+ * This method returns a value indicating the controller specific request
+ * status.
+ */
+u32 scic_request_get_controller_status(
+	struct scic_sds_request *io_request);
+
+
+
+/**
+ * scic_io_request_get_command_iu_address() - This method will return the
+ *    address to the command information unit.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ *
+ * The address of the SSP/SMP command information unit.
+ */
+void *scic_io_request_get_command_iu_address(
+	struct scic_sds_request *scic_io_request);
+
+/**
+ * scic_io_request_get_response_iu_address() - This method will return the
+ *    address to the response information unit.  For an SSP request this buffer
+ *    is only valid if the IO request is completed with the status
+ *    SCI_FAILURE_IO_RESPONSE_VALID.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ *
+ * The address of the SSP/SMP response information unit.
+ */
+void *scic_io_request_get_response_iu_address(
+	struct scic_sds_request *scic_io_request);
+
+/**
+ * scic_io_request_get_io_tag() - This method will return the IO tag utilized
+ *    by the IO request.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object for which to return the IO tag.
+ *
+ * An unsigned integer representing the IO tag being utilized.
+ * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not
+ * currently have an IO tag allocated to it. All return other values indicate a
+ * legitimate tag.
+ */
+u16 scic_io_request_get_io_tag(
+	struct scic_sds_request *scic_io_request);
+
+
+/**
+ * scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to
+ *    the io request object.  The caller of this function must make sure that
+ *    only valid NCQ tags are assigned to the io request object.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object to which to assign the ncq tag.
+ * @ncq_tag: This parameter specifies the NCQ tag to be utilized for the
+ *    supplied core IO request.  It is up to the user to make sure that this is
+ *    a valid NCQ tag.
+ *
+ * none This function is only valid for SATA NCQ requests.
+ */
+void scic_stp_io_request_set_ncq_tag(
+	struct scic_sds_request *scic_io_request,
+	u16 ncq_tag);
+
+/**
+ * scic_stp_io_request_get_h2d_reg_address() - This method will return the
+ *    address of the host to device register fis region for the io request
+ *    object.
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    object from which to get the host to device register fis buffer.
+ *
+ * The address of the host to device register fis buffer in the io request
+ * object. This function is only valid for SATA requests.
+ */
+void *scic_stp_io_request_get_h2d_reg_address(
+	struct scic_sds_request *scic_io_request);
+
+/**
+ * scic_stp_io_request_get_d2h_reg_address() - This method will return the
+ *    address of the device to host register fis region for the io request
+ *    object.
+ * @scic_io_request: This parameter specifies teh handle to the io request
+ *    object from which to get the device to host register fis buffer.
+ *
+ * The address fo the device to host register fis ending the io request. This
+ * function is only valid for SATA requests.
+ */
+void *scic_stp_io_request_get_d2h_reg_address(
+	struct scic_sds_request *scic_io_request);
+
+
+/**
+ * scic_io_request_get_number_of_bytes_transferred() - This method will return
+ *    the number of bytes transferred from the SCU
+ * @scic_io_request: This parameter specifies the handle to the io request
+ *    whose data length was not eqaul to the data length specified in the
+ *    request. When the driver gets an early io completion status from the
+ *    hardware, this routine should be called to get the actual number of bytes
+ *    transferred
+ *
+ * The return is the number of bytes transferred when the data legth is not
+ * equal to the specified length in the io request
+ */
+u32 scic_io_request_get_number_of_bytes_transferred(
+	struct scic_sds_request *scic_io_request);
+
+
+#endif  /* _SCIC_IO_REQUEST_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c
new file mode 100644
index 0000000..00bebb9
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_request.c
@@ -0,0 +1,2174 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_sas.h"
+#include "intel_sata.h"
+#include "intel_sat.h"
+#include "sci_base_request.h"
+#include "scic_controller.h"
+#include "scic_io_request.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_controller_registers.h"
+#include "scic_sds_pci.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_smp_request.h"
+#include "scic_sds_stp_request.h"
+#include "scic_sds_unsolicited_frame_control.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_completion_codes.h"
+#include "scu_constants.h"
+#include "scu_task_context.h"
+
+#if !defined(DISABLE_ATAPI)
+#include "scic_sds_stp_packet_request.h"
+#endif
+
+/*
+ * ****************************************************************************
+ * * SCIC SDS IO REQUEST CONSTANTS
+ * **************************************************************************** */
+
+/**
+ *
+ *
+ * We have no timer requirements for IO requests right now
+ */
+#define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0)
+#define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0)
+
+/*
+ * ****************************************************************************
+ * * SCIC SDS IO REQUEST MACROS
+ * **************************************************************************** */
+
+/**
+ * scic_ssp_io_request_get_object_size() -
+ *
+ * This macro returns the sizeof memory required to store the an SSP IO
+ * request.  This does not include the size of the SGL or SCU Task Context
+ * memory.
+ */
+#define scic_ssp_io_request_get_object_size() \
+	(\
+		sizeof(struct sci_ssp_command_iu) \
+		+ sizeof(struct sci_ssp_response_iu)	\
+	)
+
+/**
+ * scic_sds_ssp_request_get_command_buffer() -
+ *
+ * This macro returns the address of the ssp command buffer in the io request
+ * memory
+ */
+#define scic_sds_ssp_request_get_command_buffer(memory)	\
+	((struct sci_ssp_command_iu *)(\
+		 ((char *)(memory)) + sizeof(struct scic_sds_request) \
+		 ))
+
+/**
+ * scic_sds_ssp_request_get_response_buffer() -
+ *
+ * This macro returns the address of the ssp response buffer in the io request
+ * memory
+ */
+#define scic_sds_ssp_request_get_response_buffer(memory) \
+	((struct sci_ssp_response_iu *)(\
+		 ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \
+		 + sizeof(struct sci_ssp_command_iu)	\
+		 ))
+
+/**
+ * scic_sds_ssp_request_get_task_context_buffer() -
+ *
+ * This macro returns the address of the task context buffer in the io request
+ * memory
+ */
+#define scic_sds_ssp_request_get_task_context_buffer(memory) \
+	((struct scu_task_context *)(\
+		 ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \
+		 + sizeof(struct sci_ssp_response_iu) \
+		 ))
+
+/**
+ * scic_sds_ssp_request_get_sgl_element_buffer() -
+ *
+ * This macro returns the address of the sgl elment pairs in the io request
+ * memory buffer
+ */
+#define scic_sds_ssp_request_get_sgl_element_buffer(memory) \
+	((struct scu_sgl_element_pair *)(\
+		 ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \
+		 + sizeof(struct scu_task_context) \
+		 ))
+
+
+/**
+ * scic_ssp_task_request_get_object_size() -
+ *
+ * This macro returns the sizeof of memory required to store an SSP Task
+ * request.  This does not include the size of the SCU Task Context memory.
+ */
+#define scic_ssp_task_request_get_object_size()	\
+	(\
+		sizeof(struct sci_ssp_task_iu) \
+		+ sizeof(struct sci_ssp_response_iu)	\
+	)
+
+/**
+ * scic_sds_ssp_task_request_get_command_buffer() -
+ *
+ * This macro returns the address of the ssp command buffer in the task request
+ * memory.  Yes its the same as the above macro except for the name.
+ */
+#define scic_sds_ssp_task_request_get_command_buffer(memory) \
+	((struct sci_ssp_task_iu *)(\
+		 ((char *)(memory)) + sizeof(struct scic_sds_request) \
+		 ))
+
+/**
+ * scic_sds_ssp_task_request_get_response_buffer() -
+ *
+ * This macro returns the address of the ssp response buffer in the task
+ * request memory.
+ */
+#define scic_sds_ssp_task_request_get_response_buffer(memory) \
+	((struct sci_ssp_response_iu *)(\
+		 ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \
+		 + sizeof(struct sci_ssp_task_iu) \
+		 ))
+
+/**
+ * scic_sds_ssp_task_request_get_task_context_buffer() -
+ *
+ * This macro returs the task context buffer for the SSP task request.
+ */
+#define scic_sds_ssp_task_request_get_task_context_buffer(memory) \
+	((struct scu_task_context *)(\
+		 ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \
+		 + sizeof(struct sci_ssp_response_iu) \
+		 ))
+
+
+
+/*
+ * ****************************************************************************
+ * * SCIC SDS IO REQUEST PRIVATE METHODS
+ * **************************************************************************** */
+
+/**
+ *
+ *
+ * This method returns the size required to store an SSP IO request object. u32
+ */
+static u32 scic_sds_ssp_request_get_object_size(void)
+{
+	return sizeof(struct scic_sds_request)
+	       + scic_ssp_io_request_get_object_size()
+	       + sizeof(struct scu_task_context)
+	       + SMP_CACHE_BYTES
+	       + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS;
+}
+
+/**
+ * This method returns the sgl element pair for the specificed sgl_pair index.
+ * @this_request: This parameter specifies the IO request for which to retrieve
+ *    the Scatter-Gather List element pair.
+ * @sgl_pair_index: This parameter specifies the index into the SGL element
+ *    pair to be retrieved.
+ *
+ * This method returns a pointer to an struct scu_sgl_element_pair.
+ */
+static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair(
+	struct scic_sds_request *this_request,
+	u32 sgl_pair_index
+	) {
+	struct scu_task_context *task_context;
+
+	task_context = (struct scu_task_context *)this_request->task_context_buffer;
+
+	if (sgl_pair_index == 0) {
+		return &task_context->sgl_pair_ab;
+	} else if (sgl_pair_index == 1) {
+		return &task_context->sgl_pair_cd;
+	}
+
+	return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2];
+}
+
+/**
+ * This function will build the SGL list for an IO request.
+ * @this_request: This parameter specifies the IO request for which to build
+ *    the Scatter-Gather List.
+ *
+ */
+void scic_sds_request_build_sgl(struct scic_sds_request *sds_request)
+{
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+	struct isci_host *isci_host = isci_request->isci_host;
+	struct sas_task *task = isci_request_access_task(isci_request);
+	struct scatterlist *sg = NULL;
+	dma_addr_t dma_addr;
+	u32 sg_idx = 0;
+	struct scu_sgl_element_pair *scu_sg   = NULL;
+	struct scu_sgl_element_pair *prev_sg  = NULL;
+
+	if (task->num_scatter > 0) {
+		sg = task->scatter;
+
+		while (sg) {
+			scu_sg = scic_sds_request_get_sgl_element_pair(
+					sds_request,
+					sg_idx);
+
+			SCU_SGL_COPY(scu_sg->A, sg);
+
+			sg = sg_next(sg);
+
+			if (sg) {
+				SCU_SGL_COPY(scu_sg->B, sg);
+				sg = sg_next(sg);
+			} else
+				SCU_SGL_ZERO(scu_sg->B);
+
+			if (prev_sg) {
+				dma_addr =
+					scic_io_request_get_dma_addr(
+							sds_request,
+							scu_sg);
+
+				prev_sg->next_pair_upper =
+					upper_32_bits(dma_addr);
+				prev_sg->next_pair_lower =
+					lower_32_bits(dma_addr);
+			}
+
+			prev_sg = scu_sg;
+			sg_idx++;
+		}
+	} else {	/* handle when no sg */
+		scu_sg = scic_sds_request_get_sgl_element_pair(sds_request,
+							       sg_idx);
+
+		dma_addr = dma_map_single(&isci_host->pdev->dev,
+					  task->scatter,
+					  task->total_xfer_len,
+					  task->data_dir);
+
+		isci_request->zero_scatter_daddr = dma_addr;
+
+		scu_sg->A.length = task->total_xfer_len;
+		scu_sg->A.address_upper = upper_32_bits(dma_addr);
+		scu_sg->A.address_lower = lower_32_bits(dma_addr);
+	}
+
+	if (scu_sg) {
+		scu_sg->next_pair_upper = 0;
+		scu_sg->next_pair_lower = 0;
+	}
+}
+
+/**
+ * This method initializes common portions of the io request object. This
+ *    includes construction of the struct sci_base_request parent.
+ * @the_controller: This parameter specifies the controller for which the
+ *    request is being constructed.
+ * @the_target: This parameter specifies the remote device for which the
+ *    request is being constructed.
+ * @io_tag: This parameter specifies the IO tag to be utilized for this
+ *    request.  This parameter can be set to SCI_CONTROLLER_INVALID_IO_TAG.
+ * @user_io_request_object: This parameter specifies the user request object
+ *    for which the request is being constructed.
+ * @this_request: This parameter specifies the request being constructed.
+ *
+ */
+static void scic_sds_general_request_construct(
+	struct scic_sds_controller *the_controller,
+	struct scic_sds_remote_device *the_target,
+	u16 io_tag,
+	void *user_io_request_object,
+	struct scic_sds_request *this_request)
+{
+	sci_base_request_construct(
+		&this_request->parent,
+		scic_sds_request_state_table
+		);
+
+	this_request->io_tag = io_tag;
+	this_request->user_request = user_io_request_object;
+	this_request->owning_controller = the_controller;
+	this_request->target_device = the_target;
+	this_request->has_started_substate_machine = false;
+	this_request->protocol = SCIC_NO_PROTOCOL;
+	this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX;
+	this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target);
+
+	this_request->sci_status   = SCI_SUCCESS;
+	this_request->scu_status   = 0;
+	this_request->post_context = 0xFFFFFFFF;
+
+	this_request->is_task_management_request = false;
+
+	if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) {
+		this_request->was_tag_assigned_by_user = false;
+		this_request->task_context_buffer = NULL;
+	} else {
+		this_request->was_tag_assigned_by_user = true;
+
+		this_request->task_context_buffer =
+			scic_sds_controller_get_task_context_buffer(
+				this_request->owning_controller, io_tag);
+	}
+}
+
+/**
+ * This method build the remainder of the IO request object.
+ * @this_request: This parameter specifies the request object being constructed.
+ *
+ * The scic_sds_general_request_construct() must be called before this call is
+ * valid. none
+ */
+static void scic_sds_ssp_io_request_assign_buffers(
+	struct scic_sds_request *this_request)
+{
+	this_request->command_buffer =
+		scic_sds_ssp_request_get_command_buffer(this_request);
+	this_request->response_buffer =
+		scic_sds_ssp_request_get_response_buffer(this_request);
+	this_request->sgl_element_pair_buffer =
+		scic_sds_ssp_request_get_sgl_element_buffer(this_request);
+	this_request->sgl_element_pair_buffer =
+		PTR_ALIGN(this_request->sgl_element_pair_buffer,
+			  sizeof(struct scu_sgl_element_pair));
+
+	if (this_request->was_tag_assigned_by_user == false) {
+		this_request->task_context_buffer =
+			scic_sds_ssp_request_get_task_context_buffer(this_request);
+		this_request->task_context_buffer =
+			PTR_ALIGN(this_request->task_context_buffer,
+				  SMP_CACHE_BYTES);
+	}
+}
+
+/**
+ * This method constructs the SSP Command IU data for this io request object.
+ * @this_request: This parameter specifies the request object for which the SSP
+ *    command information unit is being built.
+ *
+ */
+static void scic_sds_io_request_build_ssp_command_iu(
+	struct scic_sds_request *sds_request)
+{
+	struct sci_ssp_command_iu *command_frame;
+	u32 cdb_length;
+	u32 *cdb_buffer;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+	command_frame =
+		(struct sci_ssp_command_iu *)sds_request->command_buffer;
+
+	command_frame->lun_upper = 0;
+	command_frame->lun_lower =
+		isci_request_ssp_io_request_get_lun(isci_request);
+
+	((u32 *)command_frame)[2] = 0;
+
+	cdb_length = isci_request_ssp_io_request_get_cdb_length(isci_request);
+	cdb_buffer = (u32 *)isci_request_ssp_io_request_get_cdb_address(
+					isci_request);
+
+	if (cdb_length > 16) {
+		command_frame->additional_cdb_length = cdb_length - 16;
+	}
+
+	/* / @todo Is it ok to leave junk at the end of the cdb buffer? */
+	scic_word_copy_with_swap(
+		(u32 *)(&command_frame->cdb),
+		(u32 *)(cdb_buffer),
+		(cdb_length + 3) / sizeof(u32)
+		);
+
+	command_frame->enable_first_burst = 0;
+	command_frame->task_priority =
+		isci_request_ssp_io_request_get_command_priority(isci_request);
+	command_frame->task_attribute =
+		isci_request_ssp_io_request_get_task_attribute(isci_request);
+}
+
+
+/**
+ * This method constructs the SSP Task IU data for this io request object.
+ * @this_request:
+ *
+ */
+static void scic_sds_task_request_build_ssp_task_iu(
+	struct scic_sds_request *sds_request)
+{
+	struct sci_ssp_task_iu *command_frame;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+	command_frame =
+		(struct sci_ssp_task_iu *)sds_request->command_buffer;
+
+	command_frame->lun_upper = 0;
+	command_frame->lun_lower = isci_request_ssp_io_request_get_lun(
+					isci_request);
+
+	((u32 *)command_frame)[2] = 0;
+
+	command_frame->task_function =
+		isci_task_ssp_request_get_function(isci_request);
+	command_frame->task_tag =
+		isci_task_ssp_request_get_io_tag_to_manage(
+				isci_request);
+}
+
+
+/**
+ * This method is will fill in the SCU Task Context for any type of SSP request.
+ * @this_request:
+ * @task_context:
+ *
+ */
+static void scu_ssp_reqeust_construct_task_context(
+	struct scic_sds_request *sds_request,
+	struct scu_task_context *task_context)
+{
+	dma_addr_t dma_addr;
+	struct scic_sds_controller *controller;
+	struct scic_sds_remote_device *target_device;
+	struct scic_sds_port *target_port;
+
+	controller = scic_sds_request_get_controller(sds_request);
+	target_device = scic_sds_request_get_device(sds_request);
+	target_port = scic_sds_request_get_port(sds_request);
+
+	/* Fill in the TC with the its required data */
+	task_context->abort = 0;
+	task_context->priority = 0;
+	task_context->initiator_request = 1;
+	task_context->connection_rate =
+		scic_remote_device_get_connection_rate(target_device);
+	task_context->protocol_engine_index =
+		scic_sds_controller_get_protocol_engine_group(controller);
+	task_context->logical_port_index =
+		scic_sds_port_get_index(target_port);
+	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
+	task_context->valid = SCU_TASK_CONTEXT_VALID;
+	task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+	task_context->remote_node_index =
+		scic_sds_remote_device_get_index(sds_request->target_device);
+	task_context->command_code = 0;
+
+	task_context->link_layer_control = 0;
+	task_context->do_not_dma_ssp_good_response = 1;
+	task_context->strict_ordering = 0;
+	task_context->control_frame = 0;
+	task_context->timeout_enable = 0;
+	task_context->block_guard_enable = 0;
+
+	task_context->address_modifier = 0;
+
+	/* task_context->type.ssp.tag = this_request->io_tag; */
+	task_context->task_phase = 0x01;
+
+	if (sds_request->was_tag_assigned_by_user) {
+		/*
+		 * Build the task context now since we have already read
+		 * the data
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
+			 scic_sds_io_tag_get_index(sds_request->io_tag));
+	} else {
+		/*
+		 * Build the task context now since we have already read
+		 * the data
+		 *
+		 * I/O tag index is not assigned because we have to wait
+		 * until we get a TCi
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							owning_controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
+	}
+
+	/*
+	 * Copy the physical address for the command buffer to the
+	 * SCU Task Context
+	 */
+	dma_addr = scic_io_request_get_dma_addr(sds_request,
+						sds_request->command_buffer);
+
+	task_context->command_iu_upper = upper_32_bits(dma_addr);
+	task_context->command_iu_lower = lower_32_bits(dma_addr);
+
+	/*
+	 * Copy the physical address for the response buffer to the
+	 * SCU Task Context
+	 */
+	dma_addr = scic_io_request_get_dma_addr(sds_request,
+						sds_request->response_buffer);
+
+	task_context->response_iu_upper = upper_32_bits(dma_addr);
+	task_context->response_iu_lower = lower_32_bits(dma_addr);
+}
+
+/**
+ * This method is will fill in the SCU Task Context for a SSP IO request.
+ * @this_request:
+ *
+ */
+static void scu_ssp_io_request_construct_task_context(
+	struct scic_sds_request *sci_req,
+	enum dma_data_direction dir,
+	u32 len)
+{
+	struct scu_task_context *task_context;
+
+	task_context = scic_sds_request_get_task_context(sci_req);
+
+	scu_ssp_reqeust_construct_task_context(sci_req, task_context);
+
+	task_context->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32);
+	task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME;
+
+	switch (dir) {
+	case DMA_FROM_DEVICE:
+	case DMA_NONE:
+	default:
+		task_context->task_type = SCU_TASK_TYPE_IOREAD;
+		break;
+	case DMA_TO_DEVICE:
+		task_context->task_type = SCU_TASK_TYPE_IOWRITE;
+		break;
+	}
+
+	task_context->transfer_length_bytes = len;
+
+	if (task_context->transfer_length_bytes > 0)
+		scic_sds_request_build_sgl(sci_req);
+}
+
+
+/**
+ * This method will fill in the remainder of the io request object for SSP Task
+ *    requests.
+ * @this_request:
+ *
+ */
+static void scic_sds_ssp_task_request_assign_buffers(
+	struct scic_sds_request *this_request)
+{
+	/* Assign all of the buffer pointers */
+	this_request->command_buffer =
+		scic_sds_ssp_task_request_get_command_buffer(this_request);
+	this_request->response_buffer =
+		scic_sds_ssp_task_request_get_response_buffer(this_request);
+	this_request->sgl_element_pair_buffer = NULL;
+
+	if (this_request->was_tag_assigned_by_user == false) {
+		this_request->task_context_buffer =
+			scic_sds_ssp_task_request_get_task_context_buffer(this_request);
+		this_request->task_context_buffer =
+			PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES);
+	}
+}
+
+/**
+ * This method will fill in the SCU Task Context for a SSP Task request.  The
+ *    following important settings are utilized: -# priority ==
+ *    SCU_TASK_PRIORITY_HIGH.  This ensures that the task request is issued
+ *    ahead of other task destined for the same Remote Node. -# task_type ==
+ *    SCU_TASK_TYPE_IOREAD.  This simply indicates that a normal request type
+ *    (i.e. non-raw frame) is being utilized to perform task management. -#
+ *    control_frame == 1.  This ensures that the proper endianess is set so
+ *    that the bytes are transmitted in the right order for a task frame.
+ * @this_request: This parameter specifies the task request object being
+ *    constructed.
+ *
+ */
+static void scu_ssp_task_request_construct_task_context(
+	struct scic_sds_request *this_request)
+{
+	struct scu_task_context *task_context;
+
+	task_context = scic_sds_request_get_task_context(this_request);
+
+	scu_ssp_reqeust_construct_task_context(this_request, task_context);
+
+	task_context->control_frame                = 1;
+	task_context->priority                     = SCU_TASK_PRIORITY_HIGH;
+	task_context->task_type                    = SCU_TASK_TYPE_RAW_FRAME;
+	task_context->transfer_length_bytes        = 0;
+	task_context->type.ssp.frame_type          = SCI_SAS_TASK_FRAME;
+	task_context->ssp_command_iu_length = sizeof(struct sci_ssp_task_iu) / sizeof(u32);
+}
+
+
+/**
+ * This method constructs the SSP Command IU data for this ssp passthrough
+ *    comand request object.
+ * @this_request: This parameter specifies the request object for which the SSP
+ *    command information unit is being built.
+ *
+ * enum sci_status, returns invalid parameter is cdb > 16
+ */
+
+
+/**
+ * This method constructs the SATA request object.
+ * @this_request:
+ * @sat_protocol:
+ * @transfer_length:
+ * @data_direction:
+ * @copy_rx_frame:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *sci_req,
+						      u8 proto, u32 len,
+						      enum dma_data_direction dir,
+						      bool copy)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	switch (proto) {
+	case SAT_PROTOCOL_PIO_DATA_IN:
+	case SAT_PROTOCOL_PIO_DATA_OUT:
+		status = scic_sds_stp_pio_request_construct(sci_req, proto, copy);
+		break;
+
+	case SAT_PROTOCOL_UDMA_DATA_IN:
+	case SAT_PROTOCOL_UDMA_DATA_OUT:
+		status = scic_sds_stp_udma_request_construct(sci_req, len, dir);
+		break;
+
+	case SAT_PROTOCOL_ATA_HARD_RESET:
+	case SAT_PROTOCOL_SOFT_RESET:
+		status = scic_sds_stp_soft_reset_request_construct(sci_req);
+		break;
+
+	case SAT_PROTOCOL_NON_DATA:
+		status = scic_sds_stp_non_data_request_construct(sci_req);
+		break;
+
+	case SAT_PROTOCOL_FPDMA:
+		status = scic_sds_stp_ncq_request_construct(sci_req, len, dir);
+		break;
+
+#if !defined(DISABLE_ATAPI)
+	case SAT_PROTOCOL_PACKET_NON_DATA:
+	case SAT_PROTOCOL_PACKET_DMA_DATA_IN:
+	case SAT_PROTOCOL_PACKET_DMA_DATA_OUT:
+	case SAT_PROTOCOL_PACKET_PIO_DATA_IN:
+	case SAT_PROTOCOL_PACKET_PIO_DATA_OUT:
+		status = scic_sds_stp_packet_request_construct(sci_req);
+		break;
+#endif
+
+	case SAT_PROTOCOL_DMA_QUEUED:
+	case SAT_PROTOCOL_DMA:
+	case SAT_PROTOCOL_DEVICE_DIAGNOSTIC:
+	case SAT_PROTOCOL_DEVICE_RESET:
+	case SAT_PROTOCOL_RETURN_RESPONSE_INFO:
+	default:
+		dev_err(scic_to_dev(sci_req->owning_controller),
+			"%s: SCIC IO Request 0x%p received un-handled "
+			"SAT Protocl %d.\n",
+			__func__, sci_req, proto);
+
+		status = SCI_FAILURE;
+		break;
+	}
+
+	return status;
+}
+
+/*
+ * ****************************************************************************
+ * * SCIC Interface Implementation
+ * **************************************************************************** */
+
+
+
+
+/* --------------------------------------------------------------------------- */
+
+u32 scic_io_request_get_object_size(void)
+{
+	u32 ssp_request_size;
+	u32 stp_request_size;
+	u32 smp_request_size;
+
+	ssp_request_size = scic_sds_ssp_request_get_object_size();
+	stp_request_size = scic_sds_stp_request_get_object_size();
+	smp_request_size = scic_sds_smp_request_get_object_size();
+
+	return max(ssp_request_size, max(stp_request_size, smp_request_size));
+}
+
+/* --------------------------------------------------------------------------- */
+
+
+/* --------------------------------------------------------------------------- */
+
+
+/* --------------------------------------------------------------------------- */
+
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_io_request_construct(
+	struct scic_sds_controller *scic_controller,
+	struct scic_sds_remote_device *scic_remote_device,
+	u16 io_tag,
+	void *user_io_request_object,
+	void *scic_io_request_memory,
+	struct scic_sds_request **new_scic_io_request_handle)
+{
+	enum sci_status status = SCI_SUCCESS;
+	struct scic_sds_request *this_request;
+	struct smp_discover_response_protocols device_protocol;
+
+	this_request = (struct scic_sds_request *)scic_io_request_memory;
+
+	/* Build the common part of the request */
+	scic_sds_general_request_construct(
+		(struct scic_sds_controller *)scic_controller,
+		(struct scic_sds_remote_device *)scic_remote_device,
+		io_tag,
+		user_io_request_object,
+		this_request
+		);
+
+	if (
+		scic_sds_remote_device_get_index((struct scic_sds_remote_device *)scic_remote_device)
+		== SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+		) {
+		return SCI_FAILURE_INVALID_REMOTE_DEVICE;
+	}
+
+	scic_remote_device_get_protocols(scic_remote_device, &device_protocol);
+
+	if (device_protocol.u.bits.attached_ssp_target) {
+		scic_sds_ssp_io_request_assign_buffers(this_request);
+	} else if (device_protocol.u.bits.attached_stp_target) {
+		scic_sds_stp_request_assign_buffers(this_request);
+		memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
+	} else if (device_protocol.u.bits.attached_smp_target) {
+		scic_sds_smp_request_assign_buffers(this_request);
+		memset(this_request->command_buffer, 0, sizeof(struct smp_request));
+	} else {
+		status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+	}
+
+	if (status == SCI_SUCCESS) {
+		memset(
+			this_request->task_context_buffer,
+			0,
+			SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab)
+			);
+		*new_scic_io_request_handle = scic_io_request_memory;
+	}
+
+	return status;
+}
+
+/* --------------------------------------------------------------------------- */
+
+
+enum sci_status scic_task_request_construct(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	u16 io_tag,
+	void *user_io_request_object,
+	void *scic_task_request_memory,
+	struct scic_sds_request **new_scic_task_request_handle)
+{
+	enum sci_status status = SCI_SUCCESS;
+	struct scic_sds_request *this_request = (struct scic_sds_request *)
+					   scic_task_request_memory;
+	struct smp_discover_response_protocols device_protocol;
+
+	/* Build the common part of the request */
+	scic_sds_general_request_construct(
+		(struct scic_sds_controller *)controller,
+		(struct scic_sds_remote_device *)remote_device,
+		io_tag,
+		user_io_request_object,
+		this_request
+		);
+
+	scic_remote_device_get_protocols(remote_device, &device_protocol);
+
+	if (device_protocol.u.bits.attached_ssp_target) {
+		scic_sds_ssp_task_request_assign_buffers(this_request);
+
+		this_request->has_started_substate_machine = true;
+
+		/* Construct the started sub-state machine. */
+		sci_base_state_machine_construct(
+			&this_request->started_substate_machine,
+			&this_request->parent.parent,
+			scic_sds_io_request_started_task_mgmt_substate_table,
+			SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+			);
+	} else if (device_protocol.u.bits.attached_stp_target) {
+		scic_sds_stp_request_assign_buffers(this_request);
+	} else {
+		status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+	}
+
+	if (status == SCI_SUCCESS) {
+		this_request->is_task_management_request = true;
+		memset(this_request->task_context_buffer, 0x00, sizeof(struct scu_task_context));
+		*new_scic_task_request_handle            = scic_task_request_memory;
+	}
+
+	return status;
+}
+
+
+enum sci_status scic_io_request_construct_basic_ssp(
+	struct scic_sds_request *sci_req)
+{
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sci_req);
+
+	sci_req->protocol = SCIC_SSP_PROTOCOL;
+
+	scu_ssp_io_request_construct_task_context(
+		sci_req,
+		isci_request_io_request_get_data_direction(isci_request),
+		isci_request_io_request_get_transfer_length(isci_request));
+
+	scic_sds_io_request_build_ssp_command_iu(sci_req);
+
+	sci_base_state_machine_change_state(
+		&sci_req->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_CONSTRUCTED
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+enum sci_status scic_task_request_construct_ssp(
+	struct scic_sds_request *sci_req)
+{
+	/* Construct the SSP Task SCU Task Context */
+	scu_ssp_task_request_construct_task_context(sci_req);
+
+	/* Fill in the SSP Task IU */
+	scic_sds_task_request_build_ssp_task_iu(sci_req);
+
+	sci_base_state_machine_change_state(
+		&sci_req->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_CONSTRUCTED
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+enum sci_status scic_io_request_construct_basic_sata(
+		struct scic_sds_request *sci_req)
+{
+	enum sci_status status;
+	struct scic_sds_stp_request *stp_req;
+	u8 proto;
+	u32 len;
+	enum dma_data_direction dir;
+	bool copy = false;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sci_req);
+	struct sas_task *task = isci_request_access_task(isci_request);
+
+	stp_req = container_of(sci_req, typeof(*stp_req), parent);
+
+	sci_req->protocol = SCIC_STP_PROTOCOL;
+
+	len = isci_request_io_request_get_transfer_length(isci_request);
+	dir = isci_request_io_request_get_data_direction(isci_request);
+	proto = isci_sata_get_sat_protocol(isci_request);
+	copy = (task->data_dir == DMA_NONE) ? false : true;
+
+	status = scic_io_request_construct_sata(sci_req, proto, len, dir, copy);
+
+	if (status == SCI_SUCCESS)
+		sci_base_state_machine_change_state(
+			&sci_req->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_CONSTRUCTED
+			);
+
+	return status;
+}
+
+
+enum sci_status scic_task_request_construct_sata(
+	struct scic_sds_request *sci_req)
+{
+	enum sci_status status;
+	u8 sat_protocol;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sci_req);
+
+	sat_protocol = isci_sata_get_sat_protocol(isci_request);
+
+	switch (sat_protocol) {
+	case SAT_PROTOCOL_ATA_HARD_RESET:
+	case SAT_PROTOCOL_SOFT_RESET:
+		status = scic_sds_stp_soft_reset_request_construct(sci_req);
+		break;
+
+	default:
+		dev_err(scic_to_dev(sci_req->owning_controller),
+			"%s: SCIC IO Request 0x%p received un-handled SAT "
+			"Protocl %d.\n",
+			__func__,
+			sci_req,
+			sat_protocol);
+
+		status = SCI_FAILURE;
+		break;
+	}
+
+	if (status == SCI_SUCCESS)
+		sci_base_state_machine_change_state(
+			&sci_req->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_CONSTRUCTED
+			);
+
+	return status;
+}
+
+
+u16 scic_io_request_get_io_tag(
+	struct scic_sds_request *sci_req)
+{
+	return sci_req->io_tag;
+}
+
+
+u32 scic_request_get_controller_status(
+	struct scic_sds_request *sci_req)
+{
+	return sci_req->scu_status;
+}
+
+
+void *scic_io_request_get_command_iu_address(
+	struct scic_sds_request *sci_req)
+{
+	return sci_req->command_buffer;
+}
+
+
+void *scic_io_request_get_response_iu_address(
+	struct scic_sds_request *sci_req)
+{
+	return sci_req->response_buffer;
+}
+
+
+#define SCU_TASK_CONTEXT_SRAM 0x200000
+u32 scic_io_request_get_number_of_bytes_transferred(
+	struct scic_sds_request *scic_sds_request)
+{
+	u32 ret_val = 0;
+
+	if (SMU_AMR_READ(scic_sds_request->owning_controller) == 0) {
+		/*
+		 * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where
+		 *   BAR1 is the scu_registers
+		 *   0x20002C = 0x200000 + 0x2c
+		 *            = start of task context SRAM + offset of (type.ssp.data_offset)
+		 *   TCi is the io_tag of struct scic_sds_request */
+		ret_val =  scic_sds_pci_read_scu_dword(
+			scic_sds_request->owning_controller,
+			(
+				(u8 *)scic_sds_request->owning_controller->scu_registers +
+				(SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(struct scu_task_context, type.ssp.data_offset)) +
+				((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag))
+			)
+			);
+	}
+
+	return ret_val;
+}
+
+
+/*
+ * ****************************************************************************
+ * * SCIC SDS Interface Implementation
+ * **************************************************************************** */
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start
+ *    operation is to be executed.
+ *
+ * This method invokes the base state start request handler for the
+ * SCIC_SDS_IO_REQUEST_T object. enum sci_status
+ */
+enum sci_status scic_sds_request_start(
+	struct scic_sds_request *this_request)
+{
+	if (
+		this_request->device_sequence
+		== scic_sds_remote_device_get_sequence(this_request->target_device)
+		) {
+		return this_request->state_handlers->parent.start_handler(
+			       &this_request->parent
+			       );
+	}
+
+	return SCI_FAILURE;
+}
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start
+ *    operation is to be executed.
+ *
+ * This method invokes the base state terminate request handber for the
+ * SCIC_SDS_IO_REQUEST_T object. enum sci_status
+ */
+enum sci_status scic_sds_io_request_terminate(
+	struct scic_sds_request *this_request)
+{
+	return this_request->state_handlers->parent.abort_handler(
+		       &this_request->parent);
+}
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start
+ *    operation is to be executed.
+ *
+ * This method invokes the base state request completion handler for the
+ * SCIC_SDS_IO_REQUEST_T object. enum sci_status
+ */
+enum sci_status scic_sds_io_request_complete(
+	struct scic_sds_request *this_request)
+{
+	return this_request->state_handlers->parent.complete_handler(
+		       &this_request->parent);
+}
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start
+ *    operation is to be executed.
+ * @event_code: The event code returned by the hardware for the task reqeust.
+ *
+ * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T
+ * object. enum sci_status
+ */
+enum sci_status scic_sds_io_request_event_handler(
+	struct scic_sds_request *this_request,
+	u32 event_code)
+{
+	return this_request->state_handlers->event_handler(this_request, event_code);
+}
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start
+ *    operation is to be executed.
+ * @frame_index: The frame index returned by the hardware for the reqeust
+ *    object.
+ *
+ * This method invokes the core state frame handler for the
+ * SCIC_SDS_IO_REQUEST_T object. enum sci_status
+ */
+enum sci_status scic_sds_io_request_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	return this_request->state_handlers->frame_handler(this_request, frame_index);
+}
+
+/**
+ *
+ * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the task start
+ *    operation is to be executed.
+ *
+ * This method invokes the core state task complete handler for the
+ * SCIC_SDS_IO_REQUEST_T object. enum sci_status
+ */
+
+/*
+ * ****************************************************************************
+ * * SCIC SDS PROTECTED METHODS
+ * **************************************************************************** */
+
+/**
+ * This method copies response data for requests returning response data
+ *    instead of sense data.
+ * @this_request: This parameter specifies the request object for which to copy
+ *    the response data.
+ *
+ */
+void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request)
+{
+	void *response_buffer;
+	u32 user_response_length;
+	u32 core_response_length;
+	struct sci_ssp_response_iu *ssp_response;
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+	ssp_response =
+		(struct sci_ssp_response_iu *)sds_request->response_buffer;
+
+	response_buffer =
+		isci_task_ssp_request_get_response_data_address(
+				isci_request);
+
+	user_response_length =
+		isci_task_ssp_request_get_response_data_length(
+				isci_request);
+
+	core_response_length = sci_ssp_get_response_data_length(
+					ssp_response->response_data_length);
+
+	user_response_length = min(user_response_length, core_response_length);
+
+	memcpy(response_buffer, ssp_response->data, user_response_length);
+}
+
+/*
+ * *****************************************************************************
+ * *  DEFAULT STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * scic_sds_request_default_start_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_start() request.  The default action is
+ * to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_start_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *scic_request =
+		(struct scic_sds_request *)request;
+
+	dev_warn(scic_to_dev(scic_request->owning_controller),
+		 "%s: SCIC IO Request requested to start while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 &((struct scic_sds_request *)request)->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+static enum sci_status scic_sds_request_default_abort_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *scic_request =
+		(struct scic_sds_request *)request;
+
+	dev_warn(scic_to_dev(scic_request->owning_controller),
+		"%s: SCIC IO Request requested to abort while in wrong "
+		"state %d\n",
+		__func__,
+		sci_base_state_machine_get_state(
+			&((struct scic_sds_request *)request)->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * scic_sds_request_default_complete_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request.  The default action
+ * is to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_complete_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *scic_request =
+		(struct scic_sds_request *)request;
+
+	dev_warn(scic_to_dev(scic_request->owning_controller),
+		"%s: SCIC IO Request requested to complete while in wrong "
+		"state %d\n",
+		__func__,
+		sci_base_state_machine_get_state(
+			&((struct scic_sds_request *)request)->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * scic_sds_request_default_destruct_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request.  The default action
+ * is to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_destruct_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *scic_request =
+		(struct scic_sds_request *)request;
+
+	dev_warn(scic_to_dev(scic_request->owning_controller),
+		 "%s: SCIC IO Request requested to destroy while in wrong "
+		 "state %d\n",
+		 __func__,
+		 sci_base_state_machine_get_state(
+			 &((struct scic_sds_request *)request)->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * scic_sds_request_default_tc_completion_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_task_request_complete() request.  The default
+ * action is to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	dev_warn(scic_to_dev(this_request->owning_controller),
+		"%s: SCIC IO Request given task completion notification %x "
+		"while in wrong state %d\n",
+		__func__,
+		completion_code,
+		sci_base_state_machine_get_state(
+			&this_request->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+
+}
+
+/**
+ * scic_sds_request_default_event_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_event_handler() request.  The default
+ * action is to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_event_handler(
+	struct scic_sds_request *this_request,
+	u32 event_code)
+{
+	dev_warn(scic_to_dev(this_request->owning_controller),
+		 "%s: SCIC IO Request given event code notification %x while "
+		 "in wrong state %d\n",
+		 __func__,
+		 event_code,
+		 sci_base_state_machine_get_state(
+			 &this_request->parent.state_machine));
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * scic_sds_request_default_frame_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_event_handler() request.  The default
+ * action is to log a warning and return a failure status. enum sci_status
+ * SCI_FAILURE_INVALID_STATE
+ */
+enum sci_status scic_sds_request_default_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	dev_warn(scic_to_dev(this_request->owning_controller),
+		 "%s: SCIC IO Request given unexpected frame %x while in "
+		 "state %d\n",
+		 __func__,
+		 frame_index,
+		 sci_base_state_machine_get_state(
+			 &this_request->parent.state_machine));
+
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index);
+
+	return SCI_FAILURE_INVALID_STATE;
+}
+
+/*
+ * *****************************************************************************
+ * *  CONSTRUCTED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * scic_sds_request_constructed_state_start_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action taken when a constructed
+ * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request.
+ * This method will, if necessary, allocate a TCi for the io request object and
+ * then will, if necessary, copy the constructed TC data into the actual TC
+ * buffer.  If everything is successful the post context field is updated with
+ * the TCi so the controller can post the request to the hardware. enum sci_status
+ * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES
+ */
+static enum sci_status scic_sds_request_constructed_state_start_handler(
+	struct sci_base_request *request)
+{
+	struct scu_task_context *task_context;
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) {
+		this_request->io_tag =
+			scic_controller_allocate_io_tag(this_request->owning_controller);
+	}
+
+	/* Record the IO Tag in the request */
+	if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) {
+		task_context = this_request->task_context_buffer;
+
+		task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag);
+
+		switch (task_context->protocol_type) {
+		case SCU_TASK_CONTEXT_PROTOCOL_SMP:
+		case SCU_TASK_CONTEXT_PROTOCOL_SSP:
+			/* SSP/SMP Frame */
+			task_context->type.ssp.tag = this_request->io_tag;
+			task_context->type.ssp.target_port_transfer_tag = 0xFFFF;
+			break;
+
+		case SCU_TASK_CONTEXT_PROTOCOL_STP:
+			/*
+			 * STP/SATA Frame
+			 * task_context->type.stp.ncq_tag = this_request->ncq_tag; */
+			break;
+
+		case SCU_TASK_CONTEXT_PROTOCOL_NONE:
+			/* / @todo When do we set no protocol type? */
+			break;
+
+		default:
+			/* This should never happen since we build the IO requests */
+			break;
+		}
+
+		/*
+		 * Check to see if we need to copy the task context buffer
+		 * or have been building into the task context buffer */
+		if (this_request->was_tag_assigned_by_user == false) {
+			scic_sds_controller_copy_task_context(
+				this_request->owning_controller, this_request
+				);
+		}
+
+		/* Add to the post_context the io tag value */
+		this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag);
+
+		/* Everything is good go ahead and change state */
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_STARTED
+			);
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+}
+
+/**
+ * scic_sds_request_constructed_state_abort_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request. Since the request
+ * has not yet been posted to the hardware the request transitions to the
+ * completed state. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_request_constructed_state_abort_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	/*
+	 * This request has been terminated by the user make sure that the correct
+	 * status code is returned */
+	scic_sds_request_set_status(
+		this_request,
+		SCU_TASK_DONE_TASK_ABORT,
+		SCI_FAILURE_IO_TERMINATED
+		);
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * *  STARTED STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * scic_sds_request_started_state_abort_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request. Since the request
+ * has been posted to the hardware the io request state is changed to the
+ * aborting state. enum sci_status SCI_SUCCESS
+ */
+enum sci_status scic_sds_request_started_state_abort_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	if (this_request->has_started_substate_machine) {
+		sci_base_state_machine_stop(&this_request->started_substate_machine);
+	}
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_ABORTING
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * scic_sds_request_started_state_tc_completion_handler() - This method process
+ *    TC (task context) completions for normal IO request (i.e. Task/Abort
+ *    Completions of type 0).  This method will update the
+ *    SCIC_SDS_IO_REQUEST_T::status field.
+ * @this_request: This parameter specifies the request for which a completion
+ *    occurred.
+ * @completion_code: This parameter specifies the completion code received from
+ *    the SCU.
+ *
+ */
+enum sci_status scic_sds_request_started_state_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	u8 data_present;
+	struct sci_ssp_response_iu *response_buffer;
+
+	/**
+	 * @todo Any SDMA return code of other than 0 is bad
+	 *       decode 0x003C0000 to determine SDMA status
+	 */
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+		break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP):
+	{
+		/*
+		 * There are times when the SCU hardware will return an early response
+		 * because the io request specified more data than is returned by the
+		 * target device (mode pages, inquiry data, etc.).  We must check the
+		 * response stats to see if this is truly a failed request or a good
+		 * request that just got completed early. */
+		struct sci_ssp_response_iu *response = (struct sci_ssp_response_iu *)
+						  this_request->response_buffer;
+		scic_word_copy_with_swap(
+			this_request->response_buffer,
+			this_request->response_buffer,
+			sizeof(struct sci_ssp_response_iu) / sizeof(u32)
+			);
+
+		if (response->status == 0) {
+			scic_sds_request_set_status(
+				this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
+				);
+		} else {
+			scic_sds_request_set_status(
+				this_request,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+		}
+	}
+	break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE):
+		scic_word_copy_with_swap(
+			this_request->response_buffer,
+			this_request->response_buffer,
+			sizeof(struct sci_ssp_response_iu) / sizeof(u32)
+			);
+
+		scic_sds_request_set_status(
+			this_request,
+			SCU_TASK_DONE_CHECK_RESPONSE,
+			SCI_FAILURE_IO_RESPONSE_VALID
+			);
+		break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR):
+		/*
+		 * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed
+		 * /       to be received before this completion status is posted? */
+		response_buffer =
+			(struct sci_ssp_response_iu *)this_request->response_buffer;
+		data_present =
+			response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK;
+
+		if ((data_present == 0x01) || (data_present == 0x02)) {
+			scic_sds_request_set_status(
+				this_request,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_IO_RESPONSE_VALID
+				);
+		} else {
+			scic_sds_request_set_status(
+				this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+				);
+		}
+		break;
+
+	/* only stp device gets suspended. */
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR):
+		if (this_request->protocol == SCIC_STP_PROTOCOL) {
+			scic_sds_request_set_status(
+				this_request,
+				SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+				SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
+				);
+		} else {
+			scic_sds_request_set_status(
+				this_request,
+				SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+				SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+				);
+		}
+		break;
+
+	/* both stp/ssp device gets suspended */
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED):
+		scic_sds_request_set_status(
+			this_request,
+			SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+			SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
+			);
+		break;
+
+	/* neither ssp nor stp gets suspended. */
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND):
+	default:
+		scic_sds_request_set_status(
+			this_request,
+			SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+		break;
+	}
+
+	/**
+	 * @todo This is probably wrong for ACK/NAK timeout conditions
+	 */
+
+	/* In all cases we will treat this as the completion of the IO request. */
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * scic_sds_request_started_state_frame_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ * @frame_index: This is the index of the unsolicited frame to be processed.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_frame_handler() request. This method
+ * first determines the frame type received.  If this is a response frame then
+ * the response data is copied to the io request response buffer for processing
+ * at completion time. If the frame type is not a response buffer an error is
+ * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE
+ */
+static enum sci_status scic_sds_request_started_state_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	struct sci_ssp_frame_header *frame_header;
+
+	/* / @todo If this is a response frame we must record that we received it */
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_request_get_controller(this_request)->uf_control),
+		frame_index,
+		(void **)&frame_header
+		);
+
+	if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) {
+		struct sci_ssp_response_iu *response_buffer;
+
+		status = scic_sds_unsolicited_frame_control_get_buffer(
+			&(scic_sds_request_get_controller(this_request)->uf_control),
+			frame_index,
+			(void **)&response_buffer
+			);
+
+		scic_word_copy_with_swap(
+			this_request->response_buffer,
+			(u32 *)response_buffer,
+			sizeof(struct sci_ssp_response_iu)
+			);
+
+		response_buffer = (struct sci_ssp_response_iu *)this_request->response_buffer;
+
+		if ((response_buffer->data_present == 0x01) ||
+		    (response_buffer->data_present == 0x02)) {
+			scic_sds_request_set_status(
+				this_request,
+				SCU_TASK_DONE_CHECK_RESPONSE,
+				SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+				);
+		} else
+			scic_sds_request_set_status(
+				this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+				);
+	} else
+		/* This was not a response frame why did it get forwarded? */
+		dev_err(scic_to_dev(this_request->owning_controller),
+			"%s: SCIC IO Request 0x%p received unexpected "
+			"frame %d type 0x%02x\n",
+			__func__,
+			this_request,
+			frame_index,
+			frame_header->frame_type);
+
+	/*
+	 * In any case we are done with this frame buffer return it to the
+	 * controller */
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * *  COMPLETED STATE HANDLERS
+ * ***************************************************************************** */
+
+
+/**
+ * scic_sds_request_completed_state_complete_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request. This method frees up
+ * any io request resources that have been allocated and transitions the
+ * request to its final state. Consider stopping the state machine instead of
+ * transitioning to the final state? enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_request_completed_state_complete_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	if (this_request->was_tag_assigned_by_user != true) {
+		scic_controller_free_io_tag(
+			this_request->owning_controller, this_request->io_tag
+			);
+	}
+
+	if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) {
+		scic_sds_controller_release_frame(
+			this_request->owning_controller, this_request->saved_rx_frame_index);
+	}
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_FINAL
+		);
+
+	return SCI_SUCCESS;
+}
+
+/*
+ * *****************************************************************************
+ * *  ABORTING STATE HANDLERS
+ * ***************************************************************************** */
+
+/**
+ * scic_sds_request_aborting_state_abort_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request. This method is the
+ * io request aborting state abort handlers.  On receipt of a multiple
+ * terminate requests the io request will transition to the completed state.
+ * This should not happen in normal operation. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_request_aborting_state_abort_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * scic_sds_request_aborting_state_tc_completion_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_task_completion() request. This method
+ * decodes the completion type waiting for the abort task complete
+ * notification. When the abort task complete is received the io request
+ * transitions to the completed state. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_request_aborting_state_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+	case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+
+	default:
+		/*
+		 * Unless we get some strange error wait for the task abort to complete
+		 * TODO: Should there be a state change for this completion? */
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * scic_sds_request_aborting_state_frame_handler() -
+ * @request: This is the struct sci_base_request object that is cast to the
+ *    SCIC_SDS_IO_REQUEST_T object for which the start operation is requested.
+ *
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_frame_handler() request. This method
+ * discards the unsolicited frame since we are waiting for the abort task
+ * completion. enum sci_status SCI_SUCCESS
+ */
+static enum sci_status scic_sds_request_aborting_state_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	/* TODO: Is it even possible to get an unsolicited frame in the aborting state? */
+
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index);
+
+	return SCI_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = {
+	[SCI_BASE_REQUEST_STATE_INITIAL] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_default_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {
+		.parent.start_handler    = scic_sds_request_constructed_state_start_handler,
+		.parent.abort_handler    = scic_sds_request_constructed_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCI_BASE_REQUEST_STATE_STARTED] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_started_state_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_started_state_frame_handler,
+	},
+	[SCI_BASE_REQUEST_STATE_COMPLETED] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_default_abort_handler,
+		.parent.complete_handler = scic_sds_request_completed_state_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCI_BASE_REQUEST_STATE_ABORTING] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_aborting_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_aborting_state_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_aborting_state_frame_handler,
+	},
+	[SCI_BASE_REQUEST_STATE_FINAL] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_default_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+};
+
+/**
+ * scic_sds_request_initial_state_enter() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occurring.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial
+ * base request is constructed. Entry into the initial state sets all handlers
+ * for the io request object to their default handlers. none
+ */
+static void scic_sds_request_initial_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_INITIAL
+		);
+}
+
+/**
+ * scic_sds_request_constructed_state_enter() -
+ * @object: The io request object that is to enter the constructed state.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers
+ * for the the constructed state. none
+ */
+static void scic_sds_request_constructed_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_CONSTRUCTED
+		);
+}
+
+/**
+ * scic_sds_request_started_state_enter() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occuring.  This is cast into a SCIC_SDS_IO_REQUEST object.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a
+ * SCSI Task request we must enter the started substate machine. none
+ */
+static void scic_sds_request_started_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_STARTED
+		);
+
+	/*
+	 * Most of the request state machines have a started substate machine so
+	 * start its execution on the entry to the started state. */
+	if (this_request->has_started_substate_machine == true)
+		sci_base_state_machine_start(&this_request->started_substate_machine);
+}
+
+/**
+ * scic_sds_request_started_state_exit() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occuring.  This object is cast into a SCIC_SDS_IO_REQUEST
+ *    object.
+ *
+ * This method implements the actions taken when exiting the
+ * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be
+ * to stop the started substate machine. none
+ */
+static void scic_sds_request_started_state_exit(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	if (this_request->has_started_substate_machine == true)
+		sci_base_state_machine_stop(&this_request->started_substate_machine);
+}
+
+/**
+ * scic_sds_request_completed_state_enter() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occuring.  This object is cast into a SCIC_SDS_IO_REQUEST
+ *    object.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_COMPLETED state.  This state is entered when the
+ * SCIC_SDS_IO_REQUEST has completed.  The method will decode the request
+ * completion status and convert it to an enum sci_status to return in the
+ * completion callback function. none
+ */
+static void scic_sds_request_completed_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	/* Tell the SCI_USER that the IO request is complete */
+	if (this_request->is_task_management_request == false) {
+		isci_event_io_request_complete(
+			scic_sds_request_get_controller(this_request),
+			scic_sds_request_get_device(this_request),
+			this_request,
+			this_request->sci_status
+			);
+	} else {
+		isci_event_task_request_complete(
+			scic_sds_request_get_controller(this_request),
+			scic_sds_request_get_device(this_request),
+			this_request,
+			this_request->sci_status
+			);
+	}
+}
+
+/**
+ * scic_sds_request_aborting_state_enter() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occuring.  This object is cast into a SCIC_SDS_IO_REQUEST
+ *    object.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_ABORTING state. none
+ */
+static void scic_sds_request_aborting_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	/* Setting the abort bit in the Task Context is required by the silicon. */
+	this_request->task_context_buffer->abort = 1;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_ABORTING
+		);
+}
+
+/**
+ * scic_sds_request_final_state_enter() -
+ * @object: This parameter specifies the base object for which the state
+ *    transition is occuring.  This is cast into a SCIC_SDS_IO_REQUEST object.
+ *
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the
+ * state handlers in place. none
+ */
+static void scic_sds_request_final_state_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_request_state_handler_table,
+		SCI_BASE_REQUEST_STATE_FINAL
+		);
+}
+
+/* --------------------------------------------------------------------------- */
+
+const struct sci_base_state scic_sds_request_state_table[] = {
+	[SCI_BASE_REQUEST_STATE_INITIAL] = {
+		.enter_state = scic_sds_request_initial_state_enter,
+	},
+	[SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {
+		.enter_state = scic_sds_request_constructed_state_enter,
+	},
+	[SCI_BASE_REQUEST_STATE_STARTED] = {
+		.enter_state = scic_sds_request_started_state_enter,
+		.exit_state  = scic_sds_request_started_state_exit
+	},
+	[SCI_BASE_REQUEST_STATE_COMPLETED] = {
+		.enter_state = scic_sds_request_completed_state_enter,
+	},
+	[SCI_BASE_REQUEST_STATE_ABORTING] = {
+		.enter_state = scic_sds_request_aborting_state_enter,
+	},
+	[SCI_BASE_REQUEST_STATE_FINAL] = {
+		.enter_state = scic_sds_request_final_state_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h
new file mode 100644
index 0000000..06b53c3
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_request.h
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_IO_REQUEST_H_
+#define _SCIC_SDS_IO_REQUEST_H_
+
+/**
+ * This file contains the structures, constants and prototypes for the
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ *
+ */
+
+#include "scic_io_request.h"
+
+#include "sci_base_request.h"
+#include "scu_task_context.h"
+#include "intel_sas.h"
+
+struct scic_sds_controller;
+struct scic_sds_remote_device;
+struct scic_sds_io_request_state_handler;
+
+/**
+ * enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration
+ *    depicts all of the substates for a task management request to be
+ *    performed in the STARTED super-state.
+ *
+ *
+ */
+enum scic_sds_raw_request_started_task_mgmt_substates {
+	/**
+	 * The AWAIT_TC_COMPLETION sub-state indicates that the started raw
+	 * task management request is waiting for the transmission of the
+	 * initial frame (i.e. command, task, etc.).
+	 */
+	SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
+
+	/**
+	 * This sub-state indicates that the started task management request
+	 * is waiting for the reception of an unsolicited frame
+	 * (i.e. response IU).
+	 */
+	SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
+};
+
+
+/**
+ * enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all
+ *    of the substates for a SMP request to be performed in the STARTED
+ *    super-state.
+ *
+ *
+ */
+enum scic_sds_smp_request_started_substates {
+	/**
+	 * This sub-state indicates that the started task management request
+	 * is waiting for the reception of an unsolicited frame
+	 * (i.e. response IU).
+	 */
+	SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
+
+	/**
+	 * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is
+	 * waiting for the transmission of the initial frame (i.e. command, task, etc.).
+	 */
+	SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
+};
+
+/**
+ * struct SCIC_SDS_IO_REQUEST - This structure contains or references all of
+ *    the data necessary to process a task management or normal IO request.
+ *
+ *
+ */
+struct scic_sds_request {
+	/**
+	 * This field indictes the parent object of the request.
+	 */
+	struct sci_base_request parent;
+
+	void *user_request;
+
+	/**
+	 * This field simply points to the controller to which this IO request
+	 * is associated.
+	 */
+	struct scic_sds_controller *owning_controller;
+
+	/**
+	 * This field simply points to the remote device to which this IO request
+	 * is associated.
+	 */
+	struct scic_sds_remote_device *target_device;
+
+	/**
+	 * This field is utilized to determine if the SCI user is managing
+	 * the IO tag for this request or if the core is managing it.
+	 */
+	bool was_tag_assigned_by_user;
+
+	/**
+	 * This field indicates the IO tag for this request.  The IO tag is
+	 * comprised of the task_index and a sequence count. The sequence count
+	 * is utilized to help identify tasks from one life to another.
+	 */
+	u16 io_tag;
+
+	/**
+	 * This field specifies the protocol being utilized for this
+	 * IO request.
+	 */
+	SCIC_TRANSPORT_PROTOCOL protocol;
+
+	/**
+	 * This field indicates the completion status taken from the SCUs
+	 * completion code.  It indicates the completion result for the SCU hardware.
+	 */
+	u32 scu_status;
+
+	/**
+	 * This field indicates the completion status returned to the SCI user.  It
+	 * indicates the users view of the io request completion.
+	 */
+	u32 sci_status;
+
+	/**
+	 * This field contains the value to be utilized when posting (e.g. Post_TC,
+	 * Post_TC_Abort) this request to the silicon.
+	 */
+	u32 post_context;
+
+	void *command_buffer;
+	void *response_buffer;
+	struct scu_task_context *task_context_buffer;
+	struct scu_sgl_element_pair *sgl_element_pair_buffer;
+
+	/**
+	 * This field indicates if this request is a task management request or
+	 * normal IO request.
+	 */
+	bool is_task_management_request;
+
+	/**
+	 * This field indicates that this request contains an initialized started
+	 * substate machine.
+	 */
+	bool has_started_substate_machine;
+
+	/**
+	 * This field is a pointer to the stored rx frame data.  It is used in STP
+	 * internal requests and SMP response frames.  If this field is non-NULL the
+	 * saved frame must be released on IO request completion.
+	 *
+	 * @todo In the future do we want to keep a list of RX frame buffers?
+	 */
+	u32 saved_rx_frame_index;
+
+	/**
+	 * This field specifies the data necessary to manage the sub-state
+	 * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state.
+	 */
+	struct sci_base_state_machine started_substate_machine;
+
+	/**
+	 * This field specifies the current state handlers in place for this
+	 * IO Request object.  This field is updated each time the request
+	 * changes state.
+	 */
+	const struct scic_sds_io_request_state_handler *state_handlers;
+
+	/**
+	 * This field in the recorded device sequence for the io request.  This is
+	 * recorded during the build operation and is compared in the start
+	 * operation.  If the sequence is different then there was a change of
+	 * devices from the build to start operations.
+	 */
+	u8 device_sequence;
+
+};
+
+
+typedef enum sci_status
+(*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame);
+
+typedef enum sci_status
+(*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event);
+
+typedef enum sci_status
+(*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code);
+
+/**
+ * struct scic_sds_io_request_state_handler - This is the SDS core definition
+ *    of the state handlers.
+ *
+ *
+ */
+struct scic_sds_io_request_state_handler {
+	struct sci_base_request_state_handler parent;
+
+	scic_sds_io_request_task_completion_handler_t tc_completion_handler;
+	scic_sds_io_request_event_handler_t event_handler;
+	scic_sds_io_request_frame_handler_t frame_handler;
+
+};
+
+extern const struct sci_base_state scic_sds_request_state_table[];
+extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[];
+
+extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[];
+extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[];
+
+extern const struct sci_base_state scic_sds_smp_request_started_substate_table[];
+extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[];
+
+/**
+ *
+ *
+ * This macro returns the maximum number of SGL element paris that we will
+ * support in a single IO request.
+ */
+#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2)
+
+/**
+ * scic_sds_request_get_controller() -
+ *
+ * This macro will return the controller for this io request object
+ */
+#define scic_sds_request_get_controller(this_request) \
+	((this_request)->owning_controller)
+
+/**
+ * scic_sds_request_get_device() -
+ *
+ * This macro will return the device for this io request object
+ */
+#define scic_sds_request_get_device(this_request) \
+	((this_request)->target_device)
+
+/**
+ * scic_sds_request_get_port() -
+ *
+ * This macro will return the port for this io request object
+ */
+#define scic_sds_request_get_port(this_request)	\
+	scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request))
+
+/**
+ * scic_sds_request_get_post_context() -
+ *
+ * This macro returns the constructed post context result for the io request.
+ */
+#define scic_sds_request_get_post_context(this_request)	\
+	((this_request)->post_context)
+
+/**
+ * scic_sds_request_get_task_context() -
+ *
+ * This is a helper macro to return the os handle for this request object.
+ */
+#define scic_sds_request_get_task_context(request) \
+	((request)->task_context_buffer)
+
+/**
+ * scic_sds_request_set_status() -
+ *
+ * This macro will set the scu hardware status and sci request completion
+ * status for an io request.
+ */
+#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
+	{ \
+		(request)->scu_status = (scu_status_code); \
+		(request)->sci_status = (sci_status_code); \
+	}
+
+#define scic_sds_request_complete(a_request) \
+	((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent))
+
+
+
+
+/**
+ * scic_sds_io_request_tc_completion() -
+ *
+ * This macro invokes the core state task completion handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ */
+#define scic_sds_io_request_tc_completion(this_request, completion_code) \
+	{ \
+		if (this_request->parent.state_machine.current_state_id	 \
+		    == SCI_BASE_REQUEST_STATE_STARTED \
+		    && this_request->has_started_substate_machine \
+		    == false) \
+			scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \
+		else \
+			this_request->state_handlers->tc_completion_handler(this_request, completion_code); \
+	}
+
+/**
+ * SCU_SGL_ZERO() -
+ *
+ * This macro zeros the hardware SGL element data
+ */
+#define SCU_SGL_ZERO(scu_sge) \
+	{ \
+		(scu_sge).length = 0; \
+		(scu_sge).address_lower = 0; \
+		(scu_sge).address_upper = 0; \
+		(scu_sge).address_modifier = 0;	\
+	}
+
+/**
+ * SCU_SGL_COPY() -
+ *
+ * This macro copys the SGL Element data from the host os to the hardware SGL
+ * elment data
+ */
+#define SCU_SGL_COPY(scu_sge, os_sge) \
+	{ \
+		(scu_sge).length = sg_dma_len(sg); \
+		(scu_sge).address_upper = \
+			upper_32_bits(sg_dma_address(sg)); \
+		(scu_sge).address_lower = \
+			lower_32_bits(sg_dma_address(sg)); \
+		(scu_sge).address_modifier = 0;	\
+	}
+
+/**
+ * scic_sds_request_get_user_request() -
+ *
+ * This is a helper macro to return the os handle for this request object.
+ */
+#define scic_sds_request_get_user_request(request) \
+	((request)->user_request)
+
+/*
+ * *****************************************************************************
+ * * CORE REQUEST PROTOTYPES
+ * ***************************************************************************** */
+
+void scic_sds_request_build_sgl(
+	struct scic_sds_request *this_request);
+
+
+
+void scic_sds_stp_request_assign_buffers(
+	struct scic_sds_request *this_request);
+
+void scic_sds_smp_request_assign_buffers(
+	struct scic_sds_request *this_request);
+
+/* --------------------------------------------------------------------------- */
+
+enum sci_status scic_sds_request_start(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_io_request_terminate(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_io_request_complete(
+	struct scic_sds_request *this_request);
+
+void scic_sds_io_request_copy_response(
+	struct scic_sds_request *this_request);
+
+enum sci_status scic_sds_io_request_event_handler(
+	struct scic_sds_request *this_request,
+	u32 event_code);
+
+enum sci_status scic_sds_io_request_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index);
+
+
+enum sci_status scic_sds_task_request_terminate(
+	struct scic_sds_request *this_request);
+
+/*
+ * *****************************************************************************
+ * * DEFAULT STATE HANDLERS
+ * ***************************************************************************** */
+
+enum sci_status scic_sds_request_default_start_handler(
+	struct sci_base_request *this_request);
+
+
+enum sci_status scic_sds_request_default_complete_handler(
+	struct sci_base_request *this_request);
+
+enum sci_status scic_sds_request_default_destruct_handler(
+	struct sci_base_request *this_request);
+
+enum sci_status scic_sds_request_default_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code);
+
+enum sci_status scic_sds_request_default_event_handler(
+	struct scic_sds_request *this_request,
+	u32 event_code);
+
+enum sci_status scic_sds_request_default_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index);
+
+/*
+ * *****************************************************************************
+ * * STARTED STATE HANDLERS
+ * ***************************************************************************** */
+
+enum sci_status scic_sds_request_started_state_abort_handler(
+	struct sci_base_request *this_request);
+
+enum sci_status scic_sds_request_started_state_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code);
+
+#endif /* _SCIC_SDS_IO_REQUEST_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c
new file mode 100644
index 0000000..962bd39
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_smp_request.c
@@ -0,0 +1,669 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_sas.h"
+#include "sci_base_state_machine.h"
+#include "scic_controller.h"
+#include "scic_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_smp_request.h"
+#include "sci_environment.h"
+#include "sci_util.h"
+#include "scu_completion_codes.h"
+#include "scu_task_context.h"
+
+static void scu_smp_request_construct_task_context(
+	struct scic_sds_request *this_request,
+	struct smp_request *smp_request);
+
+/**
+ *
+ *
+ * This method return the memory space required for STP PIO requests. u32
+ */
+u32 scic_sds_smp_request_get_object_size(void)
+{
+	return sizeof(struct scic_sds_request)
+	       + sizeof(struct smp_request)
+	       + sizeof(struct smp_response)
+	       + sizeof(struct scu_task_context)
+	       + SMP_CACHE_BYTES;
+}
+
+/**
+ * scic_sds_smp_request_get_command_buffer() -
+ *
+ * This macro returns the address of the smp command buffer in the smp request
+ * memory. No need to cast to SMP request type.
+ */
+#define scic_sds_smp_request_get_command_buffer(memory)	\
+	(((char *)(memory)) + sizeof(struct scic_sds_request))
+
+/**
+ * scic_sds_smp_request_get_response_buffer() -
+ *
+ * This macro returns the address of the smp response buffer in the smp request
+ * memory.
+ */
+#define scic_sds_smp_request_get_response_buffer(memory) \
+	(((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
+	 + sizeof(struct smp_request))
+
+/**
+ * scic_sds_smp_request_get_task_context_buffer() -
+ *
+ * This macro returs the task context buffer for the SMP request.
+ */
+#define scic_sds_smp_request_get_task_context_buffer(memory) \
+	((struct scu_task_context *)(\
+		 ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
+		 + sizeof(struct smp_response) \
+		 ))
+
+
+
+/**
+ * This method build the remainder of the IO request object.
+ * @this_request: This parameter specifies the request object being constructed.
+ *
+ * The scic_sds_general_request_construct() must be called before this call is
+ * valid. none
+ */
+
+void scic_sds_smp_request_assign_buffers(
+	struct scic_sds_request *this_request)
+{
+	/* Assign all of the buffer pointers */
+	this_request->command_buffer =
+		scic_sds_smp_request_get_command_buffer(this_request);
+	this_request->response_buffer =
+		scic_sds_smp_request_get_response_buffer(this_request);
+	this_request->sgl_element_pair_buffer = NULL;
+
+	if (this_request->was_tag_assigned_by_user == false) {
+		this_request->task_context_buffer =
+			scic_sds_smp_request_get_task_context_buffer(this_request);
+		this_request->task_context_buffer =
+			PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES);
+	}
+
+}
+/**
+ * This method is called by the SCI user to build an SMP IO request.
+ *
+ * - The user must have previously called scic_io_request_construct() on the
+ * supplied IO request. Indicate if the controller successfully built the IO
+ * request. SCI_SUCCESS This value is returned if the IO request was
+ * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
+ * if the remote_device does not support the SMP protocol.
+ * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
+ * properly set the association between the SCIC IO request and the user's IO
+ * request.  Please refer to the sci_object_set_association() routine for more
+ * information.
+ */
+enum sci_status scic_io_request_construct_smp(
+	struct scic_sds_request *sci_req)
+{
+	struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL);
+
+	if (!smp_req)
+		return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+
+	sci_req->protocol                     = SCIC_SMP_PROTOCOL;
+	sci_req->has_started_substate_machine = true;
+
+	/* Construct the started sub-state machine. */
+	sci_base_state_machine_construct(
+		&sci_req->started_substate_machine,
+		&sci_req->parent.parent,
+		scic_sds_smp_request_started_substate_table,
+		SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+		);
+
+	/* Construct the SMP SCU Task Context */
+	memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req));
+
+	/*
+	 * Look at the SMP requests' header fields; for certain SAS 1.x SMP
+	 * functions under SAS 2.0, a zero request length really indicates
+	 * a non-zero default length. */
+	if (smp_req->header.request_length == 0) {
+		switch (smp_req->header.function) {
+		case SMP_FUNCTION_DISCOVER:
+		case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
+		case SMP_FUNCTION_REPORT_PHY_SATA:
+		case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
+			smp_req->header.request_length = 2;
+			break;
+		case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
+		case SMP_FUNCTION_PHY_CONTROL:
+		case SMP_FUNCTION_PHY_TEST:
+			smp_req->header.request_length = 9;
+			break;
+			/* Default - zero is a valid default for 2.0. */
+		}
+	}
+
+	scu_smp_request_construct_task_context(sci_req, smp_req);
+
+	sci_base_state_machine_change_state(
+		&sci_req->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_CONSTRUCTED
+		);
+
+	kfree(smp_req);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method is called by the SCI user to build an SMP pass-through IO
+ *    request.
+ * @scic_smp_request: This parameter specifies the handle to the io request
+ *    object to be built.
+ * @passthru_cb: This parameter specifies the pointer to the callback structure
+ *    that contains the function pointers
+ *
+ * - The user must have previously called scic_io_request_construct() on the
+ * supplied IO request. Indicate if the controller successfully built the IO
+ * request.
+ */
+
+/**
+ * This method will fill in the SCU Task Context for a SMP request. The
+ *    following important settings are utilized: -# task_type ==
+ *    SCU_TASK_TYPE_SMP.  This simply indicates that a normal request type
+ *    (i.e. non-raw frame) is being utilized to perform task management. -#
+ *    control_frame == 1.  This ensures that the proper endianess is set so
+ *    that the bytes are transmitted in the right order for a smp request frame.
+ * @this_request: This parameter specifies the smp request object being
+ *    constructed.
+ *
+ */
+static void scu_smp_request_construct_task_context(
+	struct scic_sds_request *sds_request,
+	struct smp_request *smp_request)
+{
+	dma_addr_t dma_addr;
+	struct scic_sds_controller *controller;
+	struct scic_sds_remote_device *target_device;
+	struct scic_sds_port *target_port;
+	struct scu_task_context *task_context;
+
+	/* byte swap the smp request. */
+	scic_word_copy_with_swap(sds_request->command_buffer,
+				 (u32 *)smp_request,
+				 sizeof(struct smp_request) / sizeof(u32));
+
+	task_context = scic_sds_request_get_task_context(sds_request);
+
+	controller = scic_sds_request_get_controller(sds_request);
+	target_device = scic_sds_request_get_device(sds_request);
+	target_port = scic_sds_request_get_port(sds_request);
+
+	/*
+	 * Fill in the TC with the its required data
+	 * 00h
+	 */
+	task_context->priority = 0;
+	task_context->initiator_request = 1;
+	task_context->connection_rate =
+		scic_remote_device_get_connection_rate(target_device);
+	task_context->protocol_engine_index =
+		scic_sds_controller_get_protocol_engine_group(controller);
+	task_context->logical_port_index =
+		scic_sds_port_get_index(target_port);
+	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
+	task_context->abort = 0;
+	task_context->valid = SCU_TASK_CONTEXT_VALID;
+	task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+	/* 04h */
+	task_context->remote_node_index =
+		sds_request->target_device->rnc->remote_node_index;
+	task_context->command_code = 0;
+	task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
+
+	/* 08h */
+	task_context->link_layer_control = 0;
+	task_context->do_not_dma_ssp_good_response = 1;
+	task_context->strict_ordering = 0;
+	task_context->control_frame = 1;
+	task_context->timeout_enable = 0;
+	task_context->block_guard_enable = 0;
+
+	/* 0ch */
+	task_context->address_modifier = 0;
+
+	/* 10h */
+	task_context->ssp_command_iu_length =
+		smp_request->header.request_length;
+
+	/* 14h */
+	task_context->transfer_length_bytes = 0;
+
+	/*
+	 * 18h ~ 30h, protocol specific
+	 * since commandIU has been build by framework at this point, we just
+	 * copy the frist DWord from command IU to this location. */
+	memcpy((void *)(&task_context->type.smp),
+	       sds_request->command_buffer,
+	       sizeof(u32));
+
+	/*
+	 * 40h
+	 * "For SMP you could program it to zero. We would prefer that way
+	 * so that done code will be consistent." - Venki
+	 */
+	task_context->task_phase = 0;
+
+	if (sds_request->was_tag_assigned_by_user) {
+		/*
+		 * Build the task context now since we have already read
+		 * the data
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
+			 scic_sds_io_tag_get_index(sds_request->io_tag));
+	} else {
+		/*
+		 * Build the task context now since we have already read
+		 * the data.
+		 * I/O tag index is not assigned because we have to wait
+		 * until we get a TCi.
+		 */
+		sds_request->post_context =
+			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
+			 (scic_sds_controller_get_protocol_engine_group(
+							controller) <<
+			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
+			 (scic_sds_port_get_index(target_port) <<
+			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
+	}
+
+	/*
+	 * Copy the physical address for the command buffer to the SCU Task
+	 * Context command buffer should not contain command header.
+	 */
+	dma_addr = scic_io_request_get_dma_addr(sds_request,
+						(char *)
+						(sds_request->command_buffer) +
+						sizeof(u32));
+
+	task_context->command_iu_upper = upper_32_bits(dma_addr);
+	task_context->command_iu_lower = lower_32_bits(dma_addr);
+
+	/* SMP response comes as UF, so no need to set response IU address. */
+	task_context->response_iu_upper = 0;
+	task_context->response_iu_lower = 0;
+}
+
+/**
+ * This method processes an unsolicited frame while the SMP request is waiting
+ *    for a response frame.  It will copy the response data, release the
+ *    unsolicited frame, and transition the request to the
+ *    SCI_BASE_REQUEST_STATE_COMPLETED state.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the response frame was handled
+ * successfully or not. SCI_SUCCESS Currently this value is always returned and
+ * indicates successful processing of the TC response.
+ */
+static enum sci_status scic_sds_smp_request_await_response_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	enum sci_status status;
+	void *frame_header;
+	struct smp_response_header *this_frame_header;
+	u8 *user_smp_buffer = this_request->response_buffer;
+
+	status = scic_sds_unsolicited_frame_control_get_header(
+		&(scic_sds_request_get_controller(this_request)->uf_control),
+		frame_index,
+		&frame_header
+		);
+
+	/* byte swap the header. */
+	scic_word_copy_with_swap(
+		(u32 *)user_smp_buffer,
+		frame_header,
+		sizeof(struct smp_response_header) / sizeof(u32)
+		);
+	this_frame_header = (struct smp_response_header *)user_smp_buffer;
+
+	if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) {
+		void *smp_response_buffer;
+
+		status = scic_sds_unsolicited_frame_control_get_buffer(
+			&(scic_sds_request_get_controller(this_request)->uf_control),
+			frame_index,
+			&smp_response_buffer
+			);
+
+		scic_word_copy_with_swap(
+			(u32 *)(user_smp_buffer + sizeof(struct smp_response_header)),
+			smp_response_buffer,
+			sizeof(union smp_response_body) / sizeof(u32)
+			);
+		if (this_frame_header->function == SMP_FUNCTION_DISCOVER) {
+			struct smp_response *this_smp_response;
+
+			this_smp_response = (struct smp_response *)user_smp_buffer;
+
+			/*
+			 * Some expanders only report an attached SATA device, and
+			 * not an STP target.  Since the core depends on the STP
+			 * target attribute to correctly build I/O, set the bit now
+			 * if necessary. */
+			if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
+			    && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) {
+				this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
+
+				dev_dbg(scic_to_dev(this_request->owning_controller),
+					"%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n",
+					__func__, this_request);
+			}
+		}
+
+		/*
+		 * Don't need to copy to user space. User instead will refer to
+		 * core request's response buffer. */
+
+		/*
+		 * copy the smp response to framework smp request's response buffer.
+		 * scic_sds_smp_request_copy_response(this_request); */
+
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+			);
+	} else {
+		/* This was not a response frame why did it get forwarded? */
+		dev_err(scic_to_dev(this_request->owning_controller),
+			"%s: SCIC SMP Request 0x%p received unexpected frame "
+			"%d type 0x%02x\n",
+			__func__,
+			this_request,
+			frame_index,
+			this_frame_header->smp_frame_type);
+
+		scic_sds_request_set_status(
+			this_request,
+			SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+	}
+
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index
+		);
+
+	return SCI_SUCCESS;
+}
+
+
+/**
+ * This method processes an abnormal TC completion while the SMP request is
+ *    waiting for a response frame.  It decides what happened to the IO based
+ *    on TC completion status.
+ * @this_request: This parameter specifies the request for which the TC
+ *    completion was received.
+ * @completion_code: This parameter indicates the completion status information
+ *    for the TC.
+ *
+ * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
+ * this method always returns success.
+ */
+static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		/*
+		 * In the AWAIT RESPONSE state, any TC completion is unexpected.
+		 * but if the TC has success status, we complete the IO anyway. */
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
+		/*
+		 * These status has been seen in a specific LSI expander, which sometimes
+		 * is not able to send smp response within 2 ms. This causes our hardware
+		 * break the connection and set TC completion with one of these SMP_XXX_XX_ERR
+		 * status. For these type of error, we ask scic user to retry the request. */
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+
+/**
+ * This method processes the completions transport layer (TL) status to
+ *    determine if the SMP request was sent successfully. If the SMP request
+ *    was sent successfully, then the state for the SMP request transits to
+ *    waiting for a response frame.
+ * @this_request: This parameter specifies the request for which the TC
+ *    completion was received.
+ * @completion_code: This parameter indicates the completion status information
+ *    for the TC.
+ *
+ * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
+ * this method always returns success.
+ */
+static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+
+const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = {
+	[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_smp_request_await_response_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_smp_request_await_response_frame_handler,
+	},
+	[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   =  scic_sds_smp_request_await_tc_completion_tc_completion_handler,
+		.event_handler           =  scic_sds_request_default_event_handler,
+		.frame_handler           =  scic_sds_request_default_frame_handler,
+	}
+};
+
+/**
+ * This method performs the actions required when entering the
+ *    SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
+ *    includes setting the IO request state handlers for this sub-state.
+ * @object: This parameter specifies the request object for which the sub-state
+ *    change is occuring.
+ *
+ * none.
+ */
+static void scic_sds_smp_request_started_await_response_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_smp_request_started_substate_handler_table,
+		SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+		);
+}
+
+/**
+ * This method performs the actions required when entering the
+ *    SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state.
+ *    This includes setting the SMP request state handlers for this sub-state.
+ * @object: This parameter specifies the request object for which the sub-state
+ *    change is occuring.
+ *
+ * none.
+ */
+static void scic_sds_smp_request_started_await_tc_completion_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_smp_request_started_substate_handler_table,
+		SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+		);
+}
+
+const struct sci_base_state scic_sds_smp_request_started_substate_table[] = {
+	[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
+		.enter_state = scic_sds_smp_request_started_await_response_substate_enter,
+	},
+	[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
+		.enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h
new file mode 100644
index 0000000..bcad282
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_smp_request.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+#ifndef _SCIC_SDS_SMP_REQUEST_T_
+#define _SCIC_SDS_SMP_REQUEST_T_
+
+#include "intel_sas.h"
+#include "scic_sds_request.h"
+
+
+u32 scic_sds_smp_request_get_object_size(void);
+
+
+void scic_sds_smp_request_copy_response(
+	struct scic_sds_request *this_request);
+
+#endif /* _SCIC_SDS_SMP_REQUEST_T_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c
new file mode 100644
index 0000000..a826e4b
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 "intel_sas.h"
+#include "sci_base_state_machine.h"
+#include "scic_controller.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_request.h"
+#include "sci_environment.h"
+#include "scu_completion_codes.h"
+#include "scu_task_context.h"
+
+/**
+ * This method processes the completions transport layer (TL) status to
+ *    determine if the RAW task management frame was sent successfully. If the
+ *    raw frame was sent successfully, then the state for the task request
+ *    transitions to waiting for a response frame.
+ * @this_request: This parameter specifies the request for which the TC
+ *    completion was received.
+ * @completion_code: This parameter indicates the completion status information
+ *    for the TC.
+ *
+ * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
+ * this method always returns success.
+ */
+static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(
+	struct scic_sds_request *this_request,
+	u32 completion_code)
+{
+	switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+		scic_sds_request_set_status(
+			this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+			);
+		break;
+
+	case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
+		/*
+		 * Currently, the decision is to simply allow the task request to
+		 * timeout if the task IU wasn't received successfully.
+		 * There is a potential for receiving multiple task responses if we
+		 * decide to send the task IU again. */
+		dev_warn(scic_to_dev(this_request->owning_controller),
+			 "%s: TaskRequest:0x%p CompletionCode:%x - "
+			 "ACK/NAK timeout\n",
+			 __func__,
+			 this_request,
+			 completion_code);
+
+		sci_base_state_machine_change_state(
+			&this_request->started_substate_machine,
+			SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+			);
+		break;
+
+	default:
+		/*
+		 * All other completion status cause the IO to be complete.  If a NAK
+		 * was received, then it is up to the user to retry the request. */
+		scic_sds_request_set_status(
+			this_request,
+			SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+			SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+			);
+
+		sci_base_state_machine_change_state(
+			&this_request->parent.state_machine,
+			SCI_BASE_REQUEST_STATE_COMPLETED
+			);
+		break;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method is responsible for processing a terminate/abort request for this
+ *    TC while the request is waiting for the task management response
+ *    unsolicited frame.
+ * @this_request: This parameter specifies the request for which the
+ *    termination was requested.
+ *
+ * This method returns an indication as to whether the abort request was
+ * successfully handled. need to update to ensure the received UF doesn't cause
+ * damage to subsequent requests (i.e. put the extended tag in a holding
+ * pattern for this particular device).
+ */
+static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler(
+	struct sci_base_request *request)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)request;
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_ABORTING
+		);
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * This method processes an unsolicited frame while the task mgmt request is
+ *    waiting for a response frame.  It will copy the response data, release
+ *    the unsolicited frame, and transition the request to the
+ *    SCI_BASE_REQUEST_STATE_COMPLETED state.
+ * @this_request: This parameter specifies the request for which the
+ *    unsolicited frame was received.
+ * @frame_index: This parameter indicates the unsolicited frame index that
+ *    should contain the response.
+ *
+ * This method returns an indication of whether the TC response frame was
+ * handled successfully or not. SCI_SUCCESS Currently this value is always
+ * returned and indicates successful processing of the TC response. Should
+ * probably update to check frame type and make sure it is a response frame.
+ */
+static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler(
+	struct scic_sds_request *this_request,
+	u32 frame_index)
+{
+	scic_sds_io_request_copy_response(this_request);
+
+	sci_base_state_machine_change_state(
+		&this_request->parent.state_machine,
+		SCI_BASE_REQUEST_STATE_COMPLETED
+		);
+
+	scic_sds_controller_release_frame(
+		this_request->owning_controller, frame_index
+		);
+
+	return SCI_SUCCESS;
+}
+
+const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = {
+	[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_request_started_state_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_request_default_frame_handler,
+	},
+	[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
+		.parent.start_handler    = scic_sds_request_default_start_handler,
+		.parent.abort_handler    = scic_sds_ssp_task_request_await_tc_response_abort_handler,
+		.parent.complete_handler = scic_sds_request_default_complete_handler,
+		.parent.destruct_handler = scic_sds_request_default_destruct_handler,
+		.tc_completion_handler   = scic_sds_request_default_tc_completion_handler,
+		.event_handler           = scic_sds_request_default_event_handler,
+		.frame_handler           = scic_sds_ssp_task_request_await_tc_response_frame_handler,
+	}
+};
+
+/**
+ * This method performs the actions required when entering the
+ *    SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+ *    sub-state.  This includes setting the IO request state handlers for this
+ *    sub-state.
+ * @object: This parameter specifies the request object for which the sub-state
+ *    change is occuring.
+ *
+ * none.
+ */
+static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_ssp_task_request_started_substate_handler_table,
+		SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+		);
+}
+
+/**
+ * This method performs the actions required when entering the
+ *    SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
+ *    includes setting the IO request state handlers for this sub-state.
+ * @object: This parameter specifies the request object for which the sub-state
+ *    change is occuring.
+ *
+ * none.
+ */
+static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter(
+	struct sci_base_object *object)
+{
+	struct scic_sds_request *this_request = (struct scic_sds_request *)object;
+
+	SET_STATE_HANDLER(
+		this_request,
+		scic_sds_ssp_task_request_started_substate_handler_table,
+		SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+		);
+}
+
+const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = {
+	[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
+		.enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter,
+	},
+	[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
+		.enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter,
+	},
+};
+
diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h
new file mode 100644
index 0000000..7e6d20a
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_task_request.h
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_TASK_REQUEST_H_
+#define _SCIC_TASK_REQUEST_H_
+
+/**
+ * This file contains the structures and interface methods that can be
+ *    referenced and used by the SCI user for to utilize task management
+ *    requests.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+
+struct scic_sds_request;
+struct scic_sds_remote_device;
+struct scic_sds_controller;
+
+
+/**
+ * scic_task_request_construct() - This method is called by the SCI user to
+ *    construct all SCI Core task management requests, regardless of protocol.
+ *    Memory initialization and functionality common to all task request types
+ *    is performed in this method.
+ * @scic_controller: the handle to the core controller object for which to
+ *    build the task managmement request.
+ * @scic_remote_device: the handle to the core remote device object for which
+ *    to build the task management request. passed, then a copy of the request
+ *    is built internally.  The request will be copied into the actual
+ *    controller request memory when the task is allocated internally during
+ *    the scic_controller_start_task() method.
+ * @io_tag: This parameter specifies the IO tag to be associated with this
+ *    request.  If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
+ *    request is built internally.  The request will be copied into the actual
+ *    controller request memory when the IO tag is allocated internally during
+ *    the scic_controller_start_io() method.
+ * @user_task_request_object: This parameter specifies the user task request to
+ *    be utilized during construction.  This task pointer will become the
+ *    associated object for the core task request object.
+ * @scic_task_request_memory: This parameter specifies the memory location to
+ *    be utilized when building the core request.
+ * @new_scic_task_request_handle: This parameter specifies a pointer to the
+ *    handle the core will expect in further interactions with the core task
+ *    request object.
+ *
+ * The SCI core implementation will create an association between the user task
+ * request object and the core task request object. Indicate if the controller
+ * successfully built the task request. SCI_SUCCESS This value is returned if
+ * the task request was successfully built.
+ */
+enum sci_status scic_task_request_construct(
+	struct scic_sds_controller *scic_controller,
+	struct scic_sds_remote_device *scic_remote_device,
+	u16 io_tag,
+	void *user_task_request_object,
+	void *scic_task_request_memory,
+	struct scic_sds_request **new_scic_task_request_handle);
+
+/**
+ * scic_task_request_construct_ssp() - This method is called by the SCI user to
+ *    construct all SCI Core SSP task management requests.  Memory
+ *    initialization and functionality common to all task request types is
+ *    performed in this method.
+ * @scic_task_request: This parameter specifies the handle to the core task
+ *    request object for which to construct a SATA specific task management
+ *    request.
+ *
+ * Indicate if the controller successfully built the task request. SCI_SUCCESS
+ * This value is returned if the task request was successfully built.
+ */
+enum sci_status scic_task_request_construct_ssp(
+	struct scic_sds_request *scic_task_request);
+
+/**
+ * scic_task_request_construct_sata() - This method is called by the SCI user
+ *    to construct all SCI Core SATA task management requests.  Memory
+ *    initialization and functionality common to all task request types is
+ *    performed in this method.
+ * @scic_task_request_handle: This parameter specifies the handle to the core
+ *    task request object for which to construct a SATA specific task
+ *    management request.
+ *
+ * Indicate if the controller successfully built the task request. SCI_SUCCESS
+ * This value is returned if the task request was successfully built.
+ */
+enum sci_status scic_task_request_construct_sata(
+	struct scic_sds_request *scic_task_request_handle);
+
+
+
+#endif  /* _SCIC_TASK_REQUEST_H_ */
+


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 08/10] isci/core: unsolicited frame handling and registers
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (6 preceding siblings ...)
  2011-03-10 10:54 ` [RFC PATCH 07/10] isci/core: request (general, ssp and smp) Dan Williams
@ 2011-03-10 10:55 ` Dan Williams
  2011-03-10 10:55 ` [RFC PATCH 09/10] isci/core: base state machine and memory descriptors Dan Williams
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:55 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

The hardware kicks unaccelerated / unknown traffic to an unsolicited
frame queue for handling in software.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 .../isci/core/scic_sds_unsolicited_frame_control.c |  383 ++++
 .../isci/core/scic_sds_unsolicited_frame_control.h |  286 +++
 drivers/scsi/isci/core/scu_registers.h             | 1830 ++++++++++++++++++++
 drivers/scsi/isci/core/scu_unsolicited_frame.h     |  117 +
 4 files changed, 2616 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
 create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
 create mode 100644 drivers/scsi/isci/core/scu_registers.h
 create mode 100644 drivers/scsi/isci/core/scu_unsolicited_frame.h

diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
new file mode 100644
index 0000000..66be58b
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains the implementation of the
+ *    struct scic_sds_unsolicited_frame_control object and it's public, protected, and
+ *    private methods.
+ *
+ *
+ */
+
+#include "scic_sds_unsolicited_frame_control.h"
+#include "scu_registers.h"
+#include "scic_sds_controller.h"
+#include "sci_util.h"
+#include "sci_environment.h"
+
+/**
+ * The UF buffer address table size must be programmed to a power of 2.  Find
+ *    the first power of 2 that is equal to or greater then the number of
+ *    unsolicited frame buffers to be utilized.
+ * @uf_control: This parameter specifies the UF control object for which to
+ *    update the address table count.
+ *
+ */
+void scic_sds_unsolicited_frame_control_set_address_table_count(
+	struct scic_sds_unsolicited_frame_control *uf_control)
+{
+	uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES;
+	while (
+		(uf_control->address_table.count < uf_control->buffers.count)
+		&& (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES)
+		) {
+		uf_control->address_table.count <<= 1;
+	}
+}
+
+/**
+ * This method will program the unsolicited frames (UFs) into the UF address
+ *    table and construct the UF frame structure being modeled in the core.  It
+ *    will handle the case where some of the UFs are not being used and thus
+ *    should have entries programmed to zero in the address table.
+ * @uf_control: This parameter specifies the unsolicted frame control object
+ *    for which to construct the unsolicited frames objects.
+ * @uf_buffer_phys_address: This parameter specifies the physical address for
+ *    the first unsolicited frame buffer.
+ * @uf_buffer_virt_address: This parameter specifies the virtual address for
+ *    the first unsolicited frame buffer.
+ * @unused_uf_header_entries: This parameter specifies the number of unused UF
+ *    headers.  This value can be non-zero when there are a non-power of 2
+ *    number of unsolicited frames being supported.
+ * @used_uf_header_entries: This parameter specifies the number of actually
+ *    utilized UF headers.
+ *
+ */
+static void scic_sds_unsolicited_frame_control_construct_frames(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	dma_addr_t uf_buffer_phys_address,
+	void *uf_buffer_virt_address,
+	u32 unused_uf_header_entries,
+	u32 used_uf_header_entries)
+{
+	u32 index;
+	struct scic_sds_unsolicited_frame *uf;
+
+	/*
+	 * Program the unused buffers into the UF address table and the
+	 * controller's array of UFs.
+	 */
+	for (index = 0; index < unused_uf_header_entries; index++) {
+		uf = &uf_control->buffers.array[index];
+
+		sci_cb_make_physical_address(
+			uf_control->address_table.array[index], 0, 0
+			);
+		uf->buffer = NULL;
+		uf->header = &uf_control->headers.array[index];
+		uf->state  = UNSOLICITED_FRAME_EMPTY;
+	}
+
+	/*
+	 * Program the actual used UF buffers into the UF address table and
+	 * the controller's array of UFs.
+	 */
+	for (index = unused_uf_header_entries;
+	     index < unused_uf_header_entries + used_uf_header_entries;
+	     index++) {
+		uf = &uf_control->buffers.array[index];
+
+		uf_control->address_table.array[index] = uf_buffer_phys_address;
+
+		uf->buffer = uf_buffer_virt_address;
+		uf->header = &uf_control->headers.array[index];
+		uf->state  = UNSOLICITED_FRAME_EMPTY;
+
+		/*
+		 * Increment the address of the physical and virtual memory
+		 * pointers. Everything is aligned on 1k boundary with an
+		 * increment of 1k.
+		 */
+		uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
+		uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
+	}
+}
+
+/**
+ * This method constructs the various members of the unsolicted frame control
+ *    object (buffers, headers, address, table, etc).
+ * @uf_control: This parameter specifies the unsolicited frame control object
+ *    to construct.
+ * @mde: This parameter specifies the memory descriptor from which to derive
+ *    all of the address information needed to get the unsolicited frame
+ *    functionality working.
+ * @controller: This parameter specifies the controller object associated with
+ *    the uf_control being constructed.
+ *
+ */
+void scic_sds_unsolicited_frame_control_construct(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	struct sci_physical_memory_descriptor *mde,
+	struct scic_sds_controller *controller)
+{
+	u32 unused_uf_header_entries;
+	u32 used_uf_header_entries;
+	u32 used_uf_buffer_bytes;
+	u32 unused_uf_header_bytes;
+	u32 used_uf_header_bytes;
+	dma_addr_t uf_buffer_phys_address;
+	void *uf_buffer_virt_address;
+
+	/*
+	 * Prepare all of the memory sizes for the UF headers, UF address
+	 * table, and UF buffers themselves. */
+	used_uf_buffer_bytes     = uf_control->buffers.count
+				   * SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
+	unused_uf_header_entries = uf_control->address_table.count
+				   - uf_control->buffers.count;
+	used_uf_header_entries   = uf_control->buffers.count;
+	unused_uf_header_bytes   = unused_uf_header_entries
+				   * sizeof(struct scu_unsolicited_frame_header);
+	used_uf_header_bytes     = used_uf_header_entries
+				   * sizeof(struct scu_unsolicited_frame_header);
+
+	/*
+	 * The Unsolicited Frame buffers are set at the start of the UF
+	 * memory descriptor entry. The headers and address table will be
+	 * placed after the buffers.
+	 */
+	uf_buffer_phys_address = mde->physical_address;
+	uf_buffer_virt_address = mde->virtual_address;
+
+	/*
+	 * Program the location of the UF header table into the SCU.
+	 * Notes:
+	 * - The address must align on a 64-byte boundary. Guaranteed to be
+	 *   on 64-byte boundary already 1KB boundary for unsolicited frames.
+	 * - Program unused header entries to overlap with the last
+	 *   unsolicited frame.  The silicon will never DMA to these unused
+	 *   headers, since we program the UF address table pointers to
+	 *   NULL.
+	 */
+	uf_control->headers.physical_address =
+				uf_buffer_phys_address +
+				used_uf_buffer_bytes -
+				unused_uf_header_bytes;
+
+	uf_control->headers.array =
+				uf_buffer_virt_address +
+				used_uf_buffer_bytes -
+				unused_uf_header_bytes;
+
+	/*
+	 * Program the location of the UF address table into the SCU.
+	 * Notes:
+	 * - The address must align on a 64-bit boundary. Guaranteed to be on 64
+	 *   byte boundary already due to above programming headers being on a
+	 *   64-bit boundary and headers are on a 64-bytes in size.
+	 */
+	uf_control->address_table.physical_address =
+				uf_buffer_phys_address +
+				used_uf_buffer_bytes +
+				used_uf_header_bytes;
+
+	uf_control->address_table.array =
+				uf_buffer_virt_address +
+				used_uf_buffer_bytes +
+				used_uf_header_bytes;
+
+	uf_control->get = 0;
+
+	/*
+	 * UF buffer requirements are:
+	 * - The last entry in the UF queue is not NULL.
+	 * - There is a power of 2 number of entries (NULL or not-NULL)
+	 *   programmed into the queue.
+	 * - Aligned on a 1KB boundary. */
+
+	/*
+	 * If the user provided less then the maximum amount of memory,
+	 * then be sure that we programm the first entries in the UF
+	 * address table to NULL. */
+	scic_sds_unsolicited_frame_control_construct_frames(
+		uf_control,
+		uf_buffer_phys_address,
+		mde->virtual_address,
+		unused_uf_header_entries,
+		used_uf_header_entries
+		);
+}
+
+/**
+ * This method returns the frame header for the specified frame index.
+ * @uf_control:
+ * @frame_index:
+ * @frame_header:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_unsolicited_frame_control_get_header(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index,
+	void **frame_header)
+{
+	if (frame_index < uf_control->address_table.count) {
+		/*
+		 * Skip the first word in the frame since this is a controll word used
+		 * by the hardware. */
+		*frame_header = &uf_control->buffers.array[frame_index].header->data;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+}
+
+/**
+ * This method returns the frame buffer for the specified frame index.
+ * @uf_control:
+ * @frame_index:
+ * @frame_buffer:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index,
+	void **frame_buffer)
+{
+	if (frame_index < uf_control->address_table.count) {
+		*frame_buffer = uf_control->buffers.array[frame_index].buffer;
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+}
+
+/**
+ * This method releases the frame once this is done the frame is available for
+ *    re-use by the hardware.  The data contained in the frame header and frame
+ *    buffer is no longer valid.
+ * @uf_control: This parameter specifies the UF control object
+ * @frame_index: This parameter specifies the frame index to attempt to release.
+ *
+ * This method returns an indication to the caller as to whether the
+ * unsolicited frame get pointer should be updated. true This value indicates
+ * the unsolicited frame get pointer should be updated (i.e. write
+ * SCU_UFQGP_WRITE). false This value indicates the get pointer should not be
+ * updated.
+ */
+bool scic_sds_unsolicited_frame_control_release_frame(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index)
+{
+	u32 frame_get;
+	u32 frame_cycle;
+
+	frame_get   = uf_control->get & (uf_control->address_table.count - 1);
+	frame_cycle = uf_control->get & uf_control->address_table.count;
+
+	/*
+	 * In the event there are NULL entries in the UF table, we need to
+	 * advance the get pointer in order to find out if this frame should
+	 * be released (i.e. update the get pointer). */
+	while (((lower_32_bits(uf_control->address_table.array[frame_get])
+					== 0) &&
+		(upper_32_bits(uf_control->address_table.array[frame_get])
+					== 0)) &&
+	       (frame_get < uf_control->address_table.count))
+		frame_get++;
+
+	/*
+	 * The table has a NULL entry as it's last element.  This is
+	 * illegal. */
+	BUG_ON(frame_get >= uf_control->address_table.count);
+
+	if (frame_index < uf_control->address_table.count) {
+		uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED;
+
+		/*
+		 * The frame index is equal to the current get pointer so we
+		 * can now free up all of the frame entries that */
+		if (frame_get == frame_index) {
+			while (
+				uf_control->buffers.array[frame_get].state
+				== UNSOLICITED_FRAME_RELEASED
+				) {
+				uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY;
+
+				INCREMENT_QUEUE_GET(
+					frame_get,
+					frame_cycle,
+					uf_control->address_table.count - 1,
+					uf_control->address_table.count
+					);
+			}
+
+			uf_control->get =
+				(SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get);
+
+			return true;
+		} else {
+			/*
+			 * Frames remain in use until we advance the get pointer
+			 * so there is nothing we can do here */
+		}
+	}
+
+	return false;
+}
+
diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
new file mode 100644
index 0000000..49db83f
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains all of the unsolicited frame related management for the
+ *    address table, the headers, and actual payload buffers.
+ *
+ *
+ */
+
+#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
+#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
+
+#include "scu_unsolicited_frame.h"
+#include "sci_memory_descriptor_list.h"
+#include "scu_constants.h"
+#include "sci_status.h"
+
+/**
+ * enum UNSOLICITED_FRAME_STATE -
+ *
+ * This enumeration represents the current unsolicited frame state.  The
+ * controller object can not updtate the hardware unsolicited frame put pointer
+ * unless it has already processed the priror unsolicited frames.
+ */
+enum UNSOLICITED_FRAME_STATE {
+	/**
+	 * This state is when the frame is empty and not in use.  It is
+	 * different from the released state in that the hardware could DMA
+	 * data to this frame buffer.
+	 */
+	UNSOLICITED_FRAME_EMPTY,
+
+	/**
+	 * This state is set when the frame buffer is in use by by some
+	 * object in the system.
+	 */
+	UNSOLICITED_FRAME_IN_USE,
+
+	/**
+	 * This state is set when the frame is returned to the free pool
+	 * but one or more frames prior to this one are still in use.
+	 * Once all of the frame before this one are freed it will go to
+	 * the empty state.
+	 */
+	UNSOLICITED_FRAME_RELEASED,
+
+	UNSOLICITED_FRAME_MAX_STATES
+};
+
+/**
+ * struct scic_sds_unsolicited_frame -
+ *
+ * This is the unsolicited frame data structure it acts as the container for
+ * the current frame state, frame header and frame buffer.
+ */
+struct scic_sds_unsolicited_frame {
+	/**
+	 * This field contains the current frame state
+	 */
+	enum UNSOLICITED_FRAME_STATE state;
+
+	/**
+	 * This field points to the frame header data.
+	 */
+	struct scu_unsolicited_frame_header *header;
+
+	/**
+	 * This field points to the frame buffer data.
+	 */
+	void *buffer;
+
+};
+
+/**
+ * struct scic_sds_uf_header_array -
+ *
+ * This structure contains all of the unsolicited frame header information.
+ */
+struct scic_sds_uf_header_array {
+	/**
+	 * This field is represents a virtual pointer to the start
+	 * address of the UF address table.  The table contains
+	 * 64-bit pointers as required by the hardware.
+	 */
+	struct scu_unsolicited_frame_header *array;
+
+	/**
+	 * This field specifies the physical address location for the UF
+	 * buffer array.
+	 */
+	dma_addr_t physical_address;
+
+};
+
+/*
+ * Determine the size of the unsolicited frame array including
+ * unused buffers. */
+#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES
+#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES
+#else
+#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES
+#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */
+
+/**
+ * struct scic_sds_uf_buffer_array -
+ *
+ * This structure contains all of the unsolicited frame buffer (actual payload)
+ * information.
+ */
+struct scic_sds_uf_buffer_array {
+	/**
+	 * This field is the minimum number of unsolicited frames supported by the
+	 * hardware and the number of unsolicited frames requested by the software.
+	 */
+	u32 count;
+
+	/**
+	 * This field is the SCIC_UNSOLICITED_FRAME data its used to manage
+	 * the data for the unsolicited frame requests.  It also represents
+	 * the virtual address location that corresponds to the
+	 * physical_address field.
+	 */
+	struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE];
+
+	/**
+	 * This field specifies the physical address location for the UF
+	 * buffer array.
+	 */
+	dma_addr_t physical_address;
+
+};
+
+/**
+ * struct scic_sds_uf_address_table_array -
+ *
+ * This object maintains all of the unsolicited frame address table specific
+ * data.  The address table is a collection of 64-bit pointers that point to
+ * 1KB buffers into which the silicon will DMA unsolicited frames.
+ */
+struct scic_sds_uf_address_table_array {
+	/**
+	 * This field specifies the actual programmed size of the
+	 * unsolicited frame buffer address table.  The size of the table
+	 * can be larger than the actual number of UF buffers, but it must
+	 * be a power of 2 and the last entry in the table is not allowed
+	 * to be NULL.
+	 */
+	u32 count;
+
+	/**
+	 * This field represents a virtual pointer that refers to the
+	 * starting address of the UF address table.
+	 * 64-bit pointers are required by the hardware.
+	 */
+	dma_addr_t *array;
+
+	/**
+	 * This field specifies the physical address location for the UF
+	 * address table.
+	 */
+	dma_addr_t physical_address;
+
+};
+
+/**
+ * struct scic_sds_unsolicited_frame_control -
+ *
+ * This object contains all of the data necessary to handle unsolicited frames.
+ */
+struct scic_sds_unsolicited_frame_control {
+	/**
+	 * This field is the software copy of the unsolicited frame queue
+	 * get pointer.  The controller object writes this value to the
+	 * hardware to let the hardware put more unsolicited frame entries.
+	 */
+	u32 get;
+
+	/**
+	 * This field contains all of the unsolicited frame header
+	 * specific fields.
+	 */
+	struct scic_sds_uf_header_array headers;
+
+	/**
+	 * This field contains all of the unsolicited frame buffer
+	 * specific fields.
+	 */
+	struct scic_sds_uf_buffer_array buffers;
+
+	/**
+	 * This field contains all of the unsolicited frame address table
+	 * specific fields.
+	 */
+	struct scic_sds_uf_address_table_array address_table;
+
+};
+
+void scic_sds_unsolicited_frame_control_set_address_table_count(
+	struct scic_sds_unsolicited_frame_control *uf_control);
+
+struct scic_sds_controller;
+void scic_sds_unsolicited_frame_control_construct(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	struct sci_physical_memory_descriptor *mde,
+	struct scic_sds_controller *this_controller);
+
+enum sci_status scic_sds_unsolicited_frame_control_get_header(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index,
+	void **frame_header);
+
+enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index,
+	void **frame_buffer);
+
+bool scic_sds_unsolicited_frame_control_release_frame(
+	struct scic_sds_unsolicited_frame_control *uf_control,
+	u32 frame_index);
+
+/**
+ * scic_sds_unsolicited_frame_control_get_mde_size() -
+ *
+ * This macro simply calculates the size of the memory descriptor entry that
+ * relates to unsolicited frames and the surrounding silicon memory required to
+ * utilize it.
+ */
+#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \
+	(((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \
+	 + ((uf_control).address_table.count * sizeof(dma_addr_t)) \
+	 + ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header)))
+
+#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */
diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h
new file mode 100644
index 0000000..05a1411
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_registers.h
@@ -0,0 +1,1830 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCU_REGISTERS_H_
+#define _SCU_REGISTERS_H_
+
+/**
+ * This file contains the constants and structures for the SCU memory mapped
+ *    registers.
+ *
+ *
+ */
+
+#include "scu_viit_data.h"
+
+
+/* Generate a value for an SCU register */
+#define SCU_GEN_VALUE(name, value) \
+	(((value) << name ## _SHIFT) & (name ## _MASK))
+
+/*
+ * Generate a bit value for an SCU register
+ * Make sure that the register MASK is just a single bit */
+#define SCU_GEN_BIT(name) \
+	SCU_GEN_VALUE(name, ((u32)1))
+
+#define SCU_SET_BIT(name, reg_value) \
+	((reg_value) | SCU_GEN_BIT(name))
+
+#define SCU_CLEAR_BIT(name, reg_value) \
+	((reg_value)$ ~(SCU_GEN_BIT(name)))
+
+/*
+ * *****************************************************************************
+ * Unions for bitfield definitions of SCU Registers
+ * SMU Post Context Port
+ * ***************************************************************************** */
+#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT         (0)
+#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK          (0x00000FFF)
+#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT    (12)
+#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK     (0x0000F000)
+#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT       (16)
+#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK        (0x00030000)
+#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT       (18)
+#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK        (0x00FC0000)
+#define SMU_POST_CONTEXT_PORT_RESERVED_MASK               (0xFF000000)
+
+#define SMU_PCP_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_ ## name, value)
+
+/* ***************************************************************************** */
+#define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT       (31)
+#define SMU_INTERRUPT_STATUS_COMPLETION_MASK        (0x80000000)
+#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT    (1)
+#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK     (0x00000002)
+#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT      (0)
+#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK       (0x00000001)
+#define SMU_INTERRUPT_STATUS_RESERVED_MASK          (0x7FFFFFFC)
+
+#define SMU_ISR_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_INTERRUPT_STATUS_ ## name)
+
+#define SMU_ISR_QUEUE_ERROR   SMU_ISR_GEN_BIT(QUEUE_ERROR)
+#define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND)
+#define SMU_ISR_COMPLETION    SMU_ISR_GEN_BIT(COMPLETION)
+
+/* ***************************************************************************** */
+#define SMU_INTERRUPT_MASK_COMPLETION_SHIFT         (31)
+#define SMU_INTERRUPT_MASK_COMPLETION_MASK          (0x80000000)
+#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT      (1)
+#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK       (0x00000002)
+#define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT        (0)
+#define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK         (0x00000001)
+#define SMU_INTERRUPT_MASK_RESERVED_MASK            (0x7FFFFFFC)
+
+#define SMU_IMR_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_INTERRUPT_MASK_ ## name)
+
+#define SMU_IMR_QUEUE_ERROR   SMU_IMR_GEN_BIT(QUEUE_ERROR)
+#define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND)
+#define SMU_IMR_COMPLETION    SMU_IMR_GEN_BIT(COMPLETION)
+
+/* ***************************************************************************** */
+#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT    (0)
+#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK     (0x0000001F)
+#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT   (8)
+#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK    (0x0000FF00)
+#define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK  (0xFFFF00E0)
+
+#define SMU_ICC_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_ ## name, value)
+
+/* ***************************************************************************** */
+#define SMU_TASK_CONTEXT_RANGE_START_SHIFT      (0)
+#define SMU_TASK_CONTEXT_RANGE_START_MASK       (0x00000FFF)
+#define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT     (16)
+#define SMU_TASK_CONTEXT_RANGE_ENDING_MASK      (0x0FFF0000)
+#define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT     (31)
+#define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK      (0x80000000)
+#define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK    (0x7000F000)
+
+#define SMU_TCR_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_ ## name, value)
+
+#define SMU_TCR_GEN_BIT(name, value) \
+	SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_ ## name)
+
+/* ***************************************************************************** */
+
+#define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT          (0)
+#define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK           (0x00003FFF)
+#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT        (15)
+#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK         (0x00008000)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT    (16)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK     (0x03FF0000)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT  (26)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK   (0x04000000)
+#define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK          (0xF8004000)
+
+#define SMU_CQPR_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_ ## name, value)
+
+#define SMU_CQPR_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_ ## name)
+
+/* ***************************************************************************** */
+
+#define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT          (0)
+#define SMU_COMPLETION_QUEUE_GET_POINTER_MASK           (0x00003FFF)
+#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT        (15)
+#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK         (0x00008000)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT    (16)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK     (0x03FF0000)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT  (26)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK   (0x04000000)
+#define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT           (30)
+#define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK            (0x40000000)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT     (31)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK      (0x80000000)
+#define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK          (0x38004000)
+
+#define SMU_CQGR_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_ ## name, value)
+
+#define SMU_CQGR_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_ ## name)
+
+#define SMU_CQGR_CYCLE_BIT \
+	SMU_CQGR_GEN_BIT(CYCLE_BIT)
+
+#define SMU_CQGR_EVENT_CYCLE_BIT \
+	SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT)
+
+#define SMU_CQGR_GET_POINTER_SET(value)	\
+	SMU_CQGR_GEN_VAL(POINTER, value)
+
+
+/* ***************************************************************************** */
+#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT  (0)
+#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK   (0x00003FFF)
+#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT  (16)
+#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK   (0x03FF0000)
+#define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK      (0xFC00C000)
+
+#define SMU_CQC_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_ ## name, value)
+
+#define SMU_CQC_QUEUE_LIMIT_SET(value) \
+	SMU_CQC_GEN_VAL(QUEUE_LIMIT, value)
+
+#define SMU_CQC_EVENT_LIMIT_SET(value) \
+	SMU_CQC_GEN_VAL(EVENT_LIMIT, value)
+
+
+/* ***************************************************************************** */
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT    (0)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK     (0x00000FFF)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT    (12)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK     (0x00007000)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT   (15)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK    (0x07FF8000)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT   (27)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK    (0x08000000)
+#define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK   (0xF0000000)
+
+#define SMU_DCC_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_ ## name, value)
+
+#define SMU_DCC_GET_MAX_PEG(value) \
+	(\
+		((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK) \
+		>> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \
+	)
+
+#define SMU_DCC_GET_MAX_LP(value) \
+	(\
+		((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \
+		>> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \
+	)
+
+#define SMU_DCC_GET_MAX_TC(value) \
+	(\
+		((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \
+		>> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \
+	)
+
+#define SMU_DCC_GET_MAX_RNC(value) \
+	(\
+		((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \
+		>> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \
+	)
+
+/* -------------------------------------------------------------------------- */
+
+#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT      (0)
+#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK       (0x00000001)
+#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT    (1)
+#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK     (0x00000002)
+#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT     (16)
+#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK      (0x00010000)
+#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT   (17)
+#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK    (0x00020000)
+#define SMU_CONTROL_STATUS_RESERVED_MASK                        (0xFFFCFFFC)
+
+#define SMU_SMUCSR_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_CONTROL_STATUS_ ## name)
+
+#define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED	\
+	(SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED))
+
+#define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED	\
+	(SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED))
+
+#define SCU_RAM_INIT_COMPLETED \
+	(\
+		SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \
+		| SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \
+	)
+
+/* -------------------------------------------------------------------------- */
+
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT  (0)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK   (0x00000001)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT  (1)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK   (0x00000002)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT  (2)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK   (0x00000004)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT  (3)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK   (0x00000008)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT  (8)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK   (0x00000100)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT  (9)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK   (0x00000200)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT  (10)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK   (0x00000400)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT  (11)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK   (0x00000800)
+
+#define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \
+	((1 << (pe)) << ((peg) * 8))
+
+#define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \
+	(\
+		SMU_RESET_PROTOCOL_ENGINE(peg, 0) \
+		| SMU_RESET_PROTOCOL_ENGINE(peg, 1) \
+		| SMU_RESET_PROTOCOL_ENGINE(peg, 2) \
+		| SMU_RESET_PROTOCOL_ENGINE(peg, 3) \
+	)
+
+#define SMU_RESET_ALL_PROTOCOL_ENGINES() \
+	(\
+		SMU_RESET_PEG_PROTOCOL_ENGINES(0) \
+		| SMU_RESET_PEG_PROTOCOL_ENGINES(1) \
+	)
+
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT  (16)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK   (0x00010000)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT  (17)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK   (0x00020000)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT  (18)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK   (0x00040000)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT  (19)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK   (0x00080000)
+
+#define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \
+	((1 << ((wide_port) / 2)) << ((peg) * 2) << 16)
+
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT      (20)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK       (0x00100000)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT      (21)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK       (0x00200000)
+#define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT       (22)
+#define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK        (0x00400000)
+
+/*
+ * It seems to make sense that if you are going to reset the protocol
+ * engine group that you would also reset all of the protocol engines */
+#define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \
+	(\
+		(1 << ((peg) + 20)) \
+		| SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \
+		| SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \
+		| SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \
+	)
+
+#define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \
+	(\
+		SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \
+		| SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \
+	)
+
+#define SMU_RESET_SCU()  (0xFFFFFFFF)
+
+
+
+/* ***************************************************************************** */
+#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT              (0)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK               (0x00000FFF)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT                (16)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK                 (0x0FFF0000)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT    (31)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK     (0x80000000)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK               (0x7000F000)
+
+#define SMU_TCA_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name, value)
+
+#define SMU_TCA_GEN_BIT(name) \
+	SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name)
+
+/* ***************************************************************************** */
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT   (0)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK    (0x00000FFF)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK      (0xFFFFF000)
+
+#define SCU_UFQC_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_ ## name, value)
+
+#define SCU_UFQC_QUEUE_SIZE_SET(value) \
+	SCU_UFQC_GEN_VAL(QUEUE_SIZE, value)
+
+/* ***************************************************************************** */
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT      (0)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK       (0x00000FFF)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT    (12)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK     (0x00001000)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK      (0xFFFFE000)
+
+#define SCU_UFQPP_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name, value)
+
+#define SCU_UFQPP_GEN_BIT(name)	\
+	SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name)
+
+/*
+ * *****************************************************************************
+ * * SDMA Registers
+ * ***************************************************************************** */
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT      (0)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK       (0x00000FFF)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT    (12)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK     (12)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT   (31)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK    (0x80000000)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK      (0x7FFFE000)
+
+#define SCU_UFQGP_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name, value)
+
+#define SCU_UFQGP_GEN_BIT(name)	\
+	SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name)
+
+#define SCU_UFQGP_CYCLE_BIT(value) \
+	SCU_UFQGP_GEN_BIT(CYCLE_BIT, value)
+
+#define SCU_UFQGP_GET_POINTER(value) \
+	SCU_UFQGP_GEN_VALUE(POINTER, value)
+
+#define SCU_UFQGP_ENABLE(value)	\
+	(SCU_UFQGP_GEN_BIT(ENABLE) | value)
+
+#define SCU_UFQGP_DISABLE(value) \
+	(~SCU_UFQGP_GEN_BIT(ENABLE) & value)
+
+#define SCU_UFQGP_VALUE(bit, value) \
+	(SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value))
+
+/* ***************************************************************************** */
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT                               (0)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK                                (0x0000FFFF)
+#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT                    (16)
+#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK                     (0x00010000)
+#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT                            (17)
+#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK                             (0x00020000)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT                   (18)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK                    (0x00040000)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT               (19)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK                (0x00080000)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT     (20)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK      (0x00100000)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT        (21)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK         (0x00200000)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT                        (22)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK                         (0x00400000)
+#define SCU_PDMA_CONFIGURATION_RESERVED_MASK                                        (0xFF800000)
+
+#define SCU_PDMACR_GEN_VALUE(name, value) \
+	SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_ ## name, value)
+
+#define SCU_PDMACR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_ ## name)
+
+#define SCU_PDMACR_BE_GEN_BIT(name) \
+	SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_ ## name)
+
+/* ***************************************************************************** */
+#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT                    (8)
+#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK                     (0x00000100)
+
+#define SCU_CDMACR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_ ## name)
+
+/*
+ * *****************************************************************************
+ * * SCU Link Layer Registers
+ * ***************************************************************************** */
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT             (0)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK              (0x000000FF)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT           (8)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK            (0x0000FF00)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT   (16)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK    (0x00FF0000)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT  (24)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK   (0xFF000000)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK             (0x00000000)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK              (0x7D00676F)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK             (0x00FF0000)
+
+#define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \
+	SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_ ## name, value)
+
+
+#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT            (2)
+#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK             (0x00000004)
+#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT  (4)
+#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK   (0x00000010)
+#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT     (5)
+#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK      (0x00000020)
+#define SCU_LINK_STATUS_RESERVED_MASK                       (0xFFFFFFCD)
+
+#define SCU_SAS_LLSTA_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_LINK_STATUS_ ## name)
+
+
+/* TODO: Where is the SATA_PSELTOV register? */
+
+/*
+ * *****************************************************************************
+ * * SCU SAS Maximum Arbitration Wait Time Timeout Register
+ * ***************************************************************************** */
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT       (0)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK        (0x00007FFF)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT       (15)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK        (0x00008000)
+
+#define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \
+	SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name, value)
+
+#define SCU_SAS_MAWTTOV_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name)
+
+
+/*
+ * TODO: Where is the SAS_LNKTOV regsiter?
+ * TODO: Where is the SAS_PHYTOV register? */
+
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT            (1)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK             (0x00000002)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT            (2)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK             (0x00000004)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT            (3)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK             (0x00000008)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT          (8)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK           (0x00000100)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT         (9)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK          (0x00000200)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT         (10)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK          (0x00000400)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT         (11)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK          (0x00000800)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT           (16)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK            (0x000F0000)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT    (24)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK     (0x0F000000)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT           (28)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK            (0x70000000)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK               (0x80F0F1F1)
+
+#define SCU_SAS_TIID_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name, value)
+
+#define SCU_SAS_TIID_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name)
+
+/* SAS Identify Frame PHY Identifier Register */
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT      (16)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK       (0x00010000)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT   (17)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK    (0x00020000)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT  (18)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK   (0x00040000)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT                       (24)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK                        (0xFF000000)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK                  (0x00F800FF)
+
+#define SCU_SAS_TIPID_GEN_VALUE(name, value) \
+	SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name, value)
+
+#define SCU_SAS_TIPID_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name)
+
+
+#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT                     (4)
+#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK                      (0x00000010)
+#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT                          (6)
+#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK                           (0x00000040)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT                   (7)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK                    (0x00000080)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT                 (8)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK                  (0x00000100)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT            (9)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK             (0x00000200)
+#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT             (11)
+#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK              (0x00000800)
+#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT                    (12)
+#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK                     (0x00001000)
+#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT      (13)
+#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK       (0x00002000)
+#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT                          (14)
+#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK                           (0x00004000)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT                          (15)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK                           (0x00008000)
+#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT        (23)
+#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK         (0x00800000)
+#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT              (27)
+#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK               (0x08000000)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT    (28)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK     (0x10000000)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT                           (29)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK                            (0x20000000)
+#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT                    (30)
+#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK                     (0x40000000)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT                   (31)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK                    (0x80000000)
+#define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK                             (0x0100000F)
+#define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK                              (0x4180100F)
+#define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK                             (0x00000000)
+
+#define SCU_SAS_PCFG_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name)
+
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT      (0)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK       (0x000007FF)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT    (16)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK     (0x00ff0000)
+
+#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value)
+
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT    (0)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK     (0x0003FFFF)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT   (31)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK    (0x80000000)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK  (0x7FFC0000)
+
+#define SCU_ENSPINUP_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name, value)
+
+#define SCU_ENSPINUP_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name)
+
+
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT     (1)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK      (0x00000002)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT       (4)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK        (0x000000F0)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT     (8)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK      (0x00000100)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT      (9)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK       (0x00000201)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT     (10)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK      (0x00000401)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT      (11)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK       (0x00000801)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT     (12)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK      (0x00001001)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT      (13)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK       (0x00002001)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT   (31)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK    (0x80000000)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK        (0x00003F01)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK       (0x00000001)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK       (0x7FFFC00D)
+
+#define SCU_SAS_PHYCAP_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name, value)
+
+#define SCU_SAS_PHYCAP_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name)
+
+
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT  (0)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK   (0x000000FF)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT         (31)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK          (0x80000000)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK                          (0x7FFFFF00)
+
+#define SCU_PSZGCR_GEN_VAL(name, value)	\
+	SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name, value)
+
+#define SCU_PSZGCR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name)
+
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT        (1)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK         (0x00000002)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT      (2)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK       (0x00000004)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT        (4)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK         (0x00000010)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT      (5)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK       (0x00000020)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK  (0x00030000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT      (19)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK       (0x00080000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK  (0x00300000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT      (23)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK       (0x00800000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK  (0x03000000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT      (27)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK       (0x08000000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK  (0x30000000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT      (31)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK       (0x80000000)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK             (0x4444FFC9)
+
+#define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \
+	SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name, val)
+
+#define SCU_PEG_SCUVZECR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name)
+
+
+/*
+ * *****************************************************************************
+ * * Port Task Scheduler registers shift and mask values
+ * ***************************************************************************** */
+#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT     (0)
+#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK      (0x0000FFFF)
+#define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT         (16)
+#define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK          (0x00FF0000)
+#define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT          (24)
+#define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK           (0x01000000)
+#define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT           (25)
+#define SCU_PTSG_CONTROL_ETM_ENABLE_MASK            (0x02000000)
+#define SCU_PTSG_CONTROL_DEFAULT_MASK               (0x00020002)
+#define SCU_PTSG_CONTROL_REQUIRED_MASK              (0x00000000)
+#define SCU_PTSG_CONTROL_RESERVED_MASK              (0xFC000000)
+
+#define SCU_PTSGCR_GEN_VAL(name, val) \
+	SCU_GEN_VALUE(SCU_PTSG_CONTROL_ ## name, val)
+
+#define SCU_PTSGCR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_PTSG_CONTROL_ ## name)
+
+
+/* ***************************************************************************** */
+#define SCU_PTSG_REAL_TIME_CLOCK_SHIFT          (0)
+#define SCU_PTSG_REAL_TIME_CLOCK_MASK           (0x0000FFFF)
+#define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK  (0xFFFF0000)
+
+#define SCU_RTCR_GEN_VAL(name, val) \
+	SCU_GEN_VALUE(SCU_PTSG_ ## name, val)
+
+
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT  (0)
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK   (0x00FFFFFF)
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK          (0xFF000000)
+
+#define SCU_RTCCR_GEN_VAL(name, val) \
+	SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_ ## name, val)
+
+
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT  (0)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK   (0x00000001)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT   (1)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK    (0x00000002)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK  (0xFFFFFFFC)
+
+#define SCU_PTSxCR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ ## name)
+
+
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT             (0)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK              (0x00000001)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT    (1)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK     (0x00000002)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT             (2)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK              (0x00000004)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK                   (0xFFFFFFF8)
+
+#define SCU_PTSxSR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name)
+
+
+/*
+ * *****************************************************************************
+ * * SGPIO Register shift and mask values
+ * ***************************************************************************** */
+#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT                    (0)
+#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK                     (0x00000001)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT       (1)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK        (0x00000002)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK  (0x00000004)
+#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT                  (15)
+#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK                   (0x00008000)
+#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK                   (0xFFFF7FF8)
+
+#define SCU_SGICRx_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name)
+
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT      (0)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK       (0x0000000F)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT      (4)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK       (0x000000F0)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT      (8)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK       (0x00000F00)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT      (12)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK       (0x0000F000)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000)
+
+#define SCU_SGPBRx_GEN_VAL(name, value)	\
+	SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value)
+
+#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT        (0)
+#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK         (0x00000003)
+#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT        (4)
+#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK         (0x00000030)
+#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT        (8)
+#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK         (0x00000300)
+#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT        (12)
+#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK         (0x00003000)
+#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK   (0xFFFF8888)
+
+#define SCU_SGSDLRx_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
+
+#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT        (0)
+#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK         (0x00000003)
+#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT        (4)
+#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK         (0x00000030)
+#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT        (8)
+#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK         (0x00000300)
+#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT        (12)
+#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK         (0x00003000)
+#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK   (0xFFFF8888)
+
+#define SCU_SGSDURx_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
+
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT      (0)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK       (0x00000003)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT      (4)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK       (0x00000030)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT      (8)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK       (0x00000300)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT      (12)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK       (0x00003000)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888)
+
+#define SCU_SGSIDLRx_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
+
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT      (0)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK       (0x00000003)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT      (4)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK       (0x00000030)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT      (8)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK       (0x00000300)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT      (12)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK       (0x00003000)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888)
+
+#define SCU_SGSIDURx_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
+
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT            (0)
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK             (0x0000000F)
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK    (0xFFFFFFF0)
+
+#define SCU_SGVSCR_GEN_VAL(value) \
+	SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value)
+
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT           (0)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK            (0x00000003)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT    (2)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK     (0x00000004)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT      (3)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK       (0x00000008)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT           (4)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK            (0x00000030)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT    (6)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK     (0x00000040)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT      (7)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK       (0x00000080)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT           (8)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK            (0x00000300)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT    (10)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK     (0x00000400)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT      (11)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK       (0x00000800)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK               (0xFFFFF000)
+
+#define SCU_SGODSR_GEN_VAL(name, value)	\
+	SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value)
+
+#define SCU_SGODSR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name)
+
+/*
+ * *****************************************************************************
+ * * SMU Registers
+ * ***************************************************************************** */
+
+/*
+ * ----------------------------------------------------------------------------
+ * SMU Registers
+ * These registers are based off of BAR0
+ *
+ * To calculate the offset for other functions use
+ *       BAR0 + FN# * SystemPageSize * 2
+ *
+ * The TCA is only accessable from FN#0 (Physical Function) and each
+ * is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or
+ *    TCA0 for FN#0 is at BAR0 + 0x0400
+ *    TCA1 for FN#1 is at BAR0 + 0x0404
+ *    etc.
+ * ----------------------------------------------------------------------------
+ * Accessable to all FN#s */
+#define SCU_SMU_PCP_OFFSET          0x0000
+#define SCU_SMU_AMR_OFFSET          0x0004
+#define SCU_SMU_ISR_OFFSET          0x0010
+#define SCU_SMU_IMR_OFFSET          0x0014
+#define SCU_SMU_ICC_OFFSET          0x0018
+#define SCU_SMU_HTTLBAR_OFFSET      0x0020
+#define SCU_SMU_HTTUBAR_OFFSET      0x0024
+#define SCU_SMU_TCR_OFFSET          0x0028
+#define SCU_SMU_CQLBAR_OFFSET       0x0030
+#define SCU_SMU_CQUBAR_OFFSET       0x0034
+#define SCU_SMU_CQPR_OFFSET         0x0040
+#define SCU_SMU_CQGR_OFFSET         0x0044
+#define SCU_SMU_CQC_OFFSET          0x0048
+/* Accessable to FN#0 only */
+#define SCU_SMU_RNCLBAR_OFFSET      0x0080
+#define SCU_SMU_RNCUBAR_OFFSET      0x0084
+#define SCU_SMU_DCC_OFFSET          0x0090
+#define SCU_SMU_DFC_OFFSET          0x0094
+#define SCU_SMU_SMUCSR_OFFSET       0x0098
+#define SCU_SMU_SCUSRCR_OFFSET      0x009C
+#define SCU_SMU_SMAW_OFFSET         0x00A0
+#define SCU_SMU_SMDW_OFFSET         0x00A4
+/* Accessable to FN#0 only */
+#define SCU_SMU_TCA_OFFSET          0x0400
+/* Accessable to all FN#s */
+#define SCU_SMU_MT_MLAR0_OFFSET     0x2000
+#define SCU_SMU_MT_MUAR0_OFFSET     0x2004
+#define SCU_SMU_MT_MDR0_OFFSET      0x2008
+#define SCU_SMU_MT_VCR0_OFFSET      0x200C
+#define SCU_SMU_MT_MLAR1_OFFSET     0x2010
+#define SCU_SMU_MT_MUAR1_OFFSET     0x2014
+#define SCU_SMU_MT_MDR1_OFFSET      0x2018
+#define SCU_SMU_MT_VCR1_OFFSET      0x201C
+#define SCU_SMU_MPBA_OFFSET         0x3000
+
+/**
+ * struct smu_registers - These are the SMU registers
+ *
+ *
+ */
+struct smu_registers {
+/* 0x0000 PCP */
+	u32 post_context_port;
+/* 0x0004 AMR */
+	u32 address_modifier;
+	u32 reserved_08;
+	u32 reserved_0C;
+/* 0x0010 ISR */
+	u32 interrupt_status;
+/* 0x0014 IMR */
+	u32 interrupt_mask;
+/* 0x0018 ICC */
+	u32 interrupt_coalesce_control;
+	u32 reserved_1C;
+/* 0x0020 HTTLBAR */
+	u32 host_task_table_lower;
+/* 0x0024 HTTUBAR */
+	u32 host_task_table_upper;
+/* 0x0028 TCR */
+	u32 task_context_range;
+	u32 reserved_2C;
+/* 0x0030 CQLBAR */
+	u32 completion_queue_lower;
+/* 0x0034 CQUBAR */
+	u32 completion_queue_upper;
+	u32 reserved_38;
+	u32 reserved_3C;
+/* 0x0040 CQPR */
+	u32 completion_queue_put;
+/* 0x0044 CQGR */
+	u32 completion_queue_get;
+/* 0x0048 CQC */
+	u32 completion_queue_control;
+	u32 reserved_4C;
+	u32 reserved_5x[4];
+	u32 reserved_6x[4];
+	u32 reserved_7x[4];
+/*
+ * Accessable to FN#0 only
+ * 0x0080 RNCLBAR */
+	u32 remote_node_context_lower;
+/* 0x0084 RNCUBAR */
+	u32 remote_node_context_upper;
+	u32 reserved_88;
+	u32 reserved_8C;
+/* 0x0090 DCC */
+	u32 device_context_capacity;
+/* 0x0094 DFC */
+	u32 device_function_capacity;
+/* 0x0098 SMUCSR */
+	u32 control_status;
+/* 0x009C SCUSRCR */
+	u32 soft_reset_control;
+/* 0x00A0 SMAW */
+	u32 mmr_address_window;
+/* 0x00A4 SMDW */
+	u32 mmr_data_window;
+	u32 reserved_A8;
+	u32 reserved_AC;
+/* A whole bunch of reserved space */
+	u32 reserved_Bx[4];
+	u32 reserved_Cx[4];
+	u32 reserved_Dx[4];
+	u32 reserved_Ex[4];
+	u32 reserved_Fx[4];
+	u32 reserved_1xx[64];
+	u32 reserved_2xx[64];
+	u32 reserved_3xx[64];
+/*
+ * Accessable to FN#0 only
+ * 0x0400 TCA */
+	u32 task_context_assignment[256];
+/* MSI-X registers not included */
+};
+
+/*
+ * *****************************************************************************
+ * SDMA Registers
+ * ***************************************************************************** */
+#define SCU_SDMA_BASE               0x6000
+#define SCU_SDMA_PUFATLHAR_OFFSET   0x0000
+#define SCU_SDMA_PUFATUHAR_OFFSET   0x0004
+#define SCU_SDMA_UFLHBAR_OFFSET     0x0008
+#define SCU_SDMA_UFUHBAR_OFFSET     0x000C
+#define SCU_SDMA_UFQC_OFFSET        0x0010
+#define SCU_SDMA_UFQPP_OFFSET       0x0014
+#define SCU_SDMA_UFQGP_OFFSET       0x0018
+#define SCU_SDMA_PDMACR_OFFSET      0x001C
+#define SCU_SDMA_CDMACR_OFFSET      0x0080
+
+/**
+ * struct scu_sdma_registers - These are the SCU SDMA Registers
+ *
+ *
+ */
+struct scu_sdma_registers {
+/* 0x0000 PUFATLHAR */
+	u32 uf_address_table_lower;
+/* 0x0004 PUFATUHAR */
+	u32 uf_address_table_upper;
+/* 0x0008 UFLHBAR */
+	u32 uf_header_base_address_lower;
+/* 0x000C UFUHBAR */
+	u32 uf_header_base_address_upper;
+/* 0x0010 UFQC */
+	u32 unsolicited_frame_queue_control;
+/* 0x0014 UFQPP */
+	u32 unsolicited_frame_put_pointer;
+/* 0x0018 UFQGP */
+	u32 unsolicited_frame_get_pointer;
+/* 0x001C PDMACR */
+	u32 pdma_configuration;
+/* Reserved until offset 0x80 */
+	u32 reserved_0020_007C[0x18];
+/* 0x0080 CDMACR */
+	u32 cdma_configuration;
+/* Remainder SDMA register space */
+	u32 reserved_0084_0400[0xDF];
+
+};
+
+/*
+ * *****************************************************************************
+ * * SCU Link Registers
+ * ***************************************************************************** */
+#define SCU_PEG0_OFFSET    0x0000
+#define SCU_PEG1_OFFSET    0x8000
+
+#define SCU_TL0_OFFSET     0x0000
+#define SCU_TL1_OFFSET     0x0400
+#define SCU_TL2_OFFSET     0x0800
+#define SCU_TL3_OFFSET     0x0C00
+
+#define SCU_LL_OFFSET      0x0080
+#define SCU_LL0_OFFSET     (SCU_TL0_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL1_OFFSET     (SCU_TL1_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL2_OFFSET     (SCU_TL2_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL3_OFFSET     (SCU_TL3_OFFSET + SCU_LL_OFFSET)
+
+/* Transport Layer Offsets (PEG + TL) */
+#define SCU_TLCR_OFFSET         0x0000
+#define SCU_TLADTR_OFFSET       0x0004
+#define SCU_TLTTMR_OFFSET       0x0008
+#define SCU_TLEECR0_OFFSET      0x000C
+#define SCU_STPTLDARNI_OFFSET   0x0010
+
+
+#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT    (0)
+#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK     (0x00000001)
+#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1)
+#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK  (0x00000002)
+#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT     (3)
+#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK      (0x00000008)
+#define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT         (4)
+#define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK          (0x00000010)
+#define SCU_TLCR_RESERVED_MASK                     (0xFFFFFFEB)
+
+#define SCU_TLCR_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_TLCR_ ## name)
+
+/**
+ * struct scu_transport_layer_registers - These are the SCU Transport Layer
+ *    registers
+ *
+ *
+ */
+struct scu_transport_layer_registers {
+	/* 0x0000 TLCR */
+	u32 control;
+	/* 0x0004 TLADTR */
+	u32 arbitration_delay_timer;
+	/* 0x0008 TLTTMR */
+	u32 timer_test_mode;
+	/* 0x000C reserved */
+	u32 reserved_0C;
+	/* 0x0010 STPTLDARNI */
+	u32 stp_rni;
+	/* 0x0014 TLFEWPORCTRL */
+	u32 tlfe_wpo_read_control;
+	/* 0x0018 TLFEWPORDATA */
+	u32 tlfe_wpo_read_data;
+	/* 0x001C RXTLSSCSR1 */
+	u32 rxtl_single_step_control_status_1;
+	/* 0x0020 RXTLSSCSR2 */
+	u32 rxtl_single_step_control_status_2;
+	/* 0x0024 AWTRDDCR */
+	u32 tlfe_awt_retry_delay_debug_control;
+	/* Remainder of TL memory space */
+	u32 reserved_0028_007F[0x16];
+
+};
+
+/* Protocol Engine Group Registers */
+#define SCU_SCUVZECRx_OFFSET        0x1080
+
+/* Link Layer Offsets (PEG + TL + LL) */
+#define SCU_SAS_SPDTOV_OFFSET       0x0000
+#define SCU_SAS_LLSTA_OFFSET        0x0004
+#define SCU_SATA_PSELTOV_OFFSET     0x0008
+#define SCU_SAS_TIMETOV_OFFSET      0x0010
+#define SCU_SAS_LOSTOT_OFFSET       0x0014
+#define SCU_SAS_LNKTOV_OFFSET       0x0018
+#define SCU_SAS_PHYTOV_OFFSET       0x001C
+#define SCU_SAS_AFERCNT_OFFSET      0x0020
+#define SCU_SAS_WERCNT_OFFSET       0x0024
+#define SCU_SAS_TIID_OFFSET         0x0028
+#define SCU_SAS_TIDNH_OFFSET        0x002C
+#define SCU_SAS_TIDNL_OFFSET        0x0030
+#define SCU_SAS_TISSAH_OFFSET       0x0034
+#define SCU_SAS_TISSAL_OFFSET       0x0038
+#define SCU_SAS_TIPID_OFFSET        0x003C
+#define SCU_SAS_TIRES2_OFFSET       0x0040
+#define SCU_SAS_ADRSTA_OFFSET       0x0044
+#define SCU_SAS_MAWTTOV_OFFSET      0x0048
+#define SCU_SAS_FRPLDFIL_OFFSET     0x0054
+#define SCU_SAS_RFCNT_OFFSET        0x0060
+#define SCU_SAS_TFCNT_OFFSET        0x0064
+#define SCU_SAS_RFDCNT_OFFSET       0x0068
+#define SCU_SAS_TFDCNT_OFFSET       0x006C
+#define SCU_SAS_LERCNT_OFFSET       0x0070
+#define SCU_SAS_RDISERRCNT_OFFSET   0x0074
+#define SCU_SAS_CRERCNT_OFFSET      0x0078
+#define SCU_STPCTL_OFFSET           0x007C
+#define SCU_SAS_PCFG_OFFSET         0x0080
+#define SCU_SAS_CLKSM_OFFSET        0x0084
+#define SCU_SAS_TXCOMWAKE_OFFSET    0x0088
+#define SCU_SAS_TXCOMINIT_OFFSET    0x008C
+#define SCU_SAS_TXCOMSAS_OFFSET     0x0090
+#define SCU_SAS_COMINIT_OFFSET      0x0094
+#define SCU_SAS_COMWAKE_OFFSET      0x0098
+#define SCU_SAS_COMSAS_OFFSET       0x009C
+#define SCU_SAS_SFERCNT_OFFSET      0x00A0
+#define SCU_SAS_CDFERCNT_OFFSET     0x00A4
+#define SCU_SAS_DNFERCNT_OFFSET     0x00A8
+#define SCU_SAS_PRSTERCNT_OFFSET    0x00AC
+#define SCU_SAS_CNTCTL_OFFSET       0x00B0
+#define SCU_SAS_SSPTOV_OFFSET       0x00B4
+#define SCU_FTCTL_OFFSET            0x00B8
+#define SCU_FRCTL_OFFSET            0x00BC
+#define SCU_FTWMRK_OFFSET           0x00C0
+#define SCU_ENSPINUP_OFFSET         0x00C4
+#define SCU_SAS_TRNTOV_OFFSET       0x00C8
+#define SCU_SAS_PHYCAP_OFFSET       0x00CC
+#define SCU_SAS_PHYCTL_OFFSET       0x00D0
+#define SCU_SAS_LLCTL_OFFSET        0x00D8
+#define SCU_AFE_XCVRCR_OFFSET       0x00DC
+#define SCU_AFE_LUTCR_OFFSET        0x00E0
+
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT                  (0)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK                   (0x00000003)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1                   (0)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2                   (1)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3                   (2)
+#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT            (2)
+#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK             (0x000003FC)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT   (16)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK    (0x00010000)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK  (0x00020000)
+#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT       (24)
+#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK        (0xFF000000)
+#define SCU_SAS_LINK_LAYER_CONTROL_RESERVED                             (0x00FCFC00)
+
+#define SCU_SAS_LLCTL_GEN_VAL(name, value) \
+	SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_ ## name, value)
+
+#define SCU_SAS_LLCTL_GEN_BIT(name) \
+	SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name)
+
+
+/* #define SCU_FRXHECR_DCNT_OFFSET      0x00B0 */
+#define SCU_PSZGCR_OFFSET           0x00E4
+#define SCU_SAS_RECPHYCAP_OFFSET    0x00E8
+/* #define SCU_TX_LUTSEL_OFFSET         0x00B8 */
+
+#define SCU_SAS_PTxC_OFFSET         0x00D4 /* Same offset as SAS_TCTSTM */
+
+/**
+ * struct scu_link_layer_registers - SCU Link Layer Registers
+ *
+ *
+ */
+struct scu_link_layer_registers {
+/* 0x0000 SAS_SPDTOV */
+	u32 speed_negotiation_timers;
+/* 0x0004 SAS_LLSTA */
+	u32 link_layer_status;
+/* 0x0008 SATA_PSELTOV */
+	u32 port_selector_timeout;
+	u32 reserved0C;
+/* 0x0010 SAS_TIMETOV */
+	u32 timeout_unit_value;
+/* 0x0014 SAS_RCDTOV */
+	u32 rcd_timeout;
+/* 0x0018 SAS_LNKTOV */
+	u32 link_timer_timeouts;
+/* 0x001C SAS_PHYTOV */
+	u32 sas_phy_timeouts;
+/* 0x0020 SAS_AFERCNT */
+	u32 received_address_frame_error_counter;
+/* 0x0024 SAS_WERCNT */
+	u32 invalid_dword_counter;
+/* 0x0028 SAS_TIID */
+	u32 transmit_identification;
+/* 0x002C SAS_TIDNH */
+	u32 sas_device_name_high;
+/* 0x0030 SAS_TIDNL */
+	u32 sas_device_name_low;
+/* 0x0034 SAS_TISSAH */
+	u32 source_sas_address_high;
+/* 0x0038 SAS_TISSAL */
+	u32 source_sas_address_low;
+/* 0x003C SAS_TIPID */
+	u32 identify_frame_phy_id;
+/* 0x0040 SAS_TIRES2 */
+	u32 identify_frame_reserved;
+/* 0x0044 SAS_ADRSTA */
+	u32 received_address_frame;
+/* 0x0048 SAS_MAWTTOV */
+	u32 maximum_arbitration_wait_timer_timeout;
+/* 0x004C SAS_PTxC */
+	u32 transmit_primitive;
+/* 0x0050 SAS_RORES */
+	u32 error_counter_event_notification_control;
+/* 0x0054 SAS_FRPLDFIL */
+	u32 frxq_payload_fill_threshold;
+/* 0x0058 SAS_LLHANG_TOT */
+	u32 link_layer_hang_detection_timeout;
+	u32 reserved_5C;
+/* 0x0060 SAS_RFCNT */
+	u32 received_frame_count;
+/* 0x0064 SAS_TFCNT */
+	u32 transmit_frame_count;
+/* 0x0068 SAS_RFDCNT */
+	u32 received_dword_count;
+/* 0x006C SAS_TFDCNT */
+	u32 transmit_dword_count;
+/* 0x0070 SAS_LERCNT */
+	u32 loss_of_sync_error_count;
+/* 0x0074 SAS_RDISERRCNT */
+	u32 running_disparity_error_count;
+/* 0x0078 SAS_CRERCNT */
+	u32 received_frame_crc_error_count;
+/* 0x007C STPCTL */
+	u32 stp_control;
+/* 0x0080 SAS_PCFG */
+	u32 phy_configuration;
+/* 0x0084 SAS_CLKSM */
+	u32 clock_skew_management;
+/* 0x0088 SAS_TXCOMWAKE */
+	u32 transmit_comwake_signal;
+/* 0x008C SAS_TXCOMINIT */
+	u32 transmit_cominit_signal;
+/* 0x0090 SAS_TXCOMSAS */
+	u32 transmit_comsas_signal;
+/* 0x0094 SAS_COMINIT */
+	u32 cominit_control;
+/* 0x0098 SAS_COMWAKE */
+	u32 comwake_control;
+/* 0x009C SAS_COMSAS */
+	u32 comsas_control;
+/* 0x00A0 SAS_SFERCNT */
+	u32 received_short_frame_count;
+/* 0x00A4 SAS_CDFERCNT */
+	u32 received_frame_without_credit_count;
+/* 0x00A8 SAS_DNFERCNT */
+	u32 received_frame_after_done_count;
+/* 0x00AC SAS_PRSTERCNT */
+	u32 phy_reset_problem_count;
+/* 0x00B0 SAS_CNTCTL */
+	u32 counter_control;
+/* 0x00B4 SAS_SSPTOV */
+	u32 ssp_timer_timeout_values;
+/* 0x00B8 FTCTL */
+	u32 ftx_control;
+/* 0x00BC FRCTL */
+	u32 frx_control;
+/* 0x00C0 FTWMRK */
+	u32 ftx_watermark;
+/* 0x00C4 ENSPINUP */
+	u32 notify_enable_spinup_control;
+/* 0x00C8 SAS_TRNTOV */
+	u32 sas_training_sequence_timer_values;
+/* 0x00CC SAS_PHYCAP */
+	u32 phy_capabilities;
+/* 0x00D0 SAS_PHYCTL */
+	u32 phy_control;
+	u32 reserved_d4;
+/* 0x00D8 LLCTL */
+	u32 link_layer_control;
+/* 0x00DC AFE_XCVRCR */
+	u32 afe_xcvr_control;
+/* 0x00E0 AFE_LUTCR */
+	u32 afe_lookup_table_control;
+/* 0x00E4 PSZGCR */
+	u32 phy_source_zone_group_control;
+/* 0x00E8 SAS_RECPHYCAP */
+	u32 receive_phycap;
+	u32 reserved_ec;
+/* 0x00F0 SNAFERXRSTCTL */
+	u32 speed_negotiation_afe_rx_reset_control;
+/* 0x00F4 SAS_SSIPMCTL */
+	u32 power_management_control;
+/* 0x00F8 SAS_PSPREQ_PRIM */
+	u32 sas_pm_partial_request_primitive;
+/* 0x00FC SAS_PSSREQ_PRIM */
+	u32 sas_pm_slumber_request_primitive;
+/* 0x0100 SAS_PPSACK_PRIM */
+	u32 sas_pm_ack_primitive_register;
+/* 0x0104 SAS_PSNAK_PRIM */
+	u32 sas_pm_nak_primitive_register;
+/* 0x0108 SAS_SSIPMTOV */
+	u32 sas_primitive_timeout;
+	u32 reserved_10c;
+/* 0x0110 - 0x011C PLAPRDCTRLxREG */
+	u32 pla_product_control[4];
+/* 0x0120 PLAPRDSUMREG */
+	u32 pla_product_sum;
+/* 0x0124 PLACONTROLREG */
+	u32 pla_control;
+/* Remainder of memory space 896 bytes */
+	u32 reserved_0128_037f[0x96];
+
+};
+
+/*
+ * 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC
+ *   u32   primitive_transmit_control; */
+
+/*
+ * ----------------------------------------------------------------------------
+ * SGPIO
+ * ---------------------------------------------------------------------------- */
+#define SCU_SGPIO_OFFSET         0x1400
+
+/* #define SCU_SGPIO_OFFSET         0x6000   // later moves to 0x1400 see HSD 652625 */
+#define SCU_SGPIO_SGICR_OFFSET   0x0000
+#define SCU_SGPIO_SGPBR_OFFSET   0x0004
+#define SCU_SGPIO_SGSDLR_OFFSET  0x0008
+#define SCU_SGPIO_SGSDUR_OFFSET  0x000C
+#define SCU_SGPIO_SGSIDLR_OFFSET 0x0010
+#define SCU_SGPIO_SGSIDUR_OFFSET 0x0014
+#define SCU_SGPIO_SGVSCR_OFFSET  0x0018
+/* Address from 0x0820 to 0x083C */
+#define SCU_SGPIO_SGODSR_OFFSET  0x0020
+
+/**
+ * struct scu_sgpio_registers - SCU SGPIO Registers
+ *
+ *
+ */
+struct scu_sgpio_registers {
+/* 0x0000 SGPIO_SGICR */
+	u32 interface_control;
+/* 0x0004 SGPIO_SGPBR */
+	u32 blink_rate;
+/* 0x0008 SGPIO_SGSDLR */
+	u32 start_drive_lower;
+/* 0x000C SGPIO_SGSDUR */
+	u32 start_drive_upper;
+/* 0x0010 SGPIO_SGSIDLR */
+	u32 serial_input_lower;
+/* 0x0014 SGPIO_SGSIDUR */
+	u32 serial_input_upper;
+/* 0x0018 SGPIO_SGVSCR */
+	u32 vendor_specific_code;
+/* 0x0020 SGPIO_SGODSR */
+	u32 ouput_data_select[8];
+/* Remainder of memory space 256 bytes */
+	u32 reserved_1444_14ff[0x31];
+
+};
+
+/*
+ * *****************************************************************************
+ * * Defines for VIIT entry offsets
+ * * Access additional entries by SCU_VIIT_BASE + index * 0x10
+ * ***************************************************************************** */
+#define     SCU_VIIT_BASE     0x1c00
+
+struct SCU_VIIT_REGISTERS {
+	u32 registers[256];
+};
+
+/*
+ * *****************************************************************************
+ * * SCU PORT TASK SCHEDULER REGISTERS
+ * ***************************************************************************** */
+
+#define SCU_PTSG_BASE               0x1000
+
+#define SCU_PTSG_PTSGCR_OFFSET      0x0000
+#define SCU_PTSG_RTCR_OFFSET        0x0004
+#define SCU_PTSG_RTCCR_OFFSET       0x0008
+#define SCU_PTSG_PTS0CR_OFFSET      0x0010
+#define SCU_PTSG_PTS0SR_OFFSET      0x0014
+#define SCU_PTSG_PTS1CR_OFFSET      0x0018
+#define SCU_PTSG_PTS1SR_OFFSET      0x001C
+#define SCU_PTSG_PTS2CR_OFFSET      0x0020
+#define SCU_PTSG_PTS2SR_OFFSET      0x0024
+#define SCU_PTSG_PTS3CR_OFFSET      0x0028
+#define SCU_PTSG_PTS3SR_OFFSET      0x002C
+#define SCU_PTSG_PCSPE0CR_OFFSET    0x0030
+#define SCU_PTSG_PCSPE1CR_OFFSET    0x0034
+#define SCU_PTSG_PCSPE2CR_OFFSET    0x0038
+#define SCU_PTSG_PCSPE3CR_OFFSET    0x003C
+#define SCU_PTSG_ETMTSCCR_OFFSET    0x0040
+#define SCU_PTSG_ETMRNSCCR_OFFSET   0x0044
+
+/**
+ * struct scu_port_task_scheduler_registers - These are the control/stats pairs
+ *    for each Port Task Scheduler.
+ *
+ *
+ */
+struct scu_port_task_scheduler_registers {
+	u32 control;
+	u32 status;
+};
+
+typedef u32 SCU_PORT_PE_CONFIGURATION_REGISTER_T;
+
+/**
+ * struct scu_port_task_scheduler_group_registers - These are the PORT Task
+ *    Scheduler registers
+ *
+ *
+ */
+struct scu_port_task_scheduler_group_registers {
+/* 0x0000 PTSGCR */
+	u32 control;
+/* 0x0004 RTCR */
+	u32 real_time_clock;
+/* 0x0008 RTCCR */
+	u32 real_time_clock_control;
+/* 0x000C */
+	u32 reserved_0C;
+/*
+ * 0x0010 PTS0CR
+ * 0x0014 PTS0SR
+ * 0x0018 PTS1CR
+ * 0x001C PTS1SR
+ * 0x0020 PTS2CR
+ * 0x0024 PTS2SR
+ * 0x0028 PTS3CR
+ * 0x002C PTS3SR */
+	struct scu_port_task_scheduler_registers port[4];
+/*
+ * 0x0030 PCSPE0CR
+ * 0x0034 PCSPE1CR
+ * 0x0038 PCSPE2CR
+ * 0x003C PCSPE3CR */
+	SCU_PORT_PE_CONFIGURATION_REGISTER_T protocol_engine[4];
+/* 0x0040 ETMTSCCR */
+	u32 tc_scanning_interval_control;
+/* 0x0044 ETMRNSCCR */
+	u32 rnc_scanning_interval_control;
+/* Remainder of memory space 128 bytes */
+	u32 reserved_1048_107f[0x0E];
+
+};
+
+#define SCU_PTSG_SCUVZECR_OFFSET        0x003C
+
+/*
+ * *****************************************************************************
+ * * AFE REGISTERS
+ * ***************************************************************************** */
+#define SCU_AFE_MMR_BASE                  0xE000
+
+/*
+ * AFE 0 is at offset 0x0800
+ * AFE 1 is at offset 0x0900
+ * AFE 2 is at offset 0x0a00
+ * AFE 3 is at offset 0x0b00 */
+struct scu_afe_transceiver {
+	/* 0x0000 AFE_XCVR_CTRL0 */
+	u32 afe_xcvr_control0;
+	/* 0x0004 AFE_XCVR_CTRL1 */
+	u32 afe_xcvr_control1;
+	/* 0x0008 */
+	u32 reserved_0008;
+	/* 0x000c afe_dfx_rx_control0 */
+	u32 afe_dfx_rx_control0;
+	/* 0x0010 AFE_DFX_RX_CTRL1 */
+	u32 afe_dfx_rx_control1;
+	/* 0x0014 */
+	u32 reserved_0014;
+	/* 0x0018 AFE_DFX_RX_STS0 */
+	u32 afe_dfx_rx_status0;
+	/* 0x001c AFE_DFX_RX_STS1 */
+	u32 afe_dfx_rx_status1;
+	/* 0x0020 */
+	u32 reserved_0020;
+	/* 0x0024 AFE_TX_CTRL */
+	u32 afe_tx_control;
+	/* 0x0028 AFE_TX_AMP_CTRL0 */
+	u32 afe_tx_amp_control0;
+	/* 0x002c AFE_TX_AMP_CTRL1 */
+	u32 afe_tx_amp_control1;
+	/* 0x0030 AFE_TX_AMP_CTRL2 */
+	u32 afe_tx_amp_control2;
+	/* 0x0034 AFE_TX_AMP_CTRL3 */
+	u32 afe_tx_amp_control3;
+	/* 0x0038 afe_tx_ssc_control */
+	u32 afe_tx_ssc_control;
+	/* 0x003c */
+	u32 reserved_003c;
+	/* 0x0040 AFE_RX_SSC_CTRL0 */
+	u32 afe_rx_ssc_control0;
+	/* 0x0044 AFE_RX_SSC_CTRL1 */
+	u32 afe_rx_ssc_control1;
+	/* 0x0048 AFE_RX_SSC_CTRL2 */
+	u32 afe_rx_ssc_control2;
+	/* 0x004c AFE_RX_EQ_STS0 */
+	u32 afe_rx_eq_status0;
+	/* 0x0050 AFE_RX_EQ_STS1 */
+	u32 afe_rx_eq_status1;
+	/* 0x0054 AFE_RX_CDR_STS */
+	u32 afe_rx_cdr_status;
+	/* 0x0058 */
+	u32 reserved_0058;
+	/* 0x005c AFE_CHAN_CTRL */
+	u32 afe_channel_control;
+	/* 0x0060-0x006c */
+	u32 reserved_0060_006c[0x04];
+	/* 0x0070 AFE_XCVR_EC_STS0 */
+	u32 afe_xcvr_error_capture_status0;
+	/* 0x0074 AFE_XCVR_EC_STS1 */
+	u32 afe_xcvr_error_capture_status1;
+	/* 0x0078 AFE_XCVR_EC_STS2 */
+	u32 afe_xcvr_error_capture_status2;
+	/* 0x007c afe_xcvr_ec_status3 */
+	u32 afe_xcvr_error_capture_status3;
+	/* 0x0080 AFE_XCVR_EC_STS4 */
+	u32 afe_xcvr_error_capture_status4;
+	/* 0x0084 AFE_XCVR_EC_STS5 */
+	u32 afe_xcvr_error_capture_status5;
+	/* 0x0088-0x00fc */
+	u32 reserved_008c_00fc[0x1e];
+};
+
+/**
+ * struct scu_afe_registers - AFE Regsiters
+ *
+ *
+ */
+/* Uaoa AFE registers */
+struct scu_afe_registers {
+	/* 0Xe000 AFE_BIAS_CTRL */
+	u32 afe_bias_control;
+	u32 reserved_0004;
+	/* 0x0008 AFE_PLL_CTRL0 */
+	u32 afe_pll_control0;
+	/* 0x000c AFE_PLL_CTRL1 */
+	u32 afe_pll_control1;
+	/* 0x0010 AFE_PLL_CTRL2 */
+	u32 afe_pll_control2;
+	/* 0x0014 AFE_CB_STS */
+	u32 afe_common_block_status;
+	/* 0x0018-0x007c */
+	u32 reserved_18_7c[0x1a];
+	/* 0x0080 AFE_PMSN_MCTRL0 */
+	u32 afe_pmsn_master_control0;
+	/* 0x0084 AFE_PMSN_MCTRL1 */
+	u32 afe_pmsn_master_control1;
+	/* 0x0088 AFE_PMSN_MCTRL2 */
+	u32 afe_pmsn_master_control2;
+	/* 0x008C-0x00fc */
+	u32 reserved_008c_00fc[0x1D];
+	/* 0x0100 AFE_DFX_MST_CTRL0 */
+	u32 afe_dfx_master_control0;
+	/* 0x0104 AFE_DFX_MST_CTRL1 */
+	u32 afe_dfx_master_control1;
+	/* 0x0108 AFE_DFX_DCL_CTRL */
+	u32 afe_dfx_dcl_control;
+	/* 0x010c AFE_DFX_DMON_CTRL */
+	u32 afe_dfx_digital_monitor_control;
+	/* 0x0110 AFE_DFX_AMONP_CTRL */
+	u32 afe_dfx_analog_p_monitor_control;
+	/* 0x0114 AFE_DFX_AMONN_CTRL */
+	u32 afe_dfx_analog_n_monitor_control;
+	/* 0x0118 AFE_DFX_NTL_STS */
+	u32 afe_dfx_ntl_status;
+	/* 0x011c AFE_DFX_FIFO_STS0 */
+	u32 afe_dfx_fifo_status0;
+	/* 0x0120 AFE_DFX_FIFO_STS1 */
+	u32 afe_dfx_fifo_status1;
+	/* 0x0124 AFE_DFX_MPAT_CTRL */
+	u32 afe_dfx_master_pattern_control;
+	/* 0x0128 AFE_DFX_P0_CTRL */
+	u32 afe_dfx_p0_control;
+	/* 0x012c-0x01a8 AFE_DFX_P0_DRx */
+	u32 afe_dfx_p0_data[32];
+	/* 0x01ac */
+	u32 reserved_01ac;
+	/* 0x01b0-0x020c AFE_DFX_P0_IRx */
+	u32 afe_dfx_p0_instruction[24];
+	/* 0x0210 */
+	u32 reserved_0210;
+	/* 0x0214 AFE_DFX_P1_CTRL */
+	u32 afe_dfx_p1_control;
+	/* 0x0218-0x245 AFE_DFX_P1_DRx */
+	u32 afe_dfx_p1_data[16];
+	/* 0x0258-0x029c */
+	u32 reserved_0258_029c[0x12];
+	/* 0x02a0-0x02bc AFE_DFX_P1_IRx */
+	u32 afe_dfx_p1_instruction[8];
+	/* 0x02c0-0x2fc */
+	u32 reserved_02c0_02fc[0x10];
+	/* 0x0300 AFE_DFX_TX_PMSN_CTRL */
+	u32 afe_dfx_tx_pmsn_control;
+	/* 0x0304 AFE_DFX_RX_PMSN_CTRL */
+	u32 afe_dfx_rx_pmsn_control;
+	u32 reserved_0308;
+	/* 0x030c AFE_DFX_NOA_CTRL0 */
+	u32 afe_dfx_noa_control0;
+	/* 0x0310 AFE_DFX_NOA_CTRL1 */
+	u32 afe_dfx_noa_control1;
+	/* 0x0314 AFE_DFX_NOA_CTRL2 */
+	u32 afe_dfx_noa_control2;
+	/* 0x0318 AFE_DFX_NOA_CTRL3 */
+	u32 afe_dfx_noa_control3;
+	/* 0x031c AFE_DFX_NOA_CTRL4 */
+	u32 afe_dfx_noa_control4;
+	/* 0x0320 AFE_DFX_NOA_CTRL5 */
+	u32 afe_dfx_noa_control5;
+	/* 0x0324 AFE_DFX_NOA_CTRL6 */
+	u32 afe_dfx_noa_control6;
+	/* 0x0328 AFE_DFX_NOA_CTRL7 */
+	u32 afe_dfx_noa_control7;
+	/* 0x032c-0x07fc */
+	u32 reserved_032c_07fc[0x135];
+
+	/* 0x0800-0x0bfc */
+	struct scu_afe_transceiver scu_afe_xcvr[4];
+
+	/* 0x0c00-0x0ffc */
+	u32 reserved_0c00_0ffc[0x0100];
+};
+
+struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS {
+	u32 table[0xE0];
+};
+
+
+struct SCU_VIIT_IIT {
+	u32 table[256];
+};
+
+/**
+ * Placeholder for the ZONE Partition Table information ZONING will not be
+ *    included in the 1.1 release.
+ *
+ *
+ */
+struct SCU_ZONE_PARTITION_TABLE {
+	u32 table[2048];
+};
+
+/**
+ * Placeholder for the CRAM register since I am not sure if we need to
+ *    read/write to these registers as yet.
+ *
+ *
+ */
+struct SCU_COMPLETION_RAM {
+	u32 ram[128];
+};
+
+/**
+ * Placeholder for the FBRAM registers since I am not sure if we need to
+ *    read/write to these registers as yet.
+ *
+ *
+ */
+struct SCU_FRAME_BUFFER_RAM {
+	u32 ram[128];
+};
+
+#define SCU_SCRATCH_RAM_SIZE_IN_DWORDS  256
+
+/**
+ * Placeholder for the scratch RAM registers.
+ *
+ *
+ */
+struct SCU_SCRATCH_RAM {
+	u32 ram[SCU_SCRATCH_RAM_SIZE_IN_DWORDS];
+};
+
+/**
+ * Placeholder since I am not yet sure what these registers are here for.
+ *
+ *
+ */
+struct NOA_PROTOCOL_ENGINE_PARTITION {
+	u32 reserved[64];
+};
+
+/**
+ * Placeholder since I am not yet sure what these registers are here for.
+ *
+ *
+ */
+struct NOA_HUB_PARTITION {
+	u32 reserved[64];
+};
+
+/**
+ * Placeholder since I am not yet sure what these registers are here for.
+ *
+ *
+ */
+struct NOA_HOST_INTERFACE_PARTITION {
+	u32 reserved[64];
+};
+
+/**
+ * struct TRANSPORT_LINK_LAYER_PAIR - The SCU Hardware pairs up the TL
+ *    registers with the LL registers so we must place them adjcent to make the
+ *    array of registers in the PEG.
+ *
+ *
+ */
+struct TRANSPORT_LINK_LAYER_PAIR {
+	struct scu_transport_layer_registers tl;
+	struct scu_link_layer_registers ll;
+};
+
+/**
+ * struct SCU_PEG_REGISTERS - SCU Protocol Engine Memory mapped register space.
+ *     These registers are unique to each protocol engine group.  There can be
+ *    at most two PEG for a single SCU part.
+ *
+ *
+ */
+struct SCU_PEG_REGISTERS {
+	struct TRANSPORT_LINK_LAYER_PAIR pe[4];
+	struct scu_port_task_scheduler_group_registers ptsg;
+	struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS peg;
+	struct scu_sgpio_registers sgpio;
+	u32 reserved_01500_1BFF[0x1C0];
+	struct scu_viit_entry viit[64];
+	struct SCU_ZONE_PARTITION_TABLE zpt0;
+	struct SCU_ZONE_PARTITION_TABLE zpt1;
+};
+
+/**
+ * struct scu_registers - SCU regsiters including both PEG registers if we turn
+ *    on that compile option. All of these registers are in the memory mapped
+ *    space returned from BAR1.
+ *
+ *
+ */
+struct scu_registers {
+	/* 0x0000 - PEG 0 */
+	struct SCU_PEG_REGISTERS peg0;
+
+	/* 0x6000 - SDMA and Miscellaneous */
+	struct scu_sdma_registers sdma;
+	struct SCU_COMPLETION_RAM cram;
+	struct SCU_FRAME_BUFFER_RAM fbram;
+	u32 reserved_6800_69FF[0x80];
+	struct NOA_PROTOCOL_ENGINE_PARTITION noa_pe;
+	struct NOA_HUB_PARTITION noa_hub;
+	struct NOA_HOST_INTERFACE_PARTITION noa_if;
+	u32 reserved_6d00_7fff[0x4c0];
+
+	/* 0x8000 - PEG 1 */
+	struct SCU_PEG_REGISTERS peg1;
+
+	/* 0xE000 - AFE Registers */
+	struct scu_afe_registers afe;
+
+	/* 0xF000 - reserved */
+	u32 reserved_f000_211fff[0x80c00];
+
+	/* 0x212000 - scratch RAM */
+	struct SCU_SCRATCH_RAM scratch_ram;
+
+};
+
+
+#endif   /* _SCU_REGISTERS_HEADER_ */
diff --git a/drivers/scsi/isci/core/scu_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h
new file mode 100644
index 0000000..187c4f0
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_unsolicited_frame.h
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This field defines the SCU format of an unsolicited frame (UF).  A UF is a
+ *    frame received by the SCU for which there is no known corresponding task
+ *    context (TC).
+ *
+ *
+ */
+
+#ifndef _SCU_UNSOLICITED_FRAME_H_
+#define _SCU_UNSOLICITED_FRAME_H_
+
+#include <linux/string.h>
+
+/**
+ *
+ *
+ * This constant defines the number of DWORDS found the unsolicited frame
+ * header data member.
+ */
+#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15
+
+/**
+ * struct scu_unsolicited_frame_header -
+ *
+ * This structure delineates the format of an unsolicited frame header. The
+ * first DWORD are UF attributes defined by the silicon architecture. The data
+ * depicts actual header information received on the link.
+ */
+struct scu_unsolicited_frame_header {
+	/**
+	 * This field indicates if there is an Initiator Index Table entry with
+	 * which this header is associated.
+	 */
+	u32 iit_exists:1;
+
+	/**
+	 * This field simply indicates the protocol type (i.e. SSP, STP, SMP).
+	 */
+	u32 protocol_type:3;
+
+	/**
+	 * This field indicates if the frame is an address frame (IAF or OAF)
+	 * or if it is a information unit frame.
+	 */
+	u32 is_address_frame:1;
+
+	/**
+	 * This field simply indicates the connection rate at which the frame
+	 * was received.
+	 */
+	u32 connection_rate:4;
+
+	u32 reserved:23;
+
+	/**
+	 * This field represents the actual header data received on the link.
+	 */
+	u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS];
+
+};
+
+#endif /* _SCU_UNSOLICITED_FRAME_H_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 09/10] isci/core: base state machine and memory descriptors
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (7 preceding siblings ...)
  2011-03-10 10:55 ` [RFC PATCH 08/10] isci/core: unsolicited frame handling and registers Dan Williams
@ 2011-03-10 10:55 ` Dan Williams
  2011-03-10 10:55 ` [RFC PATCH 10/10] isci/core: common definitions and utility functions Dan Williams
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:55 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Generic state machine implementation, and the memory descriptor
interface for the lldd to pass buffers to the core.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 .../isci/core/sci_base_memory_descriptor_list.c    |  159 +++
 .../isci/core/sci_base_memory_descriptor_list.h    |  153 +++
 drivers/scsi/isci/core/sci_base_state.h            |   90 ++
 drivers/scsi/isci/core/sci_base_state_machine.c    |  182 ++++
 drivers/scsi/isci/core/sci_base_state_machine.h    |  141 +++
 .../scsi/isci/core/sci_memory_descriptor_list.h    |  168 ++++
 drivers/scsi/isci/core/sci_object.h                |   98 ++
 drivers/scsi/isci/core/scu_completion_codes.h      |  283 ++++++
 drivers/scsi/isci/core/scu_constants.h             |  151 +++
 drivers/scsi/isci/core/scu_event_codes.h           |  336 +++++++
 drivers/scsi/isci/core/scu_task_context.h          |  942 ++++++++++++++++++++
 drivers/scsi/isci/core/scu_viit_data.h             |  178 ++++
 12 files changed, 2881 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
 create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
 create mode 100644 drivers/scsi/isci/core/sci_base_state.h
 create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.c
 create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.h
 create mode 100644 drivers/scsi/isci/core/sci_memory_descriptor_list.h
 create mode 100644 drivers/scsi/isci/core/sci_object.h
 create mode 100644 drivers/scsi/isci/core/scu_completion_codes.h
 create mode 100644 drivers/scsi/isci/core/scu_constants.h
 create mode 100644 drivers/scsi/isci/core/scu_event_codes.h
 create mode 100644 drivers/scsi/isci/core/scu_task_context.h
 create mode 100644 drivers/scsi/isci/core/scu_viit_data.h

diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
new file mode 100644
index 0000000..2d785b5
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains the base implementation for the memory descriptor list.
+ *    This is currently comprised of MDL iterator methods.
+ *
+ *
+ */
+
+#include "sci_environment.h"
+#include "sci_base_memory_descriptor_list.h"
+
+/*
+ * ******************************************************************************
+ * * P U B L I C   M E T H O D S
+ * ****************************************************************************** */
+
+void sci_mdl_first_entry(
+	struct sci_base_memory_descriptor_list *base_mdl)
+{
+	base_mdl->next_index = 0;
+
+	/*
+	 * If this MDL is managing another MDL, then recursively rewind that MDL
+	 * object as well. */
+	if (base_mdl->next_mdl != NULL)
+		sci_mdl_first_entry(base_mdl->next_mdl);
+}
+
+
+void sci_mdl_next_entry(
+	struct sci_base_memory_descriptor_list *base_mdl)
+{
+	/*
+	 * If there is at least one more entry left in the array, then change
+	 * the next pointer to it. */
+	if (base_mdl->next_index < base_mdl->length)
+		base_mdl->next_index++;
+	else if (base_mdl->next_index == base_mdl->length) {
+		/*
+		 * This MDL has exhausted it's set of entries.  If this MDL is managing
+		 * another MDL, then start iterating through that MDL. */
+		if (base_mdl->next_mdl != NULL)
+			sci_mdl_next_entry(base_mdl->next_mdl);
+	}
+}
+
+
+struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
+	struct sci_base_memory_descriptor_list *base_mdl)
+{
+	if (base_mdl->next_index < base_mdl->length)
+		return &base_mdl->mde_array[base_mdl->next_index];
+	else if (base_mdl->next_index == base_mdl->length) {
+		/*
+		 * This MDL has exhausted it's set of entries.  If this MDL is managing
+		 * another MDL, then return it's current entry. */
+		if (base_mdl->next_mdl != NULL)
+			return sci_mdl_get_current_entry(base_mdl->next_mdl);
+	}
+
+	return NULL;
+}
+
+/*
+ * ******************************************************************************
+ * * P R O T E C T E D   M E T H O D S
+ * ****************************************************************************** */
+
+void sci_base_mdl_construct(
+	struct sci_base_memory_descriptor_list *mdl,
+	struct sci_physical_memory_descriptor *mde_array,
+	u32 mde_array_length,
+	struct sci_base_memory_descriptor_list *next_mdl)
+{
+	mdl->length     = mde_array_length;
+	mdl->mde_array  = mde_array;
+	mdl->next_index = 0;
+	mdl->next_mdl   = next_mdl;
+}
+
+/* --------------------------------------------------------------------------- */
+
+bool sci_base_mde_is_valid(
+	struct sci_physical_memory_descriptor *mde,
+	u32 alignment,
+	u32 size,
+	u16 attributes)
+{
+	/* Only need the lower 32 bits to ensure alignment is met. */
+	u32 physical_address = lower_32_bits(mde->physical_address);
+
+	if (
+		((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0)
+		|| ((physical_address & (alignment - 1)) != 0)
+		|| (mde->constant_memory_alignment != alignment)
+		|| (mde->constant_memory_size != size)
+		|| (mde->virtual_address == NULL)
+		|| (mde->constant_memory_attributes != attributes)
+		) {
+		return false;
+	}
+
+	return true;
+}
+
diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
new file mode 100644
index 0000000..b58d4e8
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
+#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
+
+/**
+ * This file contains the protected interface structures, constants and
+ *    interface methods for the struct sci_base_memory_descriptor_list object.
+ *
+ *
+ */
+
+
+#include "sci_memory_descriptor_list.h"
+
+
+/**
+ * struct sci_base_memory_descriptor_list - This structure contains all of the
+ *    fields necessary to implement a simple stack for managing the list of
+ *    available controller indices.
+ *
+ *
+ */
+struct sci_base_memory_descriptor_list {
+	/**
+	 * This field indicates the length of the memory descriptor entry array.
+	 */
+	u32 length;
+
+	/**
+	 * This field is utilized to provide iterator pattern functionality.
+	 * It indicates the index of the next memory descriptor in the iteration.
+	 */
+	u32 next_index;
+
+	/**
+	 * This field will point to the list of memory descriptors.
+	 */
+	struct sci_physical_memory_descriptor *mde_array;
+
+	/**
+	 * This field simply allows a user to chain memory descriptor lists
+	 * together if desired.  This field will be initialized to NULL.
+	 */
+	struct sci_base_memory_descriptor_list *next_mdl;
+
+};
+
+/**
+ * sci_base_mdl_construct() - This method is invoked to construct an memory
+ *    descriptor list. It initializes the fields of the MDL.
+ * @mdl: This parameter specifies the memory descriptor list to be constructed.
+ * @mde_array: This parameter specifies the array of memory descriptor entries
+ *    to be managed by this list.
+ * @mde_array_length: This parameter specifies the size of the array of entries.
+ * @next_mdl: This parameter specifies a subsequent MDL object to be managed by
+ *    this MDL object.
+ *
+ * none.
+ */
+void sci_base_mdl_construct(
+	struct sci_base_memory_descriptor_list *mdl,
+	struct sci_physical_memory_descriptor *mde_array,
+	u32 mde_array_length,
+	struct sci_base_memory_descriptor_list *next_mdl);
+
+/**
+ * sci_base_mde_construct() -
+ *
+ * This macro constructs an memory descriptor entry with the given alignment
+ * and size
+ */
+#define sci_base_mde_construct(mde, alignment, size, attributes) \
+	{ \
+		(mde)->constant_memory_alignment  = (alignment); \
+		(mde)->constant_memory_size       = (size); \
+		(mde)->constant_memory_attributes = (attributes); \
+	}
+
+/**
+ * sci_base_mde_is_valid() - This method validates that the memory descriptor
+ *    is correctly filled out by the SCI User
+ * @mde: This parameter is the mde entry to validate
+ * @alignment: This parameter specifies the expected alignment of the memory
+ *    for the mde.
+ * @size: This parameter specifies the memory size expected for the mde its
+ *    value should not have been changed by the SCI User.
+ * @attributes: This parameter specifies the attributes for the memory
+ *    descriptor provided.
+ *
+ * bool This method returns an indication as to whether the supplied MDE is
+ * valid or not. true The MDE is valid. false The MDE is not valid.
+ */
+bool sci_base_mde_is_valid(
+	struct sci_physical_memory_descriptor *mde,
+	u32 alignment,
+	u32 size,
+	u16 attributes);
+
+#endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */
diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h
new file mode 100644
index 0000000..d6b9c1a
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_state.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_STATE_H_
+#define _SCI_BASE_STATE_H_
+
+#include "sci_object.h"
+
+typedef void (*SCI_BASE_STATE_HANDLER_T)(
+	void
+	);
+
+typedef void (*SCI_STATE_TRANSITION_T)(
+	struct sci_base_object *base_object
+	);
+
+/**
+ * struct sci_base_state - The base state object abstracts the fields common to
+ *    all state objects defined in SCI.
+ *
+ *
+ */
+struct sci_base_state {
+	/**
+	 * This field is a function pointer that defines the method to be
+	 * invoked when the state is entered.
+	 */
+	SCI_STATE_TRANSITION_T enter_state;
+
+	/**
+	 * This field is a function pointer that defines the method to be
+	 * invoked when the state is exited.
+	 */
+	SCI_STATE_TRANSITION_T exit_state;
+
+};
+
+#endif /* _SCI_BASE_STATE_H_ */
diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c
new file mode 100644
index 0000000..5b1e8da
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_state_machine.c
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains all of the functionality common to all state machine
+ *    object implementations.
+ *
+ *
+ */
+
+#include "sci_base_state_machine.h"
+
+static void sci_state_machine_exit_state(struct sci_base_state_machine *sm)
+{
+	u32 state = sm->current_state_id;
+	SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state;
+
+	if (exit)
+		exit(sm->state_machine_owner);
+}
+
+static void sci_state_machine_enter_state(struct sci_base_state_machine *sm)
+{
+	u32 state = sm->current_state_id;
+	SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state;
+
+	if (enter)
+		enter(sm->state_machine_owner);
+}
+
+/*
+ * ******************************************************************************
+ * * P R O T E C T E D    M E T H O D S
+ * ****************************************************************************** */
+
+/**
+ * This method will set the initial state and state table for the state
+ *    machine. The caller should follow this request with the initialize
+ *    request to cause the state machine to start.
+ * @sm: This parameter provides the state machine object to be
+ *    constructed.
+ * @state_machine_owner: This parameter indicates the object that is owns the
+ *    state machine being constructed.
+ * @state_table: This parameter specifies the table of state objects that is
+ *    managed by this state machine.
+ * @initial_state: This parameter specifies the value of the initial state for
+ *    this state machine.
+ *
+ */
+void sci_base_state_machine_construct(struct sci_base_state_machine *sm,
+				      struct sci_base_object *owner,
+				      const struct sci_base_state *state_table,
+				      u32 initial_state)
+{
+	sm->state_machine_owner = owner;
+	sm->initial_state_id    = initial_state;
+	sm->previous_state_id   = initial_state;
+	sm->current_state_id    = initial_state;
+	sm->state_table         = state_table;
+}
+
+/**
+ * This method will cause the state machine to enter the initial state.
+ * @sm: This parameter specifies the state machine that is to
+ *    be started.
+ *
+ * sci_base_state_machine_construct() for how to set the initial state none
+ */
+void sci_base_state_machine_start(struct sci_base_state_machine *sm)
+{
+	sm->current_state_id = sm->initial_state_id;
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+	sci_base_subject_notify(&sm->parent);
+#endif
+	sci_state_machine_enter_state(sm);
+}
+
+/**
+ * This method will cause the state machine to exit it's current state only.
+ * @sm: This parameter specifies the state machine that is to
+ *    be stopped.
+ *
+ */
+void sci_base_state_machine_stop(
+	struct sci_base_state_machine *sm)
+{
+	sci_state_machine_exit_state(sm);
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+	sci_base_subject_notify(&sm->parent);
+#endif
+}
+
+/**
+ * This method performs an update to the current state of the state machine.
+ * @sm: This parameter specifies the state machine for which
+ *    the caller wishes to perform a state change.
+ * @next_state: This parameter specifies the new state for the state machine.
+ *
+ */
+void sci_base_state_machine_change_state(
+	struct sci_base_state_machine *sm,
+	u32 next_state)
+{
+	sci_state_machine_exit_state(sm);
+
+	sm->previous_state_id = sm->current_state_id;
+	sm->current_state_id = next_state;
+
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+	/* Notify of the state change prior to entering the state. */
+	sci_base_subject_notify(&sm->parent);
+#endif
+
+	sci_state_machine_enter_state(sm);
+}
+
+/**
+ * This method simply returns the current state of the state machine to the
+ *    caller.
+ * @sm: This parameter specifies the state machine for which to
+ *    retrieve the current state.
+ *
+ * This method returns a u32 value indicating the current state for the
+ * supplied state machine.
+ */
+u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm)
+{
+	return sm->current_state_id;
+}
+
diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h
new file mode 100644
index 0000000..13f6ee8
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_state_machine.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_BASE_STATE_MACHINE_H_
+#define _SCI_BASE_STATE_MACHINE_H_
+
+#include <linux/string.h>
+
+/**
+ * This file contains all structures, constants, or method declarations common
+ *    to all state machines defined in SCI.
+ *
+ *
+ */
+
+
+#include "sci_base_state.h"
+
+
+/**
+ * SET_STATE_HANDLER() -
+ *
+ * This macro simply provides simplified retrieval of an objects state handler.
+ */
+#define SET_STATE_HANDLER(object, table, state)	\
+	(object)->state_handlers = &(table)[(state)]
+
+/**
+ * struct sci_base_state_machine - This structure defines the fields common to
+ *    all state machines.
+ *
+ *
+ */
+struct sci_base_state_machine {
+	/**
+	 * This field points to the start of the state machine's state table.
+	 */
+	const struct sci_base_state *state_table;
+
+	/**
+	 * This field points to the object to which this state machine is
+	 * associated.  It serves as a cookie to be provided to the state
+	 * enter/exit methods.
+	 */
+	struct sci_base_object *state_machine_owner;
+
+	/**
+	 * This field simply indicates the state value for the state machine's
+	 * initial state.
+	 */
+	u32 initial_state_id;
+
+	/**
+	 * This field indicates the current state of the state machine.
+	 */
+	u32 current_state_id;
+
+	/**
+	 * This field indicates the previous state of the state machine.
+	 */
+	u32 previous_state_id;
+
+};
+
+/*
+ * ******************************************************************************
+ * * P R O T E C T E D    M E T H O D S
+ * ****************************************************************************** */
+
+void sci_base_state_machine_construct(
+	struct sci_base_state_machine *this_state_machine,
+	struct sci_base_object *state_machine_owner,
+	const struct sci_base_state *state_table,
+	u32 initial_state);
+
+void sci_base_state_machine_start(
+	struct sci_base_state_machine *this_state_machine);
+
+void sci_base_state_machine_stop(
+	struct sci_base_state_machine *this_state_machine);
+
+void sci_base_state_machine_change_state(
+	struct sci_base_state_machine *this_state_machine,
+	u32 next_state);
+
+u32 sci_base_state_machine_get_state(
+	struct sci_base_state_machine *this_state_machine);
+
+#endif /* _SCI_BASE_STATE_MACHINE_H_ */
diff --git a/drivers/scsi/isci/core/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h
new file mode 100644
index 0000000..a039998
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_memory_descriptor_list.h
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_
+#define _SCI_MEMORY_DESCRIPTOR_LIST_H_
+
+/**
+ * This file contains all of the basic data types utilized by an SCI user or
+ *    implementor.
+ *
+ *
+ */
+
+
+
+struct sci_base_memory_descriptor_list;
+
+/**
+ *
+ *
+ * SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory
+ * Descriptor Entries (MDEs) contained in the MDL.
+ */
+#define SCI_MDE_ATTRIBUTE_CACHEABLE              0x0001
+#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS  0x0002
+
+/**
+ * struct sci_physical_memory_descriptor - This structure defines a description
+ *    of a memory location for the SCI implementation.
+ *
+ *
+ */
+struct sci_physical_memory_descriptor {
+	/**
+	 * This field contains the virtual address associated with this descriptor
+	 * element. This field shall be zero when the descriptor is retrieved from
+	 * the SCI implementation.  The user shall set this field prior
+	 * sci_controller_start()
+	 */
+	void *virtual_address;
+
+	/**
+	 * This field contains the physical address associated with this desciptor
+	 * element. This field shall be zero when the descriptor is retrieved from
+	 * the SCI implementation.  The user shall set this field prior
+	 * sci_controller_start()
+	 */
+	dma_addr_t physical_address;
+
+	/**
+	 * This field contains the size requirement for this memory descriptor.
+	 * A value of zero for this field indicates the end of the descriptor
+	 * list.  The value should be treated as read only for an SCI user.
+	 */
+	u32 constant_memory_size;
+
+	/**
+	 * This field contains the alignment requirement for this memory
+	 * descriptor.  A value of zero for this field indicates the end of the
+	 * descriptor list.  All other values indicate the number of bytes to
+	 * achieve the necessary alignment.  The value should be treated as
+	 * read only for an SCI user.
+	 */
+	u32 constant_memory_alignment;
+
+	/**
+	 * This field contains an indication regarding the desired memory
+	 * attributes for this memory descriptor entry.
+	 * Notes:
+	 * - If the cacheable attribute is set, the user can allocate
+	 *   memory that is backed by cache for better performance. It
+	 *   is not required that the memory be backed by cache.
+	 * - If the physically contiguous attribute is set, then the
+	 *   entire memory must be physically contiguous across all
+	 *   page boundaries.
+	 */
+	u16 constant_memory_attributes;
+
+};
+
+/**
+ * sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to
+ *    the first memory descriptor entry in the list.
+ * @mdl: This parameter specifies the memory descriptor list that is to be
+ *    rewound.
+ *
+ */
+void sci_mdl_first_entry(
+	struct sci_base_memory_descriptor_list *mdl);
+
+/**
+ * sci_mdl_next_entry() - This method simply updates the "current" pointer to
+ *    the next sequential memory descriptor.
+ * @mdl: This parameter specifies the memory descriptor list for which to
+ *    return the next memory descriptor entry in the list.
+ *
+ * none.
+ */
+void sci_mdl_next_entry(
+	struct sci_base_memory_descriptor_list *mdl);
+
+/**
+ * sci_mdl_get_current_entry() - This method simply returns the current memory
+ *    descriptor entry.
+ * @mdl: This parameter specifies the memory descriptor list for which to
+ *    return the current memory descriptor entry.
+ *
+ * This method returns a pointer to the current physical memory descriptor in
+ * the MDL. NULL This value is returned if there are no descriptors in the list.
+ */
+struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
+	struct sci_base_memory_descriptor_list *mdl);
+
+
+#endif  /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */
+
diff --git a/drivers/scsi/isci/core/sci_object.h b/drivers/scsi/isci/core/sci_object.h
new file mode 100644
index 0000000..801b01b
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_object.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_OBJECT_H_
+#define _SCI_OBJECT_H_
+
+/**
+ * This file contains all of the method and constants associated with the SCI
+ *    base object.  The SCI base object is the class from which all other
+ *    objects derive in the Storage Controller Interface.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+
+/**
+ * struct sci_base_object - all core objects must include this as their
+ *     first member to permit the casting below
+ *
+ * TODO: unwind this assumption, convert these routines and callers to pass a struct
+ * sci_base_object pointer without casting, or convert 'private' to the
+ * expected type per-object
+ *
+ */
+struct sci_base_object {
+	void *private;
+};
+
+static inline void *sci_object_get_association(void *obj)
+{
+	struct sci_base_object *base = obj;
+
+	return base->private;
+}
+
+static inline void sci_object_set_association(void *obj, void *private)
+{
+	struct sci_base_object *base = obj;
+
+	base->private = private;
+}
+
+#endif  /* _SCI_OBJECT_H_ */
+
diff --git a/drivers/scsi/isci/core/scu_completion_codes.h b/drivers/scsi/isci/core/scu_completion_codes.h
new file mode 100644
index 0000000..c8b329c
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_completion_codes.h
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCU_COMPLETION_CODES_HEADER_
+#define _SCU_COMPLETION_CODES_HEADER_
+
+/**
+ * This file contains the constants and macros for the SCU hardware completion
+ *    codes.
+ *
+ *
+ */
+
+#define SCU_COMPLETION_TYPE_SHIFT      28
+#define SCU_COMPLETION_TYPE_MASK       0x70000000
+
+/**
+ * SCU_COMPLETION_TYPE() -
+ *
+ * This macro constructs an SCU completion type
+ */
+#define SCU_COMPLETION_TYPE(type) \
+	((u32)(type) << SCU_COMPLETION_TYPE_SHIFT)
+
+/**
+ * SCU_COMPLETION_TYPE() -
+ *
+ * These macros contain the SCU completion types SCU_COMPLETION_TYPE
+ */
+#define SCU_COMPLETION_TYPE_TASK       SCU_COMPLETION_TYPE(0)
+#define SCU_COMPLETION_TYPE_SDMA       SCU_COMPLETION_TYPE(1)
+#define SCU_COMPLETION_TYPE_UFI        SCU_COMPLETION_TYPE(2)
+#define SCU_COMPLETION_TYPE_EVENT      SCU_COMPLETION_TYPE(3)
+#define SCU_COMPLETION_TYPE_NOTIFY     SCU_COMPLETION_TYPE(4)
+
+/**
+ *
+ *
+ * These constants provide the shift and mask values for the various parts of
+ * an SCU completion code.
+ */
+#define SCU_COMPLETION_STATUS_MASK       0x0FFC0000
+#define SCU_COMPLETION_TL_STATUS_MASK    0x0FC00000
+#define SCU_COMPLETION_TL_STATUS_SHIFT   22
+#define SCU_COMPLETION_SDMA_STATUS_MASK  0x003C0000
+#define SCU_COMPLETION_PEG_MASK          0x00010000
+#define SCU_COMPLETION_PORT_MASK         0x00007000
+#define SCU_COMPLETION_PE_MASK           SCU_COMPLETION_PORT_MASK
+#define SCU_COMPLETION_PE_SHIFT          12
+#define SCU_COMPLETION_INDEX_MASK        0x00000FFF
+
+/**
+ * SCU_GET_COMPLETION_TYPE() -
+ *
+ * This macro returns the SCU completion type.
+ */
+#define SCU_GET_COMPLETION_TYPE(completion_code) \
+	((completion_code) & SCU_COMPLETION_TYPE_MASK)
+
+/**
+ * SCU_GET_COMPLETION_STATUS() -
+ *
+ * This macro returns the SCU completion status.
+ */
+#define SCU_GET_COMPLETION_STATUS(completion_code) \
+	((completion_code) & SCU_COMPLETION_STATUS_MASK)
+
+/**
+ * SCU_GET_COMPLETION_TL_STATUS() -
+ *
+ * This macro returns the transport layer completion status.
+ */
+#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \
+	((completion_code) & SCU_COMPLETION_TL_STATUS_MASK)
+
+/**
+ * SCU_MAKE_COMPLETION_STATUS() -
+ *
+ * This macro takes a completion code and performs the shift and mask
+ * operations to turn it into a completion code that can be compared to a
+ * SCU_GET_COMPLETION_TL_STATUS.
+ */
+#define SCU_MAKE_COMPLETION_STATUS(completion_code) \
+	((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT)
+
+/**
+ * SCU_NORMALIZE_COMPLETION_STATUS() -
+ *
+ * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a
+ * return code.
+ */
+#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \
+	(\
+		((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \
+		>> SCU_COMPLETION_TL_STATUS_SHIFT \
+	)
+
+/**
+ * SCU_GET_COMPLETION_SDMA_STATUS() -
+ *
+ * This macro returns the SDMA completion status.
+ */
+#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code)	\
+	((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK)
+
+/**
+ * SCU_GET_COMPLETION_PEG() -
+ *
+ * This macro returns the Protocol Engine Group from the completion code.
+ */
+#define SCU_GET_COMPLETION_PEG(completion_code)	\
+	((completion_code) & SCU_COMPLETION_PEG_MASK)
+
+/**
+ * SCU_GET_COMPLETION_PORT() -
+ *
+ * This macro reuturns the logical port index from the completion code.
+ */
+#define SCU_GET_COMPLETION_PORT(completion_code) \
+	((completion_code) & SCU_COMPLETION_PORT_MASK)
+
+/**
+ * SCU_GET_PROTOCOL_ENGINE_INDEX() -
+ *
+ * This macro returns the PE index from the completion code.
+ */
+#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \
+	(((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT)
+
+/**
+ * SCU_GET_COMPLETION_INDEX() -
+ *
+ * This macro returns the index of the completion which is either a TCi or an
+ * RNi depending on the completion type.
+ */
+#define SCU_GET_COMPLETION_INDEX(completion_code) \
+	((completion_code) & SCU_COMPLETION_INDEX_MASK)
+
+#define SCU_UNSOLICITED_FRAME_MASK     0x0FFF0000
+#define SCU_UNSOLICITED_FRAME_SHIFT    16
+
+/**
+ * SCU_GET_FRAME_INDEX() -
+ *
+ * This macro returns a normalized frame index from an unsolicited frame
+ * completion.
+ */
+#define SCU_GET_FRAME_INDEX(completion_code) \
+	(\
+		((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \
+		>> SCU_UNSOLICITED_FRAME_SHIFT \
+	)
+
+#define SCU_UNSOLICITED_FRAME_ERROR_MASK  0x00008000
+
+/**
+ * SCU_GET_FRAME_ERROR() -
+ *
+ * This macro returns a zero (0) value if there is no frame error otherwise it
+ * returns non-zero (!0).
+ */
+#define SCU_GET_FRAME_ERROR(completion_code) \
+	((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK)
+
+/**
+ *
+ *
+ * These constants represent normalized completion codes which must be shifted
+ * 18 bits to match it with the hardware completion code. In a 16-bit compiler,
+ * immediate constants are 16-bit values (the size of an int). If we shift
+ * those by 18 bits, we completely lose the value. To ensure the value is a
+ * 32-bit value like we want, each immediate value must be cast to a u32.
+ */
+#define SCU_TASK_DONE_GOOD                                  ((u32)0x00)
+#define SCU_TASK_DONE_CRC_ERR                               ((u32)0x14)
+#define SCU_TASK_DONE_CHECK_RESPONSE                        ((u32)0x14)
+#define SCU_TASK_DONE_GEN_RESPONSE                          ((u32)0x15)
+#define SCU_TASK_DONE_NAK_CMD_ERR                           ((u32)0x16)
+#define SCU_TASK_DONE_CMD_LL_R_ERR                          ((u32)0x16)
+#define SCU_TASK_DONE_LL_R_ERR                              ((u32)0x17)
+#define SCU_TASK_DONE_ACK_NAK_TO                            ((u32)0x17)
+#define SCU_TASK_DONE_LL_PERR                               ((u32)0x18)
+#define SCU_TASK_DONE_LL_SY_TERM                            ((u32)0x19)
+#define SCU_TASK_DONE_NAK_ERR                               ((u32)0x19)
+#define SCU_TASK_DONE_LL_LF_TERM                            ((u32)0x1A)
+#define SCU_TASK_DONE_DATA_LEN_ERR                          ((u32)0x1A)
+#define SCU_TASK_DONE_LL_CL_TERM                            ((u32)0x1B)
+#define SCU_TASK_DONE_LL_ABORT_ERR                          ((u32)0x1B)
+#define SCU_TASK_DONE_SEQ_INV_TYPE                          ((u32)0x1C)
+#define SCU_TASK_DONE_UNEXP_XR                              ((u32)0x1C)
+#define SCU_TASK_DONE_INV_FIS_TYPE                          ((u32)0x1D)
+#define SCU_TASK_DONE_XR_IU_LEN_ERR                         ((u32)0x1D)
+#define SCU_TASK_DONE_INV_FIS_LEN                           ((u32)0x1E)
+#define SCU_TASK_DONE_XR_WD_LEN                             ((u32)0x1E)
+#define SCU_TASK_DONE_SDMA_ERR                              ((u32)0x1F)
+#define SCU_TASK_DONE_OFFSET_ERR                            ((u32)0x20)
+#define SCU_TASK_DONE_MAX_PLD_ERR                           ((u32)0x21)
+#define SCU_TASK_DONE_EXCESS_DATA                           ((u32)0x22)
+#define SCU_TASK_DONE_LF_ERR                                ((u32)0x23)
+#define SCU_TASK_DONE_UNEXP_FIS                             ((u32)0x24)
+#define SCU_TASK_DONE_UNEXP_RESP                            ((u32)0x24)
+#define SCU_TASK_DONE_EARLY_RESP                            ((u32)0x25)
+#define SCU_TASK_DONE_SMP_RESP_TO_ERR                       ((u32)0x26)
+#define SCU_TASK_DONE_DMASETUP_DIRERR                       ((u32)0x27)
+#define SCU_TASK_DONE_SMP_UFI_ERR                           ((u32)0x27)
+#define SCU_TASK_DONE_XFERCNT_ERR                           ((u32)0x28)
+#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR                      ((u32)0x28)
+#define SCU_TASK_DONE_SMP_LL_RX_ERR                         ((u32)0x29)
+#define SCU_TASK_DONE_RESP_LEN_ERR                          ((u32)0x2A)
+#define SCU_TASK_DONE_UNEXP_DATA                            ((u32)0x2B)
+#define SCU_TASK_DONE_OPEN_FAIL                             ((u32)0x2C)
+#define SCU_TASK_DONE_UNEXP_SDBFIS                          ((u32)0x2D)
+#define SCU_TASK_DONE_REG_ERR                               ((u32)0x2E)
+#define SCU_TASK_DONE_SDB_ERR                               ((u32)0x2F)
+#define SCU_TASK_DONE_TASK_ABORT                            ((u32)0x30)
+#define SCU_TASK_DONE_CMD_SDMA_ERR                          ((U32)0x32)
+#define SCU_TASK_DONE_CMD_LL_ABORT_ERR                      ((U32)0x33)
+#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION              ((u32)0x34)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1             ((u32)0x35)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2             ((u32)0x36)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3             ((u32)0x37)
+#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION                ((u32)0x38)
+#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION                 ((u32)0x39)
+#define SCU_TASK_DONE_VIIT_ENTRY_NV                         ((u32)0x3A)
+#define SCU_TASK_DONE_IIT_ENTRY_NV                          ((u32)0x3B)
+#define SCU_TASK_DONE_RNCNV_OUTBOUND                        ((u32)0x3C)
+#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY             ((u32)0x3D)
+#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED         ((u32)0x3E)
+#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED  ((u32)0x3F)
+
+#endif /* _SCU_COMPLETION_CODES_HEADER_ */
diff --git a/drivers/scsi/isci/core/scu_constants.h b/drivers/scsi/isci/core/scu_constants.h
new file mode 100644
index 0000000..a99d110
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_constants.h
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCU_CONSTANTS_H_
+#define _SCU_CONSTANTS_H_
+
+/**
+ * This file contains the SCU hardware constants.
+ *
+ *
+ */
+
+#include "sci_controller_constants.h"
+
+/**
+ *
+ *
+ * 2 indicates the maximum number of UFs that can occur for a given IO request.
+ *  The hardware handles reception of additional unsolicited frames while all
+ * UFs are in use, by holding off the transmitting device.  This number could
+ * be theoretically reduced to 1, but 2 provides for more reliable operation.
+ * During SATA PIO operation, it is possible under some conditions for there to
+ * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H
+ * Register). It is unlikely to have all 3 pending all at once without some of
+ * them already being processed.
+ */
+#define SCU_MIN_UNSOLICITED_FRAMES        (1)
+#define SCU_MIN_CRITICAL_NOTIFICATIONS    (24)
+#define SCU_MIN_EVENTS                    (4)
+#define SCU_MIN_COMPLETION_QUEUE_SCRATCH  (2)
+#define SCU_MIN_COMPLETION_QUEUE_ENTRIES  (SCU_MIN_CRITICAL_NOTIFICATIONS \
+					   + SCU_MIN_EVENTS \
+					   + SCU_MIN_UNSOLICITED_FRAMES	\
+					   + SCI_MIN_IO_REQUESTS \
+					   + SCU_MIN_COMPLETION_QUEUE_SCRATCH)
+
+#define SCU_MAX_CRITICAL_NOTIFICATIONS    (384)
+#define SCU_MAX_EVENTS                    (128)
+#define SCU_MAX_UNSOLICITED_FRAMES        (128)
+#define SCU_MAX_COMPLETION_QUEUE_SCRATCH  (128)
+#define SCU_MAX_COMPLETION_QUEUE_ENTRIES  (SCU_MAX_CRITICAL_NOTIFICATIONS \
+					   + SCU_MAX_EVENTS \
+					   + SCU_MAX_UNSOLICITED_FRAMES	\
+					   + SCI_MAX_IO_REQUESTS \
+					   + SCU_MAX_COMPLETION_QUEUE_SCRATCH)
+
+#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
+#define SCU_UNSOLICITED_FRAME_COUNT      SCU_MAX_UNSOLICITED_FRAMES
+#define SCU_CRITICAL_NOTIFICATION_COUNT  SCU_MAX_CRITICAL_NOTIFICATIONS
+#define SCU_EVENT_COUNT                  SCU_MAX_EVENTS
+#define SCU_COMPLETION_QUEUE_SCRATCH     SCU_MAX_COMPLETION_QUEUE_SCRATCH
+#define SCU_IO_REQUEST_COUNT             SCI_MAX_IO_REQUESTS
+#define SCU_IO_REQUEST_SGE_COUNT         SCI_MAX_SCATTER_GATHER_ELEMENTS
+#define SCU_COMPLETION_QUEUE_COUNT       SCU_MAX_COMPLETION_QUEUE_ENTRIES
+#else
+#define SCU_UNSOLICITED_FRAME_COUNT      SCU_MIN_UNSOLICITED_FRAMES
+#define SCU_CRITICAL_NOTIFICATION_COUNT  SCU_MIN_CRITICAL_NOTIFICATIONS
+#define SCU_EVENT_COUNT                  SCU_MIN_EVENTS
+#define SCU_COMPLETION_QUEUE_SCRATCH     SCU_MIN_COMPLETION_QUEUE_SCRATCH
+#define SCU_IO_REQUEST_COUNT             SCI_MIN_IO_REQUESTS
+#define SCU_IO_REQUEST_SGE_COUNT         SCI_MIN_SCATTER_GATHER_ELEMENTS
+#define SCU_COMPLETION_QUEUE_COUNT       SCU_MIN_COMPLETION_QUEUE_ENTRIES
+#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */
+
+/**
+ *
+ *
+ * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion
+ * queue into which the hardware DMAs 32-bit quantas (completion entries).
+ */
+
+/**
+ *
+ *
+ * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.).
+ */
+#if (SCU_COMPLETION_QUEUE_COUNT != 16)  && \
+	(SCU_COMPLETION_QUEUE_COUNT != 32)  && \
+	(SCU_COMPLETION_QUEUE_COUNT != 64)  && \
+	(SCU_COMPLETION_QUEUE_COUNT != 128) && \
+	(SCU_COMPLETION_QUEUE_COUNT != 256) && \
+	(SCU_COMPLETION_QUEUE_COUNT != 512) && \
+	(SCU_COMPLETION_QUEUE_COUNT != 1024)
+#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2."
+#endif
+
+#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES
+#error "Invalid configuration of unsolicited frame constants"
+#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */
+
+#define SCU_MIN_UF_TABLE_ENTRIES            (8)
+#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
+#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024)
+#define SCU_INVALID_FRAME_INDEX             (0xFFFF)
+
+#define SCU_IO_REQUEST_MAX_SGE_SIZE         (0x00FFFFFF)
+#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH  (0x00FFFFFF)
+
+#endif /* _SCU_CONSTANTS_H_ */
diff --git a/drivers/scsi/isci/core/scu_event_codes.h b/drivers/scsi/isci/core/scu_event_codes.h
new file mode 100644
index 0000000..36a945a
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_event_codes.h
@@ -0,0 +1,336 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef __SCU_EVENT_CODES_HEADER__
+#define __SCU_EVENT_CODES_HEADER__
+
+/**
+ * This file contains the constants and macros for the SCU event codes.
+ *
+ *
+ */
+
+#define SCU_EVENT_TYPE_CODE_SHIFT      24
+#define SCU_EVENT_TYPE_CODE_MASK       0x0F000000
+
+#define SCU_EVENT_SPECIFIC_CODE_SHIFT  18
+#define SCU_EVENT_SPECIFIC_CODE_MASK   0x00FC0000
+
+#define SCU_EVENT_CODE_MASK \
+	(SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK)
+
+/**
+ * SCU_EVENT_TYPE() -
+ *
+ * This macro constructs an SCU event type from the type value.
+ */
+#define SCU_EVENT_TYPE(type) \
+	((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT)
+
+/**
+ * SCU_EVENT_SPECIFIC() -
+ *
+ * This macro constructs an SCU event specifier from the code value.
+ */
+#define SCU_EVENT_SPECIFIC(code) \
+	((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT)
+
+/**
+ * SCU_EVENT_MESSAGE() -
+ *
+ * This macro constructs a combines an SCU event type and SCU event specifier
+ * from the type and code values.
+ */
+#define SCU_EVENT_MESSAGE(type, code) \
+	((type) | SCU_EVENT_SPECIFIC(code))
+
+/**
+ * SCU_EVENT_TYPE() -
+ *
+ * SCU_EVENT_TYPES
+ */
+#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR  SCU_EVENT_TYPE(0x08)
+#define SCU_EVENT_TYPE_SMU_PCQ_ERROR      SCU_EVENT_TYPE(0x09)
+#define SCU_EVENT_TYPE_SMU_ERROR          SCU_EVENT_TYPE(0x00)
+#define SCU_EVENT_TYPE_TRANSPORT_ERROR    SCU_EVENT_TYPE(0x01)
+#define SCU_EVENT_TYPE_BROADCAST_CHANGE   SCU_EVENT_TYPE(0x02)
+#define SCU_EVENT_TYPE_OSSP_EVENT         SCU_EVENT_TYPE(0x03)
+#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F)
+#define SCU_EVENT_TYPE_RNC_SUSPEND_TX     SCU_EVENT_TYPE(0x04)
+#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX  SCU_EVENT_TYPE(0x05)
+#define SCU_EVENT_TYPE_RNC_OPS_MISC       SCU_EVENT_TYPE(0x06)
+#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07)
+#define SCU_EVENT_TYPE_ERR_CNT_EVENT      SCU_EVENT_TYPE(0x0A)
+
+/**
+ *
+ *
+ * SCU_EVENT_SPECIFIERS
+ */
+#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20
+#define SCU_EVENT_SPECIFIER_RNC_RELEASE    0x00
+
+/**
+ *
+ *
+ * SMU_COMMAND_EVENTS
+ */
+#define SCU_EVENT_INVALID_CONTEXT_COMMAND \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00)
+
+/**
+ *
+ *
+ * SMU_PCQ_EVENTS
+ */
+#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00)
+
+/**
+ *
+ *
+ * SMU_EVENTS
+ */
+#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02)
+#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03)
+#define SCU_EVENT_PCIE_INTERFACE_ERROR \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04)
+#define SCU_EVENT_FUNCTION_LEVEL_RESET \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05)
+
+/**
+ *
+ *
+ * TRANSPORT_LEVEL_ERRORS
+ */
+#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR	\
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00)
+
+/**
+ *
+ *
+ * BROADCAST_CHANGE_EVENTS
+ */
+#define SCU_EVENT_BROADCAST_CHANGE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01)
+#define SCU_EVENT_BROADCAST_RESERVED0 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02)
+#define SCU_EVENT_BROADCAST_RESERVED1 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03)
+#define SCU_EVENT_BROADCAST_SES	\
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04)
+#define SCU_EVENT_BROADCAST_EXPANDER \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05)
+#define SCU_EVENT_BROADCAST_AEN	\
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06)
+#define SCU_EVENT_BROADCAST_RESERVED3 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07)
+#define SCU_EVENT_BROADCAST_RESERVED4 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08)
+#define SCU_EVENT_PE_SUSPENDED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09)
+
+/**
+ *
+ *
+ * OSSP_EVENTS
+ */
+#define SCU_EVENT_PORT_SELECTOR_DETECTED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10)
+#define SCU_EVENT_SENT_PORT_SELECTION \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11)
+#define SCU_EVENT_HARD_RESET_TRANSMITTED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12)
+#define SCU_EVENT_HARD_RESET_RECEIVED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13)
+#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15)
+#define SCU_EVENT_LINK_FAILURE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16)
+#define SCU_EVENT_SATA_SPINUP_HOLD \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17)
+#define SCU_EVENT_SAS_15_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18)
+#define SCU_EVENT_SAS_15 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19)
+#define SCU_EVENT_SAS_30_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A)
+#define SCU_EVENT_SAS_30 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B)
+#define SCU_EVENT_SAS_60_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C)
+#define SCU_EVENT_SAS_60 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D)
+#define SCU_EVENT_SATA_15_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E)
+#define SCU_EVENT_SATA_15 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F)
+#define SCU_EVENT_SATA_30_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20)
+#define SCU_EVENT_SATA_30 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21)
+#define SCU_EVENT_SATA_60_SSC \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22)
+#define SCU_EVENT_SATA_60 \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23)
+#define SCU_EVENT_SAS_PHY_DETECTED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24)
+#define SCU_EVENT_SATA_PHY_DETECTED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25)
+
+/**
+ *
+ *
+ * FATAL_INTERNAL_MEMORY_ERROR_EVENTS
+ */
+#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x00)
+#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x01)
+#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x02)
+
+/**
+ *
+ *
+ * REMOTE_NODE_SUSPEND_EVENTS
+ */
+#define SCU_EVENT_TL_RNC_SUSPEND_TX \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00)
+#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20)
+#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX	\
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20)
+
+/**
+ *
+ *
+ * REMOTE_NODE_MISC_EVENTS
+ */
+#define SCU_EVENT_POST_RCN_RELEASE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE)
+#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01)
+#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02)
+#define SCU_EVENT_POST_RNC_COMPLETE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03)
+#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04)
+
+/**
+ *
+ *
+ * ERROR_COUNT_EVENT
+ */
+#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00)
+#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01)
+#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02)
+
+/**
+ * scu_get_event_type() -
+ *
+ * This macro returns the SCU event type from the event code.
+ */
+#define scu_get_event_type(event_code) \
+	((event_code) & SCU_EVENT_TYPE_CODE_MASK)
+
+/**
+ * scu_get_event_specifier() -
+ *
+ * This macro returns the SCU event specifier from the event code.
+ */
+#define scu_get_event_specifier(event_code) \
+	((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK)
+
+/**
+ * scu_get_event_code() -
+ *
+ * This macro returns the combined SCU event type and SCU event specifier from
+ * the event code.
+ */
+#define scu_get_event_code(event_code) \
+	((event_code) & SCU_EVENT_CODE_MASK)
+
+
+/**
+ *
+ *
+ * PTS_SCHEDULE_EVENT
+ */
+#define SCU_EVENT_SMP_RESPONSE_NO_PE \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00)
+#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \
+	scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE)
+
+#define SCU_EVENT_TASK_TIMEOUT \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01)
+#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT	\
+	scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT)
+
+#define SCU_EVENT_IT_NEXUS_TIMEOUT \
+	SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02)
+#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \
+	scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT)
+
+
+#endif /* __SCU_EVENT_CODES_HEADER__ */
diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h
new file mode 100644
index 0000000..818a575
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_task_context.h
@@ -0,0 +1,942 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCU_TASK_CONTEXT_H_
+#define _SCU_TASK_CONTEXT_H_
+
+/**
+ * This file contains the structures and constants for the SCU hardware task
+ *    context.
+ *
+ *
+ */
+
+
+/**
+ * enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task
+ *    types the SCU hardware will accept. The definition for the various task
+ *    types the SCU hardware will accept can be found in the DS specification.
+ *
+ *
+ */
+typedef enum {
+	SCU_TASK_TYPE_IOREAD,           /* /< IO READ direction or no direction */
+	SCU_TASK_TYPE_IOWRITE,          /* /< IO Write direction */
+	SCU_TASK_TYPE_SMP_REQUEST,      /* /< SMP Request type */
+	SCU_TASK_TYPE_RESPONSE,         /* /< Driver generated response frame (targt mode) */
+	SCU_TASK_TYPE_RAW_FRAME,        /* /< Raw frame request type */
+	SCU_TASK_TYPE_PRIMITIVE         /* /< Request for a primitive to be transmitted */
+} SCU_SSP_TASK_TYPE;
+
+/**
+ * enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task
+ *    types the SCU hardware will accept. The definition for the various task
+ *    types the SCU hardware will accept can be found in the DS specification.
+ *
+ *
+ */
+typedef enum {
+	SCU_TASK_TYPE_DMA_IN,           /* /< Read request */
+	SCU_TASK_TYPE_FPDMAQ_READ,      /* /< NCQ read request */
+	SCU_TASK_TYPE_PACKET_DMA_IN,    /* /< Packet read request */
+	SCU_TASK_TYPE_SATA_RAW_FRAME,   /* /< Raw frame request */
+	RESERVED_4,
+	RESERVED_5,
+	RESERVED_6,
+	RESERVED_7,
+	SCU_TASK_TYPE_DMA_OUT,          /* /< Write request */
+	SCU_TASK_TYPE_FPDMAQ_WRITE,     /* /< NCQ write Request */
+	SCU_TASK_TYPE_PACKET_DMA_OUT    /* /< Packet write request */
+} SCU_SATA_TASK_TYPE;
+
+
+/**
+ *
+ *
+ * SCU_CONTEXT_TYPE
+ */
+#define SCU_TASK_CONTEXT_TYPE  0
+#define SCU_RNC_CONTEXT_TYPE   1
+
+/**
+ *
+ *
+ * SCU_TASK_CONTEXT_VALIDITY
+ */
+#define SCU_TASK_CONTEXT_INVALID          0
+#define SCU_TASK_CONTEXT_VALID            1
+
+/**
+ *
+ *
+ * SCU_COMMAND_CODE
+ */
+#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK   0
+#define SCU_COMMAND_CODE_ACTIVE_TASK          1
+#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK   2
+#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES    3
+
+/**
+ *
+ *
+ * SCU_TASK_PRIORITY
+ */
+/**
+ *
+ *
+ * This priority is used when there is no priority request for this request.
+ */
+#define SCU_TASK_PRIORITY_NORMAL          0
+
+/**
+ *
+ *
+ * This priority indicates that the task should be scheduled to the head of the
+ * queue.  The task will NOT be executed if the TX is suspended for the remote
+ * node.
+ */
+#define SCU_TASK_PRIORITY_HEAD_OF_Q       1
+
+/**
+ *
+ *
+ * This priority indicates that the task will be executed before all
+ * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task
+ * WILL be executed if the TX is suspended for the remote node.
+ */
+#define SCU_TASK_PRIORITY_HIGH            2
+
+/**
+ *
+ *
+ * This task priority is reserved and should not be used.
+ */
+#define SCU_TASK_PRIORITY_RESERVED        3
+
+#define SCU_TASK_INITIATOR_MODE           1
+#define SCU_TASK_TARGET_MODE              0
+
+#define SCU_TASK_REGULAR                  0
+#define SCU_TASK_ABORTED                  1
+
+/* direction bit defintion */
+/**
+ *
+ *
+ * SATA_DIRECTION
+ */
+#define SCU_SATA_WRITE_DATA_DIRECTION     0
+#define SCU_SATA_READ_DATA_DIRECTION      1
+
+/**
+ *
+ *
+ * SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift
+ * operations to construct the various SCU commands
+ */
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT           21
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK            0x00E00000
+#define scu_get_command_request_type(x)	\
+	((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT        18
+#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK         0x001C0000
+#define scu_get_command_request_subtype(x) \
+	((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK	 \
+	(\
+		SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK		  \
+		| SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK	    \
+	)
+#define scu_get_command_request_full_type(x) \
+	((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT  16
+#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK   0x00010000
+#define scu_get_command_protocl_engine_group(x)	\
+	((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK)
+
+#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT           12
+#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK            0x00007000
+#define scu_get_command_reqeust_logical_port(x)	\
+	((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK)
+
+
+#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \
+	((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT)
+
+/**
+ * MAKE_SCU_CONTEXT_COMMAND_TYPE() -
+ *
+ * SCU_COMMAND_TYPES These constants provide the grouping of the different SCU
+ * command types.
+ */
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC    MAKE_SCU_CONTEXT_COMMAND_TYPE(0)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC    MAKE_SCU_CONTEXT_COMMAND_TYPE(1)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC   MAKE_SCU_CONTEXT_COMMAND_TYPE(2)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC   MAKE_SCU_CONTEXT_COMMAND_TYPE(3)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC  MAKE_SCU_CONTEXT_COMMAND_TYPE(6)
+
+#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command)	\
+	((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT))
+
+/**
+ *
+ *
+ * SCU_REQUEST_TYPES These constants are the various request types that can be
+ * posted to the SCU hardware.
+ */
+#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0))
+
+#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1))
+
+#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_32	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_96	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2))
+
+#define SCU_CONTEXT_COMMAND_DUMP_RNC_32	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_DUMP_RNC_96	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2))
+
+#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3))
+
+#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE	\
+	(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4))
+
+/**
+ *
+ *
+ * SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to
+ * program the SCU Task context protocol field in word 0x00.
+ */
+#define SCU_TASK_CONTEXT_PROTOCOL_SMP    0x00
+#define SCU_TASK_CONTEXT_PROTOCOL_SSP    0x01
+#define SCU_TASK_CONTEXT_PROTOCOL_STP    0x02
+#define SCU_TASK_CONTEXT_PROTOCOL_NONE   0x07
+
+/**
+ * struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP
+ *    request.
+ *
+ *
+ */
+struct SSP_TASK_CONTEXT {
+	/* OFFSET 0x18 */
+	u32 reserved00:24;
+	u32 frame_type:8;
+
+	/* OFFSET 0x1C */
+	u32 reserved01;
+
+	/* OFFSET 0x20 */
+	u32 fill_bytes:2;
+	u32 reserved02:6;
+	u32 changing_data_pointer:1;
+	u32 retransmit:1;
+	u32 retry_data_frame:1;
+	u32 tlr_control:2;
+	u32 reserved03:19;
+
+	/* OFFSET 0x24 */
+	u32 uiRsvd4;
+
+	/* OFFSET 0x28 */
+	u32 target_port_transfer_tag:16;
+	u32 tag:16;
+
+	/* OFFSET 0x2C */
+	u32 data_offset;
+};
+
+/**
+ * struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP
+ *    request.
+ *
+ *
+ */
+struct STP_TASK_CONTEXT {
+	/* OFFSET 0x18 */
+	u32 fis_type:8;
+	u32 pm_port:4;
+	u32 reserved0:3;
+	u32 control:1;
+	u32 command:8;
+	u32 features:8;
+
+	/* OFFSET 0x1C */
+	u32 reserved1;
+
+	/* OFFSET 0x20 */
+	u32 reserved2;
+
+	/* OFFSET 0x24 */
+	u32 reserved3;
+
+	/* OFFSET 0x28 */
+	u32 ncq_tag:5;
+	u32 reserved4:27;
+
+	/* OFFSET 0x2C */
+	u32 data_offset; /* TODO: What is this used for? */
+};
+
+/**
+ * struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP
+ *    request.
+ *
+ *
+ */
+struct SMP_TASK_CONTEXT {
+	/* OFFSET 0x18 */
+	u32 response_length:8;
+	u32 function_result:8;
+	u32 function:8;
+	u32 frame_type:8;
+
+	/* OFFSET 0x1C */
+	u32 smp_response_ufi:12;
+	u32 reserved1:20;
+
+	/* OFFSET 0x20 */
+	u32 reserved2;
+
+	/* OFFSET 0x24 */
+	u32 reserved3;
+
+	/* OFFSET 0x28 */
+	u32 reserved4;
+
+	/* OFFSET 0x2C */
+	u32 reserved5;
+};
+
+/**
+ * struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used
+ *    when the driver wants to send a primitive on the link.
+ *
+ *
+ */
+struct PRIMITIVE_TASK_CONTEXT {
+	/* OFFSET 0x18 */
+	/**
+	 * This field is the control word and it must be 0.
+	 */
+	u32 control; /* /< must be set to 0 */
+
+	/* OFFSET 0x1C */
+	/**
+	 * This field specifies the primitive that is to be transmitted.
+	 */
+	u32 sequence;
+
+	/* OFFSET 0x20 */
+	u32 reserved0;
+
+	/* OFFSET 0x24 */
+	u32 reserved1;
+
+	/* OFFSET 0x28 */
+	u32 reserved2;
+
+	/* OFFSET 0x2C */
+	u32 reserved3;
+};
+
+/**
+ * The union of the protocols that can be selected in the SCU task context
+ *    field.
+ *
+ * PROTOCOL_CONTEXT
+ */
+union PROTOCOL_CONTEXT {
+	struct SSP_TASK_CONTEXT ssp;
+	struct STP_TASK_CONTEXT stp;
+	struct SMP_TASK_CONTEXT smp;
+	struct PRIMITIVE_TASK_CONTEXT primitive;
+	u32 words[6];
+};
+
+/**
+ * struct scu_sgl_element - This structure represents a single SCU defined SGL
+ *    element. SCU SGLs contain a 64 bit address with the maximum data transfer
+ *    being 24 bits in size.  The SGL can not cross a 4GB boundary.
+ *
+ * struct scu_sgl_element
+ */
+struct scu_sgl_element {
+	/**
+	 * This field is the upper 32 bits of the 64 bit physical address.
+	 */
+	u32 address_upper;
+
+	/**
+	 * This field is the lower 32 bits of the 64 bit physical address.
+	 */
+	u32 address_lower;
+
+	/**
+	 * This field is the number of bytes to transfer.
+	 */
+	u32 length:24;
+
+	/**
+	 * This field is the address modifier to be used when a virtual function is
+	 * requesting a data transfer.
+	 */
+	u32 address_modifier:8;
+
+};
+
+#define SCU_SGL_ELEMENT_PAIR_A   0
+#define SCU_SGL_ELEMENT_PAIR_B   1
+
+/**
+ * struct scu_sgl_element_pair - This structure is the SCU hardware definition
+ *    of a pair of SGL elements. The SCU hardware always works on SGL pairs.
+ *    They are refered to in the DS specification as SGL A and SGL B.  Each SGL
+ *    pair is followed by the address of the next pair.
+ *
+ *
+ */
+struct scu_sgl_element_pair {
+	/* OFFSET 0x60-0x68 */
+	/**
+	 * This field is the SGL element A of the SGL pair.
+	 */
+	struct scu_sgl_element A;
+
+	/* OFFSET 0x6C-0x74 */
+	/**
+	 * This field is the SGL element B of the SGL pair.
+	 */
+	struct scu_sgl_element B;
+
+	/* OFFSET 0x78-0x7C */
+	/**
+	 * This field is the upper 32 bits of the 64 bit address to the next SGL
+	 * element pair.
+	 */
+	u32 next_pair_upper;
+
+	/**
+	 * This field is the lower 32 bits of the 64 bit address to the next SGL
+	 * element pair.
+	 */
+	u32 next_pair_lower;
+
+};
+
+/**
+ * struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area
+ *    for the task context. This is set to 0 by the driver but can be read by
+ *    issuing a dump TC request to the SCU.
+ *
+ *
+ */
+struct TRANSPORT_SNAPSHOT {
+	/* OFFSET 0x48 */
+	u32 xfer_rdy_write_data_length;
+
+	/* OFFSET 0x4C */
+	u32 data_offset;
+
+	/* OFFSET 0x50 */
+	u32 data_transfer_size:24;
+	u32 reserved_50_0:8;
+
+	/* OFFSET 0x54 */
+	u32 next_initiator_write_data_offset;
+
+	/* OFFSET 0x58 */
+	u32 next_initiator_write_data_xfer_size:24;
+	u32 reserved_58_0:8;
+};
+
+/**
+ * struct scu_task_context - This structure defines the contents of the SCU
+ *    silicon task context. It lays out all of the fields according to the
+ *    expected order and location for the Storage Controller unit.
+ *
+ *
+ */
+struct scu_task_context {
+	/* OFFSET 0x00 ------ */
+	/**
+	 * This field must be encoded to one of the valid SCU task priority values
+	 *    - SCU_TASK_PRIORITY_NORMAL
+	 *    - SCU_TASK_PRIORITY_HEAD_OF_Q
+	 *    - SCU_TASK_PRIORITY_HIGH
+	 */
+	u32 priority:2;
+
+	/**
+	 * This field must be set to true if this is an initiator generated request.
+	 * Until target mode is supported all task requests are initiator requests.
+	 */
+	u32 initiator_request:1;
+
+	/**
+	 * This field must be set to one of the valid connection rates valid values
+	 * are 0x8, 0x9, and 0xA.
+	 */
+	u32 connection_rate:4;
+
+	/**
+	 * This field muse be programed when generating an SMP response since the SMP
+	 * connection remains open until the SMP response is generated.
+	 */
+	u32 protocol_engine_index:3;
+
+	/**
+	 * This field must contain the logical port for the task request.
+	 */
+	u32 logical_port_index:3;
+
+	/**
+	 * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values
+	 *    - SCU_TASK_CONTEXT_PROTOCOL_SMP
+	 *    - SCU_TASK_CONTEXT_PROTOCOL_SSP
+	 *    - SCU_TASK_CONTEXT_PROTOCOL_STP
+	 *    - SCU_TASK_CONTEXT_PROTOCOL_NONE
+	 */
+	u32 protocol_type:3;
+
+	/**
+	 * This filed must be set to the TCi allocated for this task
+	 */
+	u32 task_index:12;
+
+	/**
+	 * This field is reserved and must be set to 0x00
+	 */
+	u32 reserved_00_0:1;
+
+	/**
+	 * For a normal task request this must be set to 0.  If this is an abort of
+	 * this task request it must be set to 1.
+	 */
+	u32 abort:1;
+
+	/**
+	 * This field must be set to true for the SCU hardware to process the task.
+	 */
+	u32 valid:1;
+
+	/**
+	 * This field must be set to SCU_TASK_CONTEXT_TYPE
+	 */
+	u32 context_type:1;
+
+	/* OFFSET 0x04 */
+	/**
+	 * This field contains the RNi that is the target of this request.
+	 */
+	u32 remote_node_index:12;
+
+	/**
+	 * This field is programmed if this is a mirrored request, which we are not
+	 * using, in which case it is the RNi for the mirrored target.
+	 */
+	u32 mirrored_node_index:12;
+
+	/**
+	 * This field is programmed with the direction of the SATA reqeust
+	 *    - SCU_SATA_WRITE_DATA_DIRECTION
+	 *    - SCU_SATA_READ_DATA_DIRECTION
+	 */
+	u32 sata_direction:1;
+
+	/**
+	 * This field is programmsed with one of the following SCU_COMMAND_CODE
+	 *    - SCU_COMMAND_CODE_INITIATOR_NEW_TASK
+	 *    - SCU_COMMAND_CODE_ACTIVE_TASK
+	 *    - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK
+	 *    - SCU_COMMAND_CODE_TARGET_RAW_FRAMES
+	 */
+	u32 command_code:2;
+
+	/**
+	 * This field is set to true if the remote node should be suspended.
+	 * This bit is only valid for SSP & SMP target devices.
+	 */
+	u32 suspend_node:1;
+
+	/**
+	 * This field is programmed with one of the following command type codes
+	 *
+	 * For SAS requests use the SCU_SSP_TASK_TYPE
+	 *    - SCU_TASK_TYPE_IOREAD
+	 *    - SCU_TASK_TYPE_IOWRITE
+	 *    - SCU_TASK_TYPE_SMP_REQUEST
+	 *    - SCU_TASK_TYPE_RESPONSE
+	 *    - SCU_TASK_TYPE_RAW_FRAME
+	 *    - SCU_TASK_TYPE_PRIMITIVE
+	 *
+	 * For SATA requests use the SCU_SATA_TASK_TYPE
+	 *    - SCU_TASK_TYPE_DMA_IN
+	 *    - SCU_TASK_TYPE_FPDMAQ_READ
+	 *    - SCU_TASK_TYPE_PACKET_DMA_IN
+	 *    - SCU_TASK_TYPE_SATA_RAW_FRAME
+	 *    - SCU_TASK_TYPE_DMA_OUT
+	 *    - SCU_TASK_TYPE_FPDMAQ_WRITE
+	 *    - SCU_TASK_TYPE_PACKET_DMA_OUT
+	 */
+	u32 task_type:4;
+
+	/* OFFSET 0x08 */
+	/**
+	 * This field is reserved and the must be set to 0x00
+	 */
+	u32 link_layer_control:8; /* presently all reserved */
+
+	/**
+	 * This field is set to true when TLR is to be enabled
+	 */
+	u32 ssp_tlr_enable:1;
+
+	/**
+	 * This is field specifies if the SCU DMAs a response frame to host
+	 * memory for good response frames when operating in target mode.
+	 */
+	u32 dma_ssp_target_good_response:1;
+
+	/**
+	 * This field indicates if the SCU should DMA the response frame to
+	 * host memory.
+	 */
+	u32 do_not_dma_ssp_good_response:1;
+
+	/**
+	 * This field is set to true when strict ordering is to be enabled
+	 */
+	u32 strict_ordering:1;
+
+	/**
+	 * This field indicates the type of endianess to be utilized for the
+	 * frame.  command, task, and response frames utilized control_frame
+	 * set to 1.
+	 */
+	u32 control_frame:1;
+
+	/**
+	 * This field is reserved and the driver should set to 0x00
+	 */
+	u32 tl_control_reserved:3;
+
+	/**
+	 * This field is set to true when the SCU hardware task timeout control is to
+	 * be enabled
+	 */
+	u32 timeout_enable:1;
+
+	/**
+	 * This field is reserved and the driver should set it to 0x00
+	 */
+	u32 pts_control_reserved:7;
+
+	/**
+	 * This field should be set to true when block guard is to be enabled
+	 */
+	u32 block_guard_enable:1;
+
+	/**
+	 * This field is reserved and the driver should set to 0x00
+	 */
+	u32 sdma_control_reserved:7;
+
+	/* OFFSET 0x0C */
+	/**
+	 * This field is the address modifier for this io request it should be
+	 * programmed with the virtual function that is making the request.
+	 */
+	u32 address_modifier:16;
+
+	/**
+	 * @todo What we support mirrored SMP response frame?
+	 */
+	u32 mirrored_protocol_engine:3;  /* mirrored protocol Engine Index */
+
+	/**
+	 * If this is a mirrored request the logical port index for the mirrored RNi
+	 * must be programmed.
+	 */
+	u32 mirrored_logical_port:4;  /* mirrored local port index */
+
+	/**
+	 * This field is reserved and the driver must set it to 0x00
+	 */
+	u32 reserved_0C_0:8;
+
+	/**
+	 * This field must be set to true if the mirrored request processing is to be
+	 * enabled.
+	 */
+	u32 mirror_request_enable:1;  /* Mirrored request Enable */
+
+	/* OFFSET 0x10 */
+	/**
+	 * This field is the command iu length in dwords
+	 */
+	u32 ssp_command_iu_length:8;
+
+	/**
+	 * This is the target TLR enable bit it must be set to 0 when creatning the
+	 * task context.
+	 */
+	u32 xfer_ready_tlr_enable:1;
+
+	/**
+	 * This field is reserved and the driver must set it to 0x00
+	 */
+	u32 reserved_10_0:7;
+
+	/**
+	 * This is the maximum burst size that the SCU hardware will send in one
+	 * connection its value is (N x 512) and N must be a multiple of 2.  If the
+	 * value is 0x00 then maximum burst size is disabled.
+	 */
+	u32 ssp_max_burst_size:16;
+
+	/* OFFSET 0x14 */
+	/**
+	 * This filed is set to the number of bytes to be transfered in the request.
+	 */
+	u32 transfer_length_bytes:24; /* In terms of bytes */
+
+	/**
+	 * This field is reserved and the driver should set it to 0x00
+	 */
+	u32 reserved_14_0:8;
+
+	/* OFFSET 0x18-0x2C */
+	/**
+	 * This union provides for the protocol specif part of the SCU Task Context.
+	 */
+	union PROTOCOL_CONTEXT type;
+
+	/* OFFSET 0x30-0x34 */
+	/**
+	 * This field is the upper 32 bits of the 64 bit physical address of the
+	 * command iu buffer
+	 */
+	u32 command_iu_upper;
+
+	/**
+	 * This field is the lower 32 bits of the 64 bit physical address of the
+	 * command iu buffer
+	 */
+	u32 command_iu_lower;
+
+	/* OFFSET 0x38-0x3C */
+	/**
+	 * This field is the upper 32 bits of the 64 bit physical address of the
+	 * response iu buffer
+	 */
+	u32 response_iu_upper;
+
+	/**
+	 * This field is the lower 32 bits of the 64 bit physical address of the
+	 * response iu buffer
+	 */
+	u32 response_iu_lower;
+
+	/* OFFSET 0x40 */
+	/**
+	 * This field is set to the task phase of the SCU hardware. The driver must
+	 * set this to 0x01
+	 */
+	u32 task_phase:8;
+
+	/**
+	 * This field is set to the transport layer task status.  The driver must set
+	 * this to 0x00
+	 */
+	u32 task_status:8;
+
+	/**
+	 * This field is used during initiator write TLR
+	 */
+	u32 previous_extended_tag:4;
+
+	/**
+	 * This field is set the maximum number of retries for a STP non-data FIS
+	 */
+	u32 stp_retry_count:2;
+
+	/**
+	 * This field is reserved and the driver must set it to 0x00
+	 */
+	u32 reserved_40_1:2;
+
+	/**
+	 * This field is used by the SCU TL to determine when to take a snapshot when
+	 * tranmitting read data frames.
+	 *    - 0x00 The entire IO
+	 *    - 0x01 32k
+	 *    - 0x02 64k
+	 *    - 0x04 128k
+	 *    - 0x08 256k
+	 */
+	u32 ssp_tlr_threshold:4;
+
+	/**
+	 * This field is reserved and the driver must set it to 0x00
+	 */
+	u32 reserved_40_2:4;
+
+	/* OFFSET 0x44 */
+	u32 write_data_length; /* read only set to 0 */
+
+	/* OFFSET 0x48-0x58 */
+	struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */
+
+	/* OFFSET 0x5C */
+	u32 block_protection_enable:1;
+	u32 block_size:2;
+	u32 block_protection_function:2;
+	u32 reserved_5C_0:9;
+	u32 active_sgl_element:2;  /* read only set to 0 */
+	u32 sgl_exhausted:1;  /* read only set to 0 */
+	u32 payload_data_transfer_error:4;  /* read only set to 0 */
+	u32 frame_buffer_offset:11; /* read only set to 0 */
+
+	/* OFFSET 0x60-0x7C */
+	/**
+	 * This field is the first SGL element pair found in the TC data structure.
+	 */
+	struct scu_sgl_element_pair sgl_pair_ab;
+	/* OFFSET 0x80-0x9C */
+	/**
+	 * This field is the second SGL element pair found in the TC data structure.
+	 */
+	struct scu_sgl_element_pair sgl_pair_cd;
+
+	/* OFFSET 0xA0-BC */
+	struct scu_sgl_element_pair sgl_snapshot_ac;
+
+	/* OFFSET 0xC0 */
+	u32 active_sgl_element_pair; /* read only set to 0 */
+
+	/* OFFSET 0xC4-0xCC */
+	u32 reserved_C4_CC[3];
+
+	/* OFFSET 0xD0 */
+	u32 intermediate_crc_value:16;
+	u32 initial_crc_seed:16;
+
+	/* OFFSET 0xD4 */
+	u32 application_tag_for_verify:16;
+	u32 application_tag_for_generate:16;
+
+	/* OFFSET 0xD8 */
+	u32 reference_tag_seed_for_verify_function;
+
+	/* OFFSET 0xDC */
+	u32 reserved_DC;
+
+	/* OFFSET 0xE0 */
+	u32 reserved_E0_0:16;
+	u32 application_tag_mask_for_generate:16;
+
+	/* OFFSET 0xE4 */
+	u32 block_protection_control:16;
+	u32 application_tag_mask_for_verify:16;
+
+	/* OFFSET 0xE8 */
+	u32 block_protection_error:8;
+	u32 reserved_E8_0:24;
+
+	/* OFFSET 0xEC */
+	u32 reference_tag_seed_for_verify;
+
+	/* OFFSET 0xF0 */
+	u32 intermediate_crc_valid_snapshot:16;
+	u32 reserved_F0_0:16;
+
+	/* OFFSET 0xF4 */
+	u32 reference_tag_seed_for_verify_function_snapshot;
+
+	/* OFFSET 0xF8 */
+	u32 snapshot_of_reserved_dword_DC_of_tc;
+
+	/* OFFSET 0xFC */
+	u32 reference_tag_seed_for_generate_function_snapshot;
+
+};
+
+#endif /* _SCU_TASK_CONTEXT_H_ */
diff --git a/drivers/scsi/isci/core/scu_viit_data.h b/drivers/scsi/isci/core/scu_viit_data.h
new file mode 100644
index 0000000..c959d91
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_viit_data.h
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCU_VIIT_DATA_HEADER_
+#define _SCU_VIIT_DATA_HEADER_
+
+/**
+ * This file contains the constants and structures for the SCU hardware VIIT
+ *    table entries.
+ *
+ *
+ */
+
+
+#define SCU_VIIT_ENTRY_ID_MASK         (0xC0000000)
+#define SCU_VIIT_ENTRY_ID_SHIFT        (30)
+
+#define SCU_VIIT_ENTRY_FUNCTION_MASK   (0x0FF00000)
+#define SCU_VIIT_ENTRY_FUNCTION_SHIFT  (20)
+
+#define SCU_VIIT_ENTRY_IPPTMODE_MASK   (0x0001F800)
+#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT  (12)
+
+#define SCU_VIIT_ENTRY_LPVIE_MASK      (0x00000F00)
+#define SCU_VIIT_ENTRY_LPVIE_SHIFT     (8)
+
+#define SCU_VIIT_ENTRY_STATUS_MASK     (0x000000FF)
+#define SCU_VIIT_ENTRY_STATUS_SHIFT    (0)
+
+#define SCU_VIIT_ENTRY_ID_INVALID   (0 << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_VIIT      (1 << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_IIT       (2 << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_VIRT_EXP  (3 << SCU_VIIT_ENTRY_ID_SHIFT)
+
+#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_INITIATOR	    \
+	(\
+		SCU_VIIT_IPPT_SSP_INITIATOR  \
+		| SCU_VIIT_IPPT_SMP_INITIATOR  \
+		| SCU_VIIT_IPPT_STP_INITIATOR  \
+	)
+
+#define SCU_VIIT_STATUS_RNC_VALID      (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_ADDRESS_VALID  (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_RNI_VALID      (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_ALL_VALID      \
+	(\
+		SCU_VIIT_STATUS_RNC_VALID	\
+		| SCU_VIIT_STATUS_ADDRESS_VALID	  \
+		| SCU_VIIT_STATUS_RNI_VALID	  \
+	)
+
+#define SCU_VIIT_IPPT_SMP_TARGET    (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+
+/**
+ * struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry
+ *
+ *
+ */
+struct scu_viit_entry {
+	/**
+	 * This must be encoded as to the type of initiator that is being constructed
+	 * for this port.
+	 */
+	u32 status;
+
+	/**
+	 * Virtual initiator high SAS Address
+	 */
+	u32 initiator_sas_address_hi;
+
+	/**
+	 * Virtual initiator low SAS Address
+	 */
+	u32 initiator_sas_address_lo;
+
+	/**
+	 * This must be 0
+	 */
+	u32 reserved;
+
+};
+
+
+/* IIT Status Defines */
+#define SCU_IIT_ENTRY_ID_MASK                (0xC0000000)
+#define SCU_IIT_ENTRY_ID_SHIFT               (30)
+
+#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK     (0x20000000)
+#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT    (29)
+
+#define SCU_IIT_ENTRY_LPI_MASK               (0x00000F00)
+#define SCU_IIT_ENTRY_LPI_SHIFT              (8)
+
+#define SCU_IIT_ENTRY_STATUS_MASK            (0x000000FF)
+#define SCU_IIT_ENTRY_STATUS_SHIFT           (0)
+
+/* IIT Remote Initiator Defines */
+#define SCU_IIT_ENTRY_REMOTE_TAG_MASK  (0x0000FFFF)
+#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0)
+
+#define SCU_IIT_ENTRY_REMOTE_RNC_MASK  (0x0FFF0000)
+#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16)
+
+#define SCU_IIT_ENTRY_ID_INVALID   (0 << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_VIIT      (1 << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_IIT       (2 << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_VIRT_EXP  (3 << SCU_IIT_ENTRY_ID_SHIFT)
+
+/**
+ * struct scu_iit_entry - This will be implemented later when we support
+ *    virtual functions
+ *
+ *
+ */
+struct scu_iit_entry {
+	u32 status;
+	u32 remote_initiator_sas_address_hi;
+	u32 remote_initiator_sas_address_lo;
+	u32 remote_initiator;
+
+};
+
+#endif /* _SCU_VIIT_DATA_HEADER_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [RFC PATCH 10/10] isci/core: common definitions and utility functions
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (8 preceding siblings ...)
  2011-03-10 10:55 ` [RFC PATCH 09/10] isci/core: base state machine and memory descriptors Dan Williams
@ 2011-03-10 10:55 ` Dan Williams
  2011-03-30 14:37   ` Christoph Hellwig
  2011-03-15 17:47 ` [RFC PATCH 00/10] isci: core Jeff Garzik
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Dan Williams @ 2011-03-10 10:55 UTC (permalink / raw)
  To: james.bottomley
  Cc: dave.jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	jeffrey.d.skirvin, edmund.nadolski

Many of these want to be deleted in favor of the in-kernel equivalent.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/isci/core/intel_ata.h                |  554 ++++++++++++
 drivers/scsi/isci/core/intel_sas.h                |  948 +++++++++++++++++++++
 drivers/scsi/isci/core/intel_sat.h                |   95 ++
 drivers/scsi/isci/core/intel_sata.h               |  280 ++++++
 drivers/scsi/isci/core/intel_scsi.h               |  474 +++++++++++
 drivers/scsi/isci/core/sati_device.h              |  156 +++
 drivers/scsi/isci/core/sati_translator_sequence.h |  304 +++++++
 drivers/scsi/isci/core/sati_types.h               |  145 +++
 drivers/scsi/isci/core/sci_pool.h                 |  199 ++++
 drivers/scsi/isci/core/sci_status.h               |  409 +++++++++
 drivers/scsi/isci/core/sci_util.c                 |  101 ++
 drivers/scsi/isci/core/sci_util.h                 |  108 ++
 drivers/scsi/isci/core/scic_config_parameters.h   |  346 ++++++++
 drivers/scsi/isci/core/scic_sds_pci.h             |   94 ++
 14 files changed, 4213 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/isci/core/intel_ata.h
 create mode 100644 drivers/scsi/isci/core/intel_sas.h
 create mode 100644 drivers/scsi/isci/core/intel_sat.h
 create mode 100644 drivers/scsi/isci/core/intel_sata.h
 create mode 100644 drivers/scsi/isci/core/intel_scsi.h
 create mode 100644 drivers/scsi/isci/core/sati_device.h
 create mode 100644 drivers/scsi/isci/core/sati_translator_sequence.h
 create mode 100644 drivers/scsi/isci/core/sati_types.h
 create mode 100644 drivers/scsi/isci/core/sci_pool.h
 create mode 100644 drivers/scsi/isci/core/sci_status.h
 create mode 100644 drivers/scsi/isci/core/sci_util.c
 create mode 100644 drivers/scsi/isci/core/sci_util.h
 create mode 100644 drivers/scsi/isci/core/scic_config_parameters.h
 create mode 100644 drivers/scsi/isci/core/scic_sds_pci.h

diff --git a/drivers/scsi/isci/core/intel_ata.h b/drivers/scsi/isci/core/intel_ata.h
new file mode 100644
index 0000000..48b297e
--- /dev/null
+++ b/drivers/scsi/isci/core/intel_ata.h
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file defines all of the ATA related constants, enumerations, and types.
+ *     Please note that this file does not necessarily contain an exhaustive
+ *    list of all constants, commands, sub-commands, etc.
+ *
+ *
+ */
+
+#ifndef _ATA_H_
+#define _ATA_H_
+
+#include <linux/types.h>
+
+/**
+ *
+ *
+ * ATA_COMMAND_CODES These constants depict the various ATA command codes
+ * defined in the ATA/ATAPI specification.
+ */
+#define ATA_IDENTIFY_DEVICE         0xEC
+#define ATA_CHECK_POWER_MODE        0xE5
+#define ATA_STANDBY                 0xE2
+#define ATA_STANDBY_IMMED           0xE0
+#define ATA_IDLE_IMMED              0xE1
+#define ATA_IDLE                    0xE3
+#define ATA_FLUSH_CACHE             0xE7
+#define ATA_FLUSH_CACHE_EXT         0xEA
+#define ATA_READ_DMA_EXT            0x25
+#define ATA_READ_DMA                0xC8
+#define ATA_READ_SECTORS_EXT        0x24
+#define ATA_READ_SECTORS            0x20
+#define ATA_WRITE_DMA_EXT           0x35
+#define ATA_WRITE_DMA               0xCA
+#define ATA_WRITE_SECTORS_EXT       0x34
+#define ATA_WRITE_SECTORS           0x30
+#define ATA_WRITE_UNCORRECTABLE     0x45
+#define ATA_READ_VERIFY_SECTORS     0x40
+#define ATA_READ_VERIFY_SECTORS_EXT 0x42
+#define ATA_READ_BUFFER             0xE4
+#define ATA_WRITE_BUFFER            0xE8
+#define ATA_EXECUTE_DEVICE_DIAG     0x90
+#define ATA_SET_FEATURES            0xEF
+#define ATA_SMART                   0xB0
+#define ATA_PACKET_IDENTIFY         0xA1
+#define ATA_PACKET                  0xA0
+#define ATA_READ_FPDMA              0x60
+#define ATA_WRITE_FPDMA             0x61
+#define ATA_READ_LOG_EXT            0x2F
+#define ATA_NOP                     0x00
+#define ATA_DEVICE_RESET            0x08
+#define ATA_MEDIA_EJECT             0xED
+
+/**
+ *
+ *
+ * ATA_SMART_SUB_COMMAND_CODES These constants define the ATA SMART command
+ * sub-codes that can be executed.
+ */
+#define ATA_SMART_SUB_CMD_ENABLE        0xD8
+#define ATA_SMART_SUB_CMD_DISABLE       0xD9
+#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA
+#define ATA_SMART_SUB_CMD_READ_LOG      0xD5
+
+/**
+ *
+ *
+ * ATA_SET_FEATURES_SUB_COMMAND_CODES These constants define the ATA SET
+ * FEATURES command sub-codes that can be executed.
+ */
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE       0x02
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE      0x82
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD  0xAA
+#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE  0x3
+
+/**
+ *
+ *
+ * ATA_READ_LOG_EXT_PAGE_CODES This is a list of log page codes available for
+ * use.
+ */
+#define ATA_LOG_PAGE_NCQ_ERROR                  0x10
+#define ATA_LOG_PAGE_SMART_SELF_TEST            0x06
+#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST   0x07
+
+/**
+ *
+ *
+ * ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS These constants define standard values for
+ * use when requesting the NCQ error log page.
+ */
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR        0
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT  1
+
+/**
+ *
+ *
+ * ATA_STATUS_REGISTER_BITS The following are status register bit definitions
+ * per ATA/ATAPI-7.
+ */
+#define ATA_STATUS_REG_BSY_BIT          0x80
+#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20
+#define ATA_STATUS_REG_ERROR_BIT        0x01
+
+/**
+ *
+ *
+ * ATA_ERROR_REGISTER_BITS The following are error register bit definitions per
+ * ATA/ATAPI-7.
+ */
+#define ATA_ERROR_REG_NO_MEDIA_BIT              0x02
+#define ATA_ERROR_REG_ABORT_BIT                 0x04
+#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT  0x08
+#define ATA_ERROR_REG_ID_NOT_FOUND_BIT          0x10
+#define ATA_ERROR_REG_MEDIA_CHANGE_BIT          0x20
+#define ATA_ERROR_REG_UNCORRECTABLE_BIT         0x40
+#define ATA_ERROR_REG_WRITE_PROTECTED_BIT       0x40
+#define ATA_ERROR_REG_ICRC_BIT                  0x80
+
+/**
+ *
+ *
+ * ATA_CONTROL_REGISTER_BITS The following are control register bit definitions
+ * per ATA/ATAPI-7
+ */
+#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02
+#define ATA_CONTROL_REG_SOFT_RESET_BIT       0x04
+#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT  0x80
+
+/**
+ *
+ *
+ * ATA_DEVICE_HEAD_REGISTER_BITS The following are device/head register bit
+ * definitions per ATA/ATAPI-7.
+ */
+#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE  0x40
+#define ATA_DEV_HEAD_REG_FUA_ENABLE       0x80
+
+/**
+ *
+ *
+ * ATA_IDENTIFY_DEVICE_FIELD_LENGTHS The following constants define the number
+ * of bytes contained in various fields found in the IDENTIFY DEVICE data
+ * structure.
+ */
+#define ATA_IDENTIFY_SERIAL_NUMBER_LEN        20
+#define ATA_IDENTIFY_MODEL_NUMBER_LEN         40
+#define ATA_IDENTIFY_FW_REVISION_LEN          8
+#define ATA_IDENTIFY_48_LBA_LEN               8
+#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN  30
+#define ATA_IDENTIFY_WWN_LEN                  8
+
+/**
+ *
+ *
+ * ATA_IDENTIFY_DEVICE_FIELD_MASKS The following constants define bit masks
+ * utilized to determine if a feature is supported/enabled or if a bit is
+ * simply set inside of the IDENTIFY DEVICE data structre.
+ */
+#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE              0x0080
+#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE     0x0100
+#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE        0x2000
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400
+#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE      0x0100
+#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE   0x0001
+#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE        0x0100
+#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE              0x001F
+#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE       0x0100
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK   0x000F
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000
+#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT         0x0004
+#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED     0x0002
+
+/**
+ *
+ *
+ * ATAPI_IDENTIFY_DEVICE_FIELD_MASKS These constants define the various bit
+ * definitions for the fields in the PACKET IDENTIFY DEVICE data structure.
+ */
+#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE       0x01
+
+/**
+ *
+ *
+ * ATA_PACKET_FEATURE_BITS These constants define the various bit definitions
+ * for the ATA PACKET feature register.
+ */
+#define ATA_PACKET_FEATURE_DMA     0x01
+#define ATA_PACKET_FEATURE_OVL     0x02
+#define ATA_PACKET_FEATURE_DMADIR  0x04
+
+/**
+ *
+ *
+ * ATA_Device_Power_Mode_Values These constants define the power mode values
+ * returned by ATA_Check_Power_Mode
+ */
+#define ATA_STANDBY_POWER_MODE    0x00
+#define ATA_IDLE_POWER_MODE       0x80
+#define ATA_ACTIVE_POWER_MODE     0xFF
+
+/**
+ *
+ *
+ * ATA_WRITE_UNCORRECTIABLE feature field values These constants define the
+ * Write Uncorrectable feature values used with the SATI translation.
+ */
+#define ATA_WRITE_UNCORRECTABLE_PSUEDO    0x55
+#define ATA_WRITE_UNCORRECTABLE_FLAGGED   0xAA
+
+
+
+/**
+ * struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE
+ *    data format.
+ *
+ *
+ */
+struct ata_identify_device_data {
+	u16 general_config_bits;                                                /* word  00 */
+	u16 obsolete0;                                                          /* word  01 (num cylinders) */
+	u16 vendor_specific_config_bits;                                        /* word  02 */
+	u16 obsolete1;                                                          /* word  03 (num heads) */
+	u16 retired1[2];                                                        /* words 04-05 */
+	u16 obsolete2;                                                          /* word  06 (sectors / track) */
+	u16 reserved_for_compact_flash1[2];                                     /* words 07-08 */
+	u16 retired0;                                                           /* word  09 */
+	u8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN];                       /* word 10-19 */
+	u16 retired2[2];                                                        /* words 20-21 */
+	u16 obsolete4;                                                          /* word  22 */
+	u8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN];                     /* words 23-26 */
+	u8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN];                         /* words 27-46 */
+	u16 max_sectors_per_multiple;                                           /* word  47 */
+	u16 reserved0;                                                          /* word  48 */
+	u16 capabilities1;                                                      /* word  49 */
+	u16 capabilities2;                                                      /* word  50 */
+	u16 obsolete5[2];                                                       /* words 51-52 */
+	u16 validity_bits;                                                      /* word  53 */
+	u16 obsolete6[5];                                                       /*
+										 * words 54-58 Used to be:
+										 * current cylinders,
+										 * current heads,
+										 * current sectors/Track,
+										 * current capacity */
+	u16 current_max_sectors_per_multiple;                                   /* word  59 */
+	u8 total_num_sectors[4];                                                /* words 60-61 */
+	u16 obsolete7;                                                          /* word  62 */
+	u16 multi_word_dma_mode;                                                /* word  63 */
+	u16 pio_modes_supported;                                                /* word  64 */
+	u16 min_multiword_dma_transfer_cycle;                                   /* word  65 */
+	u16 rec_min_multiword_dma_transfer_cycle;                               /* word  66 */
+	u16 min_pio_transfer_no_flow_ctrl;                                      /* word  67 */
+	u16 min_pio_transfer_with_flow_ctrl;                                    /* word  68 */
+	u16 reserved1[2];                                                       /* words 69-70 */
+	u16 reserved2[4];                                                       /* words 71-74 */
+	u16 queue_depth;                                                        /* word  75 */
+	u16 serial_ata_capabilities;                                            /* word  76 */
+	u16 serial_ata_reserved;                                                /* word  77 */
+	u16 serial_ata_features_supported;                                      /* word  78 */
+	u16 serial_ata_features_enabled;                                        /* word  79 */
+	u16 major_version_number;                                               /* word  80 */
+	u16 minor_version_number;                                               /* word  81 */
+	u16 command_set_supported0;                                             /* word  82 */
+	u16 command_set_supported1;                                             /* word  83 */
+	u16 command_set_supported_extention;                                    /* word  84 */
+	u16 command_set_enabled0;                                               /* word  85 */
+	u16 command_set_enabled1;                                               /* word  86 */
+	u16 command_set_default;                                                /* word  87 */
+	u16 ultra_dma_mode;                                                     /* word  88 */
+	u16 security_erase_completion_time;                                     /* word  89 */
+	u16 enhanced_security_erase_time;                                       /* word  90 */
+	u16 current_power_mgmt_value;                                           /* word  91 */
+	u16 master_password_revision;                                           /* word  92 */
+	u16 hardware_reset_result;                                              /* word  93 */
+	u16 current_acoustic_management_value;                                  /* word  94 */
+	u16 stream_min_request_size;                                            /* word  95 */
+	u16 stream_transfer_time;                                               /* word  96 */
+	u16 stream_access_latency;                                              /* word  97 */
+	u16 stream_performance_granularity[2];                                  /* words 98-99 */
+	u8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN];                              /* words 100-103 */
+	u16 streaming_transfer_time;                                            /* word  104 */
+	u16 reserved3;                                                          /* word  105 */
+	u16 physical_logical_sector_info;                                       /* word  106 */
+	u16 acoustic_test_interseek_delay;                                      /* word  107 */
+	u8 world_wide_name[ATA_IDENTIFY_WWN_LEN];                               /* words 108-111 */
+	u8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN];                    /* words 112-115 */
+	u16 reserved4;                                                          /* word  116 */
+	u8 words_per_logical_sector[4];                                         /* words 117-118 */
+	u16 command_set_supported2;                                             /* word  119 */
+	u16 reserved5[7];                                                       /* words 120-126 */
+	u16 removable_media_status;                                             /* word  127 */
+	u16 security_status;                                                    /* word  128 */
+	u16 vendor_specific1[31];                                               /* words 129-159 */
+	u16 cfa_power_mode1;                                                    /* word  160 */
+	u16 reserved_for_compact_flash2[7];                                     /* words 161-167 */
+	u16 device_nominal_form_factor;                                         /* word 168 */
+	u16 reserved_for_compact_flash3[7];                                     /* words 169-175 */
+	u16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN];  /* words 176-205 */
+	u16 reserved6[3];                                                       /* words 206-208 */
+	u16 logical_sector_alignment;                                           /* words 209 */
+	u16 reserved7[7];                                                       /* words 210-216 */
+	u16 nominal_media_rotation_rate;                                        /* word 217 */
+	u16 reserved8[37];                                                      /* words 218-254 */
+	u16 integrity_word;                                                     /* word  255 */
+
+};
+
+#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \
+	((unsigned long)&(((struct ata_identify_device_data *)0)->field_name))
+#define ATA_IDENTIFY_DEVICE_WCE_ENABLE  0x20
+#define ATA_IDENTIFY_DEVICE_RA_ENABLE   0x40
+
+/**
+ * struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the
+ *    ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure.
+ *
+ *
+ */
+struct atapi_identify_packet_device {
+	u16 generalConfigBits;                                  /* word  00 */
+	u16 reserved0;                                          /* word  01 (num cylinders) */
+	u16 uniqueConfigBits;                                   /* word  02 */
+	u16 reserved1[7];                                       /* words 03 - 09 */
+	u8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN];        /* word 10-19 */
+	u16 reserved2[3];                                       /* words 20-22 */
+	u8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN];      /* words 23-26 */
+	u8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN];          /* words 27-46 */
+	u16 reserved4[2];                                       /* words 47-48 */
+	u16 capabilities1;                                      /* word  49 */
+	u16 capabilities2;                                      /* word  50 */
+	u16 obsolete0[2];                                       /* words 51-52 */
+	u16 validityBits;                                       /* word  53 */
+	u16 reserved[8];                                        /* words 54-61 */
+
+	u16 DMADIRBitRequired;                                  /* word  62, page2 */
+	u16 multiWordDmaMode;                                   /* word  63 */
+	u16 pioModesSupported;                                  /* word  64 */
+	u16 minMultiwordDmaTransferCycle;                       /* word  65 */
+	u16 recMinMultiwordDmaTransferCycle;                    /* word  66 */
+	u16 minPioTransferNoFlowCtrl;                           /* word  67 */
+	u16 minPioTransferWithFlowCtrl;                         /* word  68 */
+	u16 reserved6[2];                                       /* words 69-70 */
+	u16 nsFromPACKETReceiptToBusRelease;                    /* word  71 */
+	u16 nsFromSERVICEReceiptToBSYreset;                     /* wore  72 */
+	u16 reserved7[2];                                       /* words 73-74 */
+	u16 queueDepth;                                         /* word  75 */
+	u16 serialAtaCapabilities;                              /* word  76 */
+	u16 serialAtaReserved;                                  /* word  77 */
+	u16 serialAtaFeaturesSupported;                         /* word  78 */
+	u16 serialAtaFeaturesEnabled;                           /* word  79 */
+
+	u16 majorVersionNumber;                                 /* word  80, page3 */
+	u16 minorVersionNumber;                                 /* word  81 */
+	u16 commandSetSupported0;                               /* word  82 */
+	u16 commandSetSupported1;                               /* word  83 */
+
+	u16 commandSetSupportedExtention;                       /* word  84, page4 */
+	u16 commandSetEnabled0;                                 /* word  85 */
+	u16 commandSetEnabled1;                                 /* word  86 */
+	u16 commandSetDefault;                                  /* word  87 */
+
+	u16 ultraDmaMode;                                       /* word  88, page5 */
+	u16 reserved8[4];                                       /* words 89 - 92 */
+
+	u16 hardwareResetResult;                                /* word  93, page6 */
+	u16 currentAcousticManagementValue;                     /* word  94 */
+	u16 reserved9[30];                                      /* words 95-124 */
+	u16 ATAPIByteCount0Behavior;                            /* word  125 */
+	u16 obsolete1;                                          /* word  126 */
+	u16 removableMediaStatus;                               /* word  127, */
+
+	u16 securityStatus;                                     /* word  128, page7 */
+	u16 vendorSpecific1[31];                                /* words 129-159 */
+	u16 reservedForCompactFlash[16];                        /* words 160-175 */
+	u16 reserved10[79];                                     /* words 176-254 */
+	u16 integrityWord;                                      /* word  255 */
+};
+
+/**
+ * struct ata_extended_smart_self_test_log - The following structure depicts
+ *    the ATA-8 version of the Extended SMART self test log page descriptor
+ *    entry.
+ *
+ *
+ */
+union ata_descriptor_entry {
+	struct DESCRIPTOR_ENTRY {
+		u8 lba_field;
+		u8 status_byte;
+		u8 time_stamp_low;
+		u8 time_stamp_high;
+		u8 checkpoint_byte;
+		u8 failing_lba_low;
+		u8 failing_lba_mid;
+		u8 failing_lba_high;
+		u8 failing_lba_low_ext;
+		u8 failing_lba_mid_ext;
+		u8 failing_lba_high_ext;
+
+		u8 vendor_specific1;
+		u8 vendor_specific2;
+		u8 vendor_specific3;
+		u8 vendor_specific4;
+		u8 vendor_specific5;
+		u8 vendor_specific6;
+		u8 vendor_specific7;
+		u8 vendor_specific8;
+		u8 vendor_specific9;
+		u8 vendor_specific10;
+		u8 vendor_specific11;
+		u8 vendor_specific12;
+		u8 vendor_specific13;
+		u8 vendor_specific14;
+		u8 vendor_specific15;
+	} DESCRIPTOR_ENTRY;
+
+	u8 descriptor_entry[26];
+
+};
+
+/**
+ * struct ata_extended_smart_self_test_log - The following structure depicts
+ *    the ATA-8 version of the SMART self test log page descriptor entry.
+ *
+ *
+ */
+union ata_smart_descriptor_entry {
+	struct SMART_DESCRIPTOR_ENTRY {
+		u8 lba_field;
+		u8 status_byte;
+		u8 time_stamp_low;
+		u8 time_stamp_high;
+		u8 checkpoint_byte;
+		u8 failing_lba_low;
+		u8 failing_lba_mid;
+		u8 failing_lba_high;
+		u8 failing_lba_low_ext;
+
+		u8 vendor_specific1;
+		u8 vendor_specific2;
+		u8 vendor_specific3;
+		u8 vendor_specific4;
+		u8 vendor_specific5;
+		u8 vendor_specific6;
+		u8 vendor_specific7;
+		u8 vendor_specific8;
+		u8 vendor_specific9;
+		u8 vendor_specific10;
+		u8 vendor_specific11;
+		u8 vendor_specific12;
+		u8 vendor_specific13;
+		u8 vendor_specific14;
+		u8 vendor_specific15;
+	} SMART_DESCRIPTOR_ENTRY;
+
+	u8 smart_descriptor_entry[24];
+
+};
+
+/**
+ * struct ata_extended_smart_self_test_log - The following structure depicts
+ *    the ATA-8 version of the Extended SMART self test log page.
+ *
+ *
+ */
+struct ata_extended_smart_self_test_log {
+	u8 self_test_log_data_structure_revision_number;        /* byte 0 */
+	u8 reserved0;                                           /* byte 1 */
+	u8 self_test_descriptor_index[2];                       /* byte 2-3 */
+
+	union ata_descriptor_entry descriptor_entrys[19];           /* bytes 4-497 */
+
+	u8 vendor_specific[2];                                  /* byte 498-499 */
+	u8 reserved1[11];                                       /* byte 500-510 */
+	u8 data_structure_checksum;                             /* byte 511 */
+
+};
+
+/**
+ * struct ata_extended_smart_self_test_log - The following structure depicts
+ *    the ATA-8 version of the SMART self test log page.
+ *
+ *
+ */
+struct ata_smart_self_test_log {
+	u8 self_test_log_data_structure_revision_number[2];     /* bytes 0-1 */
+
+	union ata_smart_descriptor_entry descriptor_entrys[21];     /* bytes 2-505 */
+
+	u8 vendor_specific[2];                                  /* byte 506-507 */
+	u8 self_test_index;                                     /* byte 508 */
+	u8 reserved1[2];                                        /* byte 509-510 */
+	u8 data_structure_checksum;                             /* byte 511 */
+
+};
+
+#endif /* _ATA_H_ */
+
diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h
new file mode 100644
index 0000000..eb9686e
--- /dev/null
+++ b/drivers/scsi/isci/core/intel_sas.h
@@ -0,0 +1,948 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _INTEL_SAS_H_
+#define _INTEL_SAS_H_
+
+/**
+ * This file contains all of the definitions relating to structures, constants,
+ *    etc. defined by the SAS specification.
+ *
+ *
+ */
+
+#include "intel_sata.h"
+#include "intel_scsi.h"
+
+/**
+ * struct sci_sas_address - This structure depicts how a SAS address is
+ *    represented by SCI.
+ *
+ *
+ */
+struct sci_sas_address {
+	/**
+	 * This member contains the higher 32-bits of the SAS address.
+	 */
+	u32 high;
+
+	/**
+	 * This member contains the lower 32-bits of the SAS address.
+	 */
+	u32 low;
+
+};
+
+/**
+ * struct sci_sas_identify_address_frame_protocols - This structure depicts the
+ *    contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF).
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification Link layer section on address frames.
+ */
+struct sci_sas_identify_address_frame_protocols {
+	union {
+		struct {
+			u16 restricted1:1;
+			u16 smp_initiator:1;
+			u16 stp_initiator:1;
+			u16 ssp_initiator:1;
+			u16 reserved3:4;
+			u16 restricted2:1;
+			u16 smp_target:1;
+			u16 stp_target:1;
+			u16 ssp_target:1;
+			u16 reserved4:4;
+		} bits;
+
+		u16 all;
+	} u;
+
+};
+
+/**
+ * struct sci_sas_identify_address_frame - This structure depicts the contents
+ *    of the SAS IDENTIFY ADDRESS FRAME (IAF).
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification Link layer section on address frames.
+ */
+struct sci_sas_identify_address_frame {
+	u16 address_frame_type:4;
+	u16 device_type:3;
+	u16 reserved1:1;
+	u16 reason:4;
+	u16 reserved2:4;
+
+	struct sci_sas_identify_address_frame_protocols protocols;
+
+	struct sci_sas_address device_name;
+	struct sci_sas_address sas_address;
+
+	u32 phy_identifier:8;
+	u32 break_reply_capable:1;
+	u32 requested_in_zpsds:1;
+	u32 in_zpsds_persistent:1;
+	u32 reserved5:21;
+
+	u32 reserved6[4];
+
+};
+
+/**
+ * struct sas_capabilities - This structure depicts the various SAS
+ *    capabilities supported by the directly attached target device.  For
+ *    specific information on each of these individual fields please reference
+ *    the SAS specification Phy layer section on speed negotiation windows.
+ *
+ *
+ */
+struct sas_capabilities {
+	union {
+#if defined (SCIC_SDS_4_ENABLED)
+		struct {
+			/**
+			 * The SAS specification indicates the start bit shall always be set to
+			 * 1.  This implementation will have the start bit set to 0 if the
+			 * PHY CAPABILITIES were either not received or speed negotiation failed.
+			 */
+			u32 start:1;
+			u32 tx_ssc_type:1;
+			u32 reserved1:2;
+			u32 requested_logical_link_rate:4;
+
+			u32 gen1_without_ssc_supported:1;
+			u32 gen1_with_ssc_supported:1;
+			u32 gen2_without_ssc_supported:1;
+			u32 gen2_with_ssc_supported:1;
+			u32 gen3_without_ssc_supported:1;
+			u32 gen3_with_ssc_supported:1;
+			u32 reserved2:17;
+			u32 parity:1;
+		} bits;
+#endif          /* (SCIC_SDS_4_ENABLED) */
+
+		u32 all;
+	} u;
+
+};
+
+/**
+ * enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification
+ *    defined link speeds.
+ *
+ *
+ */
+enum sci_sas_link_rate {
+	SCI_SAS_NO_LINK_RATE = 0,
+	SCI_SATA_SPINUP_HOLD = 0x3,
+	SCI_SAS_150_GB = 0x8,
+	SCI_SAS_300_GB = 0x9,
+	SCI_SAS_600_GB = 0xA
+};
+
+/**
+ * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS
+ *    specification defined task attribute values for a command information
+ *    unit.
+ *
+ *
+ */
+enum sci_sas_task_attribute {
+	SCI_SAS_SIMPLE_ATTRIBUTE = 0,
+	SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1,
+	SCI_SAS_ORDERED_ATTRIBUTE = 2,
+	SCI_SAS_ACA_ATTRIBUTE = 4,
+};
+
+/**
+ * enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS
+ *    specification defined task management functions.
+ *
+ * This HARD_RESET function listed here is not actually defined as a task
+ * management function in the industry standard.
+ */
+enum sci_sas_task_mgmt_function {
+	SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK,
+	SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET,
+	SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET,
+	SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET,
+	SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET,
+	SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA,
+	SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK,
+	SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET,
+	SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION,
+	SCI_SAS_HARD_RESET = 0xFF
+};
+
+
+/**
+ * enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification
+ *    defined SSP frame types.
+ *
+ *
+ */
+enum sci_sas_frame_type {
+	SCI_SAS_DATA_FRAME = 0x01,
+	SCI_SAS_XFER_RDY_FRAME = 0x05,
+	SCI_SAS_COMMAND_FRAME = 0x06,
+	SCI_SAS_RESPONSE_FRAME = 0x07,
+	SCI_SAS_TASK_FRAME = 0x16
+};
+
+/**
+ * struct sci_ssp_command_iu - This structure depicts the contents of the SSP
+ *    COMMAND INFORMATION UNIT. For specific information on each of these
+ *    individual fields please reference the SAS specification SSP transport
+ *    layer section.
+ *
+ *
+ */
+struct sci_ssp_command_iu {
+	u32 lun_upper;
+	u32 lun_lower;
+
+	u32 additional_cdb_length:6;
+	u32 reserved0:2;
+	u32 reserved1:8;
+	u32 enable_first_burst:1;
+	u32 task_priority:4;
+	u32 task_attribute:3;
+	u32 reserved2:8;
+
+	u32 cdb[4];
+
+};
+
+/**
+ * struct sci_ssp_task_iu - This structure depicts the contents of the SSP TASK
+ *    INFORMATION UNIT. For specific information on each of these individual
+ *    fields please reference the SAS specification SSP transport layer section.
+ *
+ *
+ */
+struct sci_ssp_task_iu {
+	u32 lun_upper;
+	u32 lun_lower;
+
+	u32 reserved0:8;
+	u32 task_function:8;
+	u32 reserved1:8;
+	u32 reserved2:8;
+
+	u32 reserved3:16;
+	u32 task_tag:16;
+
+	u32 reserved4[3];
+
+};
+
+#define SSP_RESPONSE_IU_MAX_DATA 64
+
+#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK   (0x03)
+
+
+#define sci_ssp_get_sense_data_length(sense_data_length_buffer)	\
+	SCIC_BUILD_DWORD(sense_data_length_buffer)
+
+#define sci_ssp_get_response_data_length(response_data_length_buffer) \
+	SCIC_BUILD_DWORD(response_data_length_buffer)
+
+/**
+ * struct sci_ssp_response_iu - This structure depicts the contents of the SSP
+ *    RESPONSE INFORMATION UNIT. For specific information on each of these
+ *    individual fields please reference the SAS specification SSP transport
+ *    layer section.
+ *
+ *
+ */
+struct sci_ssp_response_iu {
+	u8 reserved0[8];
+
+	u8 retry_delay_timer[2];
+	u8 data_present;
+	u8 status;
+
+	u8 reserved1[4];
+	u8 sense_data_length[4];
+	u8 response_data_length[4];
+
+	u32 data[SSP_RESPONSE_IU_MAX_DATA];
+
+};
+
+/**
+ * enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS
+ *    specification defined SSP data present types in struct sci_ssp_response_iu.
+ *
+ *
+ */
+enum sci_ssp_response_iu_data_present_type {
+	SCI_SSP_RESPONSE_IU_NO_DATA = 0x00,
+	SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01,
+	SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02
+};
+
+/**
+ * struct sci_ssp_frame_header - This structure depicts the contents of an SSP
+ *    frame header.  For specific information on the individual fields please
+ *    reference the SAS specification transport layer SSP frame format.
+ *
+ *
+ */
+struct sci_ssp_frame_header {
+	/* Word 0 */
+	u32 hashed_destination_address:24;
+	u32 frame_type:8;
+
+	/* Word 1 */
+	u32 hashed_source_address:24;
+	u32 reserved1_0:8;
+
+	/* Word 2 */
+	u32 reserved2_2:6;
+	u32 fill_bytes:2;
+	u32 reserved2_1:3;
+	u32 tlr_control:2;
+	u32 retry_data_frames:1;
+	u32 retransmit:1;
+	u32 changing_data_pointer:1;
+	u32 reserved2_0:16;
+
+	/* Word 3 */
+	u32 uiResv4;
+
+	/* Word 4 */
+	u16 target_port_transfer_tag;
+	u16 tag;
+
+	/* Word 5 */
+	u32 data_offset;
+
+};
+
+/**
+ * struct smp_request_header - This structure defines the contents of an SMP
+ *    Request header.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification.
+ */
+struct smp_request_header {
+	u8 smp_frame_type;              /* byte 0 */
+	u8 function;                    /* byte 1 */
+	u8 allocated_response_length;   /* byte 2 */
+	u8 request_length;              /* byte 3 */
+};
+
+/**
+ * struct smp_response_header - This structure depicts the contents of the SAS
+ *    SMP DISCOVER RESPONSE frame.  For specific information on each of these
+ *    individual fields please reference the SAS specification Link layer
+ *    section on address frames.
+ *
+ *
+ */
+struct smp_response_header {
+	u8 smp_frame_type;      /* byte 0 */
+	u8 function;            /* byte 1 */
+	u8 function_result;     /* byte 2 */
+	u8 response_length;     /* byte 3 */
+};
+
+/**
+ * struct smp_request_general - This structure defines the contents of an SMP
+ *    Request that is comprised of the struct smp_request_header and a CRC.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification.
+ */
+struct smp_request_general {
+	u32 crc;      /* bytes 4-7 */
+
+};
+
+/**
+ * struct smp_request_phy_identifier - This structure defines the contents of
+ *    an SMP Request that is comprised of the struct smp_request_header and a phy
+ *    identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification.
+ */
+struct smp_request_phy_identifier {
+	u32 reserved_byte4_7;           /* bytes 4-7 */
+
+	u32 ignore_zone_group:1;      /* byte 8 */
+	u32 reserved_byte8:7;
+
+	u32 phy_identifier:8;         /* byte 9 */
+	u32 reserved_byte10:8;        /* byte 10 */
+	u32 reserved_byte11:8;        /* byte 11 */
+
+};
+
+/**
+ * struct smp_request_configure_route_information - This structure defines the
+ *    contents of an SMP Configure Route Information request.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification.
+ */
+struct smp_request_configure_route_information {
+	u32 expected_expander_change_count:16;        /* bytes 4-5 */
+	u32 expander_route_index_high:8;
+	u32 expander_route_index:8;                   /* bytes 6-7 */
+
+	u32 reserved_byte8:8;                         /* bytes 8 */
+	u32 phy_identifier:8;                         /* bytes 9 */
+	u32 reserved_byte_10_11:16;                   /* bytes 10-11 */
+
+	u32 reserved_byte_12_bit_0_6:7;
+	u32 disable_route_entry:1;    /* byte 12 */
+	u32 reserved_byte_13_15:24;   /* bytes 13-15 */
+
+	u32 routed_sas_address[2];      /* bytes 16-23 */
+	u8 reserved_byte_24_39[16];     /* bytes 24-39 */
+
+};
+
+/**
+ * struct smp_request_phy_control - This structure defines the contents of an
+ *    SMP Phy Controler request.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification.
+ */
+struct smp_request_phy_control {
+	u16 expected_expander_change_count;     /* byte 4-5 */
+
+	u16 reserved_byte_6_7;                  /* byte 6-7 */
+	u8 reserved_byte_8;                     /* byte 8 */
+
+	u8 phy_identifier;                      /* byte 9 */
+	u8 phy_operation;                       /* byte 10 */
+
+	u8 update_partial_pathway_timeout_value:1;
+	u8 reserved_byte_11_bit_1_7:7;        /* byte 11 */
+
+	u8 reserved_byte_12_23[12];             /* byte 12-23 */
+
+	u8 attached_device_name[8];             /* byte 24-31 */
+
+	u8 reserved_byte_32_bit_3_0:4;        /* byte 32 */
+	u8 programmed_minimum_physical_link_rate:4;
+
+	u8 reserved_byte_33_bit_3_0:4; /* byte 33 */
+	u8 programmed_maximum_physical_link_rate:4;
+
+	u16 reserved_byte_34_35; /* byte 34-35 */
+
+	u8 partial_pathway_timeout_value:4;
+	u8 reserved_byte_36_bit_4_7:4;        /* byte 36 */
+
+	u16 reserved_byte_37_38;                /* byte 37-38 */
+	u8 reserved_byte_39;                    /* byte 39 */
+
+};
+
+/**
+ * struct smp_request_vendor_specific - This structure depicts the vendor
+ *    specific space for SMP request.
+ *
+ *
+ */
+ #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016
+struct smp_request_vendor_specific {
+	u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+};
+
+/**
+ * struct smp_request - This structure simply unionizes the existing request
+ *    structures into a common request type.
+ *
+ *
+ */
+struct smp_request {
+	struct smp_request_header header;
+
+	union { /* bytes 4-N */
+		struct smp_request_general report_general;
+		struct smp_request_phy_identifier discover;
+		struct smp_request_general report_manufacturer_information;
+		struct smp_request_phy_identifier report_phy_sata;
+		struct smp_request_phy_control phy_control;
+		struct smp_request_phy_identifier report_phy_error_log;
+		struct smp_request_phy_identifier report_route_information;
+		struct smp_request_configure_route_information configure_route_information;
+		struct smp_request_vendor_specific vendor_specific_request;
+	} request;
+
+};
+
+
+/**
+ * struct smp_response_report_general - This structure depicts the SMP Report
+ *    General for expander devices.  It adheres to the SAS-2.1 specification.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification Application layer section on SMP.
+ */
+struct smp_response_report_general {
+	u16 expander_change_count;              /* byte 4-5 */
+	u16 expander_route_indexes;             /* byte 6-7 */
+
+	u32 reserved_byte8:7;                 /* byte 8 bit 0-6 */
+	u32 long_response:1;                  /* byte 8 bit 7 */
+
+	u32 number_of_phys:8;                 /* byte 9 */
+
+	u32 configurable_route_table:1;       /* byte 10 */
+	u32 configuring:1;
+	u32 configures_others:1;
+	u32 open_reject_retry_supported:1;
+	u32 stp_continue_awt:1;
+	u32 self_configuring:1;
+	u32 zone_configuring:1;
+	u32 table_to_table_supported:1;
+
+	u32 reserved_byte11:8;                /* byte 11 */
+
+	u32 enclosure_logical_identifier_high;  /* byte 12-15 */
+	u32 enclosure_logical_identifier_low;   /* byte 16-19 */
+
+	u32 reserved_byte20_23;
+	u32 reserved_byte24_27;
+
+};
+
+struct smp_response_report_general_long {
+	struct smp_response_report_general sas1_1;
+
+	struct {
+		u16 reserved1;
+		u16 stp_bus_inactivity_time_limit;
+		u16 stp_max_connect_time_limit;
+		u16 stp_smp_i_t_nexus_loss_time;
+
+		u32 zoning_enabled:1;
+		u32 zoning_supported:1;
+		u32 physicaL_presence_asserted:1;
+		u32 zone_locked:1;
+		u32 reserved2:1;
+		u32 num_zone_groups:3;
+		u32 saving_zoning_enabled_supported:3;
+		u32 saving_zone_perms_table_supported:1;
+		u32 saving_zone_phy_info_supported:1;
+		u32 saving_zone_manager_password_supported:1;
+		u32 saving:1;
+		u32 reserved3:1;
+		u32 max_number_routed_sas_addresses:16;
+
+		struct sci_sas_address active_zone_manager_sas_address;
+
+		u16 zone_lock_inactivity_time_limit;
+		u16 reserved4;
+
+		u8 reserved5;
+		u8 first_enclosure_connector_element_index;
+		u8 number_of_enclosure_connector_element_indices;
+		u8 reserved6;
+
+		u32 reserved7:7;
+		u32 reduced_functionality:1;
+		u32 time_to_reduce_functionality:8;
+		u32 initial_time_to_reduce_functionality:8;
+		u8 max_reduced_functionality_time;
+
+		u16 last_self_config_status_descriptor_index;
+		u16 max_number_of_stored_self_config_status_descriptors;
+
+		u16 last_phy_event_list_descriptor_index;
+		u16 max_number_of_stored_phy_event_list_descriptors;
+	} sas2;
+
+};
+
+/**
+ * struct smp_response_report_manufacturer_information - This structure depicts
+ *    the SMP report manufacturer information for expander devices.  It adheres
+ *    to the SAS-2.1 specification.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification Application layer section on SMP.
+ */
+struct smp_response_report_manufacturer_information {
+	u32 expander_change_count:16; /* bytes 4-5 */
+	u32 reserved1:16;
+
+	u32 sas1_1_format:1;
+	u32 reserved2:31;
+
+	u8 vendor_id[8];
+	u8 product_id[16];
+	u8 product_revision_level[4];
+	u8 component_vendor_id[8];
+	u8 component_id[2];
+	u8 component_revision_level;
+	u8 reserved3;
+	u8 vendor_specific[8];
+
+};
+
+#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52
+#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE   116
+
+/**
+ * struct smp_discover_response_protocols - This structure depicts the discover
+ *    response where the supported protocols by the remote phy are specified.
+ *
+ * For specific information on each of these individual fields please reference
+ * the SAS specification Link layer section on address frames.
+ */
+struct smp_discover_response_protocols {
+	union {
+		struct {
+			u16 attached_sata_host:1;
+			u16 attached_smp_initiator:1;
+			u16 attached_stp_initiator:1;
+			u16 attached_ssp_initiator:1;
+			u16 reserved3:4;
+			u16 attached_sata_device:1;
+			u16 attached_smp_target:1;
+			u16 attached_stp_target:1;
+			u16 attached_ssp_target:1;
+			u16 reserved4:3;
+			u16 attached_sata_port_selector:1;
+		} bits;
+
+		u16 all;
+	} u;
+
+};
+
+/**
+ * struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy
+ *    discover response format. It handles both SAS1.1 and SAS 2 definitions.
+ *    The unions indicate locations where the SAS specification versions differ
+ *    from one another.
+ *
+ *
+ */
+struct smp_response_discover {
+
+	union {
+		struct {
+			u8 reserved[2];
+		} sas1_1;
+
+		struct {
+			u16 expander_change_count;
+		} sas2;
+
+	} u1;
+
+	u8 reserved1[3];
+	u8 phy_identifier;
+	u8 reserved2[2];
+
+	union {
+		struct {
+			u16 reserved1:4;
+			u16 attached_device_type:3;
+			u16 reserved2:1;
+			u16 negotiated_physical_link_rate:4;
+			u16 reserved3:4;
+		} sas1_1;
+
+		struct {
+			u16 attached_reason:4;
+			u16 attached_device_type:3;
+			u16 reserved2:1;
+			u16 negotiated_logical_link_rate:4;
+			u16 reserved3:4;
+		} sas2;
+
+	} u2;
+
+	struct smp_discover_response_protocols protocols;
+	struct sci_sas_address sas_address;
+	struct sci_sas_address attached_sas_address;
+
+	u8 attached_phy_identifier;
+
+	union {
+		struct {
+			u8 reserved;
+		} sas1_1;
+
+		struct {
+			u8 attached_break_reply_capable:1;
+			u8 attached_requested_inside_zpsds:1;
+			u8 attached_inside_zpsds_persistent:1;
+			u8 reserved1:5;
+		} sas2;
+
+	} u3;
+
+	u8 reserved_for_identify[6];
+
+	u32 hardware_min_physical_link_rate:4;
+	u32 programmed_min_physical_link_rate:4;
+	u32 hardware_max_physical_link_rate:4;
+	u32 programmed_max_physical_link_rate:4;
+	u32 phy_change_count:8;
+	u32 partial_pathway_timeout_value:4;
+	u32 reserved5:3;
+	u32 virtual_phy:1;
+
+	u32 routing_attribute:4;
+	u32 reserved6:4;
+	u32 connector_type:7;
+	u32 reserved7:1;
+	u32 connector_element_index:8;
+	u32 connector_physical_link:8;
+
+	u16 reserved8;
+	u16 vendor_specific;
+
+	union {
+		struct {
+			/**
+			 * In the SAS 1.1 specification this structure ends after 52 bytes.
+			 * As a result, the contents of this field should never have a
+			 * real value.  It is undefined.
+			 */
+			u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE
+				     - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE];
+		} sas1_1;
+
+		struct {
+			struct sci_sas_address attached_device_name;
+
+			u32 zoning_enabled:1;
+			u32 inside_zpsds:1;
+			u32 zone_group_persistent:1;
+			u32 reserved1:1;
+			u32 requested_inside_zpsds:1;
+			u32 inside_zpsds_persistent:1;
+			u32 requested_inside_zpsds_changed_by_expander:1;
+			u32 reserved2:1;
+			u32 reserved_for_zoning_fields:16;
+			u32 zone_group:8;
+
+			u8 self_configuration_status;
+			u8 self_configuration_levels_completed;
+			u16 reserved_for_self_config_fields;
+
+			struct sci_sas_address self_configuration_sas_address;
+
+			u32 programmed_phy_capabilities;
+			u32 current_phy_capabilities;
+			u32 attached_phy_capabilities;
+
+			u32 reserved3;
+
+			u32 reserved4:16;
+			u32 negotiated_physical_link_rate:4;
+			u32 reason:4;
+			u32 hardware_muxing_supported:1;
+			u32 negotiated_ssc:1;
+			u32 reserved5:6;
+
+			u32 default_zoning_enabled:1;
+			u32 reserved6:1;
+			u32 default_zone_group_persistent:1;
+			u32 reserved7:1;
+			u32 default_requested_inside_zpsds:1;
+			u32 default_inside_zpsds_persistent:1;
+			u32 reserved8:2;
+			u32 reserved9:16;
+			u32 default_zone_group:8;
+
+			u32 saved_zoning_enabled:1;
+			u32 reserved10:1;
+			u32 saved_zone_group_persistent:1;
+			u32 reserved11:1;
+			u32 saved_requested_inside_zpsds:1;
+			u32 saved_inside_zpsds_persistent:1;
+			u32 reserved12:18;
+			u32 saved_zone_group:8;
+
+			u32 reserved14:2;
+			u32 shadow_zone_group_persistent:1;
+			u32 reserved15:1;
+			u32 shadow_requested_inside_zpsds:1;
+			u32 shadow_inside_zpsds_persistent:1;
+			u32 reserved16:18;
+			u32 shadow_zone_group:8;
+
+			u8 device_slot_number;
+			u8 device_slot_group_number;
+			u8 device_slot_group_output_connector[6];
+		} sas2;
+
+	} u4;
+
+};
+
+/**
+ * struct smp_response_report_phy_sata - This structure depicts the contents of
+ *    the SAS SMP REPORT PHY SATA frame.  For specific information on each of
+ *    these individual fields please reference the SAS specification Link layer
+ *    section on address frames.
+ *
+ *
+ */
+struct smp_response_report_phy_sata {
+	u32 ignored_byte_4_7; /* bytes 4-7 */
+
+	u32 affiliations_valid:1;
+	u32 affiliations_supported:1;
+	u32 reserved_byte11:6;        /* byte 11 */
+	u32 ignored_byte10:8;         /* byte 10 */
+	u32 phy_identifier:8;         /* byte  9 */
+	u32 reserved_byte_8:8;        /* byte  8 */
+
+	u32 reserved_12_15;
+	u32 stp_sas_address[2];
+	u8 device_to_host_fis[20];
+	u32 reserved_44_47;
+	u32 affiliated_stp_initiator_sas_address[2];
+
+};
+
+struct smp_response_vendor_specific {
+	u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+};
+
+union smp_response_body {
+	struct smp_response_report_general report_general;
+	struct smp_response_report_manufacturer_information report_manufacturer_information;
+	struct smp_response_discover discover;
+	struct smp_response_report_phy_sata report_phy_sata;
+	struct smp_response_vendor_specific vendor_specific_response;
+};
+
+/**
+ * struct smp_response - This structure simply unionizes the existing response
+ *    structures into a common response type.
+ *
+ *
+ */
+struct smp_response {
+	struct smp_response_header header;
+
+	union smp_response_body response;
+
+};
+
+/* SMP Request Functions */
+#define SMP_FUNCTION_REPORT_GENERAL                   0x00
+#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION  0x01
+#define SMP_FUNCTION_DISCOVER                         0x10
+#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG             0x11
+#define SMP_FUNCTION_REPORT_PHY_SATA                  0x12
+#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION         0X13
+#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION      0X90
+#define SMP_FUNCTION_PHY_CONTROL                      0x91
+#define SMP_FUNCTION_PHY_TEST                         0x92
+
+#define SMP_FRAME_TYPE_REQUEST          0x40
+#define SMP_FRAME_TYPE_RESPONSE         0x41
+
+#define PHY_OPERATION_NOP               0x00
+#define PHY_OPERATION_LINK_RESET        0x01
+#define PHY_OPERATION_HARD_RESET        0x02
+#define PHY_OPERATION_DISABLE           0x03
+#define PHY_OPERATION_CLEAR_ERROR_LOG   0x05
+#define PHY_OPERATION_CLEAR_AFFILIATION 0x06
+
+#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00
+#define NPLR_PHY_DISABLED     0x01
+#define NPLR_PHY_ENABLED_SPD_NEG_FAILED   0x02
+#define NPLR_PHY_ENABLED_SATA_HOLD  0x03
+#define NPLR_PHY_ENABLED_1_5G    0x08
+#define NPLR_PHY_ENABLED_3_0G    0x09
+
+/* SMP Function Result values. */
+#define SMP_RESULT_FUNCTION_ACCEPTED              0x00
+#define SMP_RESULT_UNKNOWN_FUNCTION               0x01
+#define SMP_RESULT_FUNCTION_FAILED                0x02
+#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN      0x03
+#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04
+#define SMP_RESULT_BUSY                           0x05
+#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST     0x06
+#define SMP_RESULT_PHY_DOES_NOT_EXIST             0x10
+#define SMP_RESULT_INDEX_DOES_NOT_EXIST           0x11
+#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA      0x12
+#define SMP_RESULT_UNKNOWN_PHY_OPERATION          0x13
+#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION      0x14
+#define SMP_RESULT_PHY_TEST_IN_PROGRESS           0x15
+#define SMP_RESULT_PHY_VACANT                     0x16
+
+/* Attached Device Types */
+#define SMP_NO_DEVICE_ATTACHED      0
+#define SMP_END_DEVICE_ONLY         1
+#define SMP_EDGE_EXPANDER_DEVICE    2
+#define SMP_FANOUT_EXPANDER_DEVICE  3
+
+/* Expander phy routine attribute */
+#define DIRECT_ROUTING_ATTRIBUTE        0
+#define SUBTRACTIVE_ROUTING_ATTRIBUTE   1
+#define TABLE_ROUTING_ATTRIBUTE         2
+
+#endif /* _INTEL_SAS_H_ */
+
diff --git a/drivers/scsi/isci/core/intel_sat.h b/drivers/scsi/isci/core/intel_sat.h
new file mode 100644
index 0000000..c4d78ed
--- /dev/null
+++ b/drivers/scsi/isci/core/intel_sat.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SAT_H_
+#define _SAT_H_
+
+/**
+ * This file contains constants and constructs defined in the SCSI to ATA
+ *    Translation (SAT) T10 standard.  For more information please refer to
+ *    www.t10.org.
+ *
+ *
+ */
+
+/**
+ *
+ *
+ * SAT_PROTOCOLS These constants indicate the various protocol values that can
+ * be supported in a SAT translator.
+ */
+#define SAT_PROTOCOL_ATA_HARD_RESET       0
+#define SAT_PROTOCOL_SOFT_RESET           1
+#define SAT_PROTOCOL_NON_DATA             3
+#define SAT_PROTOCOL_PIO_DATA_IN          4
+#define SAT_PROTOCOL_PIO_DATA_OUT         5
+#define SAT_PROTOCOL_DMA                  6
+#define SAT_PROTOCOL_DMA_QUEUED           7
+#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC    8
+#define SAT_PROTOCOL_DEVICE_RESET         9
+#define SAT_PROTOCOL_UDMA_DATA_IN         10
+#define SAT_PROTOCOL_UDMA_DATA_OUT        11
+#define SAT_PROTOCOL_FPDMA                12
+#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15
+
+#define SAT_PROTOCOL_PACKET               0x10
+#define SAT_PROTOCOL_PACKET_NON_DATA      (SAT_PROTOCOL_PACKET | 0x0)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_IN   (SAT_PROTOCOL_PACKET | 0x1)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT  (SAT_PROTOCOL_PACKET | 0x2)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_IN   (SAT_PROTOCOL_PACKET | 0x3)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT  (SAT_PROTOCOL_PACKET | 0x4)
+
+#endif /* _SAT_H_ */
+
diff --git a/drivers/scsi/isci/core/intel_sata.h b/drivers/scsi/isci/core/intel_sata.h
new file mode 100644
index 0000000..47390d5
--- /dev/null
+++ b/drivers/scsi/isci/core/intel_sata.h
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SATA_H_
+#define _SATA_H_
+
+#include <linux/types.h>
+
+/**
+ * This file defines all of the SATA releated constants, enumerations, and
+ *    types. Please note that this file does not necessarily contain an
+ *    exhaustive list of all contants and commands.
+ *
+ *
+ */
+
+/**
+ *
+ *
+ * SATA FIS Types These constants depict the various SATA FIS types devined in
+ * the serial ATA specification.
+ */
+#define SATA_FIS_TYPE_REGH2D          0x27
+#define SATA_FIS_TYPE_REGD2H          0x34
+#define SATA_FIS_TYPE_SETDEVBITS      0xA1
+#define SATA_FIS_TYPE_DMA_ACTIVATE    0x39
+#define SATA_FIS_TYPE_DMA_SETUP       0x41
+#define SATA_FIS_TYPE_BIST_ACTIVATE   0x58
+#define SATA_FIS_TYPE_PIO_SETUP       0x5F
+#define SATA_FIS_TYPE_DATA            0x46
+
+#define SATA_REGISTER_FIS_SIZE 0x20
+
+/**
+ * struct sata_fis_header - This is the common definition for a SATA FIS Header
+ *    word.  A different header word is defined for any FIS type that does not
+ *    use the standard header.
+ *
+ *
+ */
+struct sata_fis_header {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved:1;
+	u32 direction_flag:1;       /* direction */
+	u32 interrupt_flag:1;
+	u32 command_flag:1;       /* command, auto_activate, or notification */
+	u32 status:8;
+	u32 error:8;
+};
+
+
+/**
+ * struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device
+ *    Register FIS.
+ *
+ *
+ */
+struct sata_fis_reg_h2d {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved0:3;
+	u32 command_flag:1;
+	u32 command:8;
+	u32 features:8;
+	u32 lba_low:8; /* word 1 */
+	u32 lba_mid:8;
+	u32 lba_high:8;
+	u32 device:8;
+	u32 lba_low_exp:8; /* word 2 */
+	u32 lba_mid_exp:8;
+	u32 lba_high_exp:8;
+	u32 features_exp:8;
+	u32 sector_count:8; /* word 3 */
+	u32 sector_count_exp:8;
+	u32 reserved1:8;
+	u32 control:8;
+	u32 reserved2;          /* word 4 */
+};
+
+/**
+ * struct sata_fis_reg_d2h - SATA Device To Host FIS
+ *
+ *
+ */
+struct sata_fis_reg_d2h {
+	u32 fis_type:8;   /* word 0 */
+	u32 pm_port:4;
+	u32 reserved0:2;
+	u32 irq:1;
+	u32 reserved1:1;
+	u32 status:8;
+	u32 error:8;
+	u8 lba_low;          /* word 1 */
+	u8 lba_mid;
+	u8 lba_high;
+	u8 device;
+	u8 lba_low_exp;      /* word 2 */
+	u8 lba_mid_exp;
+	u8 lba_high_exp;
+	u8 reserved;
+	u8 sector_count;     /* word 3 */
+	u8 sector_count_exp;
+	u16 reserved2;
+	u32 reserved3;
+};
+
+/**
+ *
+ *
+ * Status field bit definitions
+ */
+#define SATA_FIS_STATUS_DEVBITS_MASK  (0x77)
+
+/**
+ * struct sata_fis_set_dev_bits - SATA Set Device Bits FIS
+ *
+ *
+ */
+struct sata_fis_set_dev_bits {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved0:2;
+	u32 irq:1;
+	u32 notification:1;
+	u32 status_low:4;
+	u32 status_high:4;
+	u32 error:8;
+	u32 s_active;      /* word 1 */
+};
+
+/**
+ * struct sata_fis_dma_activate - SATA DMA Activate FIS
+ *
+ *
+ */
+struct sata_fis_dma_activate {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved0:24;
+};
+
+/**
+ *
+ *
+ * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup are used to
+ * communicate the command tag.
+ */
+#define SATA_DMA_SETUP_TAG_ENABLE      0x1F
+
+#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80
+
+/**
+ * struct sata_fis_dma_setup - SATA DMA Setup FIS
+ *
+ *
+ */
+struct sata_fis_dma_setup {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved_00:1;
+	u32 direction:1;
+	u32 irq:1;
+	u32 auto_activate:1;
+	u32 reserved_01:16;
+	u32 dma_buffer_id_low;          /* word 1 */
+	u32 dma_buffer_id_high;         /* word 2 */
+	u32 reserved0;                  /* word 3 */
+	u32 dma_buffer_offset;          /* word 4 */
+	u32 dma_transfer_count;         /* word 5 */
+	u32 reserved1;                  /* word 6 */
+};
+
+/**
+ * struct sata_fis_bist_activate - SATA BIST Activate FIS
+ *
+ *
+ */
+struct sata_fis_bist_activate {
+	u32 fis_type:8; /* word 0 */
+	u32 reserved0:8;
+	u32 pattern_definition:8;
+	u32 reserved1:8;
+	u32 data1;                      /* word 1 */
+	u32 data2;                      /* word 1 */
+};
+
+/*
+ *  SATA PIO Setup FIS
+ */
+struct sata_fis_pio_setup {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved_00:1;
+	u32 direction:1;
+	u32 irq:1;
+	u32 reserved_01:1;
+	u32 status:8;
+	u32 error:8;
+	u32 lba_low:8; /* word 1 */
+	u32 lba_mid:8;
+	u32 lba_high:8;
+	u32 device:8;
+	u32 lba_low_exp:8; /* word 2 */
+	u32 lba_mid_exp:8;
+	u32 lba_high_exp:8;
+	u32 reserved:8;
+	u32 sector_count:8; /* word 3 */
+	u32 sector_count_exp:8;
+	u32 reserved1:8;
+	u32 ending_status:8;
+	u32 transfter_count:16; /* word 4 */
+	u32 reserved3:16;
+};
+
+/**
+ * struct sata_fis_data - SATA Data FIS
+ *
+ *
+ */
+struct sata_fis_data {
+	u32 fis_type:8; /* word 0 */
+	u32 pm_port:4;
+	u32 reserved0:24;
+	u8 data[4];        /* word 1 */
+};
+
+#endif /* _SATA_H_ */
diff --git a/drivers/scsi/isci/core/intel_scsi.h b/drivers/scsi/isci/core/intel_scsi.h
new file mode 100644
index 0000000..1e45d3c
--- /dev/null
+++ b/drivers/scsi/isci/core/intel_scsi.h
@@ -0,0 +1,474 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file defines all of the SCSI related constants, enumerations, and
+ *    types.  Please note that this file does not necessarily contain an
+ *    exhaustive list of all constants, commands, sub-commands, etc.
+ *
+ *
+ */
+
+#ifndef _SCSI_H__
+#define _SCSI_H__
+
+
+/*
+ * ******************************************************************************
+ * * C O N S T A N T S   A N D   M A C R O S
+ * ****************************************************************************** */
+
+/**
+ * enum _SCSI_TASK_MGMT_REQUEST_CODES - This enumberation contains the
+ *    constants to be used for SCSI task management request codes.  SAM does
+ *    not specify any particular values for these codes so constants used here
+ *    are the same as those specified in SAS.
+ *
+ *
+ */
+enum scsi_task_mgmt_request_codes {
+	SCSI_TASK_REQUEST_ABORT_TASK           = 0x01,
+	SCSI_TASK_REQUEST_ABORT_TASK_SET       = 0x02,
+	SCSI_TASK_REQUEST_CLEAR_TASK_SET       = 0x04,
+	SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET   = 0x08,
+	SCSI_TASK_REQUEST_I_T_NEXUS_RESET      = 0x10,
+	SCSI_TASK_REQUEST_CLEAR_ACA            = 0x40,
+	SCSI_TASK_REQUEST_QUERY_TASK           = 0x80,
+	SCSI_TASK_REQUEST_QUERY_TASK_SET       = 0x81,
+	SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82,
+
+};
+
+/**
+ * enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the
+ *    SCSI task management response codes.
+ *
+ *
+ */
+enum scsi_task_mgmt_response_codes {
+	SCSI_TASK_MGMT_FUNC_COMPLETE      = 0,
+	SCSI_INVALID_FRAME                = 2,
+	SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4,
+	SCSI_TASK_MGMT_FUNC_FAILED        = 5,
+	SCSI_TASK_MGMT_FUNC_SUCCEEDED     = 8,
+	SCSI_INVALID_LUN                  = 9
+};
+
+/**
+ * enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense
+ *    data responses as per SPC-3.
+ *
+ *
+ */
+enum scsi_sense_response_code {
+	SCSI_FIXED_CURRENT_RESPONSE_CODE       = 0x70,
+	SCSI_FIXED_DEFERRED_RESPONSE_CODE      = 0x71,
+	SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE  = 0x72,
+	SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73
+
+};
+
+/*
+ * This constant represents the valid bit located in byte 0 of a FIXED
+ * format sense data. */
+#define SCSI_FIXED_SENSE_DATA_VALID_BIT   0x80
+
+#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18
+
+/* This value is used in the DATAPRES field of the SCSI Response IU. */
+#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02
+
+/**
+ *
+ *
+ * SCSI_SENSE_KEYS These constants delineate all of the SCSI protocol sense key
+ * constants
+ */
+#define SCSI_SENSE_NO_SENSE        0x00
+#define SCSI_SENSE_RECOVERED_ERROR 0x01
+#define SCSI_SENSE_NOT_READY       0x02
+#define SCSI_SENSE_MEDIUM_ERROR    0x03
+#define SCSI_SENSE_HARDWARE_ERROR  0x04
+#define SCSI_SENSE_ILLEGAL_REQUEST 0x05
+#define SCSI_SENSE_UNIT_ATTENTION  0x06
+#define SCSI_SENSE_DATA_PROTECT    0x07
+#define SCSI_SENSE_BLANK_CHECK     0x08
+#define SCSI_SENSE_VENDOR_SPECIFIC 0x09
+#define SCSI_SENSE_COPY_ABORTED    0x0A
+#define SCSI_SENSE_ABORTED_COMMAND 0x0B
+#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D
+#define SCSI_SENSE_MISCOMPARE      0x0E
+
+/**
+ *
+ *
+ * SCSI_ADDITIONAL_SENSE_CODES These constants delineate all of the SCSI
+ * protocol additional sense code constants.
+ */
+#define SCSI_ASC_NO_ADDITIONAL_SENSE             0x00
+#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED   0x04
+#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS       0x04
+#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS          0x04
+#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION    0x05
+#define SCSI_ASC_UNRECOVERED_READ_ERROR          0x11
+#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE  0x20
+#define SCSI_ASC_LBA_OUT_OF_RANGE                0x21
+#define SCSI_ASC_INVALID_FIELD_IN_CDB            0x24
+#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST      0x26
+#define SCSI_ASC_WRITE_PROTECTED                 0x27
+#define SCSI_ASC_NOT_READY_TO_READY_CHANGE       0x28
+#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED      0x39
+#define SCSI_ASC_MEDIUM_NOT_PRESENT              0x3A
+#define SCSI_ASC_INTERNAL_TARGET_FAILURE         0x44
+#define SCSI_ASC_IU_CRC_ERROR_DETECTED           0x47
+#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST          0x5A
+#define SCSI_ASC_COMMAND_SEQUENCE_ERROR          0x2C
+#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED      0x53
+#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE      0x5D
+#define SCSI_ASC_POWER_STATE_CHANGE              0x5E
+#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT     0x40
+#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED  0x67
+
+/**
+ *
+ *
+ * SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS This enumeration contains all of the
+ * used SCSI protocol additional sense code qualifier constants.
+ */
+#define SCSI_ASCQ_NO_ADDITIONAL_SENSE                    0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_CDB                   0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST             0x00
+#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION           0x00
+#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE                0x00
+#define SCSI_ASCQ_LBA_OUT_OF_RANGE                       0x00
+#define SCSI_ASCQ_MEDIUM_NOT_PRESENT                     0x00
+#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE              0x00
+#define SCSI_ASCQ_WRITE_PROTECTED                        0x00
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR                 0x00
+#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED             0x00
+#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE         0x00
+#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST                 0x01
+#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED          0x02
+#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED                  0x03
+#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS                 0x04
+#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS              0x09
+#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE             0x10
+#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND     0x03
+#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND  0x04
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE             0x42
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY          0x43
+#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED         0x0B
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL    0x04
+
+
+
+/**
+ *
+ *
+ * SCSI_STATUS_CODES These constants define all of the used SCSI status values.
+ */
+#define SCSI_STATUS_GOOD            0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+#define SCSI_STATUS_CONDITION_MET   0x04
+#define SCSI_STATUS_BUSY            0x08
+#define SCSI_STATUS_TASKFULL        0x28
+#define SCSI_STATUS_ACA             0x30
+#define SCSI_STATUS_ABORT           0x40
+
+/**
+ *
+ *
+ * SCSI_OPERATION_CODES These constants delineate all of the SCSI
+ * command/operation codes.
+ */
+#define SCSI_INQUIRY                0x12
+#define SCSI_READ_CAPACITY_10       0x25
+#define SCSI_SERVICE_ACTION_IN_16   0x9E
+#define SCSI_TEST_UNIT_READY        0x00
+#define SCSI_START_STOP_UNIT        0x1B
+#define SCSI_SYNCHRONIZE_CACHE_10   0x35
+#define SCSI_SYNCHRONIZE_CACHE_16   0x91
+#define SCSI_REQUEST_SENSE          0x03
+#define SCSI_REPORT_LUNS            0xA0
+#define SCSI_REASSIGN_BLOCKS        0x07
+#define SCSI_READ_6                 0x08
+#define SCSI_READ_10                0x28
+#define SCSI_READ_12                0xA8
+#define SCSI_READ_16                0x88
+#define SCSI_WRITE_6                0x0A
+#define SCSI_WRITE_10               0x2A
+#define SCSI_WRITE_12               0xAA
+#define SCSI_WRITE_16               0x8A
+#define SCSI_VERIFY_10              0x2F
+#define SCSI_VERIFY_12              0xAF
+#define SCSI_VERIFY_16              0x8F
+#define SCSI_SEEK_6                 0x01
+#define SCSI_SEEK_10                0x02
+#define SCSI_WRITE_VERIFY           0x2E
+#define SCSI_FORMAT_UNIT            0x04
+#define SCSI_READ_BUFFER            0x3C
+#define SCSI_WRITE_BUFFER           0x3B
+#define SCSI_SEND_DIAGNOSTIC        0x1D
+#define SCSI_RECEIVE_DIAGNOSTIC     0x1C
+#define SCSI_MODE_SENSE_6           0x1A
+#define SCSI_MODE_SENSE_10          0x5A
+#define SCSI_MODE_SELECT_6          0x15
+#define SCSI_MODE_SELECT_10         0x55
+#define SCSI_MAINTENANCE_IN         0xA3
+#define SCSI_LOG_SENSE              0x4D
+#define SCSI_LOG_SELECT             0x4C
+#define SCSI_RESERVE_6              0x16
+#define SCSI_RESERVE_10             0x56
+#define SCSI_RELEASE_6              0x17
+#define SCSI_RELEASE_10             0x57
+#define SCSI_ATA_PASSTHRU_12        0xA1
+#define SCSI_ATA_PASSTHRU_16        0x85
+#define SCSI_WRITE_LONG_10          0x3F
+#define SCSI_WRITE_LONG_16          0x9F
+#define SCSI_PERSISTENT_RESERVE_IN  0x5E
+#define SCSI_PERSISTENT_RESERVE_OUT 0x5F
+
+/**
+ *
+ *
+ * SCSI_SERVICE_ACTION_IN_CODES Service action in operations.
+ */
+#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16     0x10
+
+#define SCSI_SERVICE_ACTION_MASK 0x1f
+
+/**
+ *
+ *
+ * SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes.
+ */
+#define SCSI_REPORT_TASK_MGMT  0x0D
+#define SCSI_REPORT_OP_CODES   0x0C
+
+/**
+ *
+ *
+ * SCSI_MODE_PAGE_CONTROLS These constants delineate all of the used SCSI Mode
+ * Page control values.
+ */
+#define SCSI_MODE_SENSE_PC_CURRENT     0x0
+#define SCSI_MODE_SENSE_PC_CHANGEABLE  0x1
+#define SCSI_MODE_SENSE_PC_DEFAULT     0x2
+#define SCSI_MODE_SENSE_PC_SAVED       0x3
+
+#define SCSI_MODE_SENSE_PC_SHIFT           0x06
+#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE   0x3F
+#define SCSI_MODE_SENSE_DBD_ENABLE         0x08
+#define SCSI_MODE_SENSE_LLBAA_ENABLE       0x10
+
+/**
+ *
+ *
+ * SCSI_MODE_PAGE_CODES These constants delineate all of the used SCSI Mode
+ * Page codes.
+ */
+#define SCSI_MODE_PAGE_READ_WRITE_ERROR           0x01
+#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT       0x02
+#define SCSI_MODE_PAGE_CACHING                    0x08
+#define SCSI_MODE_PAGE_CONTROL                    0x0A
+#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT     0x19
+#define SCSI_MODE_PAGE_POWER_CONDITION            0x1A
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C
+#define SCSI_MODE_PAGE_ALL_PAGES                  0x3F
+
+#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE         0xFF
+#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE          0x0
+#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1
+#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT          0x04
+#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT          0x20
+#define SCSI_MODE_PAGE_DEXCPT_ENABLE               0x08
+#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE          0x10
+#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY     0x1
+#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE        0x2
+
+#define SCSI_MODE_SENSE_6_HEADER_LENGTH              4
+#define SCSI_MODE_SENSE_10_HEADER_LENGTH             8
+#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH  8
+#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16
+
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08
+#define SCSI_MODE_PAGE_19_SAS_ID         0x6
+#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM  0x1
+#define SCSI_MODE_PAGE_19_SUB1_PC        0x59
+
+#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00
+
+/* Mode Select constrains related masks value */
+#define SCSI_MODE_SELECT_PF_BIT                       0x1
+#define SCSI_MODE_SELECT_PF_MASK                      0x10
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE          0x6
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK          0x0F
+#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK           0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK       0x80
+#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK       0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK  0x1F
+#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1
+#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST       0x84
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC    0xF1
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER        0xF0
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP          0x38
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO        0x47
+
+
+#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE  0x04
+#define SCSI_MOVE_FUA_BIT_ENABLE           0x08
+#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE  0x01
+#define SCSI_READ_CAPACITY_10_DATA_LENGTH  8
+#define SCSI_READ_CAPACITY_16_DATA_LENGTH  32
+
+/* Inquiry constants */
+#define SCSI_INQUIRY_EVPD_ENABLE          0x01
+#define SCSI_INQUIRY_PAGE_CODE_OFFSET     0x02
+#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00
+#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80
+#define SCSI_INQUIRY_DEVICE_ID_PAGE       0x83
+#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89
+#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE    0xB1
+#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH  0x3C
+#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24    /* 36 */
+
+#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH   0xFC     /* 252 */
+
+/** Defines the log page codes that are use in gathing Smart data
+ */
+#define SCSI_LOG_PAGE_SUPPORTED_PAGES       0x00
+#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F
+#define SCSI_LOG_PAGE_SELF_TEST             0x10
+
+/**
+ *
+ *
+ * SCSI_INQUIRY_VPD The following are constants used with vital product data
+ * inquiry pages. Values are already shifted into the proper nibble location.
+ */
+#define SCSI_PIV_ENABLE                 0x80
+#define SCSI_LUN_ASSOCIATION            0x00
+#define SCSI_TARGET_PORT_ASSOCIATION    0x10
+
+#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00
+#define SCSI_NAA_IDENTIFIER_TYPE        0x03
+
+#define SCSI_T10_IDENTIFIER_TYPE        0x01
+#define SCSI_BINARY_CODE_SET            0x01
+#define SCSI_ASCII_CODE_SET             0x02
+#define SCSI_FC_PROTOCOL_IDENTIFIER     0x00
+#define SCSI_SAS_PROTOCOL_IDENTIFIER    0x60
+
+#define SCSI_VERIFY_BYTCHK_ENABLED      0x02
+
+#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02
+/**
+ *
+ *
+ * SCSI_START_STOP_UNIT_POWER_CONDITION_CODES The following are SCSI Start Stop
+ * Unit command Power Condition codes.
+ */
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID       0x0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE            0x1
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE              0x2
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY           0x3
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL        0x7
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL   0xB
+
+#define SCSI_START_STOP_UNIT_IMMED_MASK            0x1
+#define SCSI_START_STOP_UNIT_IMMED_SHIFT           0
+
+#define SCSI_START_STOP_UNIT_START_BIT_MASK        0x1
+#define SCSI_START_STOP_UNIT_START_BIT_SHIFT       0
+
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK         0x2
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT        1
+
+#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK         0x4
+#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT        2
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK   0xF
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT  0
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK  0xF0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4
+
+#define SCSI_LOG_SENSE_PC_FIELD_MASK      0xC0
+#define SCSI_LOG_SENSE_PC_FIELD_SHIFT     6
+
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK      0x3F
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT     0
+
+/**
+ *
+ *
+ * MRIE - Method of reporting informational exceptions codes
+ */
+#define NO_REPORTING_INFO_EXCEPTION_CONDITION      0x0
+#define ASYNCHRONOUS_EVENT_REPORTING               0x1
+#define ESTABLISH_UNIT_ATTENTION_CONDITION         0x2
+#define CONDITIONALLY_GENERATE_RECOVERED_ERROR     0x3
+#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR   0x4
+#define GENERATE_NO_SENSE                          0x5
+#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6
+
+#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT      0x08
+
+/* Reassign Blocks masks */
+#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT           0x02
+#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT          0x01
+
+#endif /* _SCSI_H_ */
+
diff --git a/drivers/scsi/isci/core/sati_device.h b/drivers/scsi/isci/core/sati_device.h
new file mode 100644
index 0000000..4d1cfde
--- /dev/null
+++ b/drivers/scsi/isci/core/sati_device.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SATI_DEVICE_H_
+#define _SATI_DEVICE_H_
+
+/**
+ * This file contains all of the defintions for the SATI remote device object.
+ *    Some translations require information to be remembered on a per device
+ *    basis.  This information is stored in the object defined in this file.
+ *
+ *
+ */
+
+#include "sati_types.h"
+#include "intel_ata.h"
+
+/**
+ * enum _SATI_DEVICE_STATE - This enumeration depicts the various states
+ *    possible for the a translation remote device object.
+ *
+ *
+ */
+enum sati_device_state {
+	SATI_DEVICE_STATE_OPERATIONAL,
+	SATI_DEVICE_STATE_STOPPED,
+	SATI_DEVICE_STATE_STANDBY,
+	SATI_DEVICE_STATE_IDLE,
+	SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED,
+	SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS,
+	SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS,
+	SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE,
+	SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION
+
+};
+
+/**
+ *
+ *
+ * SATI_DEVICE_CAPABILITIES These constants define the various capabilities
+ * that a remote device may support for which there is an impact on translation.
+ */
+#define SATI_DEVICE_CAP_UDMA_ENABLE          0x00000001
+#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002
+#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004
+#define SATI_DEVICE_CAP_48BIT_ENABLE         0x00000008
+#define SATI_DEVICE_CAP_DMA_FUA_ENABLE       0x00000010
+#define SATI_DEVICE_CAP_SMART_SUPPORT        0x00000020
+#define SATI_DEVICE_CAP_REMOVABLE_MEDIA      0x00000040
+#define SATI_DEVICE_CAP_SMART_ENABLE         0x00000080
+#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE           0x00000100
+#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200
+#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT              0x00000400
+
+
+/**
+ * struct sati_device - The SATI_DEVICE structure define the state of the
+ *    remote device with respect to translation.
+ *
+ *
+ */
+struct sati_device {
+	/**
+	 * This field simply dictates the state of the SATI device.
+	 */
+	enum sati_device_state state;
+
+	/**
+	 * This field indicates features supported by the remote device that
+	 * impact translation execution.
+	 */
+	u16 capabilities;
+
+	/**
+	 * This field indicates the depth of the native command queue supported
+	 * by the device.
+	 */
+	u8 ncq_depth;
+
+	/**
+	 * This field stores the additional sense code for a unit attention
+	 * condition.
+	 */
+	u8 unit_attention_asc;
+
+	/**
+	 * This field indicates the additional sense code qualifier for a unit
+	 * attention condition.
+	 */
+	u8 unit_attention_ascq;
+
+};
+
+void sati_device_construct(
+	struct sati_device *device,
+	bool is_ncq_enabled,
+	u8 max_ncq_depth);
+
+void sati_device_update_capabilities(
+	struct sati_device *device,
+	struct ata_identify_device_data *identify);
+
+#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */
+
diff --git a/drivers/scsi/isci/core/sati_translator_sequence.h b/drivers/scsi/isci/core/sati_translator_sequence.h
new file mode 100644
index 0000000..592570d
--- /dev/null
+++ b/drivers/scsi/isci/core/sati_translator_sequence.h
@@ -0,0 +1,304 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SATI_TRANSLATOR_SEQUENCE_H_
+#define _SATI_TRANSLATOR_SEQUENCE_H_
+
+/**
+ * This file contains all of the defintions for the SATI translator sequence.
+ *    A translator sequence is simply a defintion for the various sequences of
+ *    commands that occur in this translator.
+ *
+ *
+ */
+
+#include "sati_device.h"
+
+/**
+ * enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible
+ *    sequence types for the translator.
+ *
+ *
+ */
+enum sati_translator_sequence_type {
+	/* SCSI Primary Command (SPC) sequences. */
+	SATI_SEQUENCE_REPORT_LUNS,
+	SATI_SEQUENCE_TEST_UNIT_READY,
+	SATI_SEQUENCE_INQUIRY_STANDARD,
+	SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES,
+	SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER,
+	SATI_SEQUENCE_INQUIRY_DEVICE_ID,
+	SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE,
+	SATI_SEQUENCE_MODE_SENSE_6_CACHING,
+	SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL,
+	SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR,
+	SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT,
+	SATI_SEQUENCE_MODE_SENSE_6_CONTROL,
+	SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES,
+	SATI_SEQUENCE_MODE_SENSE_10_CACHING,
+	SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL,
+	SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR,
+	SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT,
+	SATI_SEQUENCE_MODE_SENSE_10_CONTROL,
+	SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES,
+	SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING,
+	SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION,
+	SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL,
+
+	/* Log Sense Sequences */
+	SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE,
+	SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE,
+	SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE,
+	SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE,
+
+	/* SCSI Block Command (SBC) sequences. */
+
+	SATI_SEQUENCE_READ_6,
+	SATI_SEQUENCE_READ_10,
+	SATI_SEQUENCE_READ_12,
+	SATI_SEQUENCE_READ_16,
+
+	SATI_SEQUENCE_READ_CAPACITY_10,
+	SATI_SEQUENCE_READ_CAPACITY_16,
+
+	SATI_SEQUENCE_SYNCHRONIZE_CACHE,
+
+	SATI_SEQUENCE_VERIFY_10,
+	SATI_SEQUENCE_VERIFY_12,
+	SATI_SEQUENCE_VERIFY_16,
+
+	SATI_SEQUENCE_WRITE_6,
+	SATI_SEQUENCE_WRITE_10,
+	SATI_SEQUENCE_WRITE_12,
+	SATI_SEQUENCE_WRITE_16,
+
+	SATI_SEQUENCE_START_STOP_UNIT,
+
+	SATI_SEQUENCE_REASSIGN_BLOCKS,
+
+	/* SCSI Task Requests sequences */
+
+	SATI_SEQUENCE_LUN_RESET,
+
+	SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS,
+	SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE,
+
+	SATI_SEQUENCE_WRITE_LONG
+
+};
+
+#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6
+#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16
+
+/**
+ *
+ *
+ * SATI_SEQUENCE_STATES These constants depict the various state values
+ * associated with a translation sequence.
+ */
+#define SATI_SEQUENCE_STATE_INITIAL        0
+#define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1
+#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2
+#define SATI_SEQUENCE_STATE_FINAL          3
+#define SATI_SEQUENCE_STATE_INCOMPLETE     4
+
+/**
+ *
+ *
+ * SATI_DATA_DIRECTIONS These constants depict the various types of data
+ * directions for a translation sequence.  Data can flow in/out (read/write) or
+ * no data at all.
+ */
+#define SATI_DATA_DIRECTION_NONE 0
+#define SATI_DATA_DIRECTION_IN   1
+#define SATI_DATA_DIRECTION_OUT  2
+
+/**
+ * struct SATI_MODE_SELECT_PROCESSING_STATE - This structure contains all of
+ *    the current processing states for processing mode select 6 and 10
+ *    commands' parameter fields.
+ *
+ *
+ */
+typedef  struct SATI_MODE_SELECT_PROCESSING_STATE {
+	u8 *mode_pages;
+	u32 mode_page_offset;
+	u32 mode_pages_size;
+	u32 size_of_data_processed;
+	u32 total_ata_command_sent;
+	u32 ata_command_sent_for_cmp; /* cmp: current mode page */
+	bool current_mode_page_processed;
+
+} SATI_MODE_SELECT_PROCESSING_STATE_T;
+
+
+enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS {
+	SATI_REASSIGN_BLOCKS_READY_TO_SEND,
+	SATI_REASSIGN_BLOCKS_COMMAND_FAIL,
+	SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS,
+};
+
+/**
+ * struct sati_reassign_blocks_processing_state - This structure contains all
+ *    of the current processing states for processing reassign block command's
+ *    parameter fields.
+ *
+ *
+ */
+struct sati_reassign_blocks_processing_state {
+	u32 lba_offset;
+	u32 block_lists_size;
+	u8 lba_size;
+	u32 size_of_data_processed;
+	u32 ata_command_sent_for_current_lba;
+	bool current_lba_processed;
+	enum     SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status;
+
+};
+
+#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12
+
+/**
+ * struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO
+ *    specific data.
+ *
+ *
+ */
+struct sati_atapi_data {
+	u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH];
+};
+
+/**
+ * struct sati_translator_sequence - This structure contains all of the
+ *    translation information associated with a particular request.
+ *
+ *
+ */
+struct sati_translator_sequence {
+	/**
+	 * This field contains the sequence type determined by the SATI.
+	 */
+	u8 type;
+
+	/**
+	 * This field indicates the current state for the sequence.
+	 */
+	u8 state;
+
+	/**
+	 * This field indicates the data direction (none, read, or write) for
+	 * the translated request.
+	 */
+	u8 data_direction;
+
+	/**
+	 * This field contains the SATA/ATA protocol to be utilized during
+	 * the IO transfer.
+	 */
+	u8 protocol;
+
+	/**
+	 * This field is utilized for sequences requiring data translation.
+	 * It specifies the amount of data requested by the caller from the
+	 * operation.  It's necessary, because at times the user requests less
+	 * data than is available.  Thus, we need to avoid overrunning the
+	 * buffer.
+	 */
+	u32 allocation_length;
+
+	/**
+	 * This field specifies the amount of data that will actually be
+	 * transfered across the wire for this ATA request.
+	 */
+	u32 ata_transfer_length;
+
+	/**
+	 * This field specifies the amount of data bytes that have been
+	 * set in a translation sequence. It will be incremented every time
+	 * a data byte has been set by a sati translation.
+	 */
+	u16 number_data_bytes_set;
+
+	/**
+	 * This field indicates whether or not the sense response has been set
+	 * by the translation sequence.
+	 */
+	bool is_sense_response_set;
+
+	/**
+	 * This field specifies the remote device context for which this
+	 * translator sequence is destined.
+	 */
+	struct sati_device *device;
+
+	/**
+	 * This field is utilized to provide the translator with memory space
+	 * required for translations that utilize multiple requests.
+	 */
+	union {
+		u32 translated_command;
+		u32 move_sector_count;
+		u32 scratch;
+		struct sati_reassign_blocks_processing_state reassign_blocks_process_state;
+		SATI_MODE_SELECT_PROCESSING_STATE_T process_state;
+		struct sati_atapi_data sati_atapi_data;
+	} command_specific_data;
+
+};
+
+
+
+#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */
+
diff --git a/drivers/scsi/isci/core/sati_types.h b/drivers/scsi/isci/core/sati_types.h
new file mode 100644
index 0000000..b6159e0
--- /dev/null
+++ b/drivers/scsi/isci/core/sati_types.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SATI_TYPES_H_
+#define _SATI_TYPES_H_
+
+/**
+ * This file contains various type definitions to be utilized with SCSI to ATA
+ *    Translation Implementation.
+ *
+ *
+ */
+
+/**
+ * enum _SATI_STATUS - This enumeration defines the possible return values from
+ *    the SATI translation methods.
+ *
+ *
+ */
+enum sati_status {
+	/**
+	 * This indicates that the translation was supported and occurred
+	 * without error.
+	 */
+	SATI_SUCCESS,
+
+	/**
+	 * This indicates that the translation was supported, occurred without
+	 * error, and no additional translation is necessary.  This is done in
+	 * conditions where the SCSI command doesn't require any interaction with
+	 * the remote device.
+	 */
+	SATI_COMPLETE,
+
+	/**
+	 * This indicated everything SATI_COMPLETE does in addition to the response data
+	 * not using all the memory allocated by the OS.
+	 */
+	SATI_COMPLETE_IO_DONE_EARLY,
+
+	/**
+	 * This indicates that translator sequence has finished some specific
+	 * command in the sequence, but additional commands are necessary.
+	 */
+	SATI_SEQUENCE_INCOMPLETE,
+
+	/**
+	 * This indicates a general failure has occurred for which no further
+	 * specification information is available.
+	 */
+	SATI_FAILURE,
+
+	/**
+	 * This indicates that the result of the IO request indicates a
+	 * failure.  The caller should reference the corresponding response
+	 * data for further details.
+	 */
+	SATI_FAILURE_CHECK_RESPONSE_DATA,
+
+	/**
+	 * This status indicates that the supplied sequence type doesn't map
+	 * to an existing definition.
+	 */
+	SATI_FAILURE_INVALID_SEQUENCE_TYPE,
+
+	/**
+	 * This status indicates that the supplied sequence state doesn't match
+	 * the operation being requested by the user.
+	 */
+	SATI_FAILURE_INVALID_STATE
+
+};
+
+#if (!defined(DISABLE_SATI_MODE_SENSE)	    \
+	|| !defined(DISABLE_SATI_MODE_SELECT)	  \
+	|| !defined(DISABLE_SATI_REQUEST_SENSE)) \
+
+#if !defined(ENABLE_SATI_MODE_PAGES)
+/**
+ *
+ *
+ * This macro enables the common mode page data structures and code. Currently,
+ * MODE SENSE, MODE SELECT, and REQUEST SENSE all make reference to this common
+ * code.  As a result, enable the common mode page code if any of these 3 are
+ * being translated.
+ */
+#define ENABLE_SATI_MODE_PAGES
+#endif  /* !defined(ENABLE_SATI_MODE_PAGES) */
+
+#endif  /* MODE_SENSE/SELECT/REQUEST_SENSE */
+
+#endif  /* _SATI_TYPES_H_ */
+
diff --git a/drivers/scsi/isci/core/sci_pool.h b/drivers/scsi/isci/core/sci_pool.h
new file mode 100644
index 0000000..c0d2ea3
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_pool.h
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * This file contains the interface to the pool class. This class allows two
+ *    different two different priority tasks to insert and remove items from
+ *    the free pool. The user of the pool is expected to evaluate the pool
+ *    condition empty before a get operation and pool condition full before a
+ *    put operation. Methods Provided: - sci_pool_create() -
+ *    sci_pool_initialize() - sci_pool_empty() - sci_pool_full() -
+ *    sci_pool_get() - sci_pool_put()
+ *
+ *
+ */
+
+#ifndef _SCI_POOL_H_
+#define _SCI_POOL_H_
+
+/**
+ * SCI_POOL_INCREMENT() -
+ *
+ * Private operation for the pool
+ */
+#define SCI_POOL_INCREMENT(this_pool, index) \
+	(((index) + 1) == (this_pool).size ? 0 : (index) + 1)
+
+/**
+ * SCI_POOL_CREATE() -
+ *
+ * This creates a pool structure of pool_name. The members in the pool are of
+ * type with number of elements equal to size.
+ */
+#define SCI_POOL_CREATE(pool_name, type, pool_size) \
+	struct \
+	{ \
+		u32 size; \
+		u32 get; \
+		u32 put; \
+		type array[(pool_size) + 1]; \
+	} pool_name
+
+
+/**
+ * sci_pool_empty() -
+ *
+ * This macro evaluates the pool and returns true if the pool is empty. If the
+ * pool is empty the user should not perform any get operation on the pool.
+ */
+#define sci_pool_empty(this_pool) \
+	((this_pool).get == (this_pool).put)
+
+/**
+ * sci_pool_full() -
+ *
+ * This macro evaluates the pool and returns true if the pool is full.  If the
+ * pool is full the user should not perform any put operation.
+ */
+#define sci_pool_full(this_pool) \
+	(SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get)
+
+/**
+ * sci_pool_size() -
+ *
+ * This macro returns the size of the pool created.  The internal size of the
+ * pool is actually 1 larger then necessary in order to ensure get and put
+ * pointers can be written simultaneously by different users.  As a result,
+ * this macro subtracts 1 from the internal size
+ */
+#define sci_pool_size(this_pool) \
+	((this_pool).size - 1)
+
+/**
+ * sci_pool_count() -
+ *
+ * This macro indicates the number of elements currently contained in the pool.
+ */
+#define sci_pool_count(this_pool) \
+	(\
+		sci_pool_empty((this_pool)) \
+		? 0 \
+		: (\
+			sci_pool_full((this_pool)) \
+			? sci_pool_size((this_pool)) \
+			: (\
+				(this_pool).get > (this_pool).put \
+				? ((this_pool).size - (this_pool).get + (this_pool).put) \
+				: ((this_pool).put - (this_pool).get) \
+				) \
+			) \
+	)
+
+/**
+ * sci_pool_initialize() -
+ *
+ * This macro initializes the pool to an empty condition.
+ */
+#define sci_pool_initialize(this_pool) \
+	{ \
+		(this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \
+		(this_pool).get = 0; \
+		(this_pool).put = 0; \
+	}
+
+/**
+ * sci_pool_get() -
+ *
+ * This macro will get the next free element from the pool. This should only be
+ * called if the pool is not empty.
+ */
+#define sci_pool_get(this_pool, my_value) \
+	{ \
+		(my_value) = (this_pool).array[(this_pool).get]; \
+		(this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \
+	}
+
+/**
+ * sci_pool_put() -
+ *
+ * This macro will put the value into the pool. This should only be called if
+ * the pool is not full.
+ */
+#define sci_pool_put(this_pool, the_value) \
+	{ \
+		(this_pool).array[(this_pool).put] = (the_value); \
+		(this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \
+	}
+
+/**
+ * sci_pool_erase() -
+ *
+ * This macro will search the pool and remove any elements in the pool matching
+ * the supplied value. This method can only be utilized on pools
+ */
+#define sci_pool_erase(this_pool, type, the_value) \
+	{ \
+		type tmp_value;	\
+		u32 index; \
+		u32 element_count = sci_pool_count((this_pool)); \
+ \
+		for (index = 0; index < element_count; index++) {	\
+			sci_pool_get((this_pool), tmp_value); \
+			if (tmp_value != (the_value)) \
+				sci_pool_put((this_pool), tmp_value); \
+		} \
+	}
+
+#endif /* _SCI_POOL_H_ */
diff --git a/drivers/scsi/isci/core/sci_status.h b/drivers/scsi/isci/core/sci_status.h
new file mode 100644
index 0000000..72b6108
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_status.h
@@ -0,0 +1,409 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_STATUS_H_
+#define _SCI_STATUS_H_
+
+/**
+ * This file contains all of the return status codes utilized across the
+ *    various sub-components in SCI.
+ *
+ *
+ */
+
+
+/**
+ * enum _SCI_STATUS - This is the general return status enumeration for non-IO,
+ *    non-task management related SCI interface methods.
+ *
+ *
+ */
+enum sci_status {
+	/**
+	 * This member indicates successful completion.
+	 */
+	SCI_SUCCESS = 0,
+
+	/**
+	 * This value indicates that the calling method completed successfully,
+	 * but that the IO may have completed before having it's start method
+	 * invoked.  This occurs during SAT translation for requests that do
+	 * not require an IO to the target or for any other requests that may
+	 * be completed without having to submit IO.
+	 */
+	SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
+
+	/**
+	 *  This Value indicates that the SCU hardware returned an early response
+	 *  because the io request specified more data than is returned by the
+	 *  target device (mode pages, inquiry data, etc.). The completion routine
+	 *  will handle this case to get the actual number of bytes transferred.
+	 */
+	SCI_SUCCESS_IO_DONE_EARLY,
+
+	/**
+	 * This member indicates that the object for which a state change is
+	 * being requested is already in said state.
+	 */
+	SCI_WARNING_ALREADY_IN_STATE,
+
+	/**
+	 * This member indicates interrupt coalescence timer may cause SAS
+	 * specification compliance issues (i.e. SMP target mode response
+	 * frames must be returned within 1.9 milliseconds).
+	 */
+	SCI_WARNING_TIMER_CONFLICT,
+
+	/**
+	 * This field indicates a sequence of action is not completed yet. Mostly,
+	 * this status is used when multiple ATA commands are needed in a SATI translation.
+	 */
+	SCI_WARNING_SEQUENCE_INCOMPLETE,
+
+	/**
+	 * This member indicates that there was a general failure.
+	 */
+	SCI_FAILURE,
+
+	/**
+	 * This member indicates that the SCI implementation is unable to complete
+	 * an operation due to a critical flaw the prevents any further operation
+	 * (i.e. an invalid pointer).
+	 */
+	SCI_FATAL_ERROR,
+
+	/**
+	 * This member indicates the calling function failed, because the state
+	 * of the controller is in a state that prevents successful completion.
+	 */
+	SCI_FAILURE_INVALID_STATE,
+
+	/**
+	 * This member indicates the calling function failed, because there is
+	 * insufficient resources/memory to complete the request.
+	 */
+	SCI_FAILURE_INSUFFICIENT_RESOURCES,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * controller object required for the operation can't be located.
+	 */
+	SCI_FAILURE_CONTROLLER_NOT_FOUND,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * discovered controller type is not supported by the library.
+	 */
+	SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * requested initialization data version isn't supported.
+	 */
+	SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * requested configuration of SAS Phys into SAS Ports is not supported.
+	 */
+	SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * requested protocol is not supported by the remote device, port,
+	 * or controller.
+	 */
+	SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * requested information type is not supported by the SCI implementation.
+	 */
+	SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * device already exists.
+	 */
+	SCI_FAILURE_DEVICE_EXISTS,
+
+	/**
+	 * This member indicates the calling function failed, because adding
+	 * a phy to the object is not possible.
+	 */
+	SCI_FAILURE_ADDING_PHY_UNSUPPORTED,
+
+	/**
+	 * This member indicates the calling function failed, because the
+	 * requested information type is not supported by the SCI implementation.
+	 */
+	SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD,
+
+	/**
+	 * This member indicates the calling function failed, because the SCI
+	 * implementation does not support the supplied time limit.
+	 */
+	SCI_FAILURE_UNSUPPORTED_TIME_LIMIT,
+
+	/**
+	 * This member indicates the calling method failed, because the SCI
+	 * implementation does not contain the specified Phy.
+	 */
+	SCI_FAILURE_INVALID_PHY,
+
+	/**
+	 * This member indicates the calling method failed, because the SCI
+	 * implementation does not contain the specified Port.
+	 */
+	SCI_FAILURE_INVALID_PORT,
+
+	/**
+	 * This member indicates the calling method was partly successful
+	 * The port was reset but not all phys in port are operational
+	 */
+	SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS,
+
+	/**
+	 * This member indicates that calling method failed
+	 * The port reset did not complete because none of the phys are operational
+	 */
+	SCI_FAILURE_RESET_PORT_FAILURE,
+
+	/**
+	 * This member indicates the calling method failed, because the SCI
+	 * implementation does not contain the specified remote device.
+	 */
+	SCI_FAILURE_INVALID_REMOTE_DEVICE,
+
+	/**
+	 * This member indicates the calling method failed, because the remote
+	 * device is in a bad state and requires a reset.
+	 */
+	SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+
+	/**
+	 * This member indicates the calling method failed, because the SCI
+	 * implementation does not contain or support the specified IO tag.
+	 */
+	SCI_FAILURE_INVALID_IO_TAG,
+
+	/**
+	 * This member indicates that the operation failed and the user should
+	 * check the response data associated with the IO.
+	 */
+	SCI_FAILURE_IO_RESPONSE_VALID,
+
+	/**
+	 * This member indicates that the operation failed, the failure is
+	 * controller implementation specific, and the response data associated
+	 * with the request is not valid.  You can query for the controller
+	 * specific error information via scic_controller_get_request_status()
+	 */
+	SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+
+	/**
+	 * This member indicated that the operation failed because the
+	 * user requested this IO to be terminated.
+	 */
+	SCI_FAILURE_IO_TERMINATED,
+
+	/**
+	 * This member indicates that the operation failed and the associated
+	 * request requires a SCSI abort task to be sent to the target.
+	 */
+	SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
+
+	/**
+	 * This member indicates that the operation failed because the supplied
+	 * device could not be located.
+	 */
+	SCI_FAILURE_DEVICE_NOT_FOUND,
+
+	/**
+	 * This member indicates that the operation failed because the
+	 * objects association is required and is not correctly set.
+	 */
+	SCI_FAILURE_INVALID_ASSOCIATION,
+
+	/**
+	 * This member indicates that the operation failed, because a timeout
+	 * occurred.
+	 */
+	SCI_FAILURE_TIMEOUT,
+
+	/**
+	 * This member indicates that the operation failed, because the user
+	 * specified a value that is either invalid or not supported.
+	 */
+	SCI_FAILURE_INVALID_PARAMETER_VALUE,
+
+	/**
+	 * This value indicates that the operation failed, because the number
+	 * of messages (MSI-X) is not supported.
+	 */
+	SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT,
+
+	/**
+	 * This value indicates that the method failed due to a lack of
+	 * available NCQ tags.
+	 */
+	SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
+
+	/**
+	 * This value indicates that a protocol violation has occurred on the
+	 * link.
+	 */
+	SCI_FAILURE_PROTOCOL_VIOLATION,
+
+	/**
+	 * This value indicates a failure condition that retry may help to clear.
+	 */
+	SCI_FAILURE_RETRY_REQUIRED,
+
+	/**
+	 * This field indicates the retry limit was reached when a retry is attempted
+	 */
+	SCI_FAILURE_RETRY_LIMIT_REACHED,
+
+	/**
+	 * This member indicates the calling method was partly successful.
+	 * Mostly, this status is used when a LUN_RESET issued to an expander attached
+	 * STP device in READY NCQ substate needs to have RNC suspended/resumed
+	 * before posting TC.
+	 */
+	SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS,
+
+	/**
+	 * This field indicates an illegal phy connection based on the routing attribute
+	 * of both expander phy attached to each other.
+	 */
+	SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION,
+
+	/**
+	 * This field indicates a CONFIG ROUTE INFO command has a response with function result
+	 * INDEX DOES NOT EXIST, usually means exceeding max route index.
+	 */
+	SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX,
+
+	/**
+	 * This value indicates that an unsupported PCI device ID has been
+	 * specified.  This indicates that attempts to invoke
+	 * scic_library_allocate_controller() will fail.
+	 */
+	SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID
+
+};
+
+/**
+ * enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO
+ *    completion status values.  Each value in this enumeration maps directly
+ *    to a value in the enum sci_status enumeration.  Please refer to that
+ *    enumeration for detailed comments concerning what the status represents.
+ *
+ * Add the API to retrieve the SCU status from the core. Check to see that the
+ * following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL
+ * - SCI_IO_FAILURE_INVALID_IO_TAG
+ */
+enum sci_io_status {
+	SCI_IO_SUCCESS                         = SCI_SUCCESS,
+	SCI_IO_FAILURE                         = SCI_FAILURE,
+	SCI_IO_SUCCESS_COMPLETE_BEFORE_START   = SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
+	SCI_IO_SUCCESS_IO_DONE_EARLY           = SCI_SUCCESS_IO_DONE_EARLY,
+	SCI_IO_FAILURE_INVALID_STATE           = SCI_FAILURE_INVALID_STATE,
+	SCI_IO_FAILURE_INSUFFICIENT_RESOURCES  = SCI_FAILURE_INSUFFICIENT_RESOURCES,
+	SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL    = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+	SCI_IO_FAILURE_RESPONSE_VALID          = SCI_FAILURE_IO_RESPONSE_VALID,
+	SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+	SCI_IO_FAILURE_TERMINATED              = SCI_FAILURE_IO_TERMINATED,
+	SCI_IO_FAILURE_REQUIRES_SCSI_ABORT     = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
+	SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
+	SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE    = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
+	SCI_IO_FAILURE_PROTOCOL_VIOLATION      = SCI_FAILURE_PROTOCOL_VIOLATION,
+
+	SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+
+	SCI_IO_FAILURE_RETRY_REQUIRED      = SCI_FAILURE_RETRY_REQUIRED,
+	SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED,
+	SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE
+};
+
+/**
+ * enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task
+ *    completion status values.  Each value in this enumeration maps directly
+ *    to a value in the enum sci_status enumeration.  Please refer to that
+ *    enumeration for detailed comments concerning what the status represents.
+ *
+ * Check to see that the following status are properly handled:
+ */
+enum sci_task_status {
+	SCI_TASK_SUCCESS                         = SCI_SUCCESS,
+	SCI_TASK_FAILURE                         = SCI_FAILURE,
+	SCI_TASK_FAILURE_INVALID_STATE           = SCI_FAILURE_INVALID_STATE,
+	SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES  = SCI_FAILURE_INSUFFICIENT_RESOURCES,
+	SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL    = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+	SCI_TASK_FAILURE_INVALID_TAG             = SCI_FAILURE_INVALID_IO_TAG,
+	SCI_TASK_FAILURE_RESPONSE_VALID          = SCI_FAILURE_IO_RESPONSE_VALID,
+	SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+	SCI_TASK_FAILURE_TERMINATED              = SCI_FAILURE_IO_TERMINATED,
+	SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
+
+	SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+	SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS
+
+};
+
+
+#endif  /* _SCI_STATUS_H_ */
+
diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c
new file mode 100644
index 0000000..cb3e9f7
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_util.c
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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 <linux/kernel.h>
+#include "sci_util.h"
+#include "sci_environment.h"
+
+void scic_word_copy_with_swap(
+	u32 *destination,
+	u32 *source,
+	u32 word_count)
+{
+	while (word_count--) {
+		*destination = SCIC_SWAP_DWORD(*source);
+
+		source++;
+		destination++;
+	}
+}
+
+void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr)
+{
+	struct isci_request *ireq = sci_object_get_association(sci_req);
+	dma_addr_t offset;
+
+	BUG_ON(phys_addr < ireq->request_daddr);
+
+	offset = phys_addr - ireq->request_daddr;
+
+	BUG_ON(offset >= ireq->request_alloc_size);
+
+	return (char *)ireq + offset;
+}
+
+dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request,
+					void *virt_addr)
+{
+	struct isci_request *isci_request =
+		(struct isci_request *)sci_object_get_association(sds_request);
+
+	char *requested_addr = (char *)virt_addr;
+	char *base_addr = (char *)isci_request;
+
+	BUG_ON(requested_addr < base_addr);
+	BUG_ON((requested_addr - base_addr) >=
+			isci_request->request_alloc_size);
+
+	return isci_request->request_daddr + (requested_addr - base_addr);
+}
diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h
new file mode 100644
index 0000000..b6f43e2
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_util.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCI_UTIL_H_
+#define _SCI_UTIL_H_
+
+#include <linux/string.h>
+#include "scic_sds_request.h"
+
+/**
+ * SCIC_SWAP_DWORD() -
+ *
+ * Normal byte swap macro
+ */
+#define SCIC_SWAP_DWORD(x) \
+	(\
+		(((x) >> 24) & 0x000000FF) \
+		| (((x) >>  8) & 0x0000FF00) \
+		| (((x) <<  8) & 0x00FF0000) \
+		| (((x) << 24) & 0xFF000000) \
+	)
+
+#define SCIC_BUILD_DWORD(char_buffer) \
+	(\
+		((char_buffer)[0] << 24) \
+		| ((char_buffer)[1] << 16) \
+		| ((char_buffer)[2] <<  8) \
+		| ((char_buffer)[3]) \
+	)
+
+#define SCI_FIELD_OFFSET(type, field)   ((unsigned long)&(((type *)0)->field))
+
+
+#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \
+	((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32)
+
+/**
+ * scic_word_copy_with_swap() - Copy the data from source to destination and
+ *    swap the bytes during the copy.
+ * @destination: This parameter specifies the destination address to which the
+ *    data is to be copied.
+ * @source: This parameter specifies the source address from which data is to
+ *    be copied.
+ * @word_count: This parameter specifies the number of 32-bit words to copy and
+ *    byte swap.
+ *
+ */
+void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count);
+
+void *scic_request_get_virt_addr(struct scic_sds_request *sds_request,
+				 dma_addr_t phys_addr);
+
+dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request,
+					void *virt_addr);
+
+#endif /* _SCI_UTIL_H_ */
diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h
new file mode 100644
index 0000000..485fefc
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_config_parameters.h
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_USER_PARAMETERS_H_
+#define _SCIC_SDS_USER_PARAMETERS_H_
+
+/**
+ * This file contains all of the structure definitions and interface methods
+ *    that can be called by a SCIC user on the SCU Driver Standard
+ *    (struct scic_sds_user_parameters) user parameter block.
+ *
+ *
+ */
+
+
+#include "sci_status.h"
+#include "intel_sas.h"
+#include "sci_controller_constants.h"
+
+struct scic_sds_controller;
+
+/**
+ *
+ *
+ * SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a
+ * phy/port.
+ */
+#define SCIC_SDS_PARM_NO_SPEED   0
+
+/**
+ *
+ *
+ * This value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN1_SPEED 1
+
+/**
+ *
+ *
+ * This value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN2_SPEED 2
+
+/**
+ *
+ *
+ * This value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN3_SPEED 3
+
+/**
+ *
+ *
+ * For range checks, the max speed generation
+ */
+#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED
+
+/**
+ * struct scic_sds_user_parameters - This structure delineates the various user
+ *    parameters that can be changed by the core user.
+ *
+ *
+ */
+struct scic_sds_user_parameters {
+	struct sci_phy_user_params {
+		/**
+		 * This field specifies the NOTIFY (ENABLE SPIN UP) primitive
+		 * insertion frequency for this phy index.
+		 */
+		u32 notify_enable_spin_up_insertion_frequency;
+
+		/**
+		 * This method specifies the number of transmitted DWORDs within which
+		 * to transmit a single ALIGN primitive.  This value applies regardless
+		 * of what type of device is attached or connection state.  A value of
+		 * 0 indicates that no ALIGN primitives will be inserted.
+		 */
+		u16 align_insertion_frequency;
+
+		/**
+		 * This method specifies the number of transmitted DWORDs within which
+		 * to transmit 2 ALIGN primitives.  This applies for SAS connections
+		 * only.  A minimum value of 3 is required for this field.
+		 */
+		u16 in_connection_align_insertion_frequency;
+
+		/**
+		 * This field indicates the maximum speed generation to be utilized
+		 * by phys in the supplied port.
+		 * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
+		 * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
+		 * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
+		 */
+		u8 max_speed_generation;
+
+	} phys[SCI_MAX_PHYS];
+
+	/**
+	 * This field specifies the maximum number of direct attached devices
+	 * that can have power supplied to them simultaneously.
+	 */
+	u8 max_number_concurrent_device_spin_up;
+
+	/**
+	 * This field specifies the number of seconds to allow a phy to consume
+	 * power before yielding to another phy.
+	 *
+	 */
+	u8 phy_spin_up_delay_interval;
+
+	/**
+	 * These timer values specifies how long a link will remain open with no
+	 * activity in increments of a microsecond, it can be in increments of
+	 * 100 microseconds if the upper most bit is set.
+	 *
+	 */
+	u16 stp_inactivity_timeout;
+	u16 ssp_inactivity_timeout;
+
+	/**
+	 * These timer values specifies how long a link will remain open in increments
+	 * of 100 microseconds.
+	 *
+	 */
+	u16 stp_max_occupancy_timeout;
+	u16 ssp_max_occupancy_timeout;
+
+	/**
+	 * This timer value specifies how long a link will remain open with no
+	 * outbound traffic in increments of a microsecond.
+	 *
+	 */
+	u8 no_outbound_task_timeout;
+
+};
+
+/**
+ * This structure/union specifies the various different user parameter sets
+ *    available.  Each type is specific to a hardware controller version.
+ *
+ * union scic_user_parameters
+ */
+union scic_user_parameters {
+	/**
+	 * This field specifies the user parameters specific to the
+	 * Storage Controller Unit (SCU) Driver Standard (SDS) version
+	 * 1.
+	 */
+	struct scic_sds_user_parameters sds1;
+
+};
+
+
+/**
+ *
+ *
+ * SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask
+ */
+
+/**
+ *
+ *
+ * This is the min value assignable to a port's phy mask
+ */
+#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0
+
+/**
+ *
+ *
+ * This is the max value assignable to a port's phy mask
+ */
+#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
+
+/**
+ * struct scic_sds_oem_parameters - This structure delineates the various OEM
+ *    parameters that must be set the core user.
+ *
+ *
+ */
+struct scic_sds_oem_parameters {
+	struct {
+		/**
+		 * This field indicates whether Spread Spectrum Clocking (SSC)
+		 * should be enabled or disabled.
+		 */
+		bool do_enable_ssc;
+
+	} controller;
+
+	struct {
+		/**
+		 * This field specifies the phys to be contained inside a port.
+		 * The bit position in the mask specifies the index of the phy
+		 * to be contained in the port.  Multiple bits (i.e. phys)
+		 * can be contained in a single port.
+		 */
+		u8 phy_mask;
+
+	} ports[SCI_MAX_PORTS];
+
+	struct sci_phy_oem_params {
+		/**
+		 * This field specifies the SAS address to be transmitted on
+		 * for this phy index.
+		 */
+		struct sci_sas_address sas_address;
+
+	} phys[SCI_MAX_PHYS];
+
+};
+
+/**
+ * This structure/union specifies the various different OEM parameter sets
+ *    available.  Each type is specific to a hardware controller version.
+ *
+ * union scic_oem_parameters
+ */
+union scic_oem_parameters {
+	/**
+	 * This field specifies the OEM parameters specific to the
+	 * Storage Controller Unit (SCU) Driver Standard (SDS) version
+	 * 1.
+	 */
+	struct scic_sds_oem_parameters sds1;
+
+};
+
+/**
+ * scic_user_parameters_set() - This method allows the user to attempt to
+ *    change the user parameters utilized by the controller.
+ * @controller: This parameter specifies the controller on which to set the
+ *    user parameters.
+ * @user_parameters: This parameter specifies the USER_PARAMETERS object
+ *    containing the potential new values.
+ *
+ * Indicate if the update of the user parameters was successful. SCI_SUCCESS
+ * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
+ * This value is returned if the attempt to change the user parameter failed,
+ * because changing one of the parameters is not currently allowed.
+ * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
+ * supplied an invalid interrupt coalescence time, spin up delay interval, etc.
+ */
+enum sci_status scic_user_parameters_set(
+	struct scic_sds_controller *controller,
+	union scic_user_parameters *user_parameters);
+
+/**
+ * scic_user_parameters_get() - This method allows the user to retrieve the
+ *    user parameters utilized by the controller.
+ * @controller: This parameter specifies the controller on which to set the
+ *    user parameters.
+ * @user_parameters: This parameter specifies the USER_PARAMETERS object into
+ *    which the framework shall save it's parameters.
+ *
+ */
+void scic_user_parameters_get(
+	struct scic_sds_controller *controller,
+	union scic_user_parameters *user_parameters);
+
+/**
+ * scic_oem_parameters_set() - This method allows the user to attempt to change
+ *    the OEM parameters utilized by the controller.
+ * @controller: This parameter specifies the controller on which to set the
+ *    user parameters.
+ * @oem_parameters: This parameter specifies the OEM parameters object
+ *    containing the potential new values.
+ *
+ * Indicate if the update of the user parameters was successful. SCI_SUCCESS
+ * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
+ * This value is returned if the attempt to change the user parameter failed,
+ * because changing one of the parameters is not currently allowed.
+ * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
+ * supplied an unsupported value for one of the OEM parameters.
+ */
+enum sci_status scic_oem_parameters_set(
+	struct scic_sds_controller *controller,
+	union scic_oem_parameters *oem_parameters);
+
+/**
+ * scic_oem_parameters_get() - This method allows the user to retreive the OEM
+ *    parameters utilized by the controller.
+ * @controller: This parameter specifies the controller on which to set the
+ *    user parameters.
+ * @oem_parameters: This parameter specifies the OEM parameters object in which
+ *    to write the core's OEM parameters.
+ *
+ */
+void scic_oem_parameters_get(
+	struct scic_sds_controller *controller,
+	union scic_oem_parameters *oem_parameters);
+
+
+#endif  /* _SCIC_SDS_USER_PARAMETERS_H_ */
+
diff --git a/drivers/scsi/isci/core/scic_sds_pci.h b/drivers/scsi/isci/core/scic_sds_pci.h
new file mode 100644
index 0000000..bf0cbca
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_pci.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SCIC_SDS_PCI_H_
+#define _SCIC_SDS_PCI_H_
+
+/**
+ * This file contains the prototypes/macros utilized in writing out PCI data
+ *    for the SCI core.
+ *
+ *
+ */
+
+#include <asm/io.h>
+
+struct scic_sds_controller;
+
+void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic);
+
+/* for debug we separate scu and smu accesses and require a controller */
+static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
+{
+	writel(value, addr);
+}
+
+static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
+{
+	writel(value, addr);
+}
+
+
+#endif /* _SCIC_SDS_PCI_H_ */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (9 preceding siblings ...)
  2011-03-10 10:55 ` [RFC PATCH 10/10] isci/core: common definitions and utility functions Dan Williams
@ 2011-03-15 17:47 ` Jeff Garzik
  2011-03-15 17:55   ` Christoph Hellwig
  2011-03-18 15:56 ` Christoph Hellwig
  2011-03-27 22:32 ` Christoph Hellwig
  12 siblings, 1 reply; 24+ messages in thread
From: Jeff Garzik @ 2011-03-15 17:47 UTC (permalink / raw)
  To: Dan Williams
  Cc: james.bottomley, dave.jiang, linux-scsi, jacek.danecki,
	ed.ciechanowski, jeffrey.d.skirvin, edmund.nadolski

On 03/10/2011 05:54 AM, Dan Williams wrote:
> The full driver and history is available in git:
>
>     git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git master
>
> The libsas-pending branch contains proposed libsas fixes (pending
> acceptance into scsi-misc):
>
>     git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git libsas-pending
>
> The x86-pending branch contains a proposed api for mapping bios roms so
> the driver can retrieve configuration parameters (pending acceptance
> into -tip):
>
>     git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git x86-pending
>
> --
> Dan for the isci driver team
>
>
> [1]: http://marc.info/?l=linux-scsi&m=129703780424729&w=2
>
> ---
>
> Dan Williams (10):
>        isci/core: controller
>        isci/core: phy
>        isci/core: port
>        isci/core: remote device
>        isci/core: remote node context
>        isci/core: stp
>        isci/core: request (general, ssp and smp)
>        isci/core: unsolicited frame handling and registers
>        isci/core: base state machine and memory descriptors
>        isci/core: common definitions and utility functions

Let's get this driver into staging for 2.6.39, if it isn't going to hit 
the merge window for 2.6.39.

It would lame for such [presumably] high volume hardware to be in 
neither the main kernel, nor staging, at 2.6.39 release time.

	Jeff




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-15 17:47 ` [RFC PATCH 00/10] isci: core Jeff Garzik
@ 2011-03-15 17:55   ` Christoph Hellwig
  2011-03-15 18:08     ` Jeff Garzik
  0 siblings, 1 reply; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-15 17:55 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Dan Williams, james.bottomley, dave.jiang, linux-scsi,
	jacek.danecki, ed.ciechanowski, jeffrey.d.skirvin,
	edmund.nadolski

On Tue, Mar 15, 2011 at 01:47:12PM -0400, Jeff Garzik wrote:
> Let's get this driver into staging for 2.6.39, if it isn't going to
> hit the merge window for 2.6.39.
> 
> It would lame for such [presumably] high volume hardware to be in
> neither the main kernel, nor staging, at 2.6.39 release time.

What's the point of staging?  That just causes tons of poinless churn.
Linus has made it clear that normal high volume hardware drivers can go
in after the merge window.  So let's just polish it for another few
weeks and then put it in where it belongs.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-15 17:55   ` Christoph Hellwig
@ 2011-03-15 18:08     ` Jeff Garzik
  2011-03-15 20:13       ` Dan Williams
  0 siblings, 1 reply; 24+ messages in thread
From: Jeff Garzik @ 2011-03-15 18:08 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Dan Williams, james.bottomley, dave.jiang, linux-scsi,
	jacek.danecki, ed.ciechanowski, jeffrey.d.skirvin,
	edmund.nadolski

On 03/15/2011 01:55 PM, Christoph Hellwig wrote:
> On Tue, Mar 15, 2011 at 01:47:12PM -0400, Jeff Garzik wrote:
>> Let's get this driver into staging for 2.6.39, if it isn't going to
>> hit the merge window for 2.6.39.
>>
>> It would lame for such [presumably] high volume hardware to be in
>> neither the main kernel, nor staging, at 2.6.39 release time.
>
> What's the point of staging?  That just causes tons of poinless churn.
> Linus has made it clear that normal high volume hardware drivers can go
> in after the merge window.  So let's just polish it for another few
> weeks and then put it in where it belongs.

That's fine... if that really happens.

It seemed like this was turning into another driver that would get held 
outside the kernel until it's "perfect."  If that is the case, Linus has 
also made it clear we should get drivers for high volume, shipping 
hardware into the kernel, even if its staging, if the alternative is to 
deny users the driver.

	Jeff




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-15 18:08     ` Jeff Garzik
@ 2011-03-15 20:13       ` Dan Williams
  2011-03-15 21:04         ` Jeff Garzik
  0 siblings, 1 reply; 24+ messages in thread
From: Dan Williams @ 2011-03-15 20:13 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Christoph Hellwig, james.bottomley, dave.jiang, linux-scsi,
	jacek.danecki, ed.ciechanowski, jeffrey.d.skirvin,
	edmund.nadolski

On Tue, Mar 15, 2011 at 11:08 AM, Jeff Garzik <jeff@garzik.org> wrote:
> On 03/15/2011 01:55 PM, Christoph Hellwig wrote:
>>
>> On Tue, Mar 15, 2011 at 01:47:12PM -0400, Jeff Garzik wrote:
>>>
>>> Let's get this driver into staging for 2.6.39, if it isn't going to
>>> hit the merge window for 2.6.39.
>>>
>>> It would lame for such [presumably] high volume hardware to be in
>>> neither the main kernel, nor staging, at 2.6.39 release time.
>>
>> What's the point of staging?  That just causes tons of poinless churn.
>> Linus has made it clear that normal high volume hardware drivers can go
>> in after the merge window.  So let's just polish it for another few
>> weeks and then put it in where it belongs.
>
> That's fine... if that really happens.
>
> It seemed like this was turning into another driver that would get held
> outside the kernel until it's "perfect."  If that is the case, Linus has
> also made it clear we should get drivers for high volume, shipping hardware
> into the kernel, even if its staging, if the alternative is to deny users
> the driver.
>

Whether it is drivers/staging/ or drivers/scsi/ having a few more
weeks to at least allow for a SCSI focused review (and the resulting
cleanups / fixes) before merging is the important point.

Staging does not seem to be the location for high volume cleanups
after the merge window closes:
$ git diff --stat -M v2.6.38-rc1..v2.6.38 drivers/staging/
50 files changed, 832 insertions(+), 476 deletions(-)

...though there is a precedent for taking large staging drivers post
merge window (commit 9d200153: Staging: add MSM framebuffer driver).

This looks like a way forward.  Barring objections I would also go
ahead and get the current git tree into -next just to flush out any
build / integration issues.  If we (community) end up deciding the
driver should still go to staging I can just do a late "git mv
drivers/scsi/isci drivers/staging/" prior to sending the pull request
to Greg.

--
Dan
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-15 20:13       ` Dan Williams
@ 2011-03-15 21:04         ` Jeff Garzik
  0 siblings, 0 replies; 24+ messages in thread
From: Jeff Garzik @ 2011-03-15 21:04 UTC (permalink / raw)
  To: Dan Williams
  Cc: Christoph Hellwig, james.bottomley, dave.jiang, linux-scsi,
	jacek.danecki, ed.ciechanowski, jeffrey.d.skirvin,
	edmund.nadolski

On 03/15/2011 04:13 PM, Dan Williams wrote:
> Whether it is drivers/staging/ or drivers/scsi/ having a few more
> weeks to at least allow for a SCSI focused review (and the resulting
> cleanups / fixes) before merging is the important point.

Oh, agreed.  Not trying to rush past that part.  And there's still 
plenty of work that wants doing.

I just don't want to get stuck behind the "wall of perfection," either.  :)

	Jeff




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (10 preceding siblings ...)
  2011-03-15 17:47 ` [RFC PATCH 00/10] isci: core Jeff Garzik
@ 2011-03-18 15:56 ` Christoph Hellwig
  2011-03-19  6:19   ` Dan Williams
  2011-03-27 22:32 ` Christoph Hellwig
  12 siblings, 1 reply; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-18 15:56 UTC (permalink / raw)
  To: Dan Williams
  Cc: james.bottomley, dave.jiang, linux-scsi, jacek.danecki,
	ed.ciechanowski, jeffrey.d.skirvin, edmund.nadolski

On Thu, Mar 10, 2011 at 02:54:19AM -0800, Dan Williams wrote:
> As first introduced in "[RFC PATCH 0/6] isci: initial driver release
> (part1: intro and lldd) " [1], the isci driver is split into an lldd
> layer that interfaces with libsas and a core layer that interfaces with
> the hardware.  Quoting from the original introduction:

I just looked at it and that architecture is a complete fucking mess.

You absolutely have to fix it before it can be merged.  Gems like
duplicating all wire level constants and structures for SCSI, SAS
and ATA in your own headers is simply not acceptable.  I'm not sure
where you got the idea this could be remotely acceptable.


Also the source layout is a real mess, almost comparably to the broacade
FC driver - there really is no point in having a header for barely more
than a structure or inline.

Also care to explain the design rationale for all these specific
semi-statemachines?  To my untrained eye they really looks like
pointless obsfucation, but maybe there's a good reason that should be
explained in long comments.

And please don't make the code like ACPICA, macro names like
SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT or
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
just need to go.

Also please get rid of ALL UPPERCASE SCREAMING NAMES for structures.

FYI:

         u32 connection_inactivity_timeout:16;

is a really dumb idea.  Please take the crackpipe away from whatever
idiot came up with junk like that and use the proper right sized integer
types.  Also for sub-byte field please absolutely avoid bitfields.
Their layout is unportable, and properly locking them is a nightmare.
Just define a flags field and use bit operations on them.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-18 15:56 ` Christoph Hellwig
@ 2011-03-19  6:19   ` Dan Williams
  0 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2011-03-19  6:19 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: james.bottomley, dave.jiang, linux-scsi, jacek.danecki,
	ed.ciechanowski, jeffrey.d.skirvin, edmund.nadolski

On Fri, Mar 18, 2011 at 8:56 AM, Christoph Hellwig <hch@infradead.org> wrote:
[..]
> You absolutely have to fix it before it can be merged.  Gems like
> duplicating all wire level constants and structures for SCSI, SAS
> and ATA in your own headers is simply not acceptable.

Hence the comment "Many of these want to be deleted in favor of the
in-kernel equivalent." in "[RFC PATCH 10/10] isci/core: common
definitions and utility functions' [1].

> I'm not sure where you got the idea this could be remotely acceptable.

Never did.  We're reworking the driver that was handed to us.

To date fixing bugs in the current code (things like removing
phys_to_virt and virt_to_phys in favor of proper dma-api and kmap
usage) has delayed this rework... still plan to fix it.

> Also the source layout is a real mess, almost comparably to the broacade
> FC driver - there really is no point in having a header for barely more
> than a structure or inline.

Agreed.  We consolidated the c files, now need to go back and do the
same for the headers.  There is also a namespacecheck driven cleanup
that needs to happen as well.

> Also care to explain the design rationale for all these specific
> semi-statemachines?  To my untrained eye they really looks like
> pointless obsfucation, but maybe there's a good reason that should be
> explained in long comments.

They model asynchronous hardware / protocol states and are loosely
analogous to the ata_sff_hsm implementation in libata in terms of
needing to handle transport layer details of sata, smp, and ssp.   The
hardware is focused on accelerating the fast paths and let's software
handle many slow path conditions, for example ata pio requests require
driver interaction to progress the request through several states at a
per frame level.  We'll put together some better documentation but
there are a lot of conditions and states that software is required to
handle and the state machines keep these organized.

There have been some patches to make them more readable (8e131f53,
ba647271, 03355704), but this work has not been completed across all
the state machines.  I will say I think the controller state machine
is one that could be eventually factored out / absorbed into the lldd
because there are no asynchronous hardware-event driven controller
state transitions.

> And please don't make the code like ACPICA, macro names like
> SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT or
> SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
> just need to go.

Ok.

> Also please get rid of ALL UPPERCASE SCREAMING NAMES for structures.

Unfortunately, the automated scripts we developed at the beginning of
the cleanup effort only caught definitions of the form:

typedef struct UPPERCASE_STRUCT { } UPPERCASE_STRUCT_T;

...and missed ones of the form:

struct UPPERCASE_STRUCT { };

...so we need to manually handle these stragglers.

> FYI:
>
>         u32 connection_inactivity_timeout:16;
>
> is a really dumb idea.  Please take the crackpipe away from whatever
> idiot came up with junk like that and use the proper right sized integer
> types.  Also for sub-byte field please absolutely avoid bitfields.
> Their layout is unportable, and properly locking them is a nightmare.
> Just define a flags field and use bit operations on them.

Yeah. it does not make sense to define bitfields for things that are
correctly aligned base types.

--
Dan

[1]: http://marc.info/?l=linux-scsi&m=129975444506569&w=2
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
                   ` (11 preceding siblings ...)
  2011-03-18 15:56 ` Christoph Hellwig
@ 2011-03-27 22:32 ` Christoph Hellwig
  2011-03-30  1:22   ` Dan Williams
  12 siblings, 1 reply; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-27 22:32 UTC (permalink / raw)
  To: Dan Williams
  Cc: james.bottomley, dave.jiang, linux-scsi, jacek.danecki,
	ed.ciechanowski, jeffrey.d.skirvin, edmund.nadolski

Btw, the naming scheme in the driver seems utterly confusing,
with prefixed split between isci_, sci_ and scic_, where a lot of
the latter also have a second sds_ or controller_ prefix.  Especially
the use of controller_ in a lot of the nomenclature seems very
confusing to me.  Is there a scheme behind all this?


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-27 22:32 ` Christoph Hellwig
@ 2011-03-30  1:22   ` Dan Williams
  2011-03-30  7:23     ` Christoph Hellwig
  0 siblings, 1 reply; 24+ messages in thread
From: Dan Williams @ 2011-03-30  1:22 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: james.bottomley@suse.de, Jiang, Dave, linux-scsi@vger.kernel.org,
	Danecki, Jacek, Ciechanowski, Ed, Skirvin, Jeffrey D,
	Nadolski, Edmund

On Sun, 2011-03-27 at 15:32 -0700, Christoph Hellwig wrote:
> Btw, the naming scheme in the driver seems utterly confusing,
> with prefixed split between isci_, sci_ and scic_, where a lot of
> the latter also have a second sds_ or controller_ prefix.  Especially
> the use of controller_ in a lot of the nomenclature seems very
> confusing to me.  Is there a scheme behind all this?
> 

Yes, it needs to be documented, but there is some method behind the
confusion.

The expectation is that the lldd need not understand core internals
outside of a set of interface functions.  Any functions prefixed
scic_sds_ are meant to only be called by other core routines.  We have
broken that rule in places where it added unnecessary indirection, like
the isr handlers and phy enable/disable interface (should probably go
back and make those consistent before the final merge).

Core data-structure definitions are also hidden from the lldd.  All it
has access to are the forward declared structure types.

Any functions prefixed with isci_ belong to the lldd, and to remove
indirection we are teaching the core to call lldd routines and native
Linux routines directly (the bulk of the upstream cleanup effort is
covered by this theme).

During this effort it was found that local variable instances had
inconsistent, sometimes overly verbose (contributing to 80 column
collisions), and sometimes ambiguous names so we are using the following
scheme going forward and converting routines in the course of doing
other cleanups.

object            | lldd instance | core instance
------------------|---------------|---------------
controller / host | ihost         | scic
task / request    | ireq          | sci_req, stp_req, ssp_req, smp_req
sas device        | idev          | sci_dev
sas phy           | iphy          | sci_phy
sas port          | iport         | sci_port



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-30  1:22   ` Dan Williams
@ 2011-03-30  7:23     ` Christoph Hellwig
  2011-03-31  0:20       ` Dan Williams
  0 siblings, 1 reply; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-30  7:23 UTC (permalink / raw)
  To: Dan Williams
  Cc: Christoph Hellwig, james.bottomley@suse.de, Jiang, Dave,
	linux-scsi@vger.kernel.org, Danecki, Jacek, Ciechanowski, Ed,
	Skirvin, Jeffrey D, Nadolski, Edmund

On Tue, Mar 29, 2011 at 06:22:30PM -0700, Dan Williams wrote:
> The expectation is that the lldd need not understand core internals
> outside of a set of interface functions.

I think you need to get rid of that stupid core/wrapper split ASAP,
as it's the root of a lot of the crap in this driver.  Removing all
the stupid indirections and duplicate structures it causes will
make the driver a lot smaller, and actually look like a normal Linux
driver and thus actually maintainable.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 10/10] isci/core: common definitions and utility functions
  2011-03-10 10:55 ` [RFC PATCH 10/10] isci/core: common definitions and utility functions Dan Williams
@ 2011-03-30 14:37   ` Christoph Hellwig
  0 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-30 14:37 UTC (permalink / raw)
  To: Dan Williams
  Cc: james.bottomley, dave.jiang, linux-scsi, jacek.danecki,
	ed.ciechanowski, jeffrey.d.skirvin, edmund.nadolski

> +/**
> + * SCIC_SWAP_DWORD() -
> + *
> + * Normal byte swap macro
> + */
> +#define SCIC_SWAP_DWORD(x) \
> +	(\
> +		(((x) >> 24) & 0x000000FF) \
> +		| (((x) >>  8) & 0x0000FF00) \
> +		| (((x) <<  8) & 0x00FF0000) \
> +		| (((x) << 24) & 0xFF000000) \
> +	)

Duplicates the kernel byte sewap macros.  Even worse it's doing an
unconditional swap instead of a conditional one if the platform
is big endian.  While we're at it this driver seems to lack any
kind of endiness awareness, but that's probably to be expected
coming from intel.  Isn't the new chipset generation supposed to
support ia64 as well, which is capable of running in big endian
mode?


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-30  7:23     ` Christoph Hellwig
@ 2011-03-31  0:20       ` Dan Williams
  2011-03-31  6:32         ` Christoph Hellwig
  0 siblings, 1 reply; 24+ messages in thread
From: Dan Williams @ 2011-03-31  0:20 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: james.bottomley@suse.de, Jiang, Dave, linux-scsi@vger.kernel.org,
	Danecki, Jacek, Ciechanowski, Ed, Skirvin, Jeffrey D,
	Nadolski, Edmund

On Wed, Mar 30, 2011 at 12:23 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Tue, Mar 29, 2011 at 06:22:30PM -0700, Dan Williams wrote:
>> The expectation is that the lldd need not understand core internals
>> outside of a set of interface functions.
>
> I think you need to get rid of that stupid core/wrapper split ASAP,
> as it's the root of a lot of the crap in this driver.  Removing all
> the stupid indirections and duplicate structures it causes will
> make the driver a lot smaller, and actually look like a normal Linux
> driver and thus actually maintainable.

I think we were already on this path, but now just need to formally
acknowledge and accelerate in this direction.  Let me outline where I
think we are and a rough outline of how to get to the removal of the
wrapper.

1/ Complete the removal of all OS agnostic indirections in the core.
We have done quite a bit here to call kernel and lldd facilities
directly, but still need to get rid of intel_{sas|sata|scsi}.h and
duplicated utilities before this step is complete.

2/ Make the core data structures member position independent (so we
can start adding / removing fields at will).  That means getting rid
of unnecessary casting (already started), the base_ structures (you
started this) and the _{get|set}_association macros.

3/ Unify the data structures so they have the same lifetimes.  Where
the lldd has a member that duplicates a core member teach it to use
the core version.  Quick example isci_phy.aif and
scic_sds_phy.sas.identify_address_frame_buffer.

4/ Remove the lldd/core data structure distinction.

Probably missing some sub-steps between three and four, but that is
the general idea.

--
Dan
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [RFC PATCH 00/10] isci: core
  2011-03-31  0:20       ` Dan Williams
@ 2011-03-31  6:32         ` Christoph Hellwig
  0 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2011-03-31  6:32 UTC (permalink / raw)
  To: Dan Williams
  Cc: Christoph Hellwig, james.bottomley@suse.de, Jiang, Dave,
	linux-scsi@vger.kernel.org, Danecki, Jacek, Ciechanowski, Ed,
	Skirvin, Jeffrey D, Nadolski, Edmund

On Wed, Mar 30, 2011 at 05:20:24PM -0700, Dan Williams wrote:
> I think we were already on this path, but now just need to formally
> acknowledge and accelerate in this direction.  Let me outline where I
> think we are and a rough outline of how to get to the removal of the
> wrapper.
> 
> 1/ Complete the removal of all OS agnostic indirections in the core.
> We have done quite a bit here to call kernel and lldd facilities
> directly, but still need to get rid of intel_{sas|sata|scsi}.h and
> duplicated utilities before this step is complete.
> 
> 2/ Make the core data structures member position independent (so we
> can start adding / removing fields at will).  That means getting rid
> of unnecessary casting (already started), the base_ structures (you
> started this) and the _{get|set}_association macros.
> 
> 3/ Unify the data structures so they have the same lifetimes.  Where
> the lldd has a member that duplicates a core member teach it to use
> the core version.  Quick example isci_phy.aif and
> scic_sds_phy.sas.identify_address_frame_buffer.
> 
> 4/ Remove the lldd/core data structure distinction.
> 
> Probably missing some sub-steps between three and four, but that is
> the general idea.

Yes, that's about the required stepts.  In general I'd try to do as much
as possible of the data structures before the procedural part, as that's
the design that really matters.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2011-03-31  6:32 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-10 10:54 [RFC PATCH 00/10] isci: core Dan Williams
2011-03-10 10:54 ` [RFC PATCH 01/10] isci/core: controller Dan Williams
2011-03-10 10:54 ` [RFC PATCH 02/10] isci/core: phy Dan Williams
2011-03-10 10:54 ` [RFC PATCH 03/10] isci/core: port Dan Williams
2011-03-10 10:54 ` [RFC PATCH 04/10] isci/core: remote device Dan Williams
2011-03-10 10:54 ` [RFC PATCH 05/10] isci/core: remote node context Dan Williams
2011-03-10 10:54 ` [RFC PATCH 06/10] isci/core: stp Dan Williams
2011-03-10 10:54 ` [RFC PATCH 07/10] isci/core: request (general, ssp and smp) Dan Williams
2011-03-10 10:55 ` [RFC PATCH 08/10] isci/core: unsolicited frame handling and registers Dan Williams
2011-03-10 10:55 ` [RFC PATCH 09/10] isci/core: base state machine and memory descriptors Dan Williams
2011-03-10 10:55 ` [RFC PATCH 10/10] isci/core: common definitions and utility functions Dan Williams
2011-03-30 14:37   ` Christoph Hellwig
2011-03-15 17:47 ` [RFC PATCH 00/10] isci: core Jeff Garzik
2011-03-15 17:55   ` Christoph Hellwig
2011-03-15 18:08     ` Jeff Garzik
2011-03-15 20:13       ` Dan Williams
2011-03-15 21:04         ` Jeff Garzik
2011-03-18 15:56 ` Christoph Hellwig
2011-03-19  6:19   ` Dan Williams
2011-03-27 22:32 ` Christoph Hellwig
2011-03-30  1:22   ` Dan Williams
2011-03-30  7:23     ` Christoph Hellwig
2011-03-31  0:20       ` Dan Williams
2011-03-31  6:32         ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).