isci: Intel(R) C600 Series Chipset Storage Control Unit Driver

Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the
chipset.

This is a snapshot of the first publicly available version of the driver,
commit 4c1db2d0 in the 'historical' branch.

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

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4a1f029..3aa664f 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -830,6 +830,40 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gdth.
 
+config SCSI_ISCI
+	tristate "Intel(R) C600 Series Chipset SAS Controller"
+	depends on PCI && SCSI
+	# little endian host assumptions
+	depends on X86
+	# (temporary): dma api misuse
+	depends on !DMAR
+	# (temporary): known alpha quality driver
+	depends on EXPERIMENTAL
+	select SCSI_SAS_LIBSAS
+	---help---
+	  This driver supports the 6Gb/s SAS capabilities of the storage
+	  control unit found in the Intel(R) C600 series chipset.
+
+	  The experimental tag will be removed after the driver exits alpha
+
+choice
+	prompt "Default Silicon Revision"
+	depends on SCSI_ISCI
+	default PBG_HBA_A2
+	# temporary A-step silicon is pre-production
+
+config PBG_HBA_BETA
+	bool "B0"
+
+config PBG_HBA_A2
+	bool "A2"
+
+config PBG_HBA_A0
+	bool "A0"
+
+endchoice
+
+
 config SCSI_GENERIC_NCR5380
 	tristate "Generic NCR5380/53c400 SCSI PIO support"
 	depends on ISA && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 7ad0b8a..3c08f53 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -73,6 +73,7 @@
 obj-$(CONFIG_SCSI_AIC7XXX_OLD)	+= aic7xxx_old.o
 obj-$(CONFIG_SCSI_AIC94XX)	+= aic94xx/
 obj-$(CONFIG_SCSI_PM8001)	+= pm8001/
+obj-$(CONFIG_SCSI_ISCI)		+= isci/
 obj-$(CONFIG_SCSI_IPS)		+= ips.o
 obj-$(CONFIG_SCSI_FD_MCS)	+= fd_mcs.o
 obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile
new file mode 100644
index 0000000..34f7af3
--- /dev/null
+++ b/drivers/scsi/isci/Makefile
@@ -0,0 +1,30 @@
+#TODO kill SCIC_SDS_4_ENABLED it is always true for this
+#generation of silicon
+EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED
+
+#temporary until atapi support ready
+EXTRA_CFLAGS += -DDISABLE_ATAPI
+
+EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/
+obj-$(CONFIG_SCSI_ISCI) += isci.o
+isci-objs := init.o phy.o request.o sata.o \
+	     remote_device.o port.o timers.o deprecated.o \
+	     host.o task.o events.o \
+	     core/scic_sds_controller.o  \
+	     core/scic_sds_remote_device.o    \
+	     core/scic_sds_request.o \
+	     core/scic_sds_stp_request.o \
+	     core/scic_sds_stp_packet_request.o \
+	     core/scic_sds_stp_remote_device.o \
+	     core/scic_sds_port.o \
+	     core/scic_sds_port_configuration_agent.o \
+	     core/scic_sds_phy.o \
+	     core/scic_sds_ssp_request.o \
+	     core/scic_sds_remote_node_context.o \
+	     core/scic_sds_smp_request.o \
+	     core/scic_sds_smp_remote_device.o \
+	     core/scic_sds_remote_node_table.o \
+	     core/scic_sds_unsolicited_frame_control.o \
+	     core/sci_base_memory_descriptor_list.o \
+	     core/sci_base_state_machine.o \
+	     core/sci_util.o
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..47390d54
--- /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_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_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
new file mode 100644
index 0000000..86ae6a8
--- /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 != SCI_INVALID_HANDLE)
+		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 != SCI_INVALID_HANDLE)
+			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 != SCI_INVALID_HANDLE)
+			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..257d6e3
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
@@ -0,0 +1,155 @@
+/*
+ * 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_types.h"
+#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
+	 * SCI_INVALID_HANDLE.
+	 */
+	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_phy.h b/drivers/scsi/isci/core/sci_base_phy.h
new file mode 100644
index 0000000..6c0d9bb
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_phy.h
@@ -0,0 +1,205 @@
+/*
+ * 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,
+
+	SCI_BASE_PHY_MAX_STATES
+
+};
+
+/**
+ * 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/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/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h
new file mode 100644
index 0000000..fe6614b
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_remote_device.h
@@ -0,0 +1,277 @@
+/*
+ * 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,
+
+	SCI_BASE_REMOTE_DEVICE_MAX_STATES
+
+};
+
+/**
+ * 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/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/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..cee38bd
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_base_state_machine.h
@@ -0,0 +1,139 @@
+/*
+ * 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_
+
+/**
+ * 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_controller.h b/drivers/scsi/isci/core/sci_controller.h
new file mode 100644
index 0000000..26c3548
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_controller.h
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+
+#include "sci_types.h"
+
+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/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h
new file mode 100644
index 0000000..44de1c1
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_memory_descriptor_list.h
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+
+#include "sci_types.h"
+
+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..9306942
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_object.h
@@ -0,0 +1,99 @@
+/*
+ * 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_types.h"
+#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/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_types.h b/drivers/scsi/isci/core/sci_types.h
new file mode 100644
index 0000000..431735d
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_types.h
@@ -0,0 +1,88 @@
+/*
+ * 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_TYPES_H_
+#define _SCI_TYPES_H_
+
+#include <linux/string.h>
+
+#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \
+	((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32)
+
+#define SCI_INVALID_HANDLE 0x0
+
+/**
+ * The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle
+ *    for the SCI Library object.
+ *
+ * SCI_LIBRARY_HANDLE_T
+ */
+typedef void *SCI_LIBRARY_HANDLE_T;
+
+
+typedef enum {
+	SCI_IO_REQUEST_DATA_IN = 0,	/* Read operation */
+	SCI_IO_REQUEST_DATA_OUT,	/* Write operation */
+	SCI_IO_REQUEST_NO_DATA
+} SCI_IO_REQUEST_DATA_DIRECTION;
+
+
+enum sci_controller_mode {
+	SCI_MODE_SPEED,		/* Optimized for performance */
+	SCI_MODE_SIZE		/* Optimized for memory use */
+};
+
+#endif  /* _SCI_TYPES_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..5cdd96f
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_util.c
@@ -0,0 +1,70 @@
+/*
+ * 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_util.h"
+
+void scic_word_copy_with_swap(
+	u32 *destination,
+	u32 *source,
+	u32 word_count)
+{
+	while (word_count--) {
+		*destination = SCIC_SWAP_DWORD(*source);
+
+		source++;
+		destination++;
+	}
+}
+
diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h
new file mode 100644
index 0000000..67e2bad
--- /dev/null
+++ b/drivers/scsi/isci/core/sci_util.h
@@ -0,0 +1,138 @@
+/*
+ * 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 "sci_types.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))
+
+/**
+ * sci_physical_address_add() -
+ *
+ * This macro simply performs addition on an dma_addr_t type.  The
+ * lower u32 value is "clipped" or "wrapped" back through 0.  When this occurs
+ * the upper 32-bits are incremented by 1.
+ */
+#define sci_physical_address_add(physical_address, value) \
+	{ \
+		u32 lower = lower_32_bits((physical_address)); \
+		u32 upper = upper_32_bits((physical_address)); \
+ \
+		if (lower + (value) < lower) \
+			upper += 1; \
+ \
+		lower += (value); \
+		sci_cb_make_physical_address(physical_address, upper, lower); \
+	}
+
+/**
+ * sci_physical_address_subtract() -
+ *
+ * This macro simply performs subtraction on an dma_addr_t type.  The
+ * lower u32 value is "clipped" or "wrapped" back through 0.  When this occurs
+ * the upper 32-bits are decremented by 1.
+ */
+#define sci_physical_address_subtract(physical_address, value) \
+	{ \
+		u32 lower = lower_32_bits((physical_address)); \
+		u32 upper = upper_32_bits((physical_address)); \
+ \
+		if (lower - (value) > lower) \
+			upper -= 1; \
+ \
+		lower -= (value); \
+		sci_cb_make_physical_address(physical_address, upper, lower); \
+	}
+
+/**
+ * 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);
+
+#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..4c16a50
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_config_parameters.h
@@ -0,0 +1,347 @@
+/*
+ * 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_types.h"
+#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 {
+		/**
+		 * 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 {
+		/**
+		 * 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_controller.h b/drivers/scsi/isci/core/scic_controller.h
new file mode 100644
index 0000000..756b14f
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_controller.h
@@ -0,0 +1,586 @@
+/*
+ * 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_types.h"
+#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 _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of
+ *    interrupts that are potentially supported by a SCI Core implementation.
+ *
+ *
+ */
+enum scic_interrupt_type {
+	SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+	SCIC_MSIX_INTERRUPT_TYPE,
+
+	/**
+	 * This enumeration value indicates the use of polling.
+	 */
+	SCIC_NO_INTERRUPTS
+
+};
+
+/**
+ * This method is called by the SCI user in order to have the SCI
+ *    implementation handle the interrupt.  This method performs minimal
+ *    processing to allow for streamlined interrupt time usage.
+ *
+ * SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to
+ * process and it was processed. false: returned if no interrupt was processed.
+ */
+typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)(
+	struct scic_sds_controller *controller
+	);
+
+/**
+ * This method is called by the SCI user to process completions generated as a
+ *    result of a previously handled interrupt.  This method will result in the
+ *    completion of IO requests and handling of other controller generated
+ *    events.  This method should be called some time after the interrupt
+ *    handler.
+ *
+ * Most, if not all, of the user callback APIs are invoked from within this
+ * API.  As a result, the user should be cognizent of the operating level at
+ * which they invoke this API.
+ */
+typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)(
+	struct scic_sds_controller *controller
+	);
+
+/**
+ * struct scic_controller_handler_methods - This structure contains an
+ *    interrupt handler and completion handler function pointers.
+ *
+ *
+ */
+struct scic_controller_handler_methods {
+	SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler;
+	SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+
+};
+
+/**
+ * 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_get_handler_methods() - This method will return provide
+ *    function pointers for the interrupt handler and completion handler.  The
+ *    interrupt handler is expected to be invoked at interrupt time.  The
+ *    completion handler is scheduled to run as a result of the interrupt
+ *    handler. The completion handler performs the bulk work for processing
+ *    silicon events.
+ * @interrupt_type: This parameter informs the core which type of
+ *    interrupt/completion methods are being requested. These are the types:
+ *    SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE,
+ *    SCIC_NO_INTERRUPTS (POLLING)
+ * @message_count: This parameter informs the core the number of MSI-X messages
+ *    to be utilized.  This parameter must be 0 when requesting legacy line
+ *    based handlers.
+ * @handler_methods: The caller provides a pointer to a buffer of type
+ *    struct scic_controller_handler_methods. The size depends on the combination of
+ *    the interrupt_type and message_count input parameters:
+ *    SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size =
+ *    sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE:
+ *    sizeof(struct scic_controller_handler_methods)
+ * @handler_methods: SCIC fills out the caller's buffer with the appropriate
+ *    interrupt and completion handlers based on the info provided in the
+ *    interrupt_type and message_count input parameters. For
+ *    SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single
+ *    struct scic_controller_handler_methods element regardless that the
+ *    message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer
+ *    receives an array of elements of type struct scic_controller_handler_methods
+ *    where the array size is equivalent to the message_count parameter. The
+ *    array is zero-relative where entry zero corresponds to message-vector
+ *    zero, entry one corresponds to message-vector one, and so forth.
+ *
+ * Indicate if the handler retrieval operation was successful. SCI_SUCCESS This
+ * value is returned if retrieval succeeded.
+ * SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user
+ * supplied an unsupported number of MSI-X messages. For legacy line interrupts
+ * the only valid value is 0.
+ */
+enum sci_status scic_controller_get_handler_methods(
+	enum scic_interrupt_type interrupt_type,
+	u16 message_count,
+	struct scic_controller_handler_methods *handler_methods);
+
+/**
+ * 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_io_request.h b/drivers/scsi/isci/core/scic_io_request.h
new file mode 100644
index 0000000..7378f33
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_io_request.h
@@ -0,0 +1,512 @@
+/*
+ * 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_types.h"
+#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_phy.h b/drivers/scsi/isci/core/scic_phy.h
new file mode 100644
index 0000000..25a6140
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_phy.h
@@ -0,0 +1,303 @@
+/*
+ * 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_types.h"
+#include "sci_status.h"
+
+#include "intel_sata.h"
+#include "intel_sas.h"
+
+struct scic_sds_phy;
+struct scic_sds_port;
+
+/**
+ * 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 SCI_INVALID_HANDLE
+	 * 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_port.h b/drivers/scsi/isci/core/scic_port.h
new file mode 100644
index 0000000..34d22c0
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_port.h
@@ -0,0 +1,213 @@
+/*
+ * 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_types.h"
+#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_start() - This method will make the port ready for operation.
+ *    Prior to calling the start method IO operation is not possible.
+ * @port: This parameter specifies the port to be started.
+ *
+ * Indicate if the port was successfully started. SCI_SUCCESS This value is
+ * returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE
+ * This value is returned if the port is in the process of starting.
+ * 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 start operation
+ * can't be completed due to the state of port.
+ */
+enum sci_status scic_port_start(
+	struct scic_sds_port *port);
+
+/**
+ * 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_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h
new file mode 100644
index 0000000..e8c0459
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_remote_device.h
@@ -0,0 +1,295 @@
+/*
+ * 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_types.h"
+#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_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
new file mode 100644
index 0000000..35f7796
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -0,0 +1,4147 @@
+/*
+ * 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 "scic_user_callback.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.
+ */
+void scic_sds_controller_initialize_phy_startup(
+	struct scic_sds_controller *this_controller)
+{
+	this_controller->phy_startup_timer = scic_cb_timer_create(
+		this_controller,
+		scic_sds_controller_phy_startup_timeout_handler,
+		this_controller
+		);
+
+	this_controller->next_phy_to_start = 0;
+	this_controller->phy_startup_timer_pending = false;
+}
+
+/**
+ *
+ *
+ * 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 = scic_cb_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.
+ *
+ */
+static 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
+
+static bool is_a0(void)
+{
+	return isci_si_rev == ISCI_SI_REVA0;
+}
+
+static bool is_a2(void)
+{
+	return isci_si_rev == ISCI_SI_REVA2;
+}
+
+static bool is_b0(void)
+{
+	return isci_si_rev > ISCI_SI_REVA2;
+}
+
+/* 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);
+	scic_cb_stall_execution(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);
+	
+
+	scic_cb_stall_execution(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);
+		
+	scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+	/* Wait for the PLL to lock */
+	do {
+		afe_status = scu_afe_register_read(
+			scic, afe_common_block_status);
+		scic_cb_stall_execution(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);
+		scic_cb_stall_execution(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);
+			scic_cb_stall_execution(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);
+			scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+			scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F);
+			scic_cb_stall_execution(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);
+			scic_cb_stall_execution(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);
+		}
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+		if (is_a0() || is_a2()) {
+			/* Enable TX equalization (0xe824) */
+			scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
+			scic_cb_stall_execution(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);
+		scic_cb_stall_execution(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);
+			scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+			/* Enable TX equalization (0xe824) */
+			scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
+		}
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03);
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03);
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03);
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03);
+		scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+	}
+
+	/* Transfer control to the PEs */
+	scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00);
+	scic_cb_stall_execution(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
+			);
+
+		scic_cb_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);
+		scic_cb_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++) {
+		port_status = scic_port_stop(&scic->port_table[index]);
+
+		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__,
+				 scic->port_table[index].logical_port_index,
+				 port_status);
+		}
+	}
+
+	return status;
+}
+
+/**
+ *
+ *
+ *
+ */
+static void scic_sds_controller_phy_timer_start(
+	struct scic_sds_controller *this_controller)
+{
+	scic_cb_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)
+{
+	scic_cb_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) != SCI_INVALID_HANDLE) {
+					/**
+					 * 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) == SCI_INVALID_HANDLE) {
+					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] != SCI_INVALID_HANDLE) {
+			/* / @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)
+{
+	scic_cb_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 != SCI_INVALID_HANDLE)
+		&& (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 != SCI_INVALID_HANDLE)
+				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 != SCI_INVALID_HANDLE)
+				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);
+
+}
+
+/**
+ * This method is a private routine for processing the completion queue entries.
+ * @this_controller:
+ *
+ */
+static void scic_sds_controller_transitioned_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_NOTIFY:
+		case SCU_COMPLETION_TYPE_EVENT:
+			/*
+			 * 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);
+		/* Fall-through */
+
+		case SCU_COMPLETION_TYPE_SDMA:
+		case SCU_COMPLETION_TYPE_UFI:
+		default:
+			dev_warn(scic_to_dev(this_controller),
+				 "%s: SCIC Controller ignoring 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);
+}
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller Interrupt and Completion functions
+ * ****************************************************************************- */
+
+/**
+ * This method provides standard (common) processing of interrupts for polling
+ *    and legacy based interrupts.
+ * @controller:
+ * @interrupt_status:
+ *
+ * This method returns a boolean (bool) indication as to whether an completions
+ * are pending to be processed. true if an interrupt is to be processed false
+ * if no interrupt was pending
+ */
+static bool scic_sds_controller_standard_interrupt_handler(
+	struct scic_sds_controller *this_controller,
+	u32 interrupt_status)
+{
+	bool is_completion_needed = false;
+
+	if ((interrupt_status & SMU_ISR_QUEUE_ERROR) ||
+	    ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
+	     (!scic_sds_controller_completion_queue_has_entries(
+							this_controller)))) {
+		/*
+		 * We have a fatal error on the read of the completion queue bar
+		 * OR
+		 * We have a fatal error there is nothing in the completion queue
+		 * but we have a report from the hardware that the queue is full
+		 * / @todo how do we request the a controller reset */
+		is_completion_needed = true;
+		this_controller->encountered_fatal_error = true;
+	}
+
+	if (scic_sds_controller_completion_queue_has_entries(this_controller)) {
+		is_completion_needed = true;
+	}
+
+	return is_completion_needed;
+}
+
+/**
+ * This is the method provided to handle polling for interrupts for the
+ *    controller object.
+ *
+ * bool true if an interrupt is to be processed false if no interrupt was
+ * pending
+ */
+static bool scic_sds_controller_polling_interrupt_handler(
+	struct scic_sds_controller *scic)
+{
+	u32 interrupt_status;
+
+	/*
+	 * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the
+	 * hardware indicates nothing is pending. Since we are not being
+	 * called from a real interrupt, we don't want to confuse the hardware
+	 * by servicing the completion queue before the hardware indicates it
+	 * is ready. We'll simply wait for another polling interval and check
+	 * again.
+	 */
+	interrupt_status = SMU_ISR_READ(scic);
+	if ((interrupt_status &
+	     (SMU_ISR_COMPLETION |
+	      SMU_ISR_QUEUE_ERROR |
+	      SMU_ISR_QUEUE_SUSPEND)) == 0) {
+		return false;
+	}
+
+	return scic_sds_controller_standard_interrupt_handler(
+		       scic, interrupt_status);
+}
+
+/**
+ * This is the method provided to handle completions when interrupt polling is
+ *    in use.
+ */
+static void scic_sds_controller_polling_completion_handler(
+	struct scic_sds_controller *scic)
+{
+	if (scic->encountered_fatal_error == true) {
+		dev_err(scic_to_dev(scic),
+			"%s: SCIC Controller has encountered a fatal error.\n",
+			__func__);
+
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(scic),
+			SCI_BASE_CONTROLLER_STATE_FAILED);
+	} else if (scic_sds_controller_completion_queue_has_entries(scic)) {
+		if (scic->restrict_completions == false)
+			scic_sds_controller_process_completions(scic);
+		else
+			scic_sds_controller_transitioned_process_completions(
+				scic);
+	}
+
+	/*
+	 * The interrupt handler does not adjust the CQ's
+	 * get pointer.  So, SCU's INTx pin stays asserted during the
+	 * interrupt handler even though it tries to clear the interrupt
+	 * source.  Therefore, the completion handler must ensure that the
+	 * interrupt source is cleared.  Otherwise, we get a spurious
+	 * interrupt for which the interrupt handler will not issue a
+	 * corresponding completion event. Also, we unmask interrupts.
+	 */
+	SMU_ISR_WRITE(
+		scic,
+		(u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
+		);
+}
+
+/**
+ * This is the method provided to handle legacy interrupts for the controller
+ *    object.
+ *
+ * bool true if an interrupt is processed false if no interrupt was processed
+ */
+static bool scic_sds_controller_legacy_interrupt_handler(
+	struct scic_sds_controller *scic)
+{
+	u32 interrupt_status;
+	bool is_completion_needed;
+
+	interrupt_status     = SMU_ISR_READ(scic);
+	is_completion_needed = scic_sds_controller_standard_interrupt_handler(
+		scic, interrupt_status);
+
+	return is_completion_needed;
+}
+
+
+/**
+ * This is the method provided to handle legacy completions it is expected that
+ *    the SCI User will call this completion handler anytime the interrupt
+ *    handler reports that it has handled an interrupt.
+ */
+static void scic_sds_controller_legacy_completion_handler(
+	struct scic_sds_controller *scic)
+{
+	scic_sds_controller_polling_completion_handler(scic);
+	SMU_IMR_WRITE(scic, 0x00000000);
+}
+
+/**
+ * This is the method provided to handle an MSIX interrupt message when there
+ *    is just a single MSIX message being provided by the hardware.  This mode
+ *    of operation is single vector mode.
+ *
+ * bool true if an interrupt is processed false if no interrupt was processed
+ */
+static bool scic_sds_controller_single_vector_interrupt_handler(
+	struct scic_sds_controller *scic)
+{
+	u32 interrupt_status;
+
+	/*
+	 * Mask the interrupts
+	 * 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 unmask
+	 * the interrupts in the completion routine. */
+	SMU_IMR_WRITE(scic, 0xFFFFFFFF);
+
+	interrupt_status = SMU_ISR_READ(scic);
+	interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+	if ((interrupt_status == 0) &&
+	    scic_sds_controller_completion_queue_has_entries(scic)) {
+		/*
+		 * There is at least one completion queue entry to process so we can
+		 * return a success and ignore for now the case of an error interrupt */
+		SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION);
+		return true;
+	}
+
+	if (interrupt_status != 0) {
+		/*
+		 * There is an error interrupt pending so let it through and handle
+		 * in the callback */
+		return true;
+	}
+
+	/*
+	 * Clear any offending interrupts since we could not find any to handle
+	 * and unmask them all */
+	SMU_ISR_WRITE(scic, 0x00000000);
+	SMU_IMR_WRITE(scic, 0x00000000);
+
+	return false;
+}
+
+/**
+ * This is the method provided to handle completions for a single MSIX message.
+ */
+static void scic_sds_controller_single_vector_completion_handler(
+	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 & SMU_ISR_QUEUE_ERROR) {
+		dev_err(scic_to_dev(scic),
+			"%s: SCIC Controller has encountered a fatal error.\n",
+			__func__);
+
+		/*
+		 * We have a fatal condition and must reset the controller
+		 * Leave the interrupt mask in place and get the controller reset */
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(scic),
+			SCI_BASE_CONTROLLER_STATE_FAILED);
+		return;
+	}
+
+	if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
+	    !scic_sds_controller_completion_queue_has_entries(scic)) {
+		dev_err(scic_to_dev(scic),
+			"%s: SCIC Controller has encountered a fatal error.\n",
+			__func__);
+
+		/*
+		 * We have a fatal condtion and must reset the controller
+		 * Leave the interrupt mask in place and get the controller reset */
+		sci_base_state_machine_change_state(
+			scic_sds_controller_get_base_state_machine(scic),
+			SCI_BASE_CONTROLLER_STATE_FAILED);
+		return;
+	}
+
+	if (scic_sds_controller_completion_queue_has_entries(scic)) {
+		scic_sds_controller_process_completions(scic);
+
+		/*
+		 * We dont care which interrupt got us to processing the completion queu
+		 * so clear them both. */
+		SMU_ISR_WRITE(
+			scic,
+			(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND));
+	}
+
+	SMU_IMR_WRITE(scic, 0x00000000);
+}
+
+/**
+ * This is the method provided to handle a MSIX message for a normal completion.
+ *
+ * bool true if an interrupt is processed false if no interrupt was processed
+ */
+static bool scic_sds_controller_normal_vector_interrupt_handler(
+	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;
+}
+
+/**
+ * This is the method provided to handle the completions for a normal MSIX
+ *    message.
+ */
+static void scic_sds_controller_normal_vector_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);
+}
+
+/**
+ * This is the method provided to handle the error MSIX message interrupt.
+ *    This is the normal operating mode for the hardware if MSIX is enabled.
+ *
+ * bool true if an interrupt is processed false if no interrupt was processed
+ */
+static bool scic_sds_controller_error_vector_interrupt_handler(
+	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;
+}
+
+/**
+ * This is the method provided to handle the error completions when the
+ *    hardware is using two MSIX messages.
+ */
+static void scic_sds_controller_error_vector_completion_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: SCIC Controller reports CRC error on completion "
+			"ISR %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);
+}
+
+
+/*
+ * ****************************************************************************-
+ * * SCIC SDS Controller External Methods
+ * ****************************************************************************- */
+
+/**
+ * This method returns the sizeof the SCIC SDS Controller Object
+ */
+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_warn(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_warn(scic_to_dev(scic),
+			"%s: SCIC Controller linkdown 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)));
+}
+
+/**
+ * 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] != SCI_INVALID_HANDLE) {
+			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 SCI_INVALID_HANDLE;
+}
+
+/**
+ * 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] = SCI_INVALID_HANDLE;
+
+		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] != SCI_INVALID_HANDLE)
+		) {
+		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 *this_controller)
+{
+	u16 index;
+
+	/* Default to no SSC operation. */
+	this_controller->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++) {
+		this_controller->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. */
+		this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
+
+		/*
+		 * 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. */
+		this_controller->oem_parameters.sds1.phys[index].sas_address.low
+			= 0x00000001;
+		this_controller->oem_parameters.sds1.phys[index].sas_address.high
+			= 0x5FCFFFFF;
+	}
+
+	this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
+	this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
+	this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
+	this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
+	this_controller->user_parameters.sds1.no_outbound_task_timeout = 5;
+
+}
+
+
+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 == SCI_INVALID_HANDLE)
+		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_status scic_controller_get_handler_methods(
+	enum scic_interrupt_type interrupt_type,
+	u16 message_count,
+	struct scic_controller_handler_methods *handler_methods)
+{
+	enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
+
+	switch (interrupt_type) {
+	case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
+		if (message_count == 0) {
+			handler_methods[0].interrupt_handler
+				= scic_sds_controller_legacy_interrupt_handler;
+			handler_methods[0].completion_handler
+				= scic_sds_controller_legacy_completion_handler;
+
+			status = SCI_SUCCESS;
+		}
+		break;
+
+	case SCIC_MSIX_INTERRUPT_TYPE:
+		if (message_count == 1) {
+			handler_methods[0].interrupt_handler
+				= scic_sds_controller_single_vector_interrupt_handler;
+			handler_methods[0].completion_handler
+				= scic_sds_controller_single_vector_completion_handler;
+
+			status = SCI_SUCCESS;
+		} else if (message_count == 2) {
+			handler_methods[0].interrupt_handler
+				= scic_sds_controller_normal_vector_interrupt_handler;
+			handler_methods[0].completion_handler
+				= scic_sds_controller_normal_vector_completion_handler;
+
+			handler_methods[1].interrupt_handler
+				= scic_sds_controller_error_vector_interrupt_handler;
+			handler_methods[1].completion_handler
+				= scic_sds_controller_error_vector_completion_handler;
+
+			status = SCI_SUCCESS;
+		}
+		break;
+
+	case SCIC_NO_INTERRUPTS:
+		if (message_count == 0) {
+
+			handler_methods[0].interrupt_handler
+				= scic_sds_controller_polling_interrupt_handler;
+			handler_methods[0].completion_handler
+				= scic_sds_controller_polling_completion_handler;
+
+			status = SCI_SUCCESS;
+		}
+		break;
+
+	default:
+		status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+		break;
+	}
+
+	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. */
+	scic_cb_stall_execution(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;
+		}
+
+		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 = scic_cb_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 */
+			scic_cb_stall_execution(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].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.pe[index].tl,
+				&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 (SCI_SUCCESS == result) {
+		/* 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 (SCI_SUCCESS == result) {
+		/*
+		 * 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);
+	}
+
+	if (SCI_SUCCESS == result) {
+		scic_sds_controller_start_next_phy(this_controller);
+
+		scic_cb_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;
+
+	scic_cb_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] = SCI_INVALID_HANDLE;
+	}
+
+	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.
+ * @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 task handler is called. - This function is not yet
+ * implemented enum sci_status SCI_FAILURE
+ */
+
+/*
+ * *****************************************************************************
+ * * STOPPED STATE HANDLERS
+ * ***************************************************************************** */
+
+/*
+ * *****************************************************************************
+ * * FAILED STATE HANDLERS
+ * ***************************************************************************** */
+
+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,
+	},
+	[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;
+
+	scic_cb_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;
+
+	scic_cb_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..afa45f9
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_controller.h
@@ -0,0 +1,706 @@
+/*
+ * 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_
+
+/**
+ * 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;
+
+	/**
+	 * This field records the fact that the controller has encountered a fatal
+	 * error and must be reset.
+	 */
+	bool encountered_fatal_error;
+
+	/**
+	 * This field specifies that the controller should ignore
+	 * completion processing for non-fastpath events.  This will
+	 * cause the completions to be thrown away.
+	 */
+	bool restrict_completions;
+
+	/* 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 *);
+/**
+ * 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;
+};
+
+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 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);
+
+
+void scic_sds_controller_initialize_phy_startup(
+	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_ */
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..2132677
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_pci.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 _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>
+#include "sci_types.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_ */
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..7d012b5
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy.c
@@ -0,0 +1,2807 @@
+/*
+ * 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_user_callback.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)
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY Internal Methods
+ * ***************************************************************************** */
+
+/**
+ * This method will initialize the phy link layer registers
+ * @this_phy:
+ * @link_layer_registers:
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_phy_link_layer_initialization(
+	struct scic_sds_phy *this_phy,
+	struct scu_link_layer_registers *link_layer_registers)
+{
+	u32 phy_configuration;
+	struct sas_capabilities phy_capabilities;
+	u32 parity_check = 0;
+	u32 parity_count = 0;
+	u32 link_layer_control;
+
+	this_phy->link_layer_registers = link_layer_registers;
+
+	/* Set our IDENTIFY frame data */
+   #define SCI_END_DEVICE 0x01
+
+	SCU_SAS_TIID_WRITE(
+		this_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(this_phy, 0xFEDCBA98);
+	SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index);
+
+	/* Write the source SAS Address */
+	SCU_SAS_TISSAH_WRITE(
+		this_phy,
+		this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
+			this_phy->phy_index].sas_address.high
+		);
+	SCU_SAS_TISSAL_WRITE(
+		this_phy,
+		this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
+			this_phy->phy_index].sas_address.low
+		);
+
+	/* Clear and Set the PHY Identifier */
+	SCU_SAS_TIPID_WRITE(this_phy, 0x00000000);
+	SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index));
+
+	/* Change the initial state of the phy configuration register */
+	phy_configuration = SCU_SAS_PCFG_READ(this_phy);
+
+	/* Hold OOB state machine in reset */
+	phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+	SCU_SAS_PCFG_WRITE(this_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 (this_phy->owning_port->owning_controller->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(this_phy, phy_capabilities.u.all);
+
+	/* Set the enable spinup period but disable the ability to send notify enable spinup */
+	SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, 0x33));
+
+#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA)
+	/* / @todo Provide a way to write this register correctly */
+	scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
+#else
+	/* / @todo Provide a way to write this register correctly */
+	scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7);
+#endif
+
+	link_layer_control = SCU_SAS_LLCTL_GEN_VAL(
+		NO_OUTBOUND_TASK_TIMEOUT,
+		(u8)this_phy->owning_port->owning_controller->
+		user_parameters.sds1.no_outbound_task_timeout
+		);
+
+/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 */
+/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 */
+#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3
+
+	if (this_phy->owning_port->owning_controller->user_parameters.sds1.
+	    phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) {
+		link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+			MAX_LINK_RATE, COMPILED_MAX_LINK_RATE
+			);
+	} else if (this_phy->owning_port->owning_controller->user_parameters.sds1.
+		   phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) {
+		link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+			MAX_LINK_RATE,
+			min(
+				SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2,
+				COMPILED_MAX_LINK_RATE)
+			);
+	} else {
+		link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+			MAX_LINK_RATE,
+			min(
+				SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1,
+				COMPILED_MAX_LINK_RATE)
+			);
+	}
+
+	scu_link_layer_register_write(
+		this_phy, link_layer_control, link_layer_control
+		);
+
+	/*
+	 * 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. */
+#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2)
+	scu_link_layer_register_write(
+		this_phy,
+		maximum_arbitration_wait_timer_timeout,
+		SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME
+		);
+#endif  /* defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) */
+
+	/*
+	 * 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(
+		this_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(this_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.
+ */
+static 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
+		);
+}
+
+/*
+ * *****************************************************************************
+ * * SCIC SDS PHY External Methods
+ * ***************************************************************************** */
+
+/**
+ * This method returns the object size for a phy object.
+ *
+ * u32
+ */
+
+/**
+ * This method returns the minimum number of timers required for a phy object.
+ *
+ * u32
+ */
+
+/**
+ * This method returns the maximum number of timers required for a phy object.
+ *
+ * u32
+ */
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * scic_sds_phy_observe_state_change() -
+ * @our_observer:
+ *
+ * Debug code to record the state transitions in the phy
+ */
+void scic_sds_phy_observe_state_change(
+	struct sci_base_observer *our_observer,
+	struct sci_base_subject *the_subject)
+{
+	struct scic_sds_phy *this_phy;
+	struct sci_base_state_machine *the_state_machine;
+
+	u8 transition_requestor;
+	u32 base_state_id;
+	u32 starting_substate_id;
+
+	the_state_machine = (struct sci_base_state_machine *)the_subject;
+	this_phy = (struct scic_sds_phy *)the_state_machine->state_machine_owner;
+
+	if (the_state_machine == &this_phy->parent.state_machine) {
+		transition_requestor = 0x01;
+	} else if (the_state_machine == &this_phy->starting_substate_machine) {
+		transition_requestor = 0x02;
+	} else {
+		transition_requestor = 0xFF;
+	}
+
+	base_state_id =
+		sci_base_state_machine_get_state(&this_phy->parent.state_machine);
+	starting_substate_id =
+		sci_base_state_machine_get_state(&this_phy->starting_substate_machine);
+
+	this_phy->state_record.state_transition_table[
+		this_phy->state_record.index++] = ((transition_requestor << 24)
+						   | ((u8)base_state_id << 8)
+						   | ((u8)starting_substate_id));
+
+	this_phy->state_record.index =
+		this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1);
+
+}
+#endif /* SCIC_DEBUG_ENABLED */
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * scic_sds_phy_initialize_state_recording() -
+ *
+ * This method initializes the state record debug information for the phy
+ * object. The state machines for the phy object must be constructed before
+ * this function is called.
+ */
+void scic_sds_phy_initialize_state_recording(
+	struct scic_sds_phy *this_phy)
+{
+	this_phy->state_record.index = 0;
+
+	sci_base_observer_initialize(
+		&this_phy->state_record.base_state_observer,
+		scic_sds_phy_observe_state_change,
+		&this_phy->parent.state_machine.parent
+		);
+
+	sci_base_observer_initialize(
+		&this_phy->state_record.starting_state_observer,
+		scic_sds_phy_observe_state_change,
+		&this_phy->starting_substate_machine.parent
+		);
+}
+#endif /* SCIC_DEBUG_ENABLED */
+
+/**
+ * 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;
+
+	/* 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
+		);
+
+   #ifdef SCIC_DEBUG_ENABLED
+	scic_sds_phy_initialize_state_recording(this_phy);
+   #endif /* SCIC_DEBUG_ENABLED */
+}
+
+/**
+ * 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.
+ * SCI_INVALID_HANDLE This value is returned if the phy is not part of a real
+ * port (i.e. it's contained in the dummy port). !SCI_INVALID_HANDLE 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 SCI_INVALID_HANDLE;
+
+	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_link_layer_registers *link_layer_registers)
+{
+	/* Create the SIGNATURE FIS Timeout timer for this phy */
+	sci_phy->sata_timeout_timer = scic_cb_timer_create(
+		scic_sds_phy_get_controller(sci_phy),
+		scic_sds_phy_sata_timeout,
+		sci_phy
+		);
+
+	/* 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_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);
+}
+
+/**
+ *
+ * @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
+ * @this_phy:
+ *
+ * enum sci_status
+ */
+enum sci_status scic_sds_phy_start(
+	struct scic_sds_phy *this_phy)
+{
+	return this_phy->state_handlers->parent.start_handler(&this_phy->parent);
+}
+
+/**
+ * This method will attempt to stop the phy object.
+ * @this_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 *this_phy)
+{
+	return this_phy->state_handlers->parent.stop_handler(&this_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 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_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_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;
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_phy_state_handler
+scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
+{
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_ossp_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_starting_substate_await_iaf_uf_frame_handler,
+		scic_sds_phy_starting_substate_await_iaf_uf_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_sas_power_event_handler,
+		scic_sds_phy_starting_substate_await_sas_power_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_sata_power_event_handler,
+		scic_sds_phy_starting_substate_await_sata_power_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_sata_phy_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_starting_substate_await_sata_speed_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
+		scic_sds_phy_starting_substate_await_sig_fis_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_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
+		);
+
+	scic_cb_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;
+
+	scic_cb_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
+		);
+
+	scic_cb_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;
+
+	scic_cb_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);
+
+		scic_cb_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;
+
+	scic_cb_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 *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 stop 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 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_warn(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;
+
+	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) != SCI_INVALID_HANDLE)
+			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;
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_phy_state_handler
+scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] =
+{
+	/* SCI_BASE_PHY_STATE_INITIAL */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCI_BASE_PHY_STATE_STOPPED */
+	{
+		{
+			scic_sds_phy_stopped_state_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_stopped_state_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCI_BASE_PHY_STATE_STARTING */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCI_BASE_PHY_STATE_READY */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_ready_state_stop_handler,
+			scic_sds_phy_ready_state_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_ready_state_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCI_BASE_PHY_STATE_RESETTING */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_resetting_state_event_handler,
+		scic_sds_phy_default_consume_power_handler
+	},
+	/* SCI_BASE_PHY_STATE_FINAL */
+	{
+		{
+			scic_sds_phy_default_start_handler,
+			scic_sds_phy_default_stop_handler,
+			scic_sds_phy_default_reset_handler,
+			scic_sds_phy_default_destroy_handler
+		},
+		scic_sds_phy_default_frame_handler,
+		scic_sds_phy_default_event_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_STOPPED);
+}
+
+/**
+ *
+ * @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 *this_phy;
+
+	this_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(this_phy, SCI_BASE_PHY_STATE_STOPPED);
+
+	scu_link_layer_stop_protocol_engine(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_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..d9691b3
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy.h
@@ -0,0 +1,491 @@
+/*
+ * 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,
+
+	/**
+	 * Maximum number of substates for the STARTING state machine
+	 */
+	SCIC_SDS_PHY_STARTING_MAX_SUBSTATES
+};
+
+struct scic_sds_port;
+struct scic_sds_controller;
+
+#ifdef SCIC_DEBUG_ENABLED
+#define MAX_STATE_TRANSITION_RECORD    (256)
+
+/**
+ *
+ *
+ * Debug code to record the state transitions for the phy object
+ */
+struct scic_sds_phy_state_record {
+	struct sci_base_observer base_state_observer;
+	struct sci_base_observer starting_state_observer;
+
+	u16 index;
+
+	u32 state_transition_table[MAX_STATE_TRANSITION_RECORD];
+
+};
+#endif /* SCIC_DEBUG_ENABLED */
+
+/**
+ * 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;
+
+	struct scic_sds_phy_state_handler *state_handlers;
+
+	struct sci_base_state_machine starting_substate_machine;
+
+   #ifdef SCIC_DEBUG_ENABLED
+	struct scic_sds_phy_state_record state_record;
+   #endif /* SCIC_DEBUG_ENABLED */
+
+	/**
+	 * This field points to the link layer register set within the SCU.
+	 */
+	struct scu_link_layer_registers *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 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 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_link_layer_registers *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_suspend(
+	struct scic_sds_phy *this_phy);
+
+void scic_sds_phy_resume(
+	struct scic_sds_phy *this_phy);
+
+/* --------------------------------------------------------------------------- */
+
+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..7883819
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h
@@ -0,0 +1,187 @@
+/*
+ * 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 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 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_ */
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..1af3850
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port.c
@@ -0,0 +1,2757 @@
+/*
+ * 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 "scic_user_callback.h"
+#include "sci_environment.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)
+
+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] == SCI_INVALID_HANDLE)
+		&& (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE)
+		&& 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] = SCI_INVALID_HANDLE;
+
+		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;
+}
+
+/**
+ * This method returns the amount of memory requred for a port object.
+ *
+ * u32
+ */
+
+/**
+ * This method returns the minimum number of timers required for all port
+ *    objects.
+ *
+ * u32
+ */
+
+/**
+ * This method returns the maximum number of timers required for all port
+ *    objects.
+ *
+ * u32
+ */
+
+/**
+ *
+ * @this_port:
+ * @port_index:
+ *
+ *
+ */
+void scic_sds_port_construct(
+	struct scic_sds_port *this_port,
+	u8 port_index,
+	struct scic_sds_controller *owning_controller)
+{
+	u32 index;
+
+	sci_base_port_construct(
+		&this_port->parent,
+		scic_sds_port_state_table
+		);
+
+	sci_base_state_machine_construct(
+		scic_sds_port_get_ready_substate_machine(this_port),
+		&this_port->parent.parent,
+		scic_sds_port_ready_substate_table,
+		SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+		);
+
+	this_port->logical_port_index  = SCIC_SDS_DUMMY_PORT;
+	this_port->physical_port_index = port_index;
+	this_port->active_phy_mask     = 0;
+
+	this_port->owning_controller = owning_controller;
+
+	this_port->started_request_count = 0;
+	this_port->assigned_device_count = 0;
+
+	this_port->timer_handle = SCI_INVALID_HANDLE;
+
+	this_port->transport_layer_registers = NULL;
+	this_port->port_task_scheduler_registers = NULL;
+
+	for (index = 0; index < SCI_MAX_PHYS; index++) {
+		this_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 *transport_layer_registers,
+	void *port_task_scheduler_registers,
+	void *port_configuration_regsiter,
+	void *viit_registers)
+{
+	u32 tl_control;
+
+	this_port->transport_layer_registers      = transport_layer_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;
+
+	scic_sds_port_set_direct_attached_device_id(
+		this_port,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+		);
+
+	/*
+	 * Hardware team recommends that we enable the STP prefetch
+	 * for all ports */
+	tl_control = SCU_TLCR_READ(this_port);
+	tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
+	SCU_TLCR_WRITE(this_port, tl_control);
+
+	/*
+	 * If this is not the dummy port make the assignment of
+	 * the timer and start the state machine */
+	if (this_port->physical_port_index != SCI_MAX_PORTS) {
+		/* / @todo should we create the timer at create time? */
+		this_port->timer_handle = scic_cb_timer_create(
+			scic_sds_port_get_controller(this_port),
+			scic_sds_port_timeout_handler,
+			this_port
+			);
+
+	} else {
+		/*
+		 * Force the dummy port into a condition where it rejects all requests
+		 * as its in an invalid state for any operation.
+		 * / @todo should we set a set of specical handlers for the dummy port? */
+		scic_sds_port_set_base_state_handlers(
+			this_port, SCI_BASE_PORT_STATE_STOPPED
+			);
+	}
+
+	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_start(struct scic_sds_port *port)
+{
+	return port->state_handlers->parent.start_handler(&port->parent);
+}
+
+
+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 == SCI_INVALID_HANDLE) ||
+	    (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_port: The port for which the direct attached device id is to be
+ *    assigned.
+ *
+ * This method assigns the direct attached device ID for this port.
+ */
+void scic_sds_port_set_direct_attached_device_id(
+	struct scic_sds_port *this_port,
+	u32 device_id)
+{
+	u32 tl_control;
+
+	SCU_STPTLDARNI_WRITE(this_port, device_id);
+
+	/*
+	 * The read should guarntee that the first write gets posted
+	 * before the next write */
+	tl_control = SCU_TLCR_READ(this_port);
+	tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
+	SCU_TLCR_WRITE(this_port, tl_control);
+}
+
+
+/**
+ *
+ * @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)
+		scic_cb_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
+ *    scic_cb_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)
+		scic_cb_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);
+
+		scic_cb_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 */
+		scic_cb_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);
+	}
+}
+
+/* --------------------------------------------------------------------------- */
+
+#ifdef SCIC_DEBUG_ENABLED
+void scic_sds_port_decrement_request_count(struct scic_sds_port *this_port)
+{
+	if (this_port->started_request_count == 0)
+		dev_warn(sciport_to_dev(this_port),
+			 __func__,
+			 "%s: SCIC Port object requested to decrement started "
+			 "io count past zero.\n");
+	else
+		this_port->started_request_count--;
+}
+#endif
+
+/**
+ * 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. */
+	scic_cb_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 = SCI_INVALID_HANDLE;
+
+
+	/* Select a phy on which we can send the hard reset request. */
+	for (
+		phy_index = 0;
+		(phy_index < SCI_MAX_PHYS)
+		&& (selected_phy == SCI_INVALID_HANDLE);
+		phy_index++
+		) {
+		selected_phy = this_port->phy_table[phy_index];
+
+		if (
+			(selected_phy != SCI_INVALID_HANDLE)
+			&& !scic_sds_port_active_phy(this_port, selected_phy)
+			) {
+			/* We found a phy but it is not ready select different phy */
+			selected_phy = SCI_INVALID_HANDLE;
+		}
+	}
+
+	/* If we have a phy then go ahead and start the reset procedure */
+	if (selected_phy != SCI_INVALID_HANDLE) {
+		status = scic_sds_phy_reset(selected_phy);
+
+		if (status == SCI_SUCCESS) {
+			scic_cb_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;
+	u32 tl_control_value;
+
+	pts_control_value = scu_port_task_scheduler_read(this_port, control);
+	tl_control_value = scu_transport_layer_read(this_port, control);
+
+	pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
+	tl_control_value  |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
+
+	scu_port_task_scheduler_write(this_port, control, pts_control_value);
+	scu_transport_layer_write(this_port, control, tl_control_value);
+}
+
+/**
+ *
+ * @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
+		);
+
+	scic_cb_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);
+}
+
+/**
+ *
+ * @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;
+
+	scic_cb_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) {
+		scic_cb_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
+ * **************************************************************************** */
+
+/**
+ *
+ * @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 *port)
+{
+	u32 phy_mask;
+	struct scic_sds_port *this_port = (struct scic_sds_port *)port;
+
+	if (this_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;
+	}
+
+	phy_mask = scic_sds_port_get_phys(this_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(this_port, phy_mask) == true) {
+		sci_base_state_machine_change_state(
+			scic_sds_port_get_base_state_machine(this_port),
+			SCI_BASE_PORT_STATE_READY
+			);
+
+		return SCI_SUCCESS;
+	}
+
+	return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+}
+
+/**
+ *
+ * @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);
+}
+
+/*
+ * ******************************************************************************
+ * *  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
+		) {
+		scic_cb_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 */
+		scic_cb_port_not_ready(
+			scic_sds_port_get_controller(this_port),
+			this_port,
+			SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
+			);
+	}
+
+	/* 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);
+}
+
+/**
+ *
+ * @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
+		);
+
+	scic_sds_port_set_direct_attached_device_id(
+		this_port,
+		SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+		);
+}
+
+/**
+ *
+ * @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;
+
+	scic_cb_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;
+
+	scic_cb_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_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
+		);
+
+	scic_cb_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..bbb9de5
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port.h
@@ -0,0 +1,514 @@
+/*
+ * 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 "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
+
+/**
+ * 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;
+
+	/**
+	 * 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 transport layer register for the SCU
+	 * hardware.
+	 */
+	struct scu_transport_layer_registers *transport_layer_registers;
+
+	/**
+	 * This field is the pointer to the port task scheduler registers for the SCU
+	 * hardware.
+	 */
+	struct scu_port_task_scheduler_registers *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 *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)
+
+/**
+ * scic_sds_port_increment_request_count() -
+ *
+ * Helper macro to increment the started request count
+ */
+#define scic_sds_port_increment_request_count(this_port) \
+	((this_port)->started_request_count++)
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * scic_sds_port_decrement_request_count() - This method decrements the started
+ *    io request count.  The method will not decrment the started io request
+ *    count below 0 and will log a debug message if this is attempted.
+ *
+ *
+ */
+void scic_sds_port_decrement_request_count(
+	struct scic_sds_port *this_port);
+#else
+/**
+ * scic_sds_port_decrement_request_count() -
+ *
+ * Helper macro to decrement the started io request count.  The macro will not
+ * decrement the started io request count below 0.
+ */
+#define scic_sds_port_decrement_request_count(this_port) \
+	(\
+		(this_port)->started_request_count = (\
+			((this_port)->started_request_count == 0) ? \
+			(this_port)->started_request_count : \
+			((this_port)->started_request_count - 1) \
+			) \
+			)
+#endif
+
+/**
+ * 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 *transport_layer_registers,
+	void *port_task_scheduler_registers,
+	void *port_configuration_regsiter,
+	void *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_set_direct_attached_device_id(
+	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..37d4469
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
@@ -0,0 +1,851 @@
+/*
+ * 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 SCI_INVALID_HANDLE if there is no matching
+ * port. port address if the port can be found to match the phy.
+ * SCI_INVALID_HANDLE 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 SCI_INVALID_HANDLE;
+}
+
+/**
+ *
+ * @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 SCI_INVALID_HANDLE.
+ * @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 != SCI_INVALID_HANDLE) {
+		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 SCI_INVALID_HANDLE.  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 != SCI_INVALID_HANDLE) {
+		/*
+		 * 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;
+
+			scic_cb_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) {
+		scic_cb_timer_stop(controller, port_agent->timer);
+	}
+
+	port_agent->timer_pending = true;
+
+	scic_cb_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 != SCI_INVALID_HANDLE) {
+		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;
+	}
+}
+
+/**
+ *
+ * @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 SCI_INVALID_HANDLE.
+ * @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 *controller,
+	struct scic_sds_port_configuration_agent *port_agent,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	BUG_ON(port != SCI_INVALID_HANDLE);
+
+	port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
+
+	scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true);
+}
+
+/**
+ *
+ * @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 SCI_INVALID_HANDLE.
+ * @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 != SCI_INVALID_HANDLE) {
+		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 = scic_cb_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 = scic_cb_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..cf8bc07
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_port_registers.h
@@ -0,0 +1,223 @@
+/*
+ * 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_transport_layer_read() -
+ *
+ * Macro to read the transport layer register associated with this port object.
+ */
+#define scu_transport_layer_read(port, reg) \
+	scu_register_read(\
+		scic_sds_port_get_controller(port), \
+		(port)->transport_layer_registers->reg \
+		)
+
+/**
+ * scu_transport_layer_write() -
+ *
+ * Macro to write the transport layer register associated with this port object.
+ */
+#define scu_transport_layer_write(port, reg, value) \
+	scu_register_write(\
+		scic_sds_port_get_controller(port), \
+		(port)->transport_layer_registers->reg,	\
+		(value)	\
+		)
+
+/**
+ * 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)	\
+		)
+
+/*
+ * ****************************************************************************
+ * * Transport Layer registers controlled by the port object
+ * **************************************************************************** */
+
+/**
+ * SCU_TLCR_READ() -
+ *
+ * This macro reads the Transport layer control register
+ */
+#define SCU_TLCR_READ(port) \
+	scu_transport_layer_read(port, control)
+
+/**
+ * SCU_TLCR_WRITE() -
+ *
+ * This macro writes the Transport layer control register
+ */
+#define SCU_TLCR_WRITE(port, value) \
+	scu_transport_layer_write(port, control, value)
+
+/**
+ * SCU_TLADTR_READ() -
+ *
+ * This macro reads the Transport layer address translation register
+ */
+#define SCU_TLADTR_READ(port) \
+	scu_transport_layer_read(port, address_translation)
+
+/**
+ * SCU_TLADTR_WRITE() -
+ *
+ * This macro writes the Transport layer address translation register
+ */
+#define SCU_TLADTR_WRITE(port) \
+	scu_transport_layer_write(port, address_translation, value)
+
+/**
+ * SCU_STPTLDARNI_WRITE() -
+ *
+ * This macro writes the STP Transport Layer Direct Attached RNi register.
+ */
+#define SCU_STPTLDARNI_WRITE(port, index) \
+	scu_transport_layer_write(port, stp_rni, index)
+
+/**
+ * SCU_STPTLDARNI_READ() -
+ *
+ * This macro reads the STP Transport Layer Direct Attached RNi register.
+ */
+#define SCU_STPTLDARNI_READ(port) \
+	scu_transport_layer_read(port, stp_rni)
+
+/*
+ * ****************************************************************************
+ * * 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_ */
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..21f03bc
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_device.c
@@ -0,0 +1,2252 @@
+/*
+ * 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 remote device methods.
+ *
+ *
+ */
+
+#include "intel_sas.h"
+#include "sci_util.h"
+#include "sci_environment.h"
+#include "scic_port.h"
+#include "scic_phy.h"
+#include "scic_remote_device.h"
+#include "scic_sds_port.h"
+#include "scic_sds_phy.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_controller.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
+/*
+ * 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 state handlers for the struct scic_sds_remote_device for the
+ *    base state machine.
+ *
+ *
+ */
+
+#include "sci_environment.h"
+#include "scic_user_callback.h"
+#include "scic_controller.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_request.h"
+#include "scic_sds_remote_node_context.h"
+#include "scu_event_codes.h"
+
+/*
+ * *****************************************************************************
+ * *  PROTECTED METHODS
+ * ***************************************************************************** */
+
+/**
+ *
+ * @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(
+	struct scic_sds_remote_device *this_device)
+{
+	/* we need to check if this request is still valid to continue. */
+	if (this_device->working_request != NULL) {
+		struct scic_sds_request *this_request = this_device->working_request;
+		struct scic_sds_controller *scic = this_request->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, &this_request->target_device->parent,
+			    &this_request->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 == SCI_INVALID_HANDLE)
+		    || (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
+		);
+
+	scic_sds_port_set_direct_attached_device_id(
+		this_device->owning_port,
+		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
+ */
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_remote_device_state_handler
+scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
+{
+	/* SCI_BASE_REMOTE_DEVICE_STATE_INITIAL */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_default_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_default_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_STOPPED */
+	{
+		{
+			scic_sds_remote_device_stopped_state_start_handler,
+			scic_sds_remote_device_stopped_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_stopped_state_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_default_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_STARTING */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_starting_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_READY */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_ready_state_start_io_handler,
+			scic_sds_remote_device_ready_state_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_ready_state_start_task_handler,
+			scic_sds_remote_device_ready_state_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_general_frame_handler,
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_STOPPING */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_stopping_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_stopping_state_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_stopping_state_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_FAILED */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_default_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_default_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_RESETTING */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_resetting_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_resetting_state_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_resetting_state_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_resetting_state_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_default_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	},
+	/* SCI_BASE_REMOTE_DEVICE_STATE_FINAL */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_default_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_default_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	}
+};
+
+/*
+ * 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 operations that are taken on the enter and exit state
+ *    transitions for the struct sci_base_remote_device state machine.
+ *
+ *
+ */
+
+#include "scic_remote_device.h"
+#include "scic_user_callback.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+
+/**
+ *
+ * @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) {
+		scic_cb_remote_device_stop_complete(
+			scic_sds_remote_device_get_controller(this_device),
+			this_device,
+			SCI_SUCCESS
+			);
+	}
+}
+
+/**
+ *
+ * @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
+		);
+
+	scic_cb_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 */
+	scic_cb_remote_device_start_complete(
+		scic_sds_remote_device_get_controller(this_device),
+		this_device,
+		SCI_SUCCESS
+		);
+}
+
+/**
+ *
+ * @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 {
+		scic_cb_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 {
+		scic_cb_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_port_set_direct_attached_device_id(
+		scic_sds_remote_device_get_port(this_device),
+		this_device->rnc->remote_node_index
+		);
+
+	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..44185a2
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_device.h
@@ -0,0 +1,602 @@
+/*
+ * 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,
+
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+
+/**
+ * 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,
+
+	SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+
+
+
+/**
+ * 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.
+	 */
+	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 struct scic_sds_remote_device_state_handler
+	scic_sds_remote_device_state_handler_table[];
+extern struct scic_sds_remote_device_state_handler
+	scic_sds_ssp_remote_device_ready_substate_handler_table[];
+extern struct scic_sds_remote_device_state_handler
+	scic_sds_stp_remote_device_ready_substate_handler_table[];
+extern 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(
+	struct scic_sds_remote_device *this_device);
+
+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_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c
new file mode 100644
index 0000000..79fe9a8
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c
@@ -0,0 +1,1244 @@
+/*
+ * 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. */
+			scic_sds_port_set_direct_attached_device_id(
+				this_rnc->device->owning_port,
+				this_rnc->remote_node_index
+				);
+
+			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_set_direct_attached_device_id(
+				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
+		);
+
+	if (this_rnc->device->is_direct_attached) {
+		scic_sds_port_set_direct_attached_device_id(
+			this_rnc->device->owning_port,
+			SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+			);
+	}
+}
+
+/*
+ * *****************************************************************************
+ * * 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;
+
+	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
+		);
+
+	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..59eacf8
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h
@@ -0,0 +1,342 @@
+/*
+ * 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_types.h"
+#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..6ee5fbab
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.h
@@ -0,0 +1,196 @@
+/*
+ * 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_types.h"
+#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/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c
new file mode 100644
index 0000000..c696d24
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_request.c
@@ -0,0 +1,2179 @@
+/*
+ * 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 "scic_user_callback.h"
+#include "sci_environment.h"
+#include "sci_types.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_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)
+
+
+/**
+ * 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)
+	       + CACHE_LINE_SIZE
+	       + 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 *this_request)
+{
+	void *os_sge;
+	void *os_handle;
+	dma_addr_t physical_address;
+	u32 sgl_pair_index = 0;
+	struct scu_sgl_element_pair *scu_sgl_list   = NULL;
+	struct scu_sgl_element_pair *previous_pair  = NULL;
+
+	os_handle = scic_sds_request_get_user_request(this_request);
+	scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);
+
+	while (os_sge != NULL) {
+		scu_sgl_list =
+			scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);
+
+		SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
+
+		scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
+
+		if (os_sge != NULL) {
+			SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
+
+			scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
+		} else {
+			SCU_SGL_ZERO(scu_sgl_list->B);
+		}
+
+		if (previous_pair != NULL) {
+			scic_cb_io_request_get_physical_address(
+				scic_sds_request_get_controller(this_request),
+				this_request,
+				scu_sgl_list,
+				&physical_address
+				);
+
+			previous_pair->next_pair_upper =
+				upper_32_bits(physical_address);
+			previous_pair->next_pair_lower =
+				lower_32_bits(physical_address);
+		}
+
+		previous_pair = scu_sgl_list;
+		sgl_pair_index++;
+	}
+
+	if (scu_sgl_list != NULL) {
+		scu_sgl_list->next_pair_upper = 0;
+		scu_sgl_list->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 =
+		scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer);
+
+	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 =
+			scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
+	}
+}
+
+/**
+ * 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 *this_request)
+{
+	struct sci_ssp_command_iu *command_frame;
+	void *os_handle;
+	u32 cdb_length;
+	u32 *cdb_buffer;
+
+	command_frame =
+		(struct sci_ssp_command_iu *)this_request->command_buffer;
+
+	os_handle = scic_sds_request_get_user_request(this_request);
+
+	command_frame->lun_upper = 0;
+	command_frame->lun_lower = scic_cb_ssp_io_request_get_lun(os_handle);
+
+	((u32 *)command_frame)[2] = 0;
+
+	cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle);
+	cdb_buffer = (u32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle);
+
+	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 =
+		scic_cb_ssp_io_request_get_command_priority(os_handle);
+	command_frame->task_attribute =
+		scic_cb_ssp_io_request_get_task_attribute(os_handle);
+}
+
+
+/**
+ * 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 *this_request)
+{
+	struct sci_ssp_task_iu *command_frame;
+	void *os_handle;
+
+	command_frame =
+		(struct sci_ssp_task_iu *)this_request->command_buffer;
+
+	os_handle = scic_sds_request_get_user_request(this_request);
+
+	command_frame->lun_upper = 0;
+	command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle);
+
+	((u32 *)command_frame)[2] = 0;
+
+	command_frame->task_function =
+		scic_cb_ssp_task_request_get_function(os_handle);
+	command_frame->task_tag =
+		scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle);
+}
+
+
+/**
+ * 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 *this_request,
+	struct scu_task_context *task_context)
+{
+	dma_addr_t physical_address;
+	struct scic_sds_controller *owning_controller;
+	struct scic_sds_remote_device *target_device;
+	struct scic_sds_port *target_port;
+
+	owning_controller = scic_sds_request_get_controller(this_request);
+	target_device = scic_sds_request_get_device(this_request);
+	target_port = scic_sds_request_get_port(this_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(owning_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(this_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 (this_request->was_tag_assigned_by_user) {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			| scic_sds_io_tag_get_index(this_request->io_tag)
+			);
+	} else {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			/* This is not assigned because we have to wait until we get a TCi */
+			);
+	}
+
+	/* Copy the physical address for the command buffer to the SCU Task Context */
+	scic_cb_io_request_get_physical_address(
+		scic_sds_request_get_controller(this_request),
+		this_request,
+		this_request->command_buffer,
+		&physical_address
+		);
+
+	task_context->command_iu_upper =
+		upper_32_bits(physical_address);
+	task_context->command_iu_lower =
+		lower_32_bits(physical_address);
+
+	/* Copy the physical address for the response buffer to the SCU Task Context */
+	scic_cb_io_request_get_physical_address(
+		scic_sds_request_get_controller(this_request),
+		this_request,
+		this_request->response_buffer,
+		&physical_address
+		);
+
+	task_context->response_iu_upper =
+		upper_32_bits(physical_address);
+	task_context->response_iu_lower =
+		lower_32_bits(physical_address);
+}
+
+/**
+ * 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 *this_request,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction,
+	u32 transfer_length_bytes)
+{
+	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->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32);
+	task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME;
+
+	switch (data_direction) {
+	case SCI_IO_REQUEST_DATA_IN:
+	case SCI_IO_REQUEST_NO_DATA:
+		task_context->task_type = SCU_TASK_TYPE_IOREAD;
+		break;
+	case SCI_IO_REQUEST_DATA_OUT:
+		task_context->task_type = SCU_TASK_TYPE_IOWRITE;
+		break;
+	}
+
+	task_context->transfer_length_bytes = transfer_length_bytes;
+
+	if (task_context->transfer_length_bytes > 0) {
+		scic_sds_request_build_sgl(this_request);
+	}
+}
+
+
+/**
+ * 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 =
+			scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
+	}
+}
+
+/**
+ * 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 *this_request,
+	u8 sat_protocol,
+	u32 transfer_length,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction,
+	bool copy_rx_frame)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	switch (sat_protocol) {
+	case SAT_PROTOCOL_PIO_DATA_IN:
+	case SAT_PROTOCOL_PIO_DATA_OUT:
+		status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, copy_rx_frame);
+		break;
+
+	case SAT_PROTOCOL_UDMA_DATA_IN:
+	case SAT_PROTOCOL_UDMA_DATA_OUT:
+		status = scic_sds_stp_udma_request_construct(this_request, transfer_length, data_direction);
+		break;
+
+	case SAT_PROTOCOL_ATA_HARD_RESET:
+	case SAT_PROTOCOL_SOFT_RESET:
+		status = scic_sds_stp_soft_reset_request_construct(this_request);
+		break;
+
+	case SAT_PROTOCOL_NON_DATA:
+		status = scic_sds_stp_non_data_request_construct(this_request);
+		break;
+
+	case SAT_PROTOCOL_FPDMA:
+		status = scic_sds_stp_ncq_request_construct(this_request, transfer_length, data_direction);
+		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(this_request);
+		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(this_request->owning_controller),
+			"%s: SCIC IO Request 0x%p received un-handled "
+			"SAT Protocl %d.\n",
+			__func__, this_request, sat_protocol);
+
+		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)
+{
+	void *os_handle;
+
+	sci_req->protocol = SCIC_SSP_PROTOCOL;
+
+	os_handle = scic_sds_request_get_user_request(sci_req);
+
+	scu_ssp_io_request_construct_task_context(
+		sci_req,
+		scic_cb_io_request_get_data_direction(os_handle),
+		scic_cb_io_request_get_transfer_length(os_handle)
+		);
+
+
+	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 *this_stp_request;
+	u8 sat_protocol;
+	u32 transfer_length;
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction;
+	bool copy_rx_frame = false;
+
+	this_stp_request = (struct scic_sds_stp_request *)sci_req;
+
+	sci_req->protocol = SCIC_STP_PROTOCOL;
+
+	transfer_length =
+		scic_cb_io_request_get_transfer_length(sci_req->user_request);
+	data_direction =
+		scic_cb_io_request_get_data_direction(sci_req->user_request);
+
+	sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request);
+	copy_rx_frame = scic_cb_io_request_do_copy_rx_frames(this_stp_request->parent.user_request);
+
+	status = scic_io_request_construct_sata(
+		sci_req,
+		sat_protocol,
+		transfer_length,
+		data_direction,
+		copy_rx_frame
+		);
+
+	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 = scic_cb_request_get_sat_protocol(sci_req->user_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 *this_request)
+{
+	void *response_buffer;
+	u32 user_response_length;
+	u32 core_response_length;
+	struct sci_ssp_response_iu *ssp_response;
+
+	ssp_response = (struct sci_ssp_response_iu *)this_request->response_buffer;
+
+	response_buffer = scic_cb_ssp_task_request_get_response_data_address(
+		this_request->user_request
+		);
+
+	user_response_length = scic_cb_ssp_task_request_get_response_data_length(
+		this_request->user_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) {
+		scic_cb_io_request_complete(
+			scic_sds_request_get_controller(this_request),
+			scic_sds_request_get_device(this_request),
+			this_request,
+			this_request->sci_status
+			);
+	} else {
+		scic_cb_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..0691a75
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_request.h
@@ -0,0 +1,484 @@
+/*
+ * 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)
+
+#define CACHE_LINE_SIZE (64)
+#define scic_sds_request_align_task_context_buffer(address) \
+	((struct scu_task_context *)(\
+		 (((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \
+		 & ~(CACHE_LINE_SIZE - 1) \
+		 ))
+
+/**
+ * scic_sds_request_align_sgl_element_buffer() -
+ *
+ * This macro will align the memory address so that it is correct for the SCU
+ * hardware to DMA the SGL element pairs.
+ */
+#define scic_sds_request_align_sgl_element_buffer(address) \
+	((struct scu_sgl_element_pair *)(\
+		 ((char *)(address)) \
+		 + (\
+			 ((~(unsigned long)(address)) + 1) \
+			 & (sizeof(struct scu_sgl_element_pair) - 1)	\
+			 ) \
+		 ))
+
+/**
+ * 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(os_handle, scu_sge, os_sge) \
+	{ \
+		(scu_sge).length = \
+			scic_cb_sge_get_length_field(os_handle, os_sge); \
+		(scu_sge).address_upper = \
+			upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
+		(scu_sge).address_lower = \
+			lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
+		(scu_sge).address_modifier = 0;	\
+	}
+
+/*
+ * *****************************************************************************
+ * * 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_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c
new file mode 100644
index 0000000..7cf78d3
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c
@@ -0,0 +1,410 @@
+/*
+ * 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 This file contains the ready substate handlers for a SMP
+ *    device.
+ *
+ *
+ */
+
+#include "sci_environment.h"
+#include "scic_user_callback.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_request.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;
+}
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_remote_device_state_handler
+scic_sds_smp_remote_device_ready_substate_handler_table[
+	SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+	/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	},
+	/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_default_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
+			scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
+	}
+};
+/*
+ * 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 enter and exit functions for the
+ *    struct scic_sds_remote_device ready substate machine.
+ *
+ *
+ */
+
+#include "scic_remote_device.h"
+#include "scic_user_callback.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "sci_util.h"
+#include "sci_environment.h"
+
+/**
+ *
+ * @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
+		);
+
+	scic_cb_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
+		);
+
+	scic_cb_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_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c
new file mode 100644
index 0000000..949d23e
--- /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);
+}
+
+/**
+ * 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 =
+			scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
+	}
+
+}
+/**
+ * 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 *this_request,
+	struct smp_request *smp_request)
+{
+	dma_addr_t physical_address;
+	struct scic_sds_controller *owning_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(
+		this_request->command_buffer,
+		(u32 *)smp_request,
+		sizeof(struct smp_request) / sizeof(u32)
+		);
+
+	task_context = scic_sds_request_get_task_context(this_request);
+
+	owning_controller = scic_sds_request_get_controller(this_request);
+	target_device = scic_sds_request_get_device(this_request);
+	target_port = scic_sds_request_get_port(this_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(owning_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 = this_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), this_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 (this_request->was_tag_assigned_by_user) {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			| scic_sds_io_tag_get_index(this_request->io_tag)
+			);
+	} else {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			/* This is not assigned because we have to wait until we get a TCi */
+			);
+	}
+
+	/*
+	 * Copy the physical address for the command buffer to the SCU Task Context
+	 * command buffer should not contain command header. */
+	scic_cb_io_request_get_physical_address(
+		scic_sds_request_get_controller(this_request),
+		this_request,
+		((char *)(this_request->command_buffer) + sizeof(u32)),
+		&physical_address
+		);
+
+	task_context->command_iu_upper =
+		upper_32_bits(physical_address);
+	task_context->command_iu_lower =
+		lower_32_bits(physical_address);
+
+
+	/* 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..b7c5b83
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_smp_request.h
@@ -0,0 +1,70 @@
+/*
+ * 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 "sci_types.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..0d6441c
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c
@@ -0,0 +1,340 @@
+/*
+ * 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 task management substate handlers for the
+ *    SCIC_SDS_IO_REQUEST object.
+ *
+ *
+ */
+
+#include "intel_sas.h"
+#include "sci_environment.h"
+#include "scic_sds_request.h"
+#include "scic_controller.h"
+#include "scic_sds_controller.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 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 enter/exit methods associated with each of the task
+ *    management raw request states.  For more information on the task
+ *    management request state machine please refer to scic_sds_io_request.h
+ *
+ *
+ */
+
+#include "scic_sds_request.h"
+#include "sci_base_state_machine.h"
+
+/**
+ * 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_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c
new file mode 100644
index 0000000..f52a8e3
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c
@@ -0,0 +1,838 @@
+/*
+ * 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 *this_request)
+{
+	void *sge;
+	struct scu_sgl_element_pair *scu_sgl_list   = NULL;
+	struct scu_task_context *task_context;
+	dma_addr_t physical_address;
+
+	struct sci_ssp_response_iu *rsp_iu =
+		(struct sci_ssp_response_iu *)this_request->response_buffer;
+
+	sge =  (void *)&rsp_iu->data[0];
+
+	task_context = (struct scu_task_context *)this_request->task_context_buffer;
+	scu_sgl_list = &task_context->sgl_pair_ab;
+
+	scic_cb_io_request_get_physical_address(
+		scic_sds_request_get_controller(this_request),
+		this_request,
+		((char *)sge),
+		&physical_address
+		);
+
+	scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
+	scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
+	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..fc18b3f
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h
@@ -0,0 +1,154 @@
+/*
+ * 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 "sci_types.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_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c
new file mode 100644
index 0000000..abe8f33
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c
@@ -0,0 +1,975 @@
+/*
+ * 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 ready substate handlers for an STP device.
+ *
+ *
+ */
+
+#include "intel_sat.h"
+#include "intel_ata.h"
+#include "intel_sata.h"
+#include "sci_environment.h"
+#include "scic_remote_device.h"
+#include "scic_user_callback.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_request.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,
+				(SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
+				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 *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 = io_request->state_handlers->parent.start_handler(request);
+		}
+
+		if (status == SCI_SUCCESS) {
+			if (
+				scic_cb_request_get_sat_protocol(io_request->user_request)
+				== SAT_PROTOCOL_FPDMA
+				) {
+				sci_base_state_machine_change_state(
+					&this_device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
+					);
+			} else {
+				this_device->working_request = io_request;
+
+				sci_base_state_machine_change_state(
+					&this_device->ready_substate_machine,
+					SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+					);
+			}
+		}
+
+		scic_sds_remote_device_start_request(this_device, io_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 *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;
+
+	if (
+		scic_cb_request_get_sat_protocol(io_request->user_request)
+		== SAT_PROTOCOL_FPDMA
+		) {
+		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 = io_request->state_handlers->parent.start_handler(request);
+			}
+
+			scic_sds_remote_device_start_request(this_device, io_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;
+
+			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) */
+
+/* --------------------------------------------------------------------------- */
+
+struct scic_sds_remote_device_state_handler
+scic_sds_stp_remote_device_ready_substate_handler_table[
+	SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
+			scic_sds_remote_device_default_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_remote_device_default_complete_request_handler
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_stp_remote_device_ready_idle_substate_event_handler,
+		scic_sds_remote_device_default_frame_handler
+	},
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
+			scic_sds_stp_remote_device_complete_request,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_stp_remote_device_complete_request,
+		},
+		scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
+	},
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
+			scic_sds_stp_remote_device_complete_request,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_stp_remote_device_complete_request
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
+	},
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_stp_remote_device_complete_request,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_stp_remote_device_complete_request
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	},
+#if !defined(DISABLE_ATAPI)
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_remote_device_default_start_request_handler,
+			scic_sds_stp_remote_device_complete_request,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_stp_remote_device_complete_request
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	},
+#endif
+	/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */
+	{
+		{
+			scic_sds_remote_device_default_start_handler,
+			scic_sds_remote_device_ready_state_stop_handler,
+			scic_sds_remote_device_default_fail_handler,
+			scic_sds_remote_device_default_destruct_handler,
+			scic_sds_remote_device_ready_state_reset_handler,
+			scic_sds_remote_device_default_reset_complete_handler,
+			scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
+			scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
+			scic_sds_remote_device_default_continue_request_handler,
+			scic_sds_stp_remote_device_ready_substate_start_request_handler,
+			scic_sds_stp_remote_device_complete_request
+		},
+		scic_sds_remote_device_default_suspend_handler,
+		scic_sds_remote_device_default_resume_handler,
+		scic_sds_remote_device_general_event_handler,
+		scic_sds_remote_device_general_frame_handler
+	}
+};
+
+/*
+ * 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.h"
+#include "scic_remote_device.h"
+#include "scic_user_callback.h"
+#include "scic_sds_controller.h"
+#include "scic_sds_port.h"
+#include "scic_sds_remote_device.h"
+#include "sci_util.h"
+#include "sci_environment.h"
+
+/*
+ * *****************************************************************************
+ * *  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) {
+		scic_cb_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
+		);
+
+	scic_cb_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) {
+		scic_cb_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,
+	},
+};
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..c14f6f1
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_stp_request.c
@@ -0,0 +1,2004 @@
+/*
+ * 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 "scic_user_callback.h"
+#include "sci_environment.h"
+#include "sci_types.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)
+	       + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS;
+}
+
+/**
+ *
+ *
+ *
+ */
+void scic_sds_stp_request_assign_buffers(
+	struct scic_sds_request *request)
+{
+	struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
+
+	this_request->parent.command_buffer =
+		scic_sds_stp_request_get_h2d_reg_buffer(this_request);
+	this_request->parent.response_buffer =
+		scic_sds_stp_request_get_response_buffer(this_request);
+	this_request->parent.sgl_element_pair_buffer =
+		scic_sds_stp_request_get_sgl_element_buffer(this_request);
+	this_request->parent.sgl_element_pair_buffer =
+		scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer);
+
+	if (this_request->parent.was_tag_assigned_by_user == false) {
+		this_request->parent.task_context_buffer =
+			scic_sds_stp_request_get_task_context_buffer(this_request);
+		this_request->parent.task_context_buffer =
+			scic_sds_request_align_task_context_buffer(this_request->parent.task_context_buffer);
+	}
+}
+
+/**
+ * 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 *this_request,
+	struct scu_task_context *task_context)
+{
+	dma_addr_t physical_address;
+	struct scic_sds_controller *owning_controller;
+	struct scic_sds_remote_device *target_device;
+	struct scic_sds_port *target_port;
+
+	owning_controller = scic_sds_request_get_controller(this_request);
+	target_device = scic_sds_request_get_device(this_request);
+	target_port = scic_sds_request_get_port(this_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(owning_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(this_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 *)this_request->command_buffer;
+
+	if (this_request->was_tag_assigned_by_user) {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			| scic_sds_io_tag_get_index(this_request->io_tag)
+			);
+	} else {
+		/* Build the task context now since we have already read the data */
+		this_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
+				)
+			/* This is not assigned because we have to wait until we get a TCi */
+			);
+	}
+
+	/*
+	 * 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 */
+	scic_cb_io_request_get_physical_address(
+		scic_sds_request_get_controller(this_request),
+		this_request,
+		((char *)this_request->command_buffer) + sizeof(u32),
+		&physical_address
+		);
+
+	task_context->command_iu_upper =
+		upper_32_bits(physical_address);
+	task_context->command_iu_lower =
+		lower_32_bits(physical_address);
+
+	/* 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;
+}
+
+/**
+ *
+ * @this_request: 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 *this_request,
+	u8 optimized_task_type,
+	u32 transfer_length,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction)
+{
+	struct scu_task_context *task_context = this_request->task_context_buffer;
+
+	/* Build the STP task context structure */
+	scu_sata_reqeust_construct_task_context(this_request, task_context);
+
+	/* Copy over the SGL elements */
+	scic_sds_request_build_sgl(this_request);
+
+	/* Copy over the number of bytes to be transfered */
+	task_context->transfer_length_bytes = transfer_length;
+
+	if (data_direction == SCI_IO_REQUEST_DATA_OUT) {
+		/*
+		 * 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;
+	}
+}
+
+/**
+ *
+ * @this_request: 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 *this_request,
+	u32 transfer_length,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction)
+{
+	scic_sds_stp_non_ncq_request_construct(this_request);
+
+	scic_sds_stp_optimized_request_construct(
+		this_request,
+		SCU_TASK_TYPE_DMA_IN,
+		transfer_length,
+		data_direction
+		);
+
+	sci_base_state_machine_construct(
+		&this_request->started_substate_machine,
+		&this_request->parent.parent,
+		scic_sds_stp_request_started_udma_substate_table,
+		SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+		);
+
+	return SCI_SUCCESS;
+}
+
+/**
+ *
+ * @this_request: 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 *this_request,
+	u32 transfer_length,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction)
+{
+	scic_sds_stp_optimized_request_construct(
+		this_request,
+		SCU_TASK_TYPE_FPDMAQ_READ,
+		transfer_length,
+		data_direction
+		);
+	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 *this_request
+	) {
+	struct scu_sgl_element *current_sgl;
+
+	if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
+		if (
+			(this_request->type.pio.request_current.sgl_pair->B.address_lower == 0)
+			&& (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0)
+			) {
+			current_sgl = NULL;
+		} else {
+			this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B;
+			current_sgl = &(this_request->type.pio.request_current.sgl_pair->B);
+		}
+	} else {
+		if (
+			(this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0)
+			&& (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0)
+			) {
+			current_sgl = NULL;
+		} else {
+			dma_addr_t physical_address;
+
+			sci_cb_make_physical_address(
+				physical_address,
+				this_request->type.pio.request_current.sgl_pair->next_pair_upper,
+				this_request->type.pio.request_current.sgl_pair->next_pair_lower
+				);
+
+			this_request->type.pio.request_current.sgl_pair =
+				(struct scu_sgl_element_pair *)scic_cb_get_virtual_address(
+					this_request->parent.owning_controller,
+					physical_address
+					);
+
+			this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
+
+			current_sgl = &(this_request->type.pio.request_current.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;
+}
+
+/**
+ *
+ * @this_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 *this_request,
+	u8 *data_buffer,
+	u32 length)
+{
+	enum sci_status status;
+	struct scu_sgl_element *current_sgl;
+	u32 sgl_offset;
+	u32 data_offset;
+	u8 *source_address;
+	u8 *destination_address;
+	u32 copy_length;
+
+	/* Initial setup to get the current working SGL and the offset within the buffer */
+	current_sgl =
+		(this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ?
+		&(this_request->type.pio.request_current.sgl_pair->A) :
+		&(this_request->type.pio.request_current.sgl_pair->B);
+
+	sgl_offset = this_request->type.pio.request_current.sgl_offset;
+
+	source_address = data_buffer;
+	data_offset = 0;
+
+	status = SCI_SUCCESS;
+
+	/* While we are still doing Ok and there is more data to transfer */
+	while (
+		(length > 0)
+		&& (status == SCI_SUCCESS)
+		) {
+		if (current_sgl->length == sgl_offset) {
+			/* This SGL has been exauhasted so we need to get the next SGL */
+			current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request);
+
+			if (current_sgl == NULL)
+				status = SCI_FAILURE;
+			else
+				sgl_offset = 0;
+		} else {
+			dma_addr_t physical_address;
+
+			sci_cb_make_physical_address(
+				physical_address,
+				current_sgl->address_upper,
+				current_sgl->address_lower
+				);
+
+			destination_address = (u8 *)scic_cb_get_virtual_address(
+				this_request->parent.owning_controller,
+				physical_address
+				);
+
+			source_address += data_offset;
+			destination_address += sgl_offset;
+
+			copy_length = min(length, current_sgl->length - sgl_offset);
+
+			memcpy(destination_address, source_address, copy_length);
+
+			length -= copy_length;
+			sgl_offset += copy_length;
+			data_offset += copy_length;
+		}
+	}
+
+	this_request->type.pio.request_current.sgl_offset = sgl_offset;
+
+	return status;
+}
+
+/**
+ *
+ * @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. */
+	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_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..5578d2b
--- /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 "intel_sata.h"
+#include "sci_types.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 {
+				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,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction);
+
+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,
+	SCI_IO_REQUEST_DATA_DIRECTION data_direction);
+
+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_ */
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..7ca2f17
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
@@ -0,0 +1,379 @@
+/*
+ * 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 "scic_user_callback.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,
+	unsigned long 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 = (void *)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;
+		sci_physical_address_add(
+			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;
+
+	/*
+	 * 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;
+
+	/*
+	 * 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;
+	sci_physical_address_add(
+		uf_control->headers.physical_address, used_uf_buffer_bytes);
+	sci_physical_address_subtract(
+		uf_control->headers.physical_address, unused_uf_header_bytes);
+	uf_control->headers.array
+		= (struct scu_unsolicited_frame_header *)
+		  scic_cb_get_virtual_address(
+		controller, uf_control->headers.physical_address
+		);
+
+	/*
+	 * 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;
+	sci_physical_address_add(
+		uf_control->address_table.physical_address, used_uf_buffer_bytes);
+	sci_physical_address_add(
+		uf_control->address_table.physical_address, used_uf_header_bytes);
+	uf_control->address_table.array
+		= (dma_addr_t *)
+		  scic_cb_get_virtual_address(
+		controller, uf_control->address_table.physical_address
+		);
+
+	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,
+		(unsigned long)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/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h
new file mode 100644
index 0000000..ef76cb6
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_task_request.h
@@ -0,0 +1,148 @@
+/*
+ * 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_types.h"
+#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_ */
+
diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h
new file mode 100644
index 0000000..6eca5a9
--- /dev/null
+++ b/drivers/scsi/isci/core/scic_user_callback.h
@@ -0,0 +1,740 @@
+/*
+ * 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_USER_CALLBACK_H_
+#define _SCIC_USER_CALLBACK_H_
+
+/**
+ * This file contains all of the interface methods/macros that must be
+ *    implemented by an SCI Core user.
+ *
+ *
+ */
+
+
+#include "sci_types.h"
+#include "sci_status.h"
+
+struct scic_sds_request;
+struct scic_sds_phy;
+struct scic_sds_port;
+struct scic_sds_remote_device;
+struct scic_sds_controller;
+
+/**
+ * scic_cb_timer_create() - This callback method asks the user to create a
+ *    timer and provide a handle for this timer for use in further timer
+ *    interactions.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to be associated.
+ * @timer_callback: This parameter specifies the callback method to be invoked
+ *    whenever the timer expires.
+ * @cookie: This parameter specifies a piece of information that the user must
+ *    retain.  This cookie is to be supplied by the user anytime a timeout
+ *    occurs for the created timer.
+ *
+ * The "timer_callback" method should be executed in a mutually exlusive manner
+ * from the controller completion handler handler (refer to
+ * scic_controller_get_handler_methods()). This method returns a handle to a
+ * timer object created by the user.  The handle will be utilized for all
+ * further interactions relating to this timer.
+ */
+void *scic_cb_timer_create(
+	struct scic_sds_controller *controller,
+	void (*timer_callback)(void *),
+	void *cookie);
+
+
+/**
+ * scic_cb_timer_start() - This callback method asks the user to start the
+ *    supplied timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be started.
+ * @milliseconds: This parameter specifies the number of milliseconds for which
+ *    to stall.  The operating system driver is allowed to round this value up
+ *    where necessary.
+ *
+ * All timers in the system started by the SCI Core are one shot timers.
+ * Therefore, the SCI user should make sure that it removes the timer from it's
+ * list when a timer actually fires. Additionally, SCI Core user's should be
+ * able to handle calls from the SCI Core to stop a timer that may already be
+ * stopped. none
+ */
+void scic_cb_timer_start(
+	struct scic_sds_controller *controller,
+	void *timer,
+	u32 milliseconds);
+
+/**
+ * scic_cb_timer_stop() - This callback method asks the user to stop the
+ *    supplied timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be stopped.
+ *
+ */
+void scic_cb_timer_stop(
+	struct scic_sds_controller *controller,
+	void *timer);
+
+/**
+ * scic_cb_stall_execution() - This method is called when the core requires the
+ *    OS driver to stall execution.  This method is utilized during
+ *    initialization or non-performance paths only.
+ * @microseconds: This parameter specifies the number of microseconds for which
+ *    to stall.  The operating system driver is allowed to round this value up
+ *    where necessary.
+ *
+ * none.
+ */
+void scic_cb_stall_execution(
+	u32 microseconds);
+
+/**
+ * scic_cb_controller_start_complete() - This user callback will inform the
+ *    user that the controller has finished the start process.
+ * @controller: This parameter specifies the controller that was started.
+ * @completion_status: This parameter specifies the results of the start
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_controller_start_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_controller_stop_complete() - This user callback will inform the user
+ *    that the controller has finished the stop process.
+ * @controller: This parameter specifies the controller that was stopped.
+ * @completion_status: This parameter specifies the results of the stop
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_controller_stop_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_io_request_complete() - This user callback will inform the user that
+ *    an IO request has completed.
+ * @controller: This parameter specifies the controller on which the IO is
+ *    completing.
+ * @remote_device: This parameter specifies the remote device on which this IO
+ *    request is completing.
+ * @io_request: This parameter specifies the IO request that has completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_io_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *io_request,
+	enum sci_io_status completion_status);
+
+/**
+ * scic_cb_task_request_complete() - This user callback will inform the user
+ *    that a task management request completed.
+ * @controller: This parameter specifies the controller on which the task
+ *    management request is completing.
+ * @remote_device: This parameter specifies the remote device on which this
+ *    task management request is completing.
+ * @task_request: This parameter specifies the task management request that has
+ *    completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_task_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *task_request,
+	enum sci_task_status completion_status);
+
+#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED
+/**
+ * scic_cb_io_request_get_physical_address() - This callback method asks the
+ *    user to provide the physical address for the supplied virtual address
+ *    when building an io request object.
+ * @controller: This parameter is the core controller object handle.
+ * @io_request: This parameter is the io request object handle for which the
+ *    physical address is being requested.
+ * @virtual_address: This paramter is the virtual address which is to be
+ *    returned as a physical address.
+ * @physical_address: The physical address for the supplied virtual address.
+ *
+ * None.
+ */
+void scic_cb_io_request_get_physical_address(
+	struct scic_sds_controller *controller,
+	struct scic_sds_request *io_request,
+	void *virtual_address,
+	dma_addr_t *physical_address);
+#endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */
+
+/**
+ * scic_cb_io_request_get_transfer_length() - This callback method asks the
+ *    user to provide the number of bytes to be transfered as part of this
+ *    request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the number of payload data bytes to be transfered for
+ * this IO request.
+ */
+u32 scic_cb_io_request_get_transfer_length(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_io_request_get_data_direction() - This callback method asks the user
+ *    to provide the data direction for this request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the value of SCI_IO_REQUEST_DATA_OUT or
+ * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
+	void *scic_user_io_request);
+
+#ifndef SCI_SGL_OPTIMIZATION_ENABLED
+/**
+ * scic_cb_io_request_get_next_sge() - This callback method asks the user to
+ *    provide the address to where the next Scatter-Gather Element is located.
+ *    Details regarding usage: - Regarding the first SGE: the user should
+ *    initialize an index, or a pointer, prior to construction of the request
+ *    that will reference the very first scatter-gather element.  This is
+ *    important since this method is called for every scatter-gather element,
+ *    including the first element. - Regarding the last SGE: the user should
+ *    return NULL from this method when this method is called and the SGL has
+ *    exhausted all elements.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @current_sge_address: This parameter specifies the address for the current
+ *    SGE (i.e. the one that has just processed).
+ * @next_sge: An address specifying the location for the next scatter gather
+ *    element to be processed.
+ *
+ * None
+ */
+void scic_cb_io_request_get_next_sge(
+	void *scic_user_io_request,
+	void *current_sge_address,
+	void **next_sge);
+#endif /* SCI_SGL_OPTIMIZATION_ENABLED */
+
+/**
+ * scic_cb_sge_get_address_field() - This callback method asks the user to
+ *    provide the contents of the "address" field in the Scatter-Gather Element.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @sge_address: This parameter specifies the address for the SGE from which to
+ *    retrieve the address field.
+ *
+ * A physical address specifying the contents of the SGE's address field.
+ */
+dma_addr_t scic_cb_sge_get_address_field(
+	void *scic_user_io_request,
+	void *sge_address);
+
+/**
+ * scic_cb_sge_get_length_field() - This callback method asks the user to
+ *    provide the contents of the "length" field in the Scatter-Gather Element.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @sge_address: This parameter specifies the address for the SGE from which to
+ *    retrieve the address field.
+ *
+ * This method returns the length field specified inside the SGE referenced by
+ * the sge_address parameter.
+ */
+u32 scic_cb_sge_get_length_field(
+	void *scic_user_io_request,
+	void *sge_address);
+
+/**
+ * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
+ *    user to provide the address for the command descriptor block (CDB)
+ *    associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the virtual address of the CDB.
+ */
+void *scic_cb_ssp_io_request_get_cdb_address(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
+ *    to provide the length of the command descriptor block (CDB) associated
+ *    with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the length of the CDB.
+ */
+u32 scic_cb_ssp_io_request_get_cdb_length(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
+ *    provide the Logical Unit (LUN) associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * The contents of the value returned from this callback are defined by the
+ * protocol standard (e.g. T10 SAS specification).  Please refer to the
+ * transport command information unit description in the associated standard.
+ * This method returns the LUN associated with this request. This should be u64?
+ */
+u32 scic_cb_ssp_io_request_get_lun(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
+ *    user to provide the task attribute associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * The contents of the value returned from this callback are defined by the
+ * protocol standard (e.g. T10 SAS specification).  Please refer to the
+ * transport command information unit description in the associated standard.
+ * This method returns the task attribute associated with this IO request.
+ */
+u32 scic_cb_ssp_io_request_get_task_attribute(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_ssp_io_request_get_command_priority() - This callback method asks
+ *    the user to provide the command priority associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * The contents of the value returned from this callback are defined by the
+ * protocol standard (e.g. T10 SAS specification).  Please refer to the
+ * transport command information unit description in the associated standard.
+ * This method returns the command priority associated with this IO request.
+ */
+u32 scic_cb_ssp_io_request_get_command_priority(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
+ *    if the received RX frame data is to be copied to the SGL or should be
+ *    stored by the SCI core to be retrieved later with the
+ *    scic_io_request_get_rx_frame().
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns true if the SCI core should copy the received frame data
+ * to the SGL location or false if the SCI user wants to retrieve the frame
+ * data at a later time.
+ */
+bool scic_cb_io_request_do_copy_rx_frames(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_request_get_sat_protocol() - This callback method asks the user to
+ *    return the SAT protocol definition for this IO request.  This method is
+ *    only called by the SCI core if the request type constructed is SATA.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns one of the sat.h defined protocols for the given io
+ * request.
+ */
+u8 scic_cb_request_get_sat_protocol(
+	void *scic_user_io_request);
+
+
+/**
+ * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
+ *    be utilized for this task management request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * The contents of the value returned from this callback are defined by the
+ * protocol standard (e.g. T10 SAS specification).  Please refer to the
+ * transport task information unit description in the associated standard. This
+ * method returns the LUN associated with this request. This should be u64?
+ */
+u32 scic_cb_ssp_task_request_get_lun(
+	void *scic_user_task_request);
+
+/**
+ * scic_cb_ssp_task_request_get_function() - This method returns the task
+ *    management function to be utilized for this task request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * The contents of the value returned from this callback are defined by the
+ * protocol standard (e.g. T10 SAS specification).  Please refer to the
+ * transport task information unit description in the associated standard. This
+ * method returns an unsigned byte representing the task management function to
+ * be performed.
+ */
+u8 scic_cb_ssp_task_request_get_function(
+	void *scic_user_task_request);
+
+/**
+ * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the
+ *    task management IO tag to be managed. Depending upon the task management
+ *    function the value returned from this method may be ignored.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns an unsigned 16-bit word depicting the IO tag to be
+ * managed.
+ */
+u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
+	void *scic_user_task_request);
+
+/**
+ * scic_cb_ssp_task_request_get_response_data_address() - This callback method
+ *    asks the user to provide the virtual address of the response data buffer
+ *    for the supplied IO request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the virtual address for the response data buffer
+ * associated with this IO request.
+ */
+void *scic_cb_ssp_task_request_get_response_data_address(
+	void *scic_user_task_request);
+
+/**
+ * scic_cb_ssp_task_request_get_response_data_length() - This callback method
+ *    asks the user to provide the length of the response data buffer for the
+ *    supplied IO request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the length of the response buffer data associated with
+ * this IO request.
+ */
+u32 scic_cb_ssp_task_request_get_response_data_length(
+	void *scic_user_task_request);
+
+/**
+ * scic_cb_pci_get_bar() - In this method the user must return the base address
+ *    register (BAR) value for the supplied base address register number.
+ * @controller: The controller for which to retrieve the bar number.
+ * @bar_number: This parameter depicts the BAR index/number to be read.
+ *
+ * Return a pointer value indicating the contents of the BAR. NULL indicates an
+ * invalid BAR index/number was specified. All other values indicate a valid
+ * VIRTUAL address from the BAR.
+ */
+void *scic_cb_pci_get_bar(
+	struct scic_sds_controller *controller,
+	u16 bar_number);
+
+/**
+ * scic_cb_get_virtual_address() - This callback method asks the user to
+ *    provide the virtual address for the supplied physical address.
+ * @controller: This parameter is the core controller object handle.
+ * @physical_address: This parameter is the physical address which is to be
+ *    returned as a virtual address.
+ *
+ * The method returns the virtual address for the supplied physical address.
+ */
+void *scic_cb_get_virtual_address(
+	struct scic_sds_controller *controller,
+	dma_addr_t physical_address);
+
+/**
+ * scic_cb_port_stop_complete() - This method informs the user when a stop
+ *    operation on the port has completed.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void scic_cb_port_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_port_hard_reset_complete() - This method informs the user when a
+ *    hard reset on the port has completed.  This hard reset could have been
+ *    initiated by the user or by the remote port.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void scic_cb_port_hard_reset_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_port_ready() - This method informs the user that the port is now in
+ *    a ready state and can be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ *
+ */
+void scic_cb_port_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port);
+
+/**
+ * scic_cb_port_not_ready() - This method informs the user that the port is now
+ *    not in a ready (i.e. busy) state and can't be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @reason_code: This parameter specifies the reason for the port not ready
+ *    callback.
+ *
+ */
+void scic_cb_port_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	u32 reason_code);
+
+/**
+ * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that
+ *    a phy/link became ready, but the phy is not allowed in the port.  In some
+ *    situations the underlying hardware only allows for certain phy to port
+ *    mappings.  If these mappings are violated, then this API is invoked.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @phy: This parameter specifies the phy that came ready, but the phy can't be
+ *    a valid member of the port.
+ *
+ */
+void scic_cb_port_invalid_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * scic_cb_port_bc_change_primitive_received() - This callback method informs
+ *    the user that a broadcast change primitive was received.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.  For instances where the phy on which the primitive was
+ *    received is not part of a port, this parameter will be
+ *    SCI_INVALID_HANDLE_T.
+ * @phy: This parameter specifies the phy on which the primitive was received.
+ *
+ */
+void scic_cb_port_bc_change_primitive_received(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+
+
+
+/**
+ * scic_cb_port_link_up() - This callback method informs the user that a phy
+ *    has become operational and is capable of communicating with the remote
+ *    end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    SCI_INVALID_HANDLE
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ */
+void scic_cb_port_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * scic_cb_port_link_down() - This callback method informs the user that a phy
+ *    is no longer operational and is not capable of communicating with the
+ *    remote end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    SCI_INVALID_HANDLE
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ */
+void scic_cb_port_link_down(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+/**
+ * scic_cb_remote_device_start_complete() - This user callback method will
+ *    inform the user that a start operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void scic_cb_remote_device_start_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_remote_device_stop_complete() - This user callback method will
+ *    inform the user that a stop operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void scic_cb_remote_device_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status);
+
+/**
+ * scic_cb_remote_device_ready() - This user callback method will inform the
+ *    user that a remote device is now capable of handling IO requests.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ *
+ */
+void scic_cb_remote_device_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device);
+
+/**
+ * scic_cb_remote_device_not_ready() - This user callback method will inform
+ *    the user that a remote device is no longer capable of handling IO
+ *    requests (until a ready callback is invoked).
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ * @reason_code: This paramete specifies the reason the remote device is not
+ *    ready.
+ *
+ */
+void scic_cb_remote_device_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	u32 reason_code);
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets
+ *    from stp packet io's user request the CDB address.
+ * @scic_user_io_request:
+ *
+ * The cdb adress.
+ */
+void *scic_cb_stp_packet_io_request_get_cdb_address(
+	void *scic_user_io_request);
+
+/**
+ * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets
+ *    from stp packet io's user request the CDB length.
+ * @scic_user_io_request:
+ *
+ * The cdb length.
+ */
+u32 scic_cb_stp_packet_io_request_get_cdb_length(
+	void *scic_user_io_request);
+#else /* !defined(DISABLE_ATAPI) */
+#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL
+#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0
+#endif /* !defined(DISABLE_ATAPI) */
+
+
+#endif  /* _SCIC_USER_CALLBACK_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..17ee4c8
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_completion_codes.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 _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_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_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_registers.h b/drivers/scsi/isci/core/scu_registers.h
new file mode 100644
index 0000000..175d2b9
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_registers.h
@@ -0,0 +1,1824 @@
+/*
+ * 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 "sci_types.h"
+#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_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_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h
new file mode 100644
index 0000000..8006f2e
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_remote_node_context.h
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ *
+ *
+ */
+#include "sci_types.h"
+
+/**
+ * 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__ */
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..d08c51b
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_task_context.h
@@ -0,0 +1,943 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+#include "sci_types.h"
+
+/**
+ * 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_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h
new file mode 100644
index 0000000..590ea02
--- /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 "sci_types.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_ */
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..4601d19
--- /dev/null
+++ b/drivers/scsi/isci/core/scu_viit_data.h
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+#include "sci_types.h"
+
+#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_ */
diff --git a/drivers/scsi/isci/deprecated.c b/drivers/scsi/isci/deprecated.c
new file mode 100644
index 0000000..847e687
--- /dev/null
+++ b/drivers/scsi/isci/deprecated.c
@@ -0,0 +1,491 @@
+/*
+ * 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 isci module object implementation.
+ *
+ *
+ */
+
+#include "isci.h"
+#include "request.h"
+#include "sata.h"
+#include "task.h"
+
+
+/**
+ * scic_cb_stall_execution() - This method is called when the core requires the
+ *    OS driver to stall execution.  This method is utilized during
+ *    initialization or non-performance paths only.
+ * @microseconds: This parameter specifies the number of microseconds for which
+ *    to stall.  The operating system driver is allowed to round this value up
+ *    where necessary.
+ *
+ * none.
+ */
+void scic_cb_stall_execution(
+	u32 microseconds)
+{
+	udelay(microseconds);
+}
+
+
+/**
+ * scic_cb_io_request_get_physical_address() - This callback method asks the
+ *    user to provide the physical address for the supplied virtual address
+ *    when building an io request object.
+ * @controller: This parameter is the core controller object handle.
+ * @io_request: This parameter is the io request object handle for which the
+ *    physical address is being requested.
+ *
+ *
+ */
+void scic_cb_io_request_get_physical_address(
+	struct scic_sds_controller *controller,
+	struct scic_sds_request *io_request,
+	void *virtual_address,
+	dma_addr_t *physical_address)
+{
+	struct isci_request *request =
+		(struct isci_request *)sci_object_get_association(io_request);
+
+	char *requested_address = (char *)virtual_address;
+	char *base_address = (char *)request;
+
+	BUG_ON(requested_address < base_address);
+	BUG_ON((requested_address - base_address) >=
+			request->request_alloc_size);
+
+	*physical_address = request->request_daddr +
+		(requested_address - base_address);
+}
+
+/**
+ * scic_cb_io_request_get_transfer_length() - This callback method asks the
+ *    user to provide the number of bytes to be transfered as part of this
+ *    request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the number of payload data bytes to be transfered for
+ * this IO request.
+ */
+u32 scic_cb_io_request_get_transfer_length(
+	void *scic_user_io_request)
+{
+	return isci_request_io_request_get_transfer_length(
+		       scic_user_io_request
+		       );
+}
+
+
+/**
+ * scic_cb_io_request_get_data_direction() - This callback method asks the user
+ *    to provide the data direction for this request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the value of SCI_IO_REQUEST_DATA_OUT or
+ * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
+	void *scic_user_io_request)
+{
+	return isci_request_io_request_get_data_direction(
+		       scic_user_io_request
+		       );
+}
+
+
+/**
+ * scic_cb_io_request_get_next_sge() - This callback method asks the user to
+ *    provide the address to where the next Scatter-Gather Element is located.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @current_sge_address: This parameter specifies the address for the current
+ *    SGE (i.e. the one that has just processed).
+ *
+ * An address specifying the location for the next scatter gather element to be
+ * processed.
+ */
+void scic_cb_io_request_get_next_sge(
+	void *scic_user_io_request,
+	void *current_sge_address,
+	void **next_sge)
+{
+	*next_sge = isci_request_io_request_get_next_sge(
+		scic_user_io_request,
+		current_sge_address
+		);
+}
+
+/**
+ * scic_cb_sge_get_address_field() - This callback method asks the user to
+ *    provide the contents of the "address" field in the Scatter-Gather Element.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @sge_address: This parameter specifies the address for the SGE from which to
+ *    retrieve the address field.
+ *
+ * A physical address specifying the contents of the SGE's address field.
+ */
+dma_addr_t scic_cb_sge_get_address_field(
+	void *scic_user_io_request,
+	void *sge_address)
+{
+	return isci_request_sge_get_address_field(
+		       scic_user_io_request,
+		       sge_address
+		       );
+}
+
+/**
+ * scic_cb_sge_get_length_field() - This callback method asks the user to
+ *    provide the contents of the "length" field in the Scatter-Gather Element.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ * @sge_address: This parameter specifies the address for the SGE from which to
+ *    retrieve the address field.
+ *
+ * This method returns the length field specified inside the SGE referenced by
+ * the sge_address parameter.
+ */
+u32 scic_cb_sge_get_length_field(
+	void *scic_user_io_request,
+	void *sge_address)
+{
+	return isci_request_sge_get_length_field(
+		       scic_user_io_request,
+		       sge_address
+		       );
+}
+
+/**
+ * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
+ *    user to provide the address for the command descriptor block (CDB)
+ *    associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the virtual address of the CDB.
+ */
+void *scic_cb_ssp_io_request_get_cdb_address(
+	void *scic_user_io_request)
+{
+	return isci_request_ssp_io_request_get_cdb_address(
+		       scic_user_io_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
+ *    to provide the length of the command descriptor block (CDB) associated
+ *    with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the length of the CDB.
+ */
+u32 scic_cb_ssp_io_request_get_cdb_length(
+	void *scic_user_io_request)
+{
+	return isci_request_ssp_io_request_get_cdb_length(
+		       scic_user_io_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
+ *    provide the Logical Unit (LUN) associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the LUN associated with this request. This should be u64?
+ */
+u32 scic_cb_ssp_io_request_get_lun(
+	void *scic_user_io_request)
+{
+	return isci_request_ssp_io_request_get_lun(scic_user_io_request);
+}
+
+/**
+ * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
+ *    user to provide the task attribute associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the task attribute associated with this IO request.
+ */
+u32 scic_cb_ssp_io_request_get_task_attribute(
+	void *scic_user_io_request)
+{
+	return isci_request_ssp_io_request_get_task_attribute(
+		       scic_user_io_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_io_request_get_command_priority() - This callback method asks
+ *    the user to provide the command priority associated with this IO request.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the command priority associated with this IO request.
+ */
+u32 scic_cb_ssp_io_request_get_command_priority(
+	void *scic_user_io_request)
+{
+	return isci_request_ssp_io_request_get_command_priority(
+		       scic_user_io_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
+ *    be utilized for this task management request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the LUN associated with this request. This should be u64?
+ */
+u32 scic_cb_ssp_task_request_get_lun(
+	void *scic_user_task_request)
+{
+	return isci_task_ssp_request_get_lun(
+		       (struct isci_request *)scic_user_task_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_task_request_get_function() - This method returns the task
+ *    management function to be utilized for this task request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns an unsigned byte representing the task management
+ * function to be performed.
+ */
+u8 scic_cb_ssp_task_request_get_function(
+	void *scic_user_task_request)
+{
+	return isci_task_ssp_request_get_function(
+		       (struct isci_request *)scic_user_task_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the
+ *    task management IO tag to be managed. Depending upon the task management
+ *    function the value returned from this method may be ignored.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns an unsigned 16-bit word depicting the IO tag to be
+ * managed.
+ */
+u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
+	void *scic_user_task_request)
+{
+	return isci_task_ssp_request_get_io_tag_to_manage(
+		       (struct isci_request *)scic_user_task_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_task_request_get_response_data_address() - This callback method
+ *    asks the user to provide the virtual address of the response data buffer
+ *    for the supplied IO request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the virtual address for the response data buffer
+ * associated with this IO request.
+ */
+void *scic_cb_ssp_task_request_get_response_data_address(
+	void *scic_user_task_request)
+{
+	return isci_task_ssp_request_get_response_data_address(
+		       (struct isci_request *)scic_user_task_request
+		       );
+}
+
+/**
+ * scic_cb_ssp_task_request_get_response_data_length() - This callback method
+ *    asks the user to provide the length of the response data buffer for the
+ *    supplied IO request.
+ * @scic_user_task_request: This parameter points to the user's task request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns the length of the response buffer data associated with
+ * this IO request.
+ */
+u32 scic_cb_ssp_task_request_get_response_data_length(
+	void *scic_user_task_request)
+{
+	return isci_task_ssp_request_get_response_data_length(
+		       (struct isci_request *)scic_user_task_request
+		       );
+}
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks
+ *    the user to provide stp packet io's the CDB address.
+ * @scic_user_io_request:
+ *
+ * The packet IO's cdb adress.
+ */
+void *scic_cb_stp_packet_io_request_get_cdb_address(
+	void *scic_user_io_request)
+{
+	return isci_request_stp_packet_io_request_get_cdb_address(
+		       scic_user_io_request
+		       );
+}
+
+
+/**
+ * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the
+ *    user to provide stp packet io's the CDB length.
+ * @scic_user_io_request:
+ *
+ * The packet IO's cdb length.
+ */
+u32 scic_cb_stp_packet_io_request_get_cdb_length(
+	void *scic_user_io_request)
+{
+	return isci_request_stp_packet_io_request_get_cdb_length(
+		       scic_user_io_request
+		       );
+}
+#endif /* #if !defined(DISABLE_ATAPI) */
+
+
+/**
+ * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
+ *    if the received RX frame data is to be copied to the SGL or should be
+ *    stored by the SCI core to be retrieved later with the
+ *    scic_io_request_get_rx_frame().
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns true if the SCI core should copy the received frame data
+ * to the SGL location or false if the SCI user wants to retrieve the frame
+ * data at a later time.
+ */
+bool scic_cb_io_request_do_copy_rx_frames(
+	void *scic_user_io_request)
+{
+	struct sas_task *task
+		= isci_request_access_task(
+		(struct isci_request *)scic_user_io_request
+		);
+
+	return (task->data_dir == DMA_NONE) ? false : true;
+}
+
+/**
+ * scic_cb_get_virtual_address() - This callback method asks the user to
+ *    provide the virtual address for the supplied physical address.
+ * @controller: This parameter is the core controller object handle.
+ * @physical_address: This parameter is the physical address which is to be
+ *    returned as a virtual address.
+ *
+ * The method returns the virtual address for the supplied physical address.
+ */
+void *scic_cb_get_virtual_address(
+	struct scic_sds_controller *controller,
+	dma_addr_t physical_address)
+{
+	void *virt_addr = (void *)phys_to_virt(physical_address);
+
+	return virt_addr;
+}
+
+/**
+ * scic_cb_request_get_sat_protocol() - This callback method asks the user to
+ *    return the SAT protocol definition for this IO request.  This method is
+ *    only called by the SCI core if the request type constructed is SATA.
+ * @scic_user_io_request: This parameter points to the user's IO request
+ *    object.  It is a cookie that allows the user to provide the necessary
+ *    information for this callback.
+ *
+ * This method returns one of the sat.h defined protocols for the given io
+ * request.
+ */
+u8 scic_cb_request_get_sat_protocol(
+	void *scic_user_io_request)
+{
+	return isci_sata_get_sat_protocol(
+		       (struct isci_request *)scic_user_io_request
+		       );
+}
diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c
new file mode 100644
index 0000000..75f9cd5
--- /dev/null
+++ b/drivers/scsi/isci/events.c
@@ -0,0 +1,619 @@
+/*
+ * 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 isci module object implementation.
+ *
+ *
+ */
+
+#include "isci.h"
+#include "request.h"
+#include "sata.h"
+#include "task.h"
+
+/**
+ * scic_cb_timer_create() - This callback method asks the user to create a
+ *    timer and provide a handle for this timer for use in further timer
+ *    interactions. The appropriate isci timer object function is called to
+ *    create a timer object.
+ * @timer_callback: This parameter specifies the callback method to be invoked
+ *    whenever the timer expires.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to be associated.
+ * @cookie: This parameter specifies a piece of information that the user must
+ *    retain.  This cookie is to be supplied by the user anytime a timeout
+ *    occurs for the created timer.
+ *
+ * This method returns a handle to a timer object created by the user.  The
+ * handle will be utilized for all further interactions relating to this timer.
+ */
+void *scic_cb_timer_create(
+	struct scic_sds_controller *controller,
+	void (*timer_callback)(void *),
+	void *cookie)
+{
+	struct isci_host *isci_host;
+	struct isci_timer *timer = NULL;
+
+	isci_host = (struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p",
+		__func__, isci_host);
+
+	timer = isci_timer_create(&isci_host->timer_list_struct,
+				  isci_host,
+				  cookie,
+				  timer_callback);
+
+	dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer);
+
+	return (void *)timer;
+}
+
+
+/**
+ * scic_cb_timer_start() - This callback method asks the user to start the
+ *    supplied timer. The appropriate isci timer object function is called to
+ *    start the timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be started.
+ * @milliseconds: This parameter specifies the number of milliseconds for which
+ *    to stall.  The operating system driver is allowed to round this value up
+ *    where necessary.
+ *
+ */
+void scic_cb_timer_start(
+	struct scic_sds_controller *controller,
+	void *timer,
+	u32 milliseconds)
+{
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p, timer = %p, milliseconds = %d\n",
+		__func__, isci_host, timer, milliseconds);
+
+	isci_timer_start((struct isci_timer *)timer, milliseconds);
+
+}
+
+/**
+ * scic_cb_timer_stop() - This callback method asks the user to stop the
+ *    supplied timer. The appropriate isci timer object function is called to
+ *    stop the timer.
+ * @controller: This parameter specifies the controller with which this timer
+ *    is to associated.
+ * @timer: This parameter specifies the timer to be stopped.
+ *
+ */
+void scic_cb_timer_stop(
+	struct scic_sds_controller *controller,
+	void *timer)
+{
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p, timer = %p\n",
+		__func__, isci_host, timer);
+
+	isci_timer_stop((struct isci_timer *)timer);
+}
+
+/**
+ * scic_cb_controller_start_complete() - This user callback will inform the
+ *    user that the controller has finished the start process. The associated
+ *    isci host adapter's start_complete function is called.
+ * @controller: This parameter specifies the controller that was started.
+ * @completion_status: This parameter specifies the results of the start
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_controller_start_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status)
+{
+	struct isci_host *isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p\n", __func__, isci_host);
+
+	isci_host_start_complete(isci_host, completion_status);
+}
+
+/**
+ * scic_cb_controller_stop_complete() - This user callback will inform the user
+ *    that the controller has finished the stop process. The associated isci
+ *    host adapter's start_complete function is called.
+ * @controller: This parameter specifies the controller that was stopped.
+ * @completion_status: This parameter specifies the results of the stop
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_controller_stop_complete(
+	struct scic_sds_controller *controller,
+	enum sci_status completion_status)
+{
+	struct isci_host *isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: status = 0x%x\n", __func__, completion_status);
+	isci_host_stop_complete(isci_host, completion_status);
+}
+
+/**
+ * scic_cb_io_request_complete() - This user callback will inform the user that
+ *    an IO request has completed.
+ * @controller: This parameter specifies the controller on which the IO is
+ *    completing.
+ * @remote_device: This parameter specifies the remote device on which this IO
+ *    request is completing.
+ * @io_request: This parameter specifies the IO request that has completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_io_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *scic_io_request,
+	enum sci_io_status completion_status)
+{
+	struct isci_request *request;
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	request =
+		(struct isci_request *)sci_object_get_association(
+			scic_io_request
+			);
+
+	isci_request_io_request_complete(isci_host,
+					 request,
+					 completion_status);
+}
+
+/**
+ * scic_cb_task_request_complete() - This user callback will inform the user
+ *    that a task management request completed.
+ * @controller: This parameter specifies the controller on which the task
+ *    management request is completing.
+ * @remote_device: This parameter specifies the remote device on which this
+ *    task management request is completing.
+ * @task_request: This parameter specifies the task management request that has
+ *    completed.
+ * @completion_status: This parameter specifies the results of the IO request
+ *    operation.  SCI_SUCCESS indicates successful completion.
+ *
+ */
+void scic_cb_task_request_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	struct scic_sds_request *scic_task_request,
+	enum sci_task_status completion_status)
+{
+	struct isci_request *request;
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	request =
+		(struct isci_request *)sci_object_get_association(
+			scic_task_request);
+
+	isci_task_request_complete(isci_host, request, completion_status);
+}
+
+/**
+ * scic_cb_port_stop_complete() - This method informs the user when a stop
+ *    operation on the port has completed.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void scic_cb_port_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status)
+{
+	pr_warn("%s:************************************************\n",
+		__func__);
+}
+
+/**
+ * scic_cb_port_hard_reset_complete() - This method informs the user when a
+ *    hard reset on the port has completed.  This hard reset could have been
+ *    initiated by the user or by the remote port.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @completion_status: This parameter specifies the status for the operation
+ *    being completed.
+ *
+ */
+void scic_cb_port_hard_reset_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	enum sci_status completion_status)
+{
+	struct isci_port *isci_port
+		= (struct isci_port *)sci_object_get_association(port);
+
+	isci_port_hard_reset_complete(isci_port, completion_status);
+}
+
+/**
+ * scic_cb_port_ready() - This method informs the user that the port is now in
+ *    a ready state and can be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ *
+ */
+void scic_cb_port_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port)
+{
+	struct isci_port *isci_port;
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	isci_port =
+		(struct isci_port *)sci_object_get_association(port);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+
+	isci_port_ready(isci_host, isci_port);
+}
+
+/**
+ * scic_cb_port_not_ready() - This method informs the user that the port is now
+ *    not in a ready (i.e. busy) state and can't be utilized to issue IOs.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ *
+ */
+void scic_cb_port_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	u32 reason_code)
+{
+	struct isci_port *isci_port;
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	isci_port =
+		(struct isci_port *)sci_object_get_association(port);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+
+	isci_port_not_ready(isci_host, isci_port);
+}
+
+/**
+ * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that
+ *    a phy/link became ready, but the phy is not allowed in the port.  In some
+ *    situations the underlying hardware only allows for certain phy to port
+ *    mappings.  If these mappings are violated, then this API is invoked.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.
+ * @phy: This parameter specifies the phy that came ready, but the phy can't be
+ *    a valid member of the port.
+ *
+ */
+void scic_cb_port_invalid_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	pr_warn("%s:************************************************\n",
+		__func__);
+}
+
+/**
+ * scic_cb_port_bc_change_primitive_received() - This callback method informs
+ *    the user that a broadcast change primitive was received.
+ * @controller: This parameter represents the controller which contains the
+ *    port.
+ * @port: This parameter specifies the SCI port object for which the callback
+ *    is being invoked.  For instances where the phy on which the primitive was
+ *    received is not part of a port, this parameter will be
+ *    SCI_INVALID_HANDLE_T.
+ * @phy: This parameter specifies the phy on which the primitive was received.
+ *
+ */
+void scic_cb_port_bc_change_primitive_received(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: port = %p, phy = %p\n", __func__, port, phy);
+	isci_port_bc_change_received(isci_host, port, phy);
+}
+
+
+
+
+/**
+ * scic_cb_port_link_up() - This callback method informs the user that a phy
+ *    has become operational and is capable of communicating with the remote
+ *    end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    SCI_INVALID_HANDLE
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ * none.
+ */
+void scic_cb_port_link_up(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: phy = %p\n", __func__, phy);
+
+	isci_port_link_up(isci_host, port, phy);
+}
+
+/**
+ * scic_cb_port_link_down() - This callback method informs the user that a phy
+ *    is no longer operational and is not capable of communicating with the
+ *    remote end point.
+ * @controller: This parameter represents the controller associated with the
+ *    phy.
+ * @port: This parameter specifies the port object for which the user callback
+ *    is being invoked.  There may be conditions where this parameter can be
+ *    SCI_INVALID_HANDLE
+ * @phy: This parameter specifies the phy object for which the user callback is
+ *    being invoked.
+ *
+ * none.
+ */
+void scic_cb_port_link_down(
+	struct scic_sds_controller *controller,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	struct isci_host *isci_host;
+	struct isci_phy *isci_phy;
+	struct isci_port *isci_port;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	isci_phy =
+		(struct isci_phy *)sci_object_get_association(phy);
+
+	isci_port =
+		(struct isci_port *)sci_object_get_association(port);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+
+	isci_port_link_down(isci_host, isci_phy, isci_port);
+}
+
+/**
+ * scic_cb_remote_device_start_complete() - This user callback method will
+ *    inform the user that a start operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void scic_cb_remote_device_start_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status)
+{
+	struct isci_host *isci_host;
+	struct isci_remote_device *isci_device;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	isci_device =
+		(struct isci_remote_device *)sci_object_get_association(
+			remote_device
+			);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	isci_remote_device_start_complete(
+		isci_host, isci_device, completion_status);
+
+}
+
+/**
+ * scic_cb_remote_device_stop_complete() - This user callback method will
+ *    inform the user that a stop operation has completed.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the completion callback.
+ * @completion_status: This parameter specifies the completion status for the
+ *    operation.
+ *
+ */
+void scic_cb_remote_device_stop_complete(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	enum sci_status completion_status)
+{
+	struct isci_host *isci_host;
+	struct isci_remote_device *isci_device;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	isci_device =
+		(struct isci_remote_device *)sci_object_get_association(
+			remote_device
+			);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	isci_remote_device_stop_complete(
+		isci_host, isci_device, completion_status);
+
+}
+
+/**
+ * scic_cb_remote_device_ready() - This user callback method will inform the
+ *    user that a remote device is now capable of handling IO requests.
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ *
+ */
+void scic_cb_remote_device_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device)
+{
+	struct isci_remote_device *isci_device =
+		(struct isci_remote_device *)
+		sci_object_get_association(remote_device);
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	isci_remote_device_ready(isci_device);
+}
+
+/**
+ * scic_cb_remote_device_not_ready() - This user callback method will inform
+ *    the user that a remote device is no longer capable of handling IO
+ *    requests (until a ready callback is invoked).
+ * @controller: This parameter specifies the core controller associated with
+ *    the completion callback.
+ * @remote_device: This parameter specifies the remote device associated with
+ *    the callback.
+ * @reason_code: This parameter specifies the reason for the remote device
+ *    going to a not ready state.
+ *
+ */
+void scic_cb_remote_device_not_ready(
+	struct scic_sds_controller *controller,
+	struct scic_sds_remote_device *remote_device,
+	u32 reason_code)
+{
+	struct isci_remote_device *isci_device =
+		(struct isci_remote_device *)
+		sci_object_get_association(remote_device);
+
+	struct isci_host *isci_host;
+
+	isci_host =
+		(struct isci_host *)sci_object_get_association(controller);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p, reason_code = %x\n",
+		__func__, isci_device, reason_code);
+
+	isci_remote_device_not_ready(isci_device, reason_code);
+}
+
+
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile
new file mode 100644
index 0000000..5f54461
--- /dev/null
+++ b/drivers/scsi/isci/firmware/Makefile
@@ -0,0 +1,19 @@
+# Makefile for create_fw
+#
+CC=gcc
+CFLAGS=-c -Wall -O2 -g
+LDFLAGS=
+SOURCES=create_fw.c
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE=create_fw
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+	$(CC) $(LDFLAGS) $(OBJECTS) -o $@
+
+.c.o:
+	$(CC) $(CFLAGS) $< -O $@
+
+clean:
+	rm -f *.o $(EXECUTABLE)
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README
new file mode 100644
index 0000000..cf7e428
--- /dev/null
+++ b/drivers/scsi/isci/firmware/README
@@ -0,0 +1,36 @@
+This defines the temporary binary blow we are to pass to the SCU
+driver to emulate the binary firmware that we will eventually be
+able to access via NVRAM on the SCU controller.
+
+The current size of the binary blob is expected to be 149 bytes or larger
+
+Header Types:
+0x1: Phy Masks
+0x2: Phy Gens
+0x3: SAS Addrs
+0xff: End of Data
+
+ID string - u8[12]: "#SCU MAGIC#\0"
+Version - u8: 1
+SubVersion - u8: 0
+
+Header Type - u8: 0x1
+Size - u8: 8
+Phy Mask - u32[8]
+
+Header Type - u8: 0x2
+Size - u8: 8
+Phy Gen - u32[8]
+
+Header Type - u8: 0x3
+Size - u8: 8
+Sas Addr - u64[8]
+
+Header Type - u8: 0xf
+
+
+==============================================================================
+
+Place isci_firmware.bin in /lib/firmware
+Be sure to recreate the initramfs image to include the firmware. 
+
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
new file mode 100644
index 0000000..442caac96
--- /dev/null
+++ b/drivers/scsi/isci/firmware/create_fw.c
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+char blob_name[] = "isci_firmware.bin";
+char id[] = "#SCU MAGIC#";
+unsigned char version = 1;
+unsigned char sub_version = 0;
+
+
+/*
+ * For all defined arrays:
+ * elements 0-3 are for SCU0, ports 0-3
+ * elements 4-7 are for SCU1, ports 0-3
+ *
+ * valid configurations for one SCU are:
+ *  P0  P1  P2  P3
+ * ----------------
+ * 0xF,0x0,0x0,0x0 # 1 x4 port
+ * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
+ *                 # ports
+ * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
+ *                 # port
+ * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
+ * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
+ *
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value assigned to UNINIT_PARAM (255).
+ */
+unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 };
+
+
+/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */
+unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 };
+
+/*
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value "0000000000000000". SAS address of zero's is
+ * considered invalid and will not be used.
+ */
+unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL,
+				  0x5FCFFFFFF1000000ULL,
+				  0x5FCFFFFFF2000000ULL,
+				  0x5FCFFFFFF3000000ULL,
+				  0x5FCFFFFFF4000000ULL,
+				  0x5FCFFFFFF5000000ULL,
+				  0x5FCFFFFFF6000000ULL,
+				  0x5FCFFFFFF7000000ULL };
+
+int write_blob(void)
+{
+	FILE *fd;
+	int err;
+
+	fd = fopen(blob_name, "w+");
+	if (!fd) {
+		perror("Open file for write failed");
+		return -EIO;
+	}
+
+	/* write id */
+	err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd);
+	if (err == 0) {
+		perror("write id failed");
+		return err;
+	}
+
+	/* write version */
+	err = fwrite((void *)&version, sizeof(version), 1, fd);
+	if (err == 0) {
+		perror("write version failed");
+		return err;
+	}
+
+	/* write sub version */
+	err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd);
+	if (err == 0) {
+		perror("write subversion failed");
+		return err;
+	}
+
+	/* write phy mask header */
+	err = fputc(0x1, fd);
+	if (err == EOF) {
+		perror("write phy mask header failed");
+		return -EIO;
+	}
+
+	/* write size */
+	err = fputc(8, fd);
+	if (err == EOF) {
+		perror("write phy mask size failed");
+		return -EIO;
+	}
+
+	/* write phy masks */
+	err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd);
+	if (err == 0) {
+		perror("write phy_mask failed");
+		return err;
+	}
+
+	/* write phy gen header */
+	err = fputc(0x2, fd);
+	if (err == EOF) {
+		perror("write phy gen header failed");
+		return -EIO;
+	}
+
+	/* write size */
+	err = fputc(8, fd);
+	if (err == EOF) {
+		perror("write phy gen size failed");
+		return -EIO;
+	}
+
+	/* write phy_gen */
+	err = fwrite((void *)phy_gen,
+		     1,
+		     sizeof(phy_gen),
+		     fd);
+	if (err == 0) {
+		perror("write phy_gen failed");
+		return err;
+	}
+
+	/* write phy gen header */
+	err = fputc(0x3, fd);
+	if (err == EOF) {
+		perror("write sas addr header failed");
+		return -EIO;
+	}
+
+	/* write size */
+	err = fputc(8, fd);
+	if (err == EOF) {
+		perror("write sas addr size failed");
+		return -EIO;
+	}
+
+	/* write sas_addr */
+	err = fwrite((void *)sas_addr,
+		     1,
+		     sizeof(sas_addr),
+		     fd);
+	if (err == 0) {
+		perror("write sas_addr failed");
+		return err;
+	}
+
+	/* write end header */
+	err = fputc(0xff, fd);
+	if (err == EOF) {
+		perror("write end header failed");
+		return -EIO;
+	}
+
+	fclose(fd);
+
+	return 0;
+}
+
+int main(void)
+{
+	int err;
+
+	err = write_blob();
+	if (err < 0)
+		return err;
+
+	return 0;
+}
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
new file mode 100644
index 0000000..6f16f4d
--- /dev/null
+++ b/drivers/scsi/isci/host.c
@@ -0,0 +1,781 @@
+/*
+ * 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 "isci.h"
+#include "scic_io_request.h"
+#include "scic_remote_device.h"
+#include "scic_port.h"
+
+#include "port.h"
+#include "request.h"
+#include "host.h"
+
+/**
+ * isci_isr() - This function is the interrupt service routine for the
+ *    controller. It schedules the tasklet and returns.
+ * @vec: This parameter specifies the interrupt vector.
+ * @data: This parameter specifies the ISCI host object.
+ *
+ * IRQ_HANDLED if out interrupt otherwise, IRQ_NONE
+ */
+irqreturn_t isci_isr(int vec, void *data)
+{
+	struct isci_host *isci_host
+		= (struct isci_host *)data;
+	struct scic_controller_handler_methods *handlers
+		= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
+	irqreturn_t ret = IRQ_NONE;
+
+	if (isci_host_get_state(isci_host) != isci_starting
+	    && handlers->interrupt_handler) {
+
+		if (handlers->interrupt_handler(isci_host->core_controller)) {
+			if (isci_host_get_state(isci_host) != isci_stopped) {
+				tasklet_schedule(
+					&isci_host->completion_tasklet);
+			} else
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: controller stopped\n",
+					__func__);
+			ret = IRQ_HANDLED;
+		}
+	} else
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: get_handler_methods failed, "
+			 "isci_host->status = 0x%x\n",
+			 __func__,
+			 isci_host_get_state(isci_host));
+
+	return ret;
+}
+
+irqreturn_t isci_legacy_isr(int vec, void *data)
+{
+	struct pci_dev *pdev = data;
+	struct isci_host *isci_host;
+	struct scic_controller_handler_methods *handlers;
+	irqreturn_t ret = IRQ_NONE;
+
+	/*
+	 *  Since this is a legacy interrupt, either or both
+	 *  controllers could have triggered it.  Thus, we have to call
+	 *  the legacy interrupt handler for all controllers on the
+	 *  PCI function.
+	 */
+	for_each_isci_host(isci_host, pdev) {
+		handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
+
+		if (isci_host_get_state(isci_host) != isci_starting
+		    && handlers->interrupt_handler) {
+
+			if (handlers->interrupt_handler(isci_host->core_controller)) {
+				if (isci_host_get_state(isci_host) != isci_stopped) {
+					tasklet_schedule(
+						&isci_host->completion_tasklet);
+				} else
+					dev_dbg(&isci_host->pdev->dev,
+						"%s: controller stopped\n",
+						__func__);
+				ret = IRQ_HANDLED;
+			}
+		} else
+			dev_warn(&isci_host->pdev->dev,
+				 "%s: get_handler_methods failed, "
+				 "isci_host->status = 0x%x\n",
+				 __func__,
+				 isci_host_get_state(isci_host));
+	}
+	return ret;
+}
+
+
+/**
+ * isci_host_start_complete() - This function is called by the core library,
+ *    through the ISCI Module, to indicate controller start status.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @completion_status: This parameter specifies the completion status from the
+ *    core library.
+ *
+ */
+void isci_host_start_complete(
+	struct isci_host *isci_host,
+	enum sci_status completion_status)
+{
+	if (completion_status == SCI_SUCCESS) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: completion_status: SCI_SUCCESS\n", __func__);
+		isci_host_change_state(isci_host, isci_ready);
+		complete_all(&isci_host->start_complete);
+	} else
+		dev_err(&isci_host->pdev->dev,
+			"controller start failed with "
+			"completion_status = 0x%x;",
+			completion_status);
+
+}
+
+
+
+/**
+ * isci_host_scan_finished() - This function is one of the SCSI Host Template
+ *    functions. The SCSI midlayer calls this function during a target scan,
+ *    approx. once every 10 millisecs.
+ * @shost: This parameter specifies the SCSI host being scanned
+ * @time: This parameter specifies the number of ticks since the scan started.
+ *
+ * scan status, zero indicates the SCSI midlayer should continue to poll,
+ * otherwise assume controller is ready.
+ */
+int isci_host_scan_finished(
+	struct Scsi_Host *shost,
+	unsigned long time)
+{
+	struct isci_host *isci_host
+		= isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
+
+	struct scic_controller_handler_methods *handlers
+		= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
+
+	if (handlers->interrupt_handler == NULL) {
+		dev_err(&isci_host->pdev->dev,
+			"%s: scic_controller_get_handler_methods failed\n",
+			__func__);
+		return 1;
+	}
+
+	/**
+	 * check interrupt_handler's status and call completion_handler if true,
+	 * link_up events should be coming from the scu core lib, as phy's come
+	 * online. for each link_up from the core, call
+	 * get_received_identify_address_frame, copy the frame into the
+	 * sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED).
+	 * continue to return zero from thee scan_finished routine until
+	 * the scic_cb_controller_start_complete() call comes from the core.
+	 **/
+	if (handlers->interrupt_handler(isci_host->core_controller))
+		handlers->completion_handler(isci_host->core_controller);
+
+	if (isci_starting == isci_host_get_state(isci_host)
+	    && time < (HZ * 10)) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: isci_host->status = %d, time = %ld\n",
+			     __func__, isci_host_get_state(isci_host), time);
+		return 0;
+	}
+
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host->status = %d, time = %ld\n",
+		 __func__, isci_host_get_state(isci_host), time);
+
+	scic_controller_enable_interrupts(isci_host->core_controller);
+
+	return 1;
+
+}
+
+
+/**
+ * isci_host_scan_start() - This function is one of the SCSI Host Template
+ *    function, called by the SCSI mid layer berfore a target scan begins. The
+ *    core library controller start routine is called from here.
+ * @shost: This parameter specifies the SCSI host to be scanned
+ *
+ */
+void isci_host_scan_start(struct Scsi_Host *shost)
+{
+	struct isci_host *isci_host;
+
+	isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
+	isci_host_change_state(isci_host, isci_starting);
+
+	scic_controller_disable_interrupts(isci_host->core_controller);
+	init_completion(&isci_host->start_complete);
+	scic_controller_start(
+		isci_host->core_controller,
+		scic_controller_get_suggested_start_timeout(
+			isci_host->core_controller)
+		);
+}
+
+void isci_host_stop_complete(
+	struct isci_host *isci_host,
+	enum sci_status completion_status)
+{
+	isci_host_change_state(isci_host, isci_stopped);
+	scic_controller_disable_interrupts(
+		isci_host->core_controller
+		);
+	complete(&isci_host->stop_complete);
+}
+
+static struct coherent_memory_info *isci_host_alloc_mdl_struct(
+	struct isci_host *isci_host,
+	u32 size)
+{
+	struct coherent_memory_info *mdl_struct;
+	void *uncached_address = NULL;
+
+
+	mdl_struct = devm_kzalloc(&isci_host->pdev->dev,
+				  sizeof(*mdl_struct),
+				  GFP_KERNEL);
+	if (!mdl_struct)
+		return NULL;
+
+	INIT_LIST_HEAD(&mdl_struct->node);
+
+	uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev,
+					       size,
+					       &mdl_struct->dma_handle,
+					       GFP_KERNEL);
+	if (!uncached_address)
+		return NULL;
+
+	/* memset the whole memory area. */
+	memset((char *)uncached_address, 0, size);
+	mdl_struct->vaddr = uncached_address;
+	mdl_struct->size = (size_t)size;
+
+	return mdl_struct;
+}
+
+static void isci_host_build_mde(
+	struct sci_physical_memory_descriptor *mde_struct,
+	struct coherent_memory_info *mdl_struct)
+{
+	unsigned long address = 0;
+	dma_addr_t dma_addr = 0;
+
+	address = (unsigned long)mdl_struct->vaddr;
+	dma_addr = mdl_struct->dma_handle;
+
+	/* to satisfy the alignment. */
+	if ((address % mde_struct->constant_memory_alignment) != 0) {
+		int align_offset
+			= (mde_struct->constant_memory_alignment
+			   - (address % mde_struct->constant_memory_alignment));
+		address += align_offset;
+		dma_addr += align_offset;
+	}
+
+	mde_struct->virtual_address = (void *)address;
+	mde_struct->physical_address = dma_addr;
+	mdl_struct->mde = mde_struct;
+}
+
+static int isci_host_mdl_allocate_coherent(
+	struct isci_host *isci_host)
+{
+	struct sci_physical_memory_descriptor *current_mde;
+	struct coherent_memory_info *mdl_struct;
+	u32 size = 0;
+
+	struct sci_base_memory_descriptor_list *mdl_handle
+		= sci_controller_get_memory_descriptor_list_handle(
+		isci_host->core_controller);
+
+	sci_mdl_first_entry(mdl_handle);
+
+	current_mde = sci_mdl_get_current_entry(mdl_handle);
+
+	while (current_mde != NULL) {
+
+		size = (current_mde->constant_memory_size
+			+ current_mde->constant_memory_alignment);
+
+		mdl_struct = isci_host_alloc_mdl_struct(isci_host, size);
+		if (!mdl_struct)
+			return -ENOMEM;
+
+		list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list);
+
+		isci_host_build_mde(current_mde, mdl_struct);
+
+		sci_mdl_next_entry(mdl_handle);
+		current_mde = sci_mdl_get_current_entry(mdl_handle);
+	}
+
+	return 0;
+}
+
+
+/**
+ * isci_host_completion_routine() - This function is the delayed service
+ *    routine that calls the sci core library's completion handler. It's
+ *    scheduled as a tasklet from the interrupt service routine when interrupts
+ *    in use, or set as the timeout function in polled mode.
+ * @data: This parameter specifies the ISCI host object
+ *
+ */
+static void isci_host_completion_routine(unsigned long data)
+{
+	struct isci_host *isci_host = (struct isci_host *)data;
+	struct scic_controller_handler_methods *handlers
+		= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
+	struct list_head completed_request_list;
+	struct list_head aborted_request_list;
+	struct list_head *current_position;
+	struct list_head *next_position;
+	struct isci_request *request;
+	struct isci_request *next_request;
+	struct sas_task *task;
+
+	INIT_LIST_HEAD(&completed_request_list);
+	INIT_LIST_HEAD(&aborted_request_list);
+
+	spin_lock_irq(&isci_host->scic_lock);
+
+	if (handlers->completion_handler) {
+		handlers->completion_handler(
+			isci_host->core_controller
+			);
+	}
+	/* Take the lists of completed I/Os from the host. */
+	list_splice_init(&isci_host->requests_to_complete,
+			 &completed_request_list);
+
+	list_splice_init(&isci_host->requests_to_abort,
+			 &aborted_request_list);
+
+	spin_unlock_irq(&isci_host->scic_lock);
+
+	/* Process any completions in the lists. */
+	list_for_each_safe(current_position, next_position,
+			   &completed_request_list) {
+
+		request = list_entry(current_position, struct isci_request,
+				     completed_node);
+		task = isci_request_access_task(request);
+
+		/* Normal notification (task_done) */
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: Normal - request/task = %p/%p\n",
+			__func__,
+			request,
+			task);
+
+		task->task_done(task);
+		task->lldd_task = NULL;
+
+		/* Free the request object. */
+		isci_request_free(isci_host, request);
+	}
+	list_for_each_entry_safe(request, next_request, &aborted_request_list,
+				 completed_node) {
+
+		task = isci_request_access_task(request);
+
+		/* Use sas_task_abort */
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: Error - request/task = %p/%p\n",
+			 __func__,
+			 request,
+			 task);
+
+		/* Put the task into the abort path. */
+		sas_task_abort(task);
+	}
+
+}
+
+void isci_host_deinit(
+	struct isci_host *isci_host)
+{
+	int i;
+
+	isci_host_change_state(isci_host, isci_stopping);
+	for (i = 0; i < SCI_MAX_PORTS; i++) {
+		struct isci_port *port = &isci_host->isci_ports[i];
+		struct isci_remote_device *device, *tmpdev;
+		list_for_each_entry_safe(device, tmpdev,
+					 &port->remote_dev_list, node) {
+			isci_remote_device_change_state(device, isci_stopping);
+			isci_remote_device_stop(device);
+		}
+	}
+
+	/* stop the comtroller and wait for completion.  */
+	init_completion(&isci_host->stop_complete);
+	scic_controller_stop(
+		isci_host->core_controller,
+		SCIC_CONTROLLER_STOP_TIMEOUT
+		);
+	wait_for_completion(&isci_host->stop_complete);
+	/* next, reset the controller.           */
+	scic_controller_reset(isci_host->core_controller);
+}
+
+static int isci_verify_firmware(const struct firmware *fw,
+				struct isci_firmware *isci_fw)
+{
+	const u8 *tmp;
+
+	if (fw->size < ISCI_FIRMWARE_MIN_SIZE)
+		return -EINVAL;
+
+	tmp = fw->data;
+
+	/* 12th char should be the NULL terminate for the ID string */
+	if (tmp[11] != '\0')
+		return -EINVAL;
+
+	if (strncmp("#SCU MAGIC#", tmp, 11) != 0)
+		return -EINVAL;
+
+	isci_fw->id = tmp;
+	isci_fw->version = fw->data[ISCI_FW_VER_OFS];
+	isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS];
+
+	tmp = fw->data + ISCI_FW_DATA_OFS;
+
+	while (*tmp != ISCI_FW_HDR_EOF) {
+		switch (*tmp) {
+		case ISCI_FW_HDR_PHYMASK:
+			tmp++;
+			isci_fw->phy_masks_size = *tmp;
+			tmp++;
+			isci_fw->phy_masks = (const u32 *)tmp;
+			tmp += sizeof(u32) * isci_fw->phy_masks_size;
+			break;
+
+		case ISCI_FW_HDR_PHYGEN:
+			tmp++;
+			isci_fw->phy_gens_size = *tmp;
+			tmp++;
+			isci_fw->phy_gens = (const u32 *)tmp;
+			tmp += sizeof(u32) * isci_fw->phy_gens_size;
+			break;
+
+		case ISCI_FW_HDR_SASADDR:
+			tmp++;
+			isci_fw->sas_addrs_size = *tmp;
+			tmp++;
+			isci_fw->sas_addrs = (const u64 *)tmp;
+			tmp += sizeof(u64) * isci_fw->sas_addrs_size;
+			break;
+
+		default:
+			pr_err("bad field in firmware binary blob\n");
+			return -EINVAL;
+		}
+	}
+
+	pr_info("isci firmware v%u.%u loaded.\n",
+	       isci_fw->version, isci_fw->subversion);
+
+	return SCI_SUCCESS;
+}
+
+static void __iomem *scu_base(struct isci_host *isci_host)
+{
+	struct pci_dev *pdev = isci_host->pdev;
+	int id = isci_host->id;
+
+	return pcim_iomap_table(pdev)[SCI_SCU_BAR * 2] + SCI_SCU_BAR_SIZE * id;
+}
+
+static void __iomem *smu_base(struct isci_host *isci_host)
+{
+	struct pci_dev *pdev = isci_host->pdev;
+	int id = isci_host->id;
+
+	return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
+}
+
+#define SCI_MAX_TIMER_COUNT 25
+
+int isci_host_init(struct isci_host *isci_host)
+{
+	int err = 0;
+	int index = 0;
+	enum sci_status status;
+	struct scic_sds_controller *controller;
+	struct scic_sds_port *scic_port;
+	struct scic_controller_handler_methods *handlers
+		= &isci_host->scic_irq_handlers[0];
+	union scic_oem_parameters scic_oem_params;
+	union scic_user_parameters scic_user_params;
+	const struct firmware *fw = NULL;
+	struct isci_firmware *isci_fw = NULL;
+
+	INIT_LIST_HEAD(&isci_host->timer_list_struct.timers);
+	isci_timer_list_construct(
+		&isci_host->timer_list_struct,
+		SCI_MAX_TIMER_COUNT
+		);
+
+	controller = scic_controller_alloc(&isci_host->pdev->dev);
+
+	if (!controller) {
+		err = -ENOMEM;
+		dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err);
+		goto out;
+	}
+
+	isci_host->core_controller = controller;
+	spin_lock_init(&isci_host->state_lock);
+	spin_lock_init(&isci_host->scic_lock);
+	spin_lock_init(&isci_host->queue_lock);
+
+	isci_host_change_state(isci_host, isci_starting);
+	isci_host->can_queue = ISCI_CAN_QUEUE_VAL;
+
+	status = scic_controller_construct(controller, scu_base(isci_host),
+					   smu_base(isci_host));
+
+	if (status != SCI_SUCCESS) {
+		dev_err(&isci_host->pdev->dev,
+			"%s: scic_controller_construct failed - status = %x\n",
+			__func__,
+			status);
+		err = -ENODEV;
+		goto out;
+	}
+
+	isci_host->sas_ha.dev = &isci_host->pdev->dev;
+	isci_host->sas_ha.lldd_ha = isci_host;
+
+	/*----------- SCIC controller Initialization Stuff ------------------
+	 * set association host adapter struct in core controller.
+	 */
+	sci_object_set_association(isci_host->core_controller,
+				   (void *)isci_host
+				   );
+
+	/* grab initial values stored in the controller object for OEM and USER
+	 * parameters */
+	scic_oem_parameters_get(controller, &scic_oem_params);
+	scic_user_parameters_get(controller, &scic_user_params);
+
+	isci_fw = devm_kzalloc(&isci_host->pdev->dev,
+			       sizeof(struct isci_firmware),
+			       GFP_KERNEL);
+	if (!isci_fw) {
+		dev_warn(&isci_host->pdev->dev,
+			 "allocating firmware struct failed\n");
+		dev_warn(&isci_host->pdev->dev,
+			 "Default OEM configuration being used:"
+			 " 4 narrow ports, and default SAS Addresses\n");
+		goto set_default_params;
+	}
+
+	status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev);
+	if (status) {
+		dev_warn(&isci_host->pdev->dev,
+			 "Loading firmware failed, using default values\n");
+		dev_warn(&isci_host->pdev->dev,
+			 "Default OEM configuration being used:"
+			 " 4 narrow ports, and default SAS Addresses\n");
+		goto set_default_params;
+	}
+	else {
+		status = isci_verify_firmware(fw, isci_fw);
+		if (status != SCI_SUCCESS) {
+			dev_warn(&isci_host->pdev->dev,
+				 "firmware verification failed\n");
+			dev_warn(&isci_host->pdev->dev,
+				 "Default OEM configuration being used:"
+				 " 4 narrow ports, and default SAS "
+				 "Addresses\n");
+			goto set_default_params;
+		}
+
+		/* grab any OEM and USER parameters specified at module load */
+		status = isci_parse_oem_parameters(&scic_oem_params,
+						   isci_host->id, isci_fw);
+		if (status != SCI_SUCCESS) {
+			dev_warn(&isci_host->pdev->dev,
+				 "parsing firmware oem parameters failed\n");
+			err = -EINVAL;
+			goto out;
+		}
+
+		status = isci_parse_user_parameters(&scic_user_params,
+						    isci_host->id, isci_fw);
+		if (status != SCI_SUCCESS) {
+			dev_warn(&isci_host->pdev->dev,
+				 "%s: isci_parse_user_parameters"
+				 " failed\n", __func__);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
+ set_default_params:
+
+	status = scic_oem_parameters_set(isci_host->core_controller,
+					 &scic_oem_params
+					 );
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: scic_oem_parameters_set failed\n",
+			 __func__);
+		err = -ENODEV;
+		goto out;
+	}
+
+
+	status = scic_user_parameters_set(isci_host->core_controller,
+					  &scic_user_params
+					  );
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: scic_user_parameters_set failed\n",
+			 __func__);
+		err = -ENODEV;
+		goto out;
+	}
+
+	status = scic_controller_initialize(isci_host->core_controller);
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: scic_controller_initialize failed -"
+			 " status = 0x%x\n",
+			 __func__, status);
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* @todo: use both MSI-X interrupts, and don't do indirect
+	 * calls to the handlers just register direct calls
+	 */
+	if (isci_host->pdev->msix_enabled) {
+		status = scic_controller_get_handler_methods(
+			SCIC_MSIX_INTERRUPT_TYPE,
+			SCI_MSIX_DOUBLE_VECTOR,
+			handlers
+			);
+	} else {
+		status = scic_controller_get_handler_methods(
+			SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+			0,
+			handlers
+			);
+	}
+
+	if (status != SCI_SUCCESS) {
+		handlers->interrupt_handler = NULL;
+		handlers->completion_handler = NULL;
+		dev_err(&isci_host->pdev->dev,
+			"%s: scic_controller_get_handler_methods failed\n",
+			__func__);
+	}
+
+	tasklet_init(&isci_host->completion_tasklet,
+		     isci_host_completion_routine,
+		     (unsigned long)isci_host
+		     );
+
+	INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
+
+	INIT_LIST_HEAD(&isci_host->requests_to_complete);
+	INIT_LIST_HEAD(&isci_host->requests_to_abort);
+
+	/* populate mdl with dma memory. scu_mdl_allocate_coherent() */
+	err = isci_host_mdl_allocate_coherent(isci_host);
+
+	if (err)
+		goto err_out;
+
+	/*
+	 * keep the pool alloc size around, will use it for a bounds checking
+	 * when trying to convert virtual addresses to physical addresses
+	 */
+	isci_host->dma_pool_alloc_size = sizeof(struct isci_request) +
+					 scic_io_request_get_object_size();
+	isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev,
+					       isci_host->dma_pool_alloc_size,
+					       SLAB_HWCACHE_ALIGN, 0);
+
+	if (!isci_host->dma_pool) {
+		err = -ENOMEM;
+		goto req_obj_err_out;
+	}
+
+	for (index = 0; index < SCI_MAX_PORTS; index++) {
+		isci_port_init(&isci_host->isci_ports[index],
+			       isci_host, index);
+	}
+
+	for (index = 0; index < SCI_MAX_PHYS; index++)
+		isci_phy_init(&isci_host->phys[index], isci_host, index);
+
+	/* Why are we doing this? Is this even necessary? */
+	memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0],
+	       SAS_ADDR_SIZE);
+
+	/* Start the ports */
+	for (index = 0; index < SCI_MAX_PORTS; index++) {
+
+		scic_controller_get_port_handle(controller, index, &scic_port);
+		scic_port_start(scic_port);
+	}
+
+	goto out;
+
+/* SPB_Debug: destroy request object cache */
+ req_obj_err_out:
+/* SPB_Debug: destroy remote object cache */
+ err_out:
+/* SPB_Debug: undo controller init, construct and alloc, remove from parent
+ * controller list. */
+ out:
+	if (fw)
+		release_firmware(fw);
+	return err;
+}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
new file mode 100644
index 0000000..3530076
--- /dev/null
+++ b/drivers/scsi/isci/host.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.
+ */
+
+/**
+ * This file contains the isci_module initialization routines.
+ *
+ * host.h
+ */
+
+
+
+#if !defined(_SCI_HOST_H_)
+#define _SCI_HOST_H_
+
+#include "phy.h"
+/*#include "task.h"*/
+#include "timers.h"
+#include "remote_device.h"
+#include "scic_user_callback.h"
+
+#define DRV_NAME "isci"
+#define SCI_PCI_BAR_COUNT 2
+#define SCI_NUM_MSI_X_INT 2
+#define SCI_SMU_BAR       0
+#define SCI_SMU_BAR_SIZE  (16*1024)
+#define SCI_SCU_BAR       1
+#define SCI_SCU_BAR_SIZE  (4*1024*1024)
+#define SCI_IO_SPACE_BAR0 2
+#define SCI_IO_SPACE_BAR1 3
+#define SCI_MSIX_NORMAL_VECTOR 0
+#define SCI_MSIX_ERROR_VECTOR 1
+#define SCI_MSIX_SINGLE_VECTOR 1
+#define SCI_MSIX_DOUBLE_VECTOR 2
+#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
+#define SCIC_CONTROLLER_STOP_TIMEOUT 5000
+
+struct coherent_memory_info {
+	struct list_head node;
+	dma_addr_t dma_handle;
+	void *vaddr;
+	size_t size;
+	struct sci_physical_memory_descriptor *mde;
+};
+
+struct isci_host {
+	struct scic_sds_controller *core_controller;
+	struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT];
+	union scic_oem_parameters oem_parameters;
+
+	int id; /* unique within a given pci device */
+	struct isci_timer_list timer_list_struct;
+	void *core_ctrl_memory;
+	struct dma_pool *dma_pool;
+	unsigned int dma_pool_alloc_size;
+	struct isci_phy phys[SCI_MAX_PHYS];
+
+	/* isci_ports and sas_ports are implicitly parallel to the
+	 * ports maintained by the core
+	 */
+	struct isci_port isci_ports[SCI_MAX_PORTS];
+	struct asd_sas_port sas_ports[SCI_MAX_PORTS];
+	struct sas_ha_struct sas_ha;
+
+	int can_queue;
+	spinlock_t queue_lock;
+	spinlock_t state_lock;
+
+	struct pci_dev *pdev;
+	u8 sas_addr[SAS_ADDR_SIZE];
+
+	enum isci_status status;
+	struct Scsi_Host *shost;
+	struct tasklet_struct completion_tasklet;
+	struct list_head mdl_struct_list;
+	struct list_head requests_to_complete;
+	struct list_head requests_to_abort;
+	struct completion stop_complete;
+	struct completion start_complete;
+	spinlock_t scic_lock;
+	struct isci_host *next;
+};
+
+
+/**
+ * struct isci_pci_info - This class represents the pci function containing the
+ *    controllers. Depending on PCI SKU, there could be up to 2 controllers in
+ *    the PCI function.
+ */
+#define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
+
+struct isci_pci_info {
+	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
+	int core_lib_array_index;
+	SCI_LIBRARY_HANDLE_T core_lib_handle;
+	struct isci_host *hosts;
+};
+
+static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
+{
+	return pci_get_drvdata(pdev);
+}
+
+#define for_each_isci_host(isci_host, pdev) \
+	for (isci_host = to_pci_info(pdev)->hosts;\
+	     isci_host; isci_host = isci_host->next)
+
+static inline
+enum isci_status isci_host_get_state(
+	struct isci_host *isci_host)
+{
+	return isci_host->status;
+}
+
+
+static inline void isci_host_change_state(
+	struct isci_host *isci_host,
+	enum isci_status status)
+{
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p, state = 0x%x",
+		__func__,
+		isci_host,
+		status);
+	spin_lock_irqsave(&isci_host->state_lock, flags);
+	isci_host->status = status;
+	spin_unlock_irqrestore(&isci_host->state_lock, flags);
+
+}
+
+static inline int isci_host_can_queue(
+	struct isci_host *isci_host,
+	int num)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&isci_host->queue_lock, flags);
+	if ((isci_host->can_queue - num) < 0) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: isci_host->can_queue = %d\n",
+			__func__,
+			isci_host->can_queue);
+		ret = -SAS_QUEUE_FULL;
+
+	} else
+		isci_host->can_queue -= num;
+
+	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
+
+	return ret;
+}
+
+static inline void isci_host_can_dequeue(
+	struct isci_host *isci_host,
+	int num)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&isci_host->queue_lock, flags);
+	isci_host->can_queue += num;
+	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
+}
+
+/**
+ * isci_host_from_sas_ha() - This accessor retrieves the isci_host object
+ *    reference from the Linux sas_ha_struct reference.
+ * @ha_struct,: This parameter points to the Linux sas_ha_struct object
+ *
+ * A reference to the associated isci_host structure.
+ */
+#define isci_host_from_sas_ha(ha_struct) \
+	((struct isci_host *)(ha_struct)->lldd_ha)
+
+/**
+ * isci_host_scan_finished() -
+ *
+ * This function is one of the SCSI Host Template functions. The SCSI midlayer
+ * calls this function during a target scan, approx. once every 10 millisecs.
+ */
+int isci_host_scan_finished(
+	struct Scsi_Host *,
+	unsigned long);
+
+
+/**
+ * isci_host_scan_start() -
+ *
+ * This function is one of the SCSI Host Template function, called by the SCSI
+ * mid layer berfore a target scan begins. The core library controller start
+ * routine is called from here.
+ */
+void isci_host_scan_start(
+	struct Scsi_Host *);
+
+/**
+ * isci_host_start_complete() -
+ *
+ * This function is called by the core library, through the ISCI Module, to
+ * indicate controller start status.
+ */
+void isci_host_start_complete(
+	struct isci_host *,
+	enum sci_status);
+
+void isci_host_stop_complete(
+	struct isci_host *isci_host,
+	enum sci_status completion_status);
+
+int isci_host_init(struct isci_host *);
+
+void isci_host_init_controller_names(
+	struct isci_host *isci_host,
+	unsigned int controller_idx);
+
+void isci_host_deinit(
+	struct isci_host *);
+
+void isci_host_port_link_up(
+	struct isci_host *,
+	struct scic_sds_port *,
+	struct scic_sds_phy *);
+int isci_host_dev_found(struct domain_device *);
+
+void isci_host_remote_device_start_complete(
+	struct isci_host *,
+	struct isci_remote_device *,
+	enum sci_status);
+
+#endif /* !defined(_SCI_HOST_H_) */
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
new file mode 100644
index 0000000..07b072f
--- /dev/null
+++ b/drivers/scsi/isci/init.c
@@ -0,0 +1,613 @@
+/*
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <asm/string.h>
+#include "isci.h"
+#include "task.h"
+#include "sci_controller_constants.h"
+#include "scic_remote_device.h"
+#include "sci_environment.h"
+
+static struct scsi_transport_template *isci_transport_template;
+struct kmem_cache *isci_kmem_cache;
+
+static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
+	{ PCI_VDEVICE(INTEL, 0x1D61),},
+	{ PCI_VDEVICE(INTEL, 0x1D63),},
+	{ PCI_VDEVICE(INTEL, 0x1D65),},
+	{ PCI_VDEVICE(INTEL, 0x1D67),},
+	{ PCI_VDEVICE(INTEL, 0x1D69),},
+	{ PCI_VDEVICE(INTEL, 0x1D6B),},
+	{ PCI_VDEVICE(INTEL, 0x1D60),},
+	{ PCI_VDEVICE(INTEL, 0x1D62),},
+	{ PCI_VDEVICE(INTEL, 0x1D64),},
+	{ PCI_VDEVICE(INTEL, 0x1D66),},
+	{ PCI_VDEVICE(INTEL, 0x1D68),},
+	{ PCI_VDEVICE(INTEL, 0x1D6A),},
+	{}
+};
+
+static int __devinit isci_pci_probe(
+	struct pci_dev *pdev,
+	const struct pci_device_id *device_id_p);
+
+static void __devexit isci_pci_remove(struct pci_dev *pdev);
+
+MODULE_DEVICE_TABLE(pci, isci_id_table);
+
+static struct pci_driver isci_pci_driver = {
+	.name		= DRV_NAME,
+	.id_table	= isci_id_table,
+	.probe		= isci_pci_probe,
+	.remove		= __devexit_p(isci_pci_remove),
+};
+
+/* linux isci specific settings */
+int loglevel = 3;
+module_param(loglevel, int, S_IRUGO | S_IWUSR);
+
+#if defined(CONFIG_PBG_HBA_A0)
+int isci_si_rev = ISCI_SI_REVA0;
+#elif defined(CONFIG_PBG_HBA_A2)
+int isci_si_rev = ISCI_SI_REVA2;
+#else
+int isci_si_rev = ISCI_SI_REVB0;
+#endif
+module_param(isci_si_rev, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)");
+
+static struct scsi_host_template isci_sht = {
+
+	.module				= THIS_MODULE,
+	.name				= DRV_NAME,
+	.queuecommand			= sas_queuecommand,
+	.target_alloc			= sas_target_alloc,
+	.slave_configure		= sas_slave_configure,
+	.slave_destroy			= sas_slave_destroy,
+	.scan_finished			= isci_host_scan_finished,
+	.scan_start			= isci_host_scan_start,
+	.change_queue_depth		= sas_change_queue_depth,
+	.change_queue_type		= sas_change_queue_type,
+	.bios_param			= sas_bios_param,
+	.can_queue			= ISCI_CAN_QUEUE_VAL,
+	.cmd_per_lun			= 1,
+	.this_id			= -1,
+	.sg_tablesize			= SG_ALL,
+	.max_sectors			= SCSI_DEFAULT_MAX_SECTORS,
+	.use_clustering			= ENABLE_CLUSTERING,
+	.eh_device_reset_handler	= sas_eh_device_reset_handler,
+	.eh_bus_reset_handler		= isci_bus_reset_handler,
+	.slave_alloc			= sas_slave_alloc,
+	.target_destroy			= sas_target_destroy,
+	.ioctl				= sas_ioctl,
+};
+
+static struct sas_domain_function_template isci_transport_ops  = {
+
+	/* The class calls these to notify the LLDD of an event. */
+	.lldd_port_formed	= isci_port_formed,
+	.lldd_port_deformed	= isci_port_deformed,
+
+	/* The class calls these when a device is found or gone. */
+	.lldd_dev_found		= isci_remote_device_found,
+	.lldd_dev_gone		= isci_remote_device_gone,
+
+	.lldd_execute_task	= isci_task_execute_task,
+	/* Task Management Functions. Must be called from process context. */
+	.lldd_abort_task	= isci_task_abort_task,
+	.lldd_abort_task_set	= isci_task_abort_task_set,
+	.lldd_clear_aca		= isci_task_clear_aca,
+	.lldd_clear_task_set	= isci_task_clear_task_set,
+	.lldd_I_T_nexus_reset	= isci_task_I_T_nexus_reset,
+	.lldd_lu_reset		= isci_task_lu_reset,
+	.lldd_query_task	= isci_task_query_task,
+
+	/* Port and Adapter management */
+	.lldd_clear_nexus_port	= isci_task_clear_nexus_port,
+	.lldd_clear_nexus_ha	= isci_task_clear_nexus_ha,
+
+	/* Phy management */
+	.lldd_control_phy	= isci_phy_control,
+};
+
+
+/******************************************************************************
+* P R O T E C T E D  M E T H O D S
+******************************************************************************/
+
+
+
+/**
+ * isci_register_sas_ha() - This method initializes various lldd
+ *    specific members of the sas_ha struct and calls the libsas
+ *    sas_register_ha() function.
+ * @isci_host: This parameter specifies the lldd specific wrapper for the
+ *    libsas sas_ha struct.
+ *
+ * This method returns an error code indicating sucess or failure. The user
+ * should check for possible memory allocation error return otherwise, a zero
+ * indicates success.
+ */
+static int isci_register_sas_ha(struct isci_host *isci_host)
+{
+	int i;
+	struct sas_ha_struct *sas_ha = &(isci_host->sas_ha);
+	struct asd_sas_phy **sas_phys;
+	struct asd_sas_port **sas_ports;
+
+	sas_phys = devm_kzalloc(&isci_host->pdev->dev,
+				SCI_MAX_PHYS * sizeof(void *),
+				GFP_KERNEL);
+	if (!sas_phys)
+		return -ENOMEM;
+
+	sas_ports = devm_kzalloc(&isci_host->pdev->dev,
+				 SCI_MAX_PORTS * sizeof(void *),
+				 GFP_KERNEL);
+	if (!sas_ports)
+		return -ENOMEM;
+
+	/*----------------- Libsas Initialization Stuff----------------------
+	 * Set various fields in the sas_ha struct:
+	 */
+
+	sas_ha->sas_ha_name = DRV_NAME;
+	sas_ha->lldd_module = THIS_MODULE;
+	sas_ha->sas_addr    = &(isci_host->sas_addr[0]);
+
+	/* set the array of phy and port structs.  */
+	for (i = 0; i < SCI_MAX_PHYS; i++) {
+		sas_phys[i] = &(isci_host->phys[i].sas_phy);
+		sas_ports[i] = &(isci_host->sas_ports[i]);
+	}
+
+	sas_ha->sas_phy  = sas_phys;
+	sas_ha->sas_port = sas_ports;
+	sas_ha->num_phys = SCI_MAX_PHYS;
+
+	sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
+	sas_ha->lldd_max_execute_num = 1;
+	sas_ha->strict_wide_ports = 1;
+
+	sas_register_ha(sas_ha);
+
+	return 0;
+}
+
+static void isci_unregister_sas_ha(struct isci_host *isci_host)
+{
+	if (!isci_host)
+		return;
+
+	sas_unregister_ha(&(isci_host->sas_ha));
+
+	sas_remove_host(isci_host->shost);
+	scsi_remove_host(isci_host->shost);
+	scsi_host_put(isci_host->shost);
+}
+
+static int __devinit isci_pci_init(struct pci_dev *pdev)
+{
+	int err, bar_num, bar_mask;
+	void __iomem * const *iomap;
+
+	err = pcim_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev,
+			"failed enable PCI device %s!\n",
+			pci_name(pdev));
+		return err;
+	}
+
+	for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++)
+		bar_mask |= 1 << (bar_num * 2);
+
+	err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME);
+	if (err)
+		return err;
+
+	iomap = pcim_iomap_table(pdev);
+	if (!iomap)
+		return -ENOMEM;
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (err)
+			return err;
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (err) {
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id)
+{
+	struct isci_host *h;
+
+	for_each_isci_host(h, pdev)
+		if (h->id == id)
+			return h;
+	return NULL;
+}
+
+static int num_controllers(struct pci_dev *pdev)
+{
+	/* bar size alone can tell us if we are running with a dual controller
+	 * part, no need to trust revision ids that might be under broken firmware
+	 * control
+	 */
+	resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2);
+	resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2);
+	
+	if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS &&
+	    smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS)
+		return SCI_MAX_CONTROLLERS;
+	else
+		return 1;
+}
+
+static int isci_setup_interrupts(struct pci_dev *pdev)
+{
+	int err, i, num_msix;
+	struct isci_pci_info *pci_info = to_pci_info(pdev);
+
+	/*
+	 *  Determine the number of vectors associated with this
+	 *  PCI function.
+	 */
+	num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT;
+
+	for (i = 0; i < num_msix; i++)
+		pci_info->msix_entries[i].entry = i;
+
+	err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
+	if (err)
+		goto intx;
+
+	for (i = 0; i < num_msix; i++) {
+		int id = i / SCI_NUM_MSI_X_INT;
+		struct msix_entry *msix = &pci_info->msix_entries[i];
+		struct isci_host *isci_host = isci_host_by_id(pdev, id);
+
+		BUG_ON(!isci_host);
+
+		/* @todo: need to handle error case. */
+		err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0,
+				       DRV_NAME"-msix", isci_host);
+		if (!err)
+			continue;
+
+		dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
+		while (i--) {
+			id = i / SCI_NUM_MSI_X_INT;
+			isci_host = isci_host_by_id(pdev, id);
+			msix = &pci_info->msix_entries[i];
+			devm_free_irq(&pdev->dev, msix->vector, isci_host);
+		}
+		pci_disable_msix(pdev);
+		goto intx;
+	}
+
+	return 0;
+
+ intx:
+	err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr,
+			       IRQF_SHARED, DRV_NAME"-intx", pdev);
+
+	return err;
+}
+
+/**
+ * isci_parse_oem_parameters() - This method will take OEM parameters
+ *    from the module init parameters and copy them to oem_params. This will
+ *    only copy values that are not set to the module parameter default values
+ * @oem_parameters: This parameter specifies the controller default OEM
+ *    parameters. It is expected that this has been initialized to the default
+ *    parameters for the controller
+ *
+ *
+ */
+enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params,
+					  int scu_index,
+					  struct isci_firmware *fw)
+{
+	int i;
+
+	/* check for valid inputs */
+	if (!(scu_index >= 0
+	      && scu_index < SCI_MAX_CONTROLLERS
+	      && oem_params != NULL)) {
+		return SCI_FAILURE;
+	}
+
+	for (i = 0; i < SCI_MAX_PHYS; i++) {
+		int array_idx = i + (SCI_MAX_PHYS * scu_index);
+		u64 sas_addr = fw->sas_addrs[array_idx];
+
+		if (sas_addr != 0) {
+			oem_params->sds1.phys[i].sas_address.low =
+				(u32)(sas_addr & 0xffffffff);
+			oem_params->sds1.phys[i].sas_address.high =
+				(u32)((sas_addr >> 32) & 0xffffffff);
+		}
+	}
+
+	for (i = 0; i < SCI_MAX_PORTS; i++) {
+		int array_idx = i + (SCI_MAX_PORTS * scu_index);
+		u32 pmask = fw->phy_masks[array_idx];
+
+		oem_params->sds1.ports[i].phy_mask = pmask;
+	}
+
+	return SCI_SUCCESS;
+}
+
+/**
+ * isci_parse_user_parameters() - This method will take user parameters
+ *    from the module init parameters and copy them to user_params. This will
+ *    only copy values that are not set to the module parameter default values
+ * @user_parameters: This parameter specifies the controller default user
+ *    parameters. It is expected that this has been initialized to the default
+ *    parameters for the controller
+ *
+ *
+ */
+enum sci_status isci_parse_user_parameters(
+	union scic_user_parameters *user_params,
+	int scu_index,
+	struct isci_firmware *fw)
+{
+	int i;
+
+	if (!(scu_index >= 0
+	      && scu_index < SCI_MAX_CONTROLLERS
+	      && user_params != NULL)) {
+		return SCI_FAILURE;
+	}
+
+	for (i = 0; i < SCI_MAX_PORTS; i++) {
+		int array_idx = i + (SCI_MAX_PORTS * scu_index);
+		u32 gen = fw->phy_gens[array_idx];
+
+		user_params->sds1.phys[i].max_speed_generation = gen;
+
+	}
+
+	return SCI_SUCCESS;
+}
+
+static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
+{
+	struct isci_host *isci_host;
+	struct Scsi_Host *shost;
+	int err;
+
+	isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
+	if (!isci_host)
+		return NULL;
+
+	isci_host->pdev = pdev;
+	isci_host->id = id;
+
+	shost = scsi_host_alloc(&isci_sht, sizeof(void *));
+	if (!shost)
+		return NULL;
+	isci_host->shost = shost;
+
+	err = isci_host_init(isci_host);
+	if (err)
+		goto err_shost;
+
+	SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
+	isci_host->sas_ha.core.shost = shost;
+	shost->transportt = isci_transport_template;
+
+	shost->max_id = ~0;
+	shost->max_lun = ~0;
+	shost->max_cmd_len = MAX_COMMAND_SIZE;
+
+	err = scsi_add_host(shost, &pdev->dev);
+	if (err)
+		goto err_shost;
+
+	err = isci_register_sas_ha(isci_host);
+	if (err)
+		goto err_shost_remove;
+
+	return isci_host;
+
+ err_shost_remove:
+	scsi_remove_host(shost);
+ err_shost:
+	scsi_host_put(shost);
+
+	return NULL;
+}
+
+static void check_si_rev(struct pci_dev *pdev)
+{
+	if (num_controllers(pdev) > 1)
+		isci_si_rev = ISCI_SI_REVB0;
+	else {
+		switch (pdev->revision) {
+		case 0:
+		case 1:
+			/* if the id is ambiguous don't update isci_si_rev */
+			break;
+		case 3:
+			isci_si_rev = ISCI_SI_REVA2;
+			break;
+		default:
+		case 4:
+			isci_si_rev = ISCI_SI_REVB0;
+			break;
+		}
+	}
+
+	dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n",
+		 isci_si_rev == ISCI_SI_REVA0 ? "A0" :
+		 isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision);
+		
+}
+
+static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct isci_pci_info *pci_info;
+	int err, i;
+	struct isci_host *isci_host;
+
+	check_si_rev(pdev);
+
+	pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
+	if (!pci_info)
+		return -ENOMEM;
+	pci_set_drvdata(pdev, pci_info);
+
+	err = isci_pci_init(pdev);
+	if (err)
+		return err;
+
+	for (i = 0; i < num_controllers(pdev); i++) {
+		struct isci_host *h = isci_host_alloc(pdev, i);
+
+		if (!h) {
+			err = -ENOMEM;
+			goto err_host_alloc;
+		}
+
+		h->next = pci_info->hosts;
+		pci_info->hosts = h;
+	}
+
+	err = isci_setup_interrupts(pdev);
+	if (err)
+		goto err_host_alloc;
+
+	for_each_isci_host(isci_host, pdev)
+		scsi_scan_host(isci_host->shost);
+
+	return 0;
+
+ err_host_alloc:
+	for_each_isci_host(isci_host, pdev)
+		isci_unregister_sas_ha(isci_host);
+	return err;
+}
+
+static void __devexit isci_pci_remove(struct pci_dev *pdev)
+{
+	struct isci_host *isci_host;
+
+	for_each_isci_host(isci_host, pdev) {
+		isci_unregister_sas_ha(isci_host);
+		isci_host_deinit(isci_host);
+		scic_controller_disable_interrupts(isci_host->core_controller);
+	}
+}
+
+static __init int isci_init(void)
+{
+	int err = -ENOMEM;
+
+	pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
+
+	isci_kmem_cache = kmem_cache_create(DRV_NAME,
+					    sizeof(struct isci_remote_device) +
+					    scic_remote_device_get_object_size(),
+					    0, 0, NULL);
+	if (!isci_kmem_cache)
+		return err;
+
+	isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
+	if (!isci_transport_template)
+		goto err_kmem;
+
+	err = pci_register_driver(&isci_pci_driver);
+	if (err)
+		goto err_sas;
+
+	return 0;
+
+ err_sas:
+	sas_release_transport(isci_transport_template);
+ err_kmem:
+	kmem_cache_destroy(isci_kmem_cache);
+
+	return err;
+}
+
+static __exit void isci_exit(void)
+{
+	pci_unregister_driver(&isci_pci_driver);
+	sas_release_transport(isci_transport_template);
+	kmem_cache_destroy(isci_kmem_cache);
+}
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_FIRMWARE(ISCI_FW_NAME);
+module_init(isci_init);
+module_exit(isci_exit);
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
new file mode 100644
index 0000000..7d984f4
--- /dev/null
+++ b/drivers/scsi/isci/isci.h
@@ -0,0 +1,138 @@
+/*
+ * 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 isci_module object definition.
+ *
+ * isci.h
+ */
+
+#if !defined(_SCI_MODULE_H_)
+#define _SCI_MODULE_H_
+
+/**
+ * This file contains the SCI low level driver interface to the SCI and Libsas
+ *    Libraries.
+ *
+ * isci.h
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/bug.h>
+#include <scsi/libsas.h>
+#include <scsi/scsi.h>
+
+#include "sci_types.h"
+#include "sci_base_controller.h"
+#include "scic_controller.h"
+#include "host.h"
+#include "timers.h"
+#include "sci_status.h"
+
+extern int loglevel;
+extern struct kmem_cache *isci_kmem_cache;
+
+#define ISCI_FW_NAME		"isci/isci_firmware.bin"
+
+#define ISCI_FIRMWARE_MIN_SIZE	149
+
+#define ISCI_FW_IDSIZE		12
+#define ISCI_FW_VER_OFS		ISCI_FW_IDSIZE
+#define ISCI_FW_SUBVER_OFS	ISCI_FW_VER_OFS + 1
+#define ISCI_FW_DATA_OFS	ISCI_FW_SUBVER_OFS + 1
+
+#define ISCI_FW_HDR_PHYMASK	0x1
+#define ISCI_FW_HDR_PHYGEN	0x2
+#define ISCI_FW_HDR_SASADDR	0x3
+#define ISCI_FW_HDR_EOF		0xff
+
+struct isci_firmware {
+	const u8 *id;
+	u8 version;
+	u8 subversion;
+	const u32 *phy_masks;
+	u8 phy_masks_size;
+	const u32 *phy_gens;
+	u8 phy_gens_size;
+	const u64 *sas_addrs;
+	u8 sas_addrs_size;
+};
+
+irqreturn_t isci_isr(int vec, void *data);
+irqreturn_t isci_legacy_isr(int vec, void *data);
+
+enum sci_status isci_parse_oem_parameters(
+	union scic_oem_parameters *oem_params,
+	int scu_index,
+	struct isci_firmware *fw);
+
+enum sci_status isci_parse_user_parameters(
+	union scic_user_parameters *user_params,
+	int scu_index,
+	struct isci_firmware *fw);
+
+#ifdef ISCI_SLAVE_ALLOC
+extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev);
+#endif /* ISCI_SLAVE_ALLOC */
+
+#ifdef ISCI_SLAVE_DESTROY
+extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev);
+#endif  /* ISCI_SLAVE_DESTROY */
+#endif  /* !defined(_SCI_MODULE_H_) */
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
new file mode 100644
index 0000000..fbda570
--- /dev/null
+++ b/drivers/scsi/isci/phy.c
@@ -0,0 +1,179 @@
+/*
+ * 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 "isci.h"
+#include "phy.h"
+#include "scic_port.h"
+#include "scic_config_parameters.h"
+
+
+/**
+ * isci_phy_init() - This function is called by the probe function to
+ *    initialize the phy objects. This func assumes that the isci_port objects
+ *    associated with the SCU have been initialized.
+ * @isci_phy: This parameter specifies the isci_phy object to initialize
+ * @isci_host: This parameter specifies the parent SCU host object for this
+ *    isci_phy
+ * @index: This parameter specifies which SCU phy associates with this
+ *    isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc.
+ *
+ */
+void isci_phy_init(
+	struct isci_phy *phy,
+	struct isci_host *isci_host,
+	int index)
+{
+	struct scic_sds_controller *controller = isci_host->core_controller;
+	struct scic_sds_phy *scic_phy;
+	union scic_oem_parameters oem_parameters;
+	enum sci_status status = SCI_SUCCESS;
+
+	/*--------------- SCU_Phy Initialization Stuff -----------------------*/
+
+	status = scic_controller_get_phy_handle(controller, index, &scic_phy);
+	if (status == SCI_SUCCESS) {
+		sci_object_set_association(scic_phy, (void *)phy);
+		phy->sci_phy_handle = scic_phy;
+	} else
+		dev_err(&isci_host->pdev->dev,
+			"failed scic_controller_get_phy_handle\n");
+
+	scic_oem_parameters_get(controller, &oem_parameters);
+
+	phy->sas_addr[0] =  oem_parameters.sds1.phys[index].sas_address.low
+			   & 0xFF;
+	phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low
+			    >> 8)   & 0xFF;
+	phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low
+			    >> 16)  & 0xFF;
+	phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low
+			    >> 24)  & 0xFF;
+	phy->sas_addr[4] =  oem_parameters.sds1.phys[index].sas_address.high
+			   & 0xFF;
+	phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high
+			    >> 8)  & 0xFF;
+	phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high
+			    >> 16) & 0xFF;
+	phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high
+			    >> 24) & 0xFF;
+
+	phy->isci_port = NULL;
+	phy->sas_phy.enabled = 0;
+	phy->sas_phy.id = index;
+	phy->sas_phy.sas_addr = &phy->sas_addr[0];
+	phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd;
+	phy->sas_phy.ha = &isci_host->sas_ha;
+	phy->sas_phy.lldd_phy = phy;
+	phy->sas_phy.enabled = 1;
+	phy->sas_phy.class = SAS;
+	phy->sas_phy.iproto = SAS_PROTOCOL_ALL;
+	phy->sas_phy.tproto = 0;
+	phy->sas_phy.type = PHY_TYPE_PHYSICAL;
+	phy->sas_phy.role = PHY_ROLE_INITIATOR;
+	phy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
+	phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
+	memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd));
+}
+
+
+/**
+ * isci_phy_control() - This function is one of the SAS Domain Template
+ *    functions. This is a phy management function.
+ * @phy: This parameter specifies the sphy being controlled.
+ * @func: This parameter specifies the phy control function being invoked.
+ * @buf: This parameter is specific to the phy function being invoked.
+ *
+ * status, zero indicates success.
+ */
+int isci_phy_control(
+	struct asd_sas_phy *phy,
+	enum phy_func func,
+	void *buf)
+{
+	int ret            = TMF_RESP_FUNC_COMPLETE;
+	struct isci_phy *isci_phy_ptr  = (struct isci_phy *)phy->lldd_phy;
+	struct isci_port *isci_port_ptr = NULL;
+
+	if (isci_phy_ptr != NULL)
+		isci_port_ptr = isci_phy_ptr->isci_port;
+
+	if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) {
+		pr_err("%s: asd_sas_phy %p: lldd_phy %p or "
+		       "isci_port %p == NULL!\n",
+		       __func__, phy, isci_phy_ptr, isci_port_ptr);
+		return TMF_RESP_FUNC_FAILED;
+	}
+
+	pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
+		 __func__, phy, func, buf, isci_phy_ptr, isci_port_ptr);
+
+	switch (func) {
+	case PHY_FUNC_HARD_RESET:
+	case PHY_FUNC_LINK_RESET:
+
+		/* Perform the port reset. */
+		ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr);
+
+		break;
+
+	case PHY_FUNC_DISABLE:
+	default:
+		pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n",
+			 __func__, phy, func);
+		ret = TMF_RESP_FUNC_FAILED;
+		break;
+	}
+	return ret;
+}
diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h
new file mode 100644
index 0000000..44b727f
--- /dev/null
+++ b/drivers/scsi/isci/phy.h
@@ -0,0 +1,104 @@
+/*
+ * 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(_ISCI_PHY_H_)
+#define _ISCI_PHY_H_
+
+#include "port.h"
+#include "host.h"
+#include <scsi/libsas.h>
+
+
+/**
+ * struct isci_phy - This class implements the ISCI specific representation of
+ *    the phy object.
+ *
+ *
+ */
+
+struct isci_phy {
+
+	struct scic_sds_phy *sci_phy_handle;
+
+	struct asd_sas_phy sas_phy;
+	struct sas_identify_frame *frame;
+	struct isci_port *isci_port;
+	u8 sas_addr[SAS_ADDR_SIZE];
+
+	union {
+
+		u8 aif[sizeof(struct sci_sas_identify_address_frame)];
+		u8 fis[sizeof(struct sata_fis_reg_d2h)];
+
+	} frame_rcvd;
+};
+
+#define to_isci_phy(p)	\
+	container_of(p, struct isci_phy, sas_phy);
+
+struct isci_host;
+
+void isci_phy_init(
+	struct isci_phy *phy,
+	struct isci_host *isci_host,
+	int index);
+
+int isci_phy_control(
+	struct asd_sas_phy *phy,
+	enum phy_func func,
+	void *buf);
+
+#endif /* !defined(_ISCI_PHY_H_) */
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
new file mode 100644
index 0000000..2343f65
--- /dev/null
+++ b/drivers/scsi/isci/port.c
@@ -0,0 +1,484 @@
+/*
+ * 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 isci port implementation.
+ *
+ *
+ */
+
+
+#include <linux/workqueue.h>
+#include "isci.h"
+#include "scic_io_request.h"
+#include "scic_remote_device.h"
+#include "scic_phy.h"
+#include "scic_sds_phy.h"
+#include "scic_port.h"
+#include "port.h"
+#include "request.h"
+
+static void isci_port_change_state(
+	struct isci_port *isci_port,
+	enum isci_status status);
+
+
+
+/**
+ * isci_port_init() - This function initializes the given isci_port object.
+ * @isci_port: This parameter specifies the port object to be initialized.
+ * @isci_host: This parameter specifies parent controller object for the port.
+ * @index: This parameter specifies which SCU port the isci_port associates
+ *    with. Generally, SCU port 0 relates to isci_port 0, etc.
+ *
+ */
+void isci_port_init(
+	struct isci_port *isci_port,
+	struct isci_host *isci_host,
+	int index)
+{
+	struct scic_sds_port *scic_port;
+	struct scic_sds_controller *controller = isci_host->core_controller;
+
+	INIT_LIST_HEAD(&isci_port->remote_dev_list);
+	INIT_LIST_HEAD(&isci_port->domain_dev_list);
+	spin_lock_init(&isci_port->remote_device_lock);
+	spin_lock_init(&isci_port->state_lock);
+	init_completion(&isci_port->start_complete);
+	isci_port->isci_host = isci_host;
+	isci_port_change_state(isci_port, isci_freed);
+
+	(void)scic_controller_get_port_handle(controller, index, &scic_port);
+	sci_object_set_association(scic_port, isci_port);
+	isci_port->sci_port_handle = scic_port;
+}
+
+
+/**
+ * isci_port_get_state() - This function gets the status of the port object.
+ * @isci_port: This parameter points to the isci_port object
+ *
+ * status of the object as a isci_status enum.
+ */
+enum isci_status isci_port_get_state(
+	struct isci_port *isci_port)
+{
+	return isci_port->status;
+}
+
+static void isci_port_change_state(
+	struct isci_port *isci_port,
+	enum isci_status status)
+{
+	unsigned long flags;
+
+	dev_dbg(&isci_port->isci_host->pdev->dev,
+		"%s: isci_port = %p, state = 0x%x\n",
+		__func__, isci_port, status);
+
+	spin_lock_irqsave(&isci_port->state_lock, flags);
+	isci_port->status = status;
+	spin_unlock_irqrestore(&isci_port->state_lock, flags);
+}
+
+void isci_port_bc_change_received(
+	struct isci_host *isci_host,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	struct isci_phy *isci_phy =
+		(struct isci_phy *)sci_object_get_association(phy);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_phy = %p, sas_phy = %p\n",
+		__func__,
+		isci_phy,
+		&isci_phy->sas_phy);
+
+	isci_host->sas_ha.notify_port_event(
+		&isci_phy->sas_phy,
+		PORTE_BROADCAST_RCVD
+		);
+
+	scic_port_enable_broadcast_change_notification(port);
+}
+
+/**
+ * isci_port_link_up() - This function is called by the sci core when a link
+ *    becomes active. the identify address frame is retrieved from the core and
+ *    a notify port event is sent to libsas.
+ * @isci_host: This parameter specifies the isci host object.
+ * @port: This parameter specifies the sci port with the active link.
+ * @phy: This parameter specifies the sci phy with the active link.
+ *
+ */
+void isci_port_link_up(
+	struct isci_host *isci_host,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy)
+{
+	unsigned long flags;
+	struct scic_port_properties properties;
+	struct isci_phy *isci_phy
+		= (struct isci_phy *)sci_object_get_association(phy);
+	struct isci_port *isci_port
+		= (struct isci_port *)sci_object_get_association(port);
+	enum sci_status call_status;
+	unsigned long success = true;
+
+	BUG_ON(isci_phy->isci_port != NULL);
+	isci_phy->isci_port = isci_port;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n",
+		__func__, isci_port);
+
+	spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags);
+
+	isci_port_change_state(isci_phy->isci_port, isci_starting);
+
+	scic_port_get_properties(port, &properties);
+
+	if (properties.remote.protocols.u.bits.stp_target) {
+
+		struct scic_sata_phy_properties sata_phy_properties;
+
+		isci_phy->sas_phy.oob_mode = SATA_OOB_MODE;
+
+		/* Get a copy of the signature fis for libsas */
+		call_status = scic_sata_phy_get_properties(phy,
+							   &sata_phy_properties);
+
+		/* 
+		 * XXX I am concerned about this "assert". shouldn't we
+		 * handle the return appropriately?
+		 */
+		BUG_ON(call_status != SCI_SUCCESS);
+
+		memcpy(isci_phy->frame_rcvd.fis,
+		       &sata_phy_properties.signature_fis,
+		       sizeof(struct sata_fis_reg_d2h));
+
+		isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h);
+
+		/*
+		 * For direct-attached SATA devices, the SCI core will
+		 * automagically assign a SAS address to the end device
+		 * for the purpose of creating a port. This SAS address
+		 * will not be the same as assigned to the PHY and needs
+		 * to be obtained from struct scic_port_properties properties.
+		 */
+
+		BUG_ON(((size_t)SAS_ADDR_SIZE / 2)
+		       != sizeof(properties.remote.sas_address.low));
+
+		memcpy(&isci_phy->sas_phy.attached_sas_addr[0],
+		       &properties.remote.sas_address.low,
+		       SAS_ADDR_SIZE / 2);
+
+		memcpy(&isci_phy->sas_phy.attached_sas_addr[4],
+		       &properties.remote.sas_address.high,
+		       SAS_ADDR_SIZE / 2);
+
+	} else if (properties.remote.protocols.u.bits.ssp_target ||
+		   properties.remote.protocols.u.bits.smp_target) {
+
+		struct scic_sas_phy_properties sas_phy_properties;
+
+		isci_phy->sas_phy.oob_mode = SAS_OOB_MODE;
+
+		/* Get a copy of the identify address frame for libsas */
+		call_status = scic_sas_phy_get_properties(phy,
+							  &sas_phy_properties);
+
+		BUG_ON(call_status != SCI_SUCCESS);
+
+		memcpy(isci_phy->frame_rcvd.aif,
+		       &(sas_phy_properties.received_iaf),
+		       sizeof(struct sci_sas_identify_address_frame));
+
+		isci_phy->sas_phy.frame_rcvd_size
+			= sizeof(struct sci_sas_identify_address_frame);
+
+		/* Copy the attached SAS address from the IAF */
+		memcpy(isci_phy->sas_phy.attached_sas_addr,
+		       ((struct sas_identify_frame *)
+			(&isci_phy->frame_rcvd.aif))->sas_addr,
+		       SAS_ADDR_SIZE);
+
+	} else {
+		dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__);
+		success = false;
+	}
+
+	spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags);
+
+	/* Notify libsas that we have an address frame, if indeed
+	 * we've found an SSP, SMP, or STP target */
+	if (success)
+		isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy,
+						    PORTE_BYTES_DMAED);
+}
+
+
+/**
+ * isci_port_link_down() - This function is called by the sci core when a link
+ *    becomes inactive.
+ * @isci_host: This parameter specifies the isci host object.
+ * @phy: This parameter specifies the isci phy with the active link.
+ * @port: This parameter specifies the isci port with the active link.
+ *
+ */
+void isci_port_link_down(
+	struct isci_host *isci_host,
+	struct isci_phy *isci_phy,
+	struct isci_port *isci_port)
+{
+	struct isci_remote_device *isci_device;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+
+	if (isci_port) {
+
+		/* check to see if this is the last phy on this port. */
+		if (isci_phy->sas_phy.port
+		    && isci_phy->sas_phy.port->num_phys == 1) {
+
+			/* change the state for all devices on this port.
+			 * The next task sent to this device will be returned
+			 * as SAS_TASK_UNDELIVERED, and the scsi mid layer
+			 * will remove the target
+			 */
+			list_for_each_entry(isci_device,
+					    &isci_port->remote_dev_list,
+					    node) {
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: isci_device = %p\n",
+					__func__, isci_device);
+				isci_remote_device_change_state(isci_device,
+								isci_stopping);
+			}
+		}
+		isci_port_change_state(isci_port, isci_stopping);
+	}
+
+	/* Notify libsas of the borken link, this will trigger calls to our
+	 * isci_port_deformed and isci_dev_gone functions.
+	 */
+	sas_phy_disconnected(&isci_phy->sas_phy);
+	isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
+					   PHYE_LOSS_OF_SIGNAL);
+
+	isci_phy->isci_port = NULL;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p - Done\n", __func__, isci_port);
+}
+
+
+/**
+ * isci_port_deformed() - This function is called by libsas when a port becomes
+ *    inactive.
+ * @phy: This parameter specifies the libsas phy with the inactive port.
+ *
+ */
+void isci_port_deformed(
+	struct asd_sas_phy *phy)
+{
+	pr_debug("%s: sas_phy = %p\n", __func__, phy);
+}
+
+/**
+ * isci_port_formed() - This function is called by libsas when a port becomes
+ *    active.
+ * @phy: This parameter specifies the libsas phy with the active port.
+ *
+ */
+void isci_port_formed(
+	struct asd_sas_phy *phy)
+{
+	pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port);
+}
+
+/**
+ * isci_port_ready() - This function is called by the sci core when a link
+ *    becomes ready.
+ * @isci_host: This parameter specifies the isci host object.
+ * @port: This parameter specifies the sci port with the active link.
+ *
+ */
+void isci_port_ready(
+	struct isci_host *isci_host,
+	struct isci_port *isci_port)
+{
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+
+	complete_all(&isci_port->start_complete);
+	isci_port_change_state(isci_port, isci_ready);
+	return;
+}
+
+/**
+ * isci_port_not_ready() - This function is called by the sci core when a link
+ *    is not ready. All remote devices on this link will be removed if they are
+ *    in the stopping state.
+ * @isci_host: This parameter specifies the isci host object.
+ * @port: This parameter specifies the sci port with the active link.
+ *
+ */
+void isci_port_not_ready(
+	struct isci_host *isci_host,
+	struct isci_port *isci_port)
+{
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_port = %p\n", __func__, isci_port);
+}
+
+/**
+ * isci_port_hard_reset_complete() - This function is called by the sci core
+ *    when the hard reset complete notification has been received.
+ * @port: This parameter specifies the sci port with the active link.
+ * @completion_status: This parameter specifies the core status for the reset
+ *    process.
+ *
+ */
+void isci_port_hard_reset_complete(
+	struct isci_port *isci_port,
+	enum sci_status completion_status)
+{
+	dev_dbg(&isci_port->isci_host->pdev->dev,
+		"%s: isci_port = %p, completion_status=%x\n",
+		     __func__, isci_port, completion_status);
+
+	/* Save the status of the hard reset from the port. */
+	isci_port->hard_reset_status = completion_status;
+
+	complete_all(&isci_port->hard_reset_complete);
+}
+/**
+ * isci_port_perform_hard_reset() - This function is one of the SAS Domain
+ *    Template functions. This is a phy management function.
+ * @isci_port:
+ * @isci_phy:
+ *
+ * status, TMF_RESP_FUNC_COMPLETE indicates success.
+ */
+int isci_port_perform_hard_reset(
+	struct isci_port *isci_port,
+	struct isci_phy *isci_phy)
+{
+	enum sci_status status;
+	int ret = TMF_RESP_FUNC_COMPLETE;
+	unsigned long flags;
+
+
+	dev_dbg(&isci_port->isci_host->pdev->dev,
+		"%s: isci_port = %p\n",
+		__func__, isci_port);
+
+	BUG_ON(isci_port == NULL);
+
+	init_completion(&isci_port->hard_reset_complete);
+
+	spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags);
+
+	#define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+	status = scic_port_hard_reset(isci_port->sci_port_handle,
+				      ISCI_PORT_RESET_TIMEOUT);
+
+	spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags);
+
+	if (status == SCI_SUCCESS) {
+		wait_for_completion(&isci_port->hard_reset_complete);
+
+		dev_dbg(&isci_port->isci_host->pdev->dev,
+			"%s: isci_port = %p; hard reset completion\n",
+			__func__, isci_port);
+
+		if (isci_port->hard_reset_status != SCI_SUCCESS)
+			ret = TMF_RESP_FUNC_FAILED;
+	} else {
+		ret = TMF_RESP_FUNC_FAILED;
+
+		dev_err(&isci_port->isci_host->pdev->dev,
+			"%s: isci_port = %p; scic_port_hard_reset call"
+			" failed 0x%x\n",
+			__func__, isci_port, status);
+
+	}
+
+	/* If the hard reset for the port has failed, consider this
+	 * the same as link failures on all phys in the port.
+	 */
+	if (ret != TMF_RESP_FUNC_COMPLETE) {
+		BUG_ON(isci_port->isci_host == NULL);
+
+		dev_err(&isci_port->isci_host->pdev->dev,
+			"%s: isci_port = %p; hard reset failed "
+			"(0x%x) - sending link down to libsas for phy %p\n",
+			__func__,
+			isci_port,
+			isci_port->hard_reset_status,
+			isci_phy);
+
+		isci_port_link_down(isci_port->isci_host,
+				    isci_phy,
+				    isci_port);
+	}
+
+	return ret;
+}
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
new file mode 100644
index 0000000..b01b0c6
--- /dev/null
+++ b/drivers/scsi/isci/port.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.
+ */
+
+/**
+ * This file contains the isci_port object definition.
+ *
+ * port.h
+ */
+
+#if !defined(_ISCI_PORT_H_)
+#define _ISCI_PORT_H_
+
+struct isci_phy;
+struct isci_host;
+
+
+enum isci_status {
+	isci_freed        = 0x00,
+	isci_starting     = 0x01,
+	isci_ready        = 0x02,
+	isci_ready_for_io = 0x03,
+	isci_stopping     = 0x04,
+	isci_stopped      = 0x05,
+	isci_host_quiesce = 0x06
+};
+
+/**
+ * struct isci_port - This class represents the port object used to internally
+ *    represent libsas port objects. It also keeps a list of remote device
+ *    objects.
+ *
+ *
+ */
+struct isci_port {
+
+	struct scic_sds_port *sci_port_handle;
+
+	enum isci_status status;
+	struct isci_host *isci_host;
+	struct asd_sas_port sas_port;
+	struct list_head remote_dev_list;
+	spinlock_t remote_device_lock;
+	spinlock_t state_lock;
+	struct list_head domain_dev_list;
+	struct completion start_complete;
+	struct completion hard_reset_complete;
+	enum sci_status hard_reset_status;
+};
+
+#define to_isci_port(p)	\
+	container_of(p, struct isci_port, sas_port);
+
+enum isci_status isci_port_get_state(
+	struct isci_port *isci_port);
+
+
+
+void isci_port_formed(
+	struct asd_sas_phy *);
+
+void isci_port_deformed(
+	struct asd_sas_phy *);
+
+void isci_port_bc_change_received(
+	struct isci_host *isci_host,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+void isci_port_link_up(
+	struct isci_host *isci_host,
+	struct scic_sds_port *port,
+	struct scic_sds_phy *phy);
+
+void isci_port_link_down(
+	struct isci_host *isci_host,
+	struct isci_phy *isci_phy,
+	struct isci_port *port);
+
+void isci_port_ready(
+	struct isci_host *isci_host,
+	struct isci_port *isci_port);
+
+void isci_port_not_ready(
+	struct isci_host *isci_host,
+	struct isci_port *port);
+
+void isci_port_init(
+	struct isci_port *port,
+	struct isci_host *host,
+	int index);
+
+void isci_port_hard_reset_complete(
+	struct isci_port *isci_port,
+	enum sci_status completion_status);
+
+int isci_port_perform_hard_reset(
+	struct isci_port *isci_port_ptr,
+	struct isci_phy *isci_phy_ptr);
+
+#endif /* !defined(_ISCI_PORT_H_) */
+
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
new file mode 100644
index 0000000..dbf3c82
--- /dev/null
+++ b/drivers/scsi/isci/remote_device.c
@@ -0,0 +1,698 @@
+/*
+ * 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 "isci.h"
+#include "scic_io_request.h"
+#include "scic_remote_device.h"
+#include "scic_phy.h"
+#include "scic_port.h"
+#include "port.h"
+#include "remote_device.h"
+#include "request.h"
+#include "task.h"
+
+
+
+/**
+ * isci_remote_device_deconstruct() - This function frees an isci_remote_device.
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device to be freed.
+ *
+ */
+static void isci_remote_device_deconstruct(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device)
+{
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	/* There should not be any outstanding io's. All paths to
+	 * here should go through isci_remote_device_nuke_requests.
+	 * If we hit this condition, we will need a way to complete
+	 * io requests in process */
+	while (!list_empty(&isci_device->reqs_in_process)) {
+
+		dev_err(&isci_host->pdev->dev,
+			"%s: ** request list not empty! **\n", __func__);
+		BUG();
+	}
+
+	/* Remove all related references to this device and free
+	 * the cache object.
+	 */
+	scic_remote_device_destruct(isci_device->sci_device_handle);
+	isci_device->domain_dev->lldd_dev = NULL;
+	list_del(&isci_device->node);
+	kmem_cache_free(isci_kmem_cache, isci_device);
+}
+
+
+/**
+ * isci_remote_device_construct() - This function calls the scic remote device
+ *    construct and start functions, it waits on the remote device start
+ *    completion.
+ * @port: This parameter specifies the isci port with the remote device.
+ * @isci_device: This parameter specifies the isci remote device
+ *
+ * status from the scic calls, the caller to this function should clean up
+ * resources as appropriate.
+ */
+static enum sci_status isci_remote_device_construct(
+	struct isci_port *port,
+	struct isci_remote_device *isci_device)
+{
+	enum sci_status status = SCI_SUCCESS;
+
+	/* let the core do it's common constuction. */
+	scic_remote_device_construct(port->sci_port_handle,
+				     isci_device->sci_device_handle);
+
+	/* let the core do it's device specific constuction. */
+	if (isci_device->domain_dev->parent &&
+	    (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) {
+		int i;
+
+		/* struct smp_response_discover discover_response; */
+		struct discover_resp discover_response;
+		struct domain_device *parent =
+			isci_device->domain_dev->parent;
+
+		struct expander_device *parent_ex = &parent->ex_dev;
+
+		for (i = 0; i < parent_ex->num_phys; i++) {
+
+			struct ex_phy *phy = &parent_ex->ex_phy[i];
+
+			if ((phy->phy_state == PHY_VACANT) ||
+			    (phy->phy_state == PHY_NOT_PRESENT))
+				continue;
+
+			if (SAS_ADDR(phy->attached_sas_addr)
+			    == SAS_ADDR(isci_device->domain_dev->sas_addr)) {
+
+				discover_response.attached_dev_type
+					= phy->attached_dev_type;
+				discover_response.linkrate
+					= phy->linkrate;
+				discover_response.attached_sata_host
+					= phy->attached_sata_host;
+				discover_response.attached_sata_dev
+					= phy->attached_sata_dev;
+				discover_response.attached_sata_ps
+					= phy->attached_sata_ps;
+				discover_response.iproto
+					= phy->attached_iproto >> 1;
+				discover_response.tproto
+					= phy->attached_tproto >> 1;
+				memcpy(
+					discover_response.attached_sas_addr,
+					phy->attached_sas_addr,
+					SAS_ADDR_SIZE
+					);
+				discover_response.attached_phy_id
+					= phy->attached_phy_id;
+				discover_response.change_count
+					= phy->phy_change_count;
+				discover_response.routing_attr
+					= phy->routing_attr;
+				discover_response.hmin_linkrate
+					= phy->phy->minimum_linkrate_hw;
+				discover_response.hmax_linkrate
+					= phy->phy->maximum_linkrate_hw;
+				discover_response.pmin_linkrate
+					= phy->phy->minimum_linkrate;
+				discover_response.pmax_linkrate
+					= phy->phy->maximum_linkrate;
+			}
+		}
+
+
+		dev_dbg(&port->isci_host->pdev->dev,
+			"%s: parent->dev_type = EDGE_DEV\n",
+			__func__);
+
+		status = scic_remote_device_ea_construct(
+			isci_device->sci_device_handle,
+			(struct smp_response_discover *)&discover_response
+			);
+
+	} else
+		status = scic_remote_device_da_construct(
+			isci_device->sci_device_handle
+			);
+
+
+	if (status != SCI_SUCCESS) {
+		dev_dbg(&port->isci_host->pdev->dev,
+			"%s: scic_remote_device_da_construct failed - "
+			"isci_device = %p\n",
+			__func__,
+			isci_device);
+
+		return status;
+	}
+
+	sci_object_set_association(
+		isci_device->sci_device_handle,
+		isci_device
+		);
+
+	BUG_ON(port->isci_host == NULL);
+
+	/* start the device. */
+	status = scic_remote_device_start(
+		isci_device->sci_device_handle,
+		ISCI_REMOTE_DEVICE_START_TIMEOUT
+		);
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&port->isci_host->pdev->dev,
+			 "%s: scic_remote_device_start failed\n",
+			 __func__);
+		return status;
+	}
+
+	return status;
+}
+
+
+/**
+ * isci_remote_device_nuke_requests() - This function terminates all requests
+ *    for a given remote device.
+ * @isci_device: This parameter specifies the remote device
+ *
+ */
+void isci_remote_device_nuke_requests(
+	struct isci_remote_device *isci_device)
+{
+	DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
+	struct isci_host *isci_host;
+
+	isci_host = isci_device->isci_port->isci_host;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	/* Cleanup all requests pending for this device. */
+	isci_terminate_pending_requests(isci_host, isci_device, terminating);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p, done\n", __func__, isci_device);
+}
+
+
+
+/**
+ * This function builds the isci_remote_device when a libsas dev_found message
+ *    is received.
+ * @isci_host: This parameter specifies the isci host object.
+ * @port: This parameter specifies the isci_port conected to this device.
+ *
+ * pointer to new isci_remote_device.
+ */
+static struct isci_remote_device *
+isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port)
+{
+	struct isci_remote_device *isci_device;
+	struct scic_sds_remote_device *sci_dev;
+
+	isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL);
+
+	if (!isci_device) {
+		dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__);
+		return NULL;
+	}
+
+	sci_dev = (struct scic_sds_remote_device *) &isci_device[1];
+	isci_device->sci_device_handle = sci_dev;
+	INIT_LIST_HEAD(&isci_device->reqs_in_process);
+	INIT_LIST_HEAD(&isci_device->node);
+	isci_device->host_quiesce          = false;
+
+	spin_lock_init(&isci_device->state_lock);
+	spin_lock_init(&isci_device->host_quiesce_lock);
+	isci_remote_device_change_state(isci_device, isci_freed);
+
+	return isci_device;
+
+}
+/**
+ * isci_device_set_host_quiesce_lock_state() - This function sets the host I/O
+ *    quiesce lock state for the remote_device object.
+ * @isci_device,: This parameter points to the isci_remote_device object
+ * @isci_device: This parameter specifies the new quiesce state.
+ *
+ */
+void isci_device_set_host_quiesce_lock_state(
+	struct isci_remote_device *isci_device,
+	bool lock_state)
+{
+	unsigned long flags;
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device=%p, lock_state=%d\n",
+		__func__, isci_device, lock_state);
+
+	spin_lock_irqsave(&isci_device->host_quiesce_lock, flags);
+	isci_device->host_quiesce = lock_state;
+	spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags);
+}
+
+/**
+ * isci_remote_device_ready() - This function is called by the scic when the
+ *    remote device is ready. We mark the isci device as ready and signal the
+ *    waiting proccess.
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device
+ *
+ */
+void isci_remote_device_ready(struct isci_remote_device *isci_device)
+{
+	unsigned long flags;
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	/* device ready is actually a "ready for io" state. */
+	if ((isci_starting == isci_remote_device_get_state(isci_device)) ||
+	    (isci_ready == isci_remote_device_get_state(isci_device))) {
+		spin_lock_irqsave(&isci_device->isci_port->remote_device_lock,
+				  flags);
+		isci_remote_device_change_state(isci_device, isci_ready_for_io);
+		if (isci_device->completion)
+			complete(isci_device->completion);
+		spin_unlock_irqrestore(
+				&isci_device->isci_port->remote_device_lock,
+				flags);
+	}
+
+}
+
+/**
+ * isci_remote_device_not_ready() - This function is called by the scic when
+ *    the remote device is not ready. We mark the isci device as ready (not
+ *    "ready_for_io") and signal the waiting proccess.
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device
+ *
+ */
+void isci_remote_device_not_ready(
+	struct isci_remote_device *isci_device,
+	u32 reason_code)
+{
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
+		isci_remote_device_change_state(isci_device, isci_stopping);
+	else
+		/* device ready is actually a "not ready for io" state. */
+		isci_remote_device_change_state(isci_device, isci_ready);
+}
+
+/**
+ * isci_remote_device_stop_complete() - This function is called by the scic
+ *    when the remote device stop has completed. We mark the isci device as not
+ *    ready and remove the isci remote device.
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device.
+ * @status: This parameter specifies status of the completion.
+ *
+ */
+void isci_remote_device_stop_complete(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	enum sci_status status)
+{
+	struct completion *completion = isci_device->completion;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: complete isci_device = %p, status = 0x%x\n",
+		__func__,
+		isci_device,
+		status);
+
+	isci_remote_device_change_state(isci_device, isci_stopped);
+
+	/* after stop, we can tear down resources. */
+	isci_remote_device_deconstruct(isci_host, isci_device);
+
+	/* notify interested parties. */
+	if (completion)
+		complete(completion);
+}
+
+/**
+ * isci_remote_device_start_complete() - This function is called by the scic
+ *    when the remote device start has completed
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device.
+ * @status: This parameter specifies status of the completion.
+ *
+ */
+void isci_remote_device_start_complete(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	enum sci_status status)
+{
+
+
+}
+
+
+/**
+ * isci_remote_device_stop() - This function is called internally to stop the
+ *    remote device.
+ * @isci_host: This parameter specifies the isci host object.
+ * @isci_device: This parameter specifies the remote device.
+ *
+ * The status of the scic request to stop.
+ */
+enum sci_status isci_remote_device_stop(
+	struct isci_remote_device *isci_device)
+{
+	enum sci_status status;
+	unsigned long flags;
+
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	isci_remote_device_change_state(isci_device, isci_stopping);
+
+	/* We need comfirmation that stop completed. */
+	isci_device->completion = &completion;
+
+	BUG_ON(isci_device->isci_port == NULL);
+	BUG_ON(isci_device->isci_port->isci_host == NULL);
+
+	spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags);
+
+	status = scic_remote_device_stop(
+		isci_device->sci_device_handle,
+		50
+		);
+
+	spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags);
+
+	/* Wait for the stop complete callback. */
+	if (status == SCI_SUCCESS)
+		wait_for_completion(&completion);
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p - after completion wait\n",
+		__func__, isci_device);
+
+	isci_device->completion = NULL;
+	return status;
+}
+
+/**
+ * isci_remote_device_gone() - This function is called by libsas when a domain
+ *    device is removed.
+ * @domain_device: This parameter specifies the libsas domain device.
+ *
+ */
+void isci_remote_device_gone(
+	struct domain_device *domain_dev)
+{
+	struct isci_remote_device *isci_device = isci_dev_from_domain_dev(
+		domain_dev);
+
+	dev_err(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
+		__func__, domain_dev, isci_device, isci_device->isci_port);
+
+	if (isci_device != NULL)
+		isci_remote_device_stop(isci_device);
+}
+
+
+/**
+ * isci_remote_device_found() - This function is called by libsas when a remote
+ *    device is discovered. A remote device object is created and started. the
+ *    function then sleeps until the sci core device started message is
+ *    received.
+ * @domain_device: This parameter specifies the libsas domain device.
+ *
+ * status, zero indicates success.
+ */
+int isci_remote_device_found(struct domain_device *domain_dev)
+{
+	unsigned long flags;
+	struct isci_host *isci_host;
+	struct isci_port *isci_port;
+	struct isci_phy *isci_phy;
+	struct asd_sas_port *sas_port;
+	struct asd_sas_phy *sas_phy;
+	struct isci_remote_device *isci_device;
+	enum sci_status status;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	isci_host = isci_host_from_sas_ha(domain_dev->port->ha);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: domain_device = %p\n", __func__, domain_dev);
+
+	sas_port = domain_dev->port;
+	sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy,
+				   port_phy_el);
+	isci_phy = to_isci_phy(sas_phy);
+	isci_port = isci_phy->isci_port;
+
+	/* we are being called for a device on this port,
+	 * so it has to come up eventually
+	 */
+	wait_for_completion(&isci_port->start_complete);
+
+	if ((isci_stopping == isci_port_get_state(isci_port)) ||
+	    (isci_stopped == isci_port_get_state(isci_port)))
+		return -ENODEV;
+
+	isci_device = isci_remote_device_alloc(isci_host, isci_port);
+
+	INIT_LIST_HEAD(&isci_device->node);
+	domain_dev->lldd_dev = isci_device;
+	isci_device->domain_dev = domain_dev;
+	isci_device->isci_port = isci_port;
+	isci_remote_device_change_state(isci_device, isci_starting);
+
+
+	spin_lock_irqsave(&isci_port->remote_device_lock, flags);
+	list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
+
+	/* for the device ready event. */
+	isci_device->completion = &completion;
+
+	status = isci_remote_device_construct(isci_port, isci_device);
+
+	spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
+
+	/* wait for the device ready callback. */
+	wait_for_completion(isci_device->completion);
+	isci_device->completion = NULL;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n",
+		__func__, isci_device);
+
+	if (status != SCI_SUCCESS) {
+
+		spin_lock_irqsave(&isci_port->remote_device_lock, flags);
+		isci_remote_device_deconstruct(
+			isci_host,
+			isci_device
+			);
+		spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
+		return -ENODEV;
+	}
+
+	wait_for_completion(&isci_host->start_complete);
+
+	return 0;
+}
+/**
+ * isci_device_is_reset_pending() - This function will check if there is any
+ *    pending reset condition on the device.
+ * @request: This parameter is the isci_device object.
+ *
+ * true if there is a reset pending for the device.
+ */
+bool isci_device_is_reset_pending(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device)
+{
+	struct isci_request *isci_request;
+	struct isci_request *tmp_req;
+	bool reset_is_pending = false;
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	/* Check for reset on all pending requests. */
+	list_for_each_entry_safe(isci_request, tmp_req,
+				 &isci_device->reqs_in_process, dev_node) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: isci_device = %p request = %p\n",
+			__func__, isci_device, isci_request);
+
+		if (isci_request->ttype == io_task) {
+
+			unsigned long flags;
+			struct sas_task *task = isci_request_access_task(
+				isci_request);
+
+			spin_lock_irqsave(&task->task_state_lock, flags);
+			if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
+				reset_is_pending = true;
+			spin_unlock_irqrestore(&task->task_state_lock, flags);
+		}
+	}
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p reset_is_pending = %d\n",
+		__func__, isci_device, reset_is_pending);
+
+	return reset_is_pending;
+}
+
+/**
+ * isci_device_clear_reset_pending() - This function will clear if any pending
+ *    reset condition flags on the device.
+ * @request: This parameter is the isci_device object.
+ *
+ * true if there is a reset pending for the device.
+ */
+void isci_device_clear_reset_pending(struct isci_remote_device *isci_device)
+{
+	struct isci_request *isci_request;
+	struct isci_request *tmp_req;
+	struct isci_host *isci_host = NULL;
+	unsigned long flags = 0;
+
+	/* FIXME more port gone confusion, and this time it makes the
+	 * locking "fun"
+	 */
+	if (isci_device->isci_port != NULL)
+		isci_host = isci_device->isci_port->isci_host;
+
+	/*
+	 * FIXME when the isci_host gets sorted out
+	 * use dev_dbg()
+	 */
+	pr_debug("%s: isci_device=%p, isci_host=%p\n",
+		 __func__, isci_device, isci_host);
+
+	if (isci_host != NULL)
+		spin_lock_irqsave(&isci_host->scic_lock, flags);
+	else
+		pr_err("%s: isci_device %p; isci_host == NULL!\n",
+		       __func__, isci_device);
+
+	/* Clear reset pending on all pending requests. */
+	list_for_each_entry_safe(isci_request, tmp_req,
+				 &isci_device->reqs_in_process, dev_node) {
+		/*
+		 * FIXME when the conditional spinlock is gone
+		 * change to dev_dbg()
+		 */
+		pr_debug("%s: isci_device = %p request = %p\n",
+			 __func__, isci_device, isci_request);
+
+		if (isci_request->ttype == io_task) {
+
+			unsigned long flags2;
+			struct sas_task *task = isci_request_access_task(
+				isci_request);
+
+			spin_lock_irqsave(&task->task_state_lock, flags2);
+			task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+			spin_unlock_irqrestore(&task->task_state_lock, flags2);
+		}
+	}
+
+	if (isci_host != NULL)
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+}
+
+/**
+ * isci_remote_device_change_state() - This function gets the status of the
+ *    remote_device object.
+ * @isci_device: This parameter points to the isci_remote_device object
+ *
+ * status of the object as a isci_status enum.
+ */
+void isci_remote_device_change_state(
+	struct isci_remote_device *isci_device,
+	enum isci_status status)
+{
+	unsigned long flags;
+
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p, state = 0x%x",
+		__func__,
+		isci_device,
+		status);
+
+	spin_lock_irqsave(&isci_device->state_lock, flags);
+	isci_device->status = status;
+	spin_unlock_irqrestore(&isci_device->state_lock, flags);
+}
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
new file mode 100644
index 0000000..a208f81
--- /dev/null
+++ b/drivers/scsi/isci/remote_device.h
@@ -0,0 +1,154 @@
+/*
+ * 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(_ISCI_REMOTE_DEVICE_H_)
+#define _ISCI_REMOTE_DEVICE_H_
+#include "scic_user_callback.h"
+
+struct isci_host;
+struct scic_sds_remote_device;
+
+struct isci_remote_device {
+	struct scic_sds_remote_device *sci_device_handle;
+	enum isci_status status;
+	struct isci_port *isci_port;
+	struct domain_device *domain_dev;
+	struct completion *completion;
+	struct list_head node;
+	struct list_head reqs_in_process;
+	struct work_struct stop_work;
+	spinlock_t state_lock;
+	spinlock_t host_quiesce_lock;
+	bool host_quiesce;
+};
+
+#define to_isci_remote_device(p)	\
+	container_of(p, struct isci_remote_device, sci_remote_device);
+
+#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000
+
+
+/**
+ * This function gets the status of the remote_device object.
+ * @isci_device: This parameter points to the isci_remote_device object
+ *
+ * status of the object as a isci_status enum.
+ */
+static inline
+enum isci_status isci_remote_device_get_state(
+	struct isci_remote_device *isci_device)
+{
+	return (isci_device->host_quiesce)
+	       ? isci_host_quiesce
+	       : isci_device->status;
+}
+
+
+/**
+ * isci_dev_from_domain_dev() - This accessor retrieves the remote_device
+ *    object reference from the Linux domain_device reference.
+ * @domdev,: This parameter points to the Linux domain_device object .
+ *
+ * A reference to the associated isci remote device.
+ */
+#define isci_dev_from_domain_dev(domdev) \
+	((struct isci_remote_device *)(domdev)->lldd_dev)
+
+void isci_remote_device_start_complete(
+	struct isci_host *,
+	struct isci_remote_device *,
+	enum sci_status);
+
+void isci_remote_device_stop_complete(
+	struct isci_host *,
+	struct isci_remote_device *,
+	enum sci_status);
+
+enum sci_status isci_remote_device_stop(
+	struct isci_remote_device *isci_device);
+
+void isci_remote_device_nuke_requests(
+	struct isci_remote_device *isci_device);
+
+void isci_remote_device_ready(
+	struct isci_remote_device *);
+
+void isci_remote_device_not_ready(
+	struct isci_remote_device *,
+	u32);
+
+void isci_remote_device_gone(
+	struct domain_device *domain_dev);
+
+int isci_remote_device_found(
+	struct domain_device *domain_dev);
+
+bool isci_device_is_reset_pending(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device);
+
+void isci_device_clear_reset_pending(
+	struct isci_remote_device *isci_device);
+
+void isci_device_set_host_quiesce_lock_state(
+	struct isci_remote_device *isci_device,
+	bool lock_state);
+
+void isci_remote_device_change_state(
+	struct isci_remote_device *isci_device,
+	enum isci_status status);
+
+#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
+
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
new file mode 100644
index 0000000..e564121
--- /dev/null
+++ b/drivers/scsi/isci/request.c
@@ -0,0 +1,1472 @@
+/*
+ * 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 "isci.h"
+#include "scic_remote_device.h"
+#include "scic_io_request.h"
+#include "scic_task_request.h"
+#include "scic_port.h"
+#include "task.h"
+#include "request.h"
+#include "sata.h"
+#include "scu_completion_codes.h"
+
+
+static enum sci_status isci_request_ssp_request_construct(
+	struct isci_request *request)
+{
+	enum sci_status status;
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p\n",
+		__func__,
+		request);
+	status = scic_io_request_construct_basic_ssp(
+		request->sci_request_handle
+		);
+	return status;
+}
+
+static enum sci_status isci_request_stp_request_construct(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	enum sci_status status;
+	struct host_to_dev_fis *register_fis;
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p\n",
+		__func__,
+		request);
+
+	/* Get the host_to_dev_fis from the core and copy
+	 * the fis from the task into it.
+	 */
+	register_fis = isci_sata_task_to_fis_copy(task);
+
+	status = scic_io_request_construct_basic_sata(
+		request->sci_request_handle
+		);
+
+	/* Set the ncq tag in the fis, from the queue
+	 * command in the task.
+	 */
+	if (isci_sata_is_task_ncq(task)) {
+
+		isci_sata_set_ncq_tag(
+			register_fis,
+			task
+			);
+	}
+
+	return status;
+}
+
+/**
+ * isci_smp_request_build() - This function builds the smp request object.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @request: This parameter points to the isci_request object allocated in the
+ *    request construct function.
+ * @sci_device: This parameter is the handle for the sci core's remote device
+ *    object that is the destination for this request.
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+static enum sci_status isci_smp_request_build(
+	struct isci_request *request)
+{
+	enum sci_status status = SCI_FAILURE;
+	struct sas_task *task = isci_request_access_task(request);
+
+	void *command_iu_address =
+		scic_io_request_get_command_iu_address(
+			request->sci_request_handle
+			);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p\n",
+		__func__,
+		request);
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: smp_req len = %d\n",
+		__func__,
+		task->smp_task.smp_req.length);
+
+	/* copy the smp_command to the address; */
+	sg_copy_to_buffer(&task->smp_task.smp_req, 1,
+			  (char *)command_iu_address,
+			  sizeof(struct smp_request)
+			  );
+
+	status = scic_io_request_construct_smp(request->sci_request_handle);
+	if (status != SCI_SUCCESS)
+		dev_warn(&request->isci_host->pdev->dev,
+			 "%s: scic_io_request_construct_smp failed with "
+			 "status = %d\n",
+			 __func__,
+			 status);
+
+	return status;
+}
+
+/**
+ * isci_io_request_build() - This function builds the io request object.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @request: This parameter points to the isci_request object allocated in the
+ *    request construct function.
+ * @sci_device: This parameter is the handle for the sci core's remote device
+ *    object that is the destination for this request.
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+static enum sci_status isci_io_request_build(
+	struct isci_host *isci_host,
+	struct isci_request *request,
+	struct isci_remote_device *isci_device)
+{
+	struct smp_discover_response_protocols dev_protocols;
+	enum sci_status status = SCI_SUCCESS;
+	struct sas_task *task = isci_request_access_task(request);
+	struct scic_sds_remote_device *sci_device =
+		isci_device->sci_device_handle;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = 0x%p; request = %p, "
+		"num_scatter = %d\n",
+		__func__,
+		isci_device,
+		request,
+		task->num_scatter);
+
+	/* map the sgl addresses, if present.
+	 * libata does the mapping for sata devices
+	 * before we get the request.
+	 */
+	if (task->num_scatter &&
+	    !sas_protocol_ata(task->task_proto) &&
+	    !(SAS_PROTOCOL_SMP & task->task_proto)) {
+
+		request->num_sg_entries = dma_map_sg(
+			&isci_host->pdev->dev,
+			task->scatter,
+			task->num_scatter,
+			task->data_dir
+			);
+
+		if (request->num_sg_entries == 0)
+			return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+	}
+
+	/* build the common request object. For now,
+	 * we will let the core allocate the IO tag.
+	 */
+	status = scic_io_request_construct(
+		isci_host->core_controller,
+		sci_device,
+		SCI_CONTROLLER_INVALID_IO_TAG,
+		request,
+		request->sci_request_mem_ptr,
+		(struct scic_sds_request **)&request->sci_request_handle
+		);
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: failed request construct\n",
+			 __func__);
+		return SCI_FAILURE;
+	}
+
+	sci_object_set_association(request->sci_request_handle, request);
+
+	/* Determine protocol and call the appropriate basic constructor */
+	scic_remote_device_get_protocols(sci_device, &dev_protocols);
+	if (dev_protocols.u.bits.attached_ssp_target)
+		status = isci_request_ssp_request_construct(request);
+	else if (dev_protocols.u.bits.attached_stp_target)
+		status = isci_request_stp_request_construct(request);
+	else if (dev_protocols.u.bits.attached_smp_target)
+		status = isci_smp_request_build(request);
+	else {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: unknown protocol\n", __func__);
+		return SCI_FAILURE;
+	}
+
+	return SCI_SUCCESS;
+}
+
+
+/**
+ * isci_request_alloc_core() - This function gets the request object from the
+ *    isci_host dma cache.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @isci_request: This parameter will contain the pointer to the new
+ *    isci_request object.
+ * @isci_device: This parameter is the pointer to the isci remote device object
+ *    that is the destination for this request.
+ * @gfp_flags: This parameter specifies the os allocation flags.
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+static int isci_request_alloc_core(
+	struct isci_host *isci_host,
+	struct isci_request **isci_request,
+	struct isci_remote_device *isci_device,
+	gfp_t gfp_flags)
+{
+	int ret = 0;
+	dma_addr_t handle;
+	struct isci_request *request;
+
+
+	/* get pointer to dma memory. This actually points
+	 * to both the isci_remote_device object and the
+	 * sci object. The isci object is at the beginning
+	 * of the memory allocated here.
+	 */
+	request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle);
+	if (!request) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: dma_pool_alloc returned NULL\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* initialize the request object.	*/
+	spin_lock_init(&request->state_lock);
+	isci_request_change_state(request, allocated);
+	request->sci_request_mem_ptr = ((u8 *)request) +
+				       sizeof(struct isci_request);
+	request->request_daddr = handle;
+	request->isci_host = isci_host;
+	request->isci_device = isci_device;
+	request->io_request_completion = NULL;
+
+	request->request_alloc_size = isci_host->dma_pool_alloc_size;
+	request->num_sg_entries = 0;
+
+	request->complete_in_target = false;
+
+	INIT_LIST_HEAD(&request->completed_node);
+	INIT_LIST_HEAD(&request->dev_node);
+
+	*isci_request = request;
+
+	return ret;
+}
+
+static int isci_request_alloc_io(
+	struct isci_host *isci_host,
+	struct sas_task *task,
+	struct isci_request **isci_request,
+	struct isci_remote_device *isci_device,
+	gfp_t gfp_flags)
+{
+	int retval = isci_request_alloc_core(isci_host, isci_request,
+					     isci_device, gfp_flags);
+
+	if (!retval) {
+		(*isci_request)->ttype_ptr.io_task_ptr = task;
+		(*isci_request)->ttype                 = io_task;
+
+		task->lldd_task = *isci_request;
+	}
+	return retval;
+}
+
+/**
+ * isci_request_alloc_tmf() - This function gets the request object from the
+ *    isci_host dma cache and initializes the relevant fields as a sas_task.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @sas_task: This parameter is the task struct from the upper layer driver.
+ * @isci_request: This parameter will contain the pointer to the new
+ *    isci_request object.
+ * @isci_device: This parameter is the pointer to the isci remote device object
+ *    that is the destination for this request.
+ * @gfp_flags: This parameter specifies the os allocation flags.
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+int isci_request_alloc_tmf(
+	struct isci_host *isci_host,
+	struct isci_tmf *isci_tmf,
+	struct isci_request **isci_request,
+	struct isci_remote_device *isci_device,
+	gfp_t gfp_flags)
+{
+	int retval = isci_request_alloc_core(isci_host, isci_request,
+					     isci_device, gfp_flags);
+
+	if (!retval) {
+
+		(*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf;
+		(*isci_request)->ttype = tmf_task;
+	}
+	return retval;
+}
+
+/**
+ * isci_request_signal_device_reset() - This function will set the "device
+ *    needs target reset" flag in the given sas_tasks' task_state_flags, and
+ *    then cause the task to be added into the SCSI error handler queue which
+ *    will eventually be escalated to a target reset.
+ *
+ *
+ */
+static void isci_request_signal_device_reset(
+	struct isci_request *isci_request)
+{
+	unsigned long flags;
+	struct sas_task *task = isci_request_access_task(isci_request);
+
+	dev_dbg(&isci_request->isci_host->pdev->dev,
+		"%s: request=%p, task=%p\n", __func__, isci_request, task);
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
+	task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+	/* Cause this task to be scheduled in the SCSI error handler
+	 * thread.
+	 */
+	sas_task_abort(task);
+}
+
+/**
+ * isci_request_execute() - This function allocates the isci_request object,
+ *    all fills in some common fields.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @sas_task: This parameter is the task struct from the upper layer driver.
+ * @isci_request: This parameter will contain the pointer to the new
+ *    isci_request object.
+ * @gfp_flags: This parameter specifies the os allocation flags.
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+int isci_request_execute(
+	struct isci_host *isci_host,
+	struct sas_task *task,
+	struct isci_request **isci_request,
+	gfp_t gfp_flags)
+{
+	int ret = 0;
+	struct scic_sds_remote_device *sci_device;
+	enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+	struct isci_remote_device *isci_device;
+	struct isci_request *request;
+	unsigned long flags;
+
+	isci_device = isci_dev_from_domain_dev(task->dev);
+	sci_device = isci_device->sci_device_handle;
+
+	/* do common allocation and init of request object. */
+	ret = isci_request_alloc_io(
+		isci_host,
+		task,
+		&request,
+		isci_device,
+		gfp_flags
+		);
+
+	if (ret)
+		goto out;
+
+	status = isci_io_request_build(isci_host, request, isci_device);
+	if (status == SCI_SUCCESS) {
+
+		spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+		/* send the request, let the core assign the IO TAG.	*/
+		status = scic_controller_start_io(
+			isci_host->core_controller,
+			sci_device,
+			request->sci_request_handle,
+			SCI_CONTROLLER_INVALID_IO_TAG
+			);
+
+		if (status == SCI_SUCCESS ||
+		    status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
+
+			/* Either I/O started OK, or the core has signaled that
+			 * the device needs a target reset.
+			 *
+			 * In either case, hold onto the I/O for later.
+			 *
+			 * Update it's status and add it to the list in the
+			 * remote device object.
+			 */
+			isci_request_change_state(request, started);
+			list_add(&request->dev_node,
+				 &isci_device->reqs_in_process);
+
+			if (status ==
+				SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
+				/* Signal libsas that we need the SCSI error
+				 * handler thread to work on this I/O and that
+				 * we want a device reset.
+				 */
+				isci_request_signal_device_reset(request);
+
+				/* Change the status, since we are holding
+				 * the I/O until it is managed by the SCSI
+				 * error handler.
+				 */
+				status = SCI_SUCCESS;
+			}
+		} else
+			dev_warn(&isci_host->pdev->dev,
+				 "%s: failed request start\n",
+				 __func__);
+
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	} else
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: request_construct failed - status = 0x%x\n",
+			 __func__,
+			 status);
+
+ out:
+	if (status != SCI_SUCCESS) {
+
+		/* release dma memory on failure. */
+		isci_request_free(isci_host, request);
+		request = NULL;
+		ret = SCI_FAILURE;
+	}
+
+	*isci_request = request;
+	return ret;
+}
+
+
+/**
+ * isci_request_process_response_iu() - This function sets the status and
+ *    response iu, in the task struct, from the request object for the upper
+ *    layer driver.
+ * @sas_task: This parameter is the task struct from the upper layer driver.
+ * @resp_iu: This parameter points to the response iu of the completed request.
+ * @dev: This parameter specifies the linux device struct.
+ *
+ * none.
+ */
+static void isci_request_process_response_iu(
+	struct sas_task *task,
+	struct ssp_response_iu *resp_iu,
+	struct device *dev)
+{
+	dev_dbg(dev,
+		"%s: resp_iu = %p "
+		"resp_iu->status = 0x%x,\nresp_iu->datapres = %d "
+		"resp_iu->response_data_len = %x, "
+		"resp_iu->sense_data_len = %x\nrepsonse data: ",
+		__func__,
+		resp_iu,
+		resp_iu->status,
+		resp_iu->datapres,
+		resp_iu->response_data_len,
+		resp_iu->sense_data_len);
+
+	task->task_status.stat = resp_iu->status;
+
+	/* libsas updates the task status fields based on the response iu. */
+	sas_ssp_task_response(dev, task, resp_iu);
+}
+
+/**
+ * isci_request_set_open_reject_status() - This function prepares the I/O
+ *    completion for OPEN_REJECT conditions.
+ * @request: This parameter is the completed isci_request object.
+ * @response_ptr: This parameter specifies the service response for the I/O.
+ * @status_ptr: This parameter specifies the exec status for the I/O.
+ * @complete_to_host_ptr: This parameter specifies the action to be taken by
+ *    the LLDD with respect to completing this request or forcing an abort
+ *    condition on the I/O.
+ * @open_rej_reason: This parameter specifies the encoded reason for the
+ *    abandon-class reject.
+ *
+ * none.
+ */
+static void isci_request_set_open_reject_status(
+	struct isci_request *request,
+	struct sas_task *task,
+	enum service_response *response_ptr,
+	enum exec_status *status_ptr,
+	enum isci_completion_selection *complete_to_host_ptr,
+	enum sas_open_rej_reason open_rej_reason)
+{
+	/* Task in the target is done. */
+	request->complete_in_target       = true;
+	*response_ptr                     = SAS_TASK_UNDELIVERED;
+	*status_ptr                       = SAS_OPEN_REJECT;
+	*complete_to_host_ptr             = isci_perform_normal_io_completion;
+	task->task_status.open_rej_reason = open_rej_reason;
+}
+
+/**
+ * isci_request_handle_controller_specific_errors() - This function decodes
+ *    controller-specific I/O completion error conditions.
+ * @request: This parameter is the completed isci_request object.
+ * @response_ptr: This parameter specifies the service response for the I/O.
+ * @status_ptr: This parameter specifies the exec status for the I/O.
+ * @complete_to_host_ptr: This parameter specifies the action to be taken by
+ *    the LLDD with respect to completing this request or forcing an abort
+ *    condition on the I/O.
+ *
+ * none.
+ */
+static void isci_request_handle_controller_specific_errors(
+	struct isci_remote_device *isci_device,
+	struct isci_request *request,
+	struct sas_task *task,
+	enum service_response *response_ptr,
+	enum exec_status *status_ptr,
+	enum isci_completion_selection *complete_to_host_ptr)
+{
+	unsigned int cstatus;
+
+	cstatus = scic_request_get_controller_status(
+		request->sci_request_handle
+		);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR "
+		"- controller status = 0x%x\n",
+		__func__, request, cstatus);
+
+	/* Decode the controller-specific errors; most
+	 * important is to recognize those conditions in which
+	 * the target may still have a task outstanding that
+	 * must be aborted.
+	 *
+	 * Note that there are SCU completion codes being
+	 * named in the decode below for which SCIC has already
+	 * done work to handle them in a way other than as
+	 * a controller-specific completion code; these are left
+	 * in the decode below for completeness sake.
+	 */
+	switch (cstatus) {
+	case SCU_TASK_DONE_DMASETUP_DIRERR:
+	/* Also SCU_TASK_DONE_SMP_FRM_TYPE_ERR: */
+	case SCU_TASK_DONE_XFERCNT_ERR:
+		/* Also SCU_TASK_DONE_SMP_UFI_ERR: */
+		if (task->task_proto == SAS_PROTOCOL_SMP) {
+			/* SCU_TASK_DONE_SMP_UFI_ERR == Task Done. */
+			*response_ptr = SAS_TASK_COMPLETE;
+
+			/* See if the device has been/is being stopped. Note
+			 * that we ignore the quiesce state, since we are
+			 * concerned about the actual device state.
+			 */
+			if ((isci_device->status == isci_stopping) ||
+			    (isci_device->status == isci_stopped))
+				*status_ptr = SAS_DEVICE_UNKNOWN;
+			else
+				*status_ptr = SAS_ABORTED_TASK;
+
+			request->complete_in_target = true;
+
+			*complete_to_host_ptr =
+				isci_perform_normal_io_completion;
+		} else {
+			/* Task in the target is not done. */
+			*response_ptr = SAS_TASK_UNDELIVERED;
+
+			if ((isci_device->status == isci_stopping) ||
+			    (isci_device->status == isci_stopped))
+				*status_ptr = SAS_DEVICE_UNKNOWN;
+			else
+				*status_ptr = SAM_STAT_TASK_ABORTED;
+
+			request->complete_in_target = false;
+
+			*complete_to_host_ptr =
+				isci_perform_error_io_completion;
+		}
+
+		break;
+
+	case SCU_TASK_DONE_CRC_ERR:
+	case SCU_TASK_DONE_NAK_CMD_ERR:
+	case SCU_TASK_DONE_EXCESS_DATA:
+	case SCU_TASK_DONE_UNEXP_FIS:
+	/* Also SCU_TASK_DONE_UNEXP_RESP: */
+	case SCU_TASK_DONE_VIIT_ENTRY_NV:       /* TODO - conditions? */
+	case SCU_TASK_DONE_IIT_ENTRY_NV:        /* TODO - conditions? */
+	case SCU_TASK_DONE_RNCNV_OUTBOUND:      /* TODO - conditions? */
+		/* These are conditions in which the target
+		 * has completed the task, so that no cleanup
+		 * is necessary.
+		 */
+		*response_ptr = SAS_TASK_COMPLETE;
+
+		/* See if the device has been/is being stopped. Note
+		 * that we ignore the quiesce state, since we are
+		 * concerned about the actual device state.
+		 */
+		if ((isci_device->status == isci_stopping) ||
+		    (isci_device->status == isci_stopped))
+			*status_ptr = SAS_DEVICE_UNKNOWN;
+		else
+			*status_ptr = SAS_ABORTED_TASK;
+
+		request->complete_in_target = true;
+
+		*complete_to_host_ptr = isci_perform_normal_io_completion;
+		break;
+
+
+	/* Note that the only open reject completion codes seen here will be
+	 * abandon-class codes; all others are automatically retried in the SCU.
+	 */
+	case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_WRONG_DEST);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
+
+		/* Note - the return of AB0 will change when
+		 * libsas implements detection of zone violations.
+		 */
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_RESV_AB0);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_RESV_AB1);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_RESV_AB2);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_RESV_AB3);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_BAD_DEST);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_STP_NORES);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_EPROTO);
+		break;
+
+	case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
+
+		isci_request_set_open_reject_status(
+			request, task, response_ptr, status_ptr,
+			complete_to_host_ptr, SAS_OREJ_CONN_RATE);
+		break;
+
+	case SCU_TASK_DONE_LL_R_ERR:
+	/* Also SCU_TASK_DONE_ACK_NAK_TO: */
+	case SCU_TASK_DONE_LL_PERR:
+	case SCU_TASK_DONE_LL_SY_TERM:
+	/* Also SCU_TASK_DONE_NAK_ERR:*/
+	case SCU_TASK_DONE_LL_LF_TERM:
+	/* Also SCU_TASK_DONE_DATA_LEN_ERR: */
+	case SCU_TASK_DONE_LL_ABORT_ERR:
+	case SCU_TASK_DONE_SEQ_INV_TYPE:
+	/* Also SCU_TASK_DONE_UNEXP_XR: */
+	case SCU_TASK_DONE_XR_IU_LEN_ERR:
+	case SCU_TASK_DONE_INV_FIS_LEN:
+	/* Also SCU_TASK_DONE_XR_WD_LEN: */
+	case SCU_TASK_DONE_SDMA_ERR:
+	case SCU_TASK_DONE_OFFSET_ERR:
+	case SCU_TASK_DONE_MAX_PLD_ERR:
+	case SCU_TASK_DONE_LF_ERR:
+	case SCU_TASK_DONE_SMP_RESP_TO_ERR:  /* Escalate to dev reset? */
+	case SCU_TASK_DONE_SMP_LL_RX_ERR:
+	case SCU_TASK_DONE_UNEXP_DATA:
+	case SCU_TASK_DONE_UNEXP_SDBFIS:
+	case SCU_TASK_DONE_REG_ERR:
+	case SCU_TASK_DONE_SDB_ERR:
+	case SCU_TASK_DONE_TASK_ABORT:
+	default:
+		/* Task in the target is not done. */
+		*response_ptr = SAS_TASK_UNDELIVERED;
+		*status_ptr = SAM_STAT_TASK_ABORTED;
+		request->complete_in_target = false;
+
+		*complete_to_host_ptr = isci_perform_error_io_completion;
+		break;
+	}
+}
+
+/**
+ * isci_task_save_for_upper_layer_completion() - This function saves the
+ *    request for later completion to the upper layer driver.
+ * @host: This parameter is a pointer to the host on which the the request
+ *    should be queued (either as an error or success).
+ * @request: This parameter is the completed request.
+ * @response: This parameter is the response code for the completed task.
+ * @status: This parameter is the status code for the completed task.
+ *
+ * none.
+ */
+static void isci_task_save_for_upper_layer_completion(
+	struct isci_host *host,
+	struct isci_request *request,
+	enum service_response response,
+	enum exec_status status,
+	enum isci_completion_selection task_notification_selection)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	isci_task_set_completion_status(task, response, status,
+					 task_notification_selection);
+
+
+	/* Tasks aborted specifically by a call to the lldd_abort_task
+	 * function should not be completed to the host in the regular path.
+	 */
+	switch (task_notification_selection) {
+
+	case isci_perform_normal_io_completion:
+
+		/* Normal notification (task_done) */
+		dev_dbg(&host->pdev->dev,
+			"%s: Normal - task = %p, response=%d, status=%d\n",
+			__func__,
+			task,
+			response,
+			status);
+		/* Add to the completed list. */
+		list_add(&request->completed_node,
+			 &host->requests_to_complete);
+		break;
+
+	case isci_perform_aborted_io_completion:
+		/*
+		 * No notification because this request is already
+		 * in the abort path.
+		 */
+		dev_warn(&host->pdev->dev,
+			 "%s: Aborted - task = %p, response=%d, status=%d\n",
+			 __func__,
+			 task,
+			 response,
+			 status);
+		break;
+
+	case isci_perform_error_io_completion:
+		/* Use sas_task_abort */
+		dev_warn(&host->pdev->dev,
+			 "%s: Error - task = %p, response=%d, status=%d\n",
+			 __func__,
+			 task,
+			 response,
+			 status);
+		/* Add to the aborted list. */
+		list_add(&request->completed_node,
+			 &host->requests_to_abort);
+		break;
+
+	default:
+		dev_warn(&host->pdev->dev,
+			 "%s: Unknown - task = %p, response=%d, status=%d\n",
+			 __func__,
+			 task,
+			 response,
+			 status);
+
+		/* Add to the aborted list. */
+		list_add(&request->completed_node,
+			 &host->requests_to_abort);
+		break;
+	}
+}
+
+/**
+ * isci_request_io_request_complete() - This function is called by the sci core
+ *    when an io request completes.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @request: This parameter is the completed isci_request object.
+ * @completion_status: This parameter specifies the completion status from the
+ *    sci core.
+ *
+ * none.
+ */
+void isci_request_io_request_complete(
+	struct        isci_host *isci_host,
+	struct        isci_request *request,
+	enum sci_io_status completion_status)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	struct ssp_response_iu *resp_iu;
+	void *resp_buf;
+	unsigned long task_flags;
+	unsigned long state_flags;
+	struct completion *io_request_completion;
+	struct isci_remote_device *isci_device   = request->isci_device;
+	enum service_response response       = SAS_TASK_UNDELIVERED;
+	enum exec_status status         = SAS_ABORTED_TASK;
+	enum isci_request_status request_status;
+	enum isci_completion_selection complete_to_host
+		= isci_perform_normal_io_completion;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: request = %p, task = %p,\n"
+		"task->data_dir = %d completion_status = 0x%x\n",
+		__func__,
+		request,
+		task,
+		task->data_dir,
+		completion_status);
+
+	spin_lock_irqsave(&request->state_lock, state_flags);
+	request_status = isci_request_get_state(request);
+	spin_unlock_irqrestore(&request->state_lock, state_flags);
+
+	/* Decode the request status.  Note that if the request has been
+	 * aborted by a task management function, we don't care
+	 * what the status is.
+	 */
+	switch (request_status) {
+
+	case aborted:
+		/* "aborted" indicates that the request was aborted by a task
+		 * management function, since once a task management request is
+		 * perfomed by the device, the request only completes because
+		 * of the subsequent driver terminate.
+		 *
+		 * Aborted also means an external thread is explicitly managing
+		 * this request, so that we do not complete it up the stack.
+		 *
+		 * The target is still there (since the TMF was successful).
+		 */
+		request->complete_in_target = true;
+		response = SAS_TASK_COMPLETE;
+
+		/* See if the device has been/is being stopped. Note
+		 * that we ignore the quiesce state, since we are
+		 * concerned about the actual device state.
+		 */
+		if ((isci_device->status == isci_stopping)
+		    || (isci_device->status == isci_stopped)
+		    )
+			status = SAS_DEVICE_UNKNOWN;
+		else
+			status = SAS_ABORTED_TASK;
+
+		complete_to_host = isci_perform_aborted_io_completion;
+		/* This was an aborted request. */
+		break;
+
+	case aborting:
+		/* aborting means that the task management function tried and
+		 * failed to abort the request. We need to note the request
+		 * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the
+		 * target as down.
+		 *
+		 * Aborting also means an external thread is explicitly managing
+		 * this request, so that we do not complete it up the stack.
+		 */
+		request->complete_in_target = true;
+		response = SAS_TASK_UNDELIVERED;
+
+		if ((isci_device->status == isci_stopping) ||
+		    (isci_device->status == isci_stopped))
+			/* The device has been /is being stopped. Note that
+			 * we ignore the quiesce state, since we are
+			 * concerned about the actual device state.
+			 */
+			status = SAS_DEVICE_UNKNOWN;
+		else
+			status = SAS_PHY_DOWN;
+
+		complete_to_host = isci_perform_aborted_io_completion;
+
+		/* This was an aborted request. */
+		break;
+
+	case terminating:
+
+		/* This was an terminated request.  This happens when
+		 * the I/O is being terminated because of an action on
+		 * the device (reset, tear down, etc.), and the I/O needs
+		 * to be completed up the stack.
+		 */
+		request->complete_in_target = true;
+		response = SAS_TASK_UNDELIVERED;
+
+		/* See if the device has been/is being stopped. Note
+		 * that we ignore the quiesce state, since we are
+		 * concerned about the actual device state.
+		 */
+		if ((isci_device->status == isci_stopping) ||
+		    (isci_device->status == isci_stopped))
+			status = SAS_DEVICE_UNKNOWN;
+		else
+			status = SAS_ABORTED_TASK;
+
+		complete_to_host = isci_perform_normal_io_completion;
+
+		/* This was a terminated request. */
+		break;
+
+	default:
+
+		/* This is an active request being completed from the core. */
+		switch (completion_status) {
+
+		case SCI_IO_FAILURE_RESPONSE_VALID:
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n",
+				__func__,
+				request,
+				task);
+
+			if (sas_protocol_ata(task->task_proto)) {
+				resp_buf
+					= scic_stp_io_request_get_d2h_reg_address(
+					request->sci_request_handle
+					);
+				isci_request_process_stp_response(task,
+								  resp_buf
+								  );
+
+			} else if (SAS_PROTOCOL_SSP == task->task_proto) {
+
+				/* crack the iu response buffer. */
+				resp_iu
+					= scic_io_request_get_response_iu_address(
+					request->sci_request_handle
+					);
+
+				isci_request_process_response_iu(task, resp_iu,
+								 &isci_host->pdev->dev
+								 );
+
+			} else if (SAS_PROTOCOL_SMP == task->task_proto) {
+
+				dev_err(&isci_host->pdev->dev,
+					"%s: SCI_IO_FAILURE_RESPONSE_VALID: "
+					"SAS_PROTOCOL_SMP protocol\n",
+					__func__);
+
+			} else
+				dev_err(&isci_host->pdev->dev,
+					"%s: unknown protocol\n", __func__);
+
+			/* use the task status set in the task struct by the
+			 * isci_request_process_response_iu call.
+			 */
+			request->complete_in_target = true;
+			response = task->task_status.resp;
+			status = task->task_status.stat;
+			break;
+
+		case SCI_IO_SUCCESS:
+		case SCI_IO_SUCCESS_IO_DONE_EARLY:
+
+			response = SAS_TASK_COMPLETE;
+			status   = SAM_STAT_GOOD;
+			request->complete_in_target = true;
+
+			if (task->task_proto == SAS_PROTOCOL_SMP) {
+
+				u8 *command_iu_address
+					= scic_io_request_get_command_iu_address(
+					request->sci_request_handle
+					);
+
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: SMP protocol completion\n",
+					__func__);
+
+				sg_copy_from_buffer(
+					&task->smp_task.smp_resp, 1,
+					command_iu_address
+					+ sizeof(struct smp_request),
+					sizeof(struct smp_resp)
+					);
+			} else if (completion_status
+				   == SCI_IO_SUCCESS_IO_DONE_EARLY) {
+
+				/* This was an SSP / STP / SATA transfer.
+				 * There is a possibility that less data than
+				 * the maximum was transferred.
+				 */
+				u32 transferred_length
+					= scic_io_request_get_number_of_bytes_transferred(
+					request->sci_request_handle);
+
+				task->task_status.residual
+					= task->total_xfer_len - transferred_length;
+
+				/* If there were residual bytes, call this an
+				 * underrun.
+				 */
+				if (task->task_status.residual != 0)
+					status = SAS_DATA_UNDERRUN;
+
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n",
+					__func__,
+					status);
+
+			} else
+				dev_dbg(&isci_host->pdev->dev,
+					"%s: SCI_IO_SUCCESS\n",
+					__func__);
+
+			break;
+
+		case SCI_IO_FAILURE_TERMINATED:
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n",
+				__func__,
+				request,
+				task);
+
+			/* The request was terminated explicitly.  No handling
+			 * is needed in the SCSI error handler path.
+			 */
+			request->complete_in_target = true;
+			response = SAS_TASK_UNDELIVERED;
+
+			/* See if the device has been/is being stopped. Note
+			 * that we ignore the quiesce state, since we are
+			 * concerned about the actual device state.
+			 */
+			if ((isci_device->status == isci_stopping) ||
+			    (isci_device->status == isci_stopped))
+				status = SAS_DEVICE_UNKNOWN;
+			else
+				status = SAS_ABORTED_TASK;
+
+			complete_to_host = isci_perform_normal_io_completion;
+			break;
+
+		case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR:
+
+			isci_request_handle_controller_specific_errors(
+				isci_device, request, task, &response, &status,
+				&complete_to_host);
+
+			break;
+
+		case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED:
+			/* This is a special case, in that the I/O completion
+			 * is telling us that the device needs a reset.
+			 * In order for the device reset condition to be
+			 * noticed, the I/O has to be handled in the error
+			 * handler.  Set the reset flag and cause the
+			 * SCSI error thread to be scheduled.
+			 */
+			spin_lock_irqsave(&task->task_state_lock, task_flags);
+			task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+			spin_unlock_irqrestore(&task->task_state_lock, task_flags);
+
+			complete_to_host = isci_perform_error_io_completion;
+			request->complete_in_target = false;
+			break;
+
+		default:
+			/* Catch any otherwise unhandled error codes here. */
+			dev_warn(&isci_host->pdev->dev,
+				 "%s: invalid completion code: 0x%x - "
+				 "isci_request = %p\n",
+				 __func__, completion_status, request);
+
+			response = SAS_TASK_UNDELIVERED;
+
+			/* See if the device has been/is being stopped. Note
+			 * that we ignore the quiesce state, since we are
+			 * concerned about the actual device state.
+			 */
+			if ((isci_device->status == isci_stopping) ||
+			    (isci_device->status == isci_stopped))
+				status = SAS_DEVICE_UNKNOWN;
+			else
+				status = SAS_ABORTED_TASK;
+
+			complete_to_host = isci_perform_error_io_completion;
+			request->complete_in_target = false;
+			break;
+		}
+		break;
+	}
+
+	isci_request_unmap_sgl(request, isci_host->pdev);
+
+	/* Put the completed request on the correct list */
+	isci_task_save_for_upper_layer_completion(isci_host, request, response,
+						  status, complete_to_host
+						  );
+
+	/* complete the io request to the core. */
+	scic_controller_complete_io(
+		isci_host->core_controller,
+		isci_device->sci_device_handle,
+		request->sci_request_handle
+		);
+	/* NULL the request handle so it cannot be completed or
+	 * terminated again, and to cause any calls into abort
+	 * task to recognize the already completed case.
+	 */
+	request->sci_request_handle = NULL;
+
+	/* Only remove the request from the remote device list
+	 * of pending requests if we have not requested error
+	 * handling on this request.
+	 */
+	if (complete_to_host != isci_perform_error_io_completion)
+		list_del_init(&request->dev_node);
+
+
+	/* Save possible completion ptr. */
+	io_request_completion = request->io_request_completion;
+
+	if (io_request_completion) {
+
+		/* This is inherantly a regular I/O request,
+		 * since we are currently in the regular
+		 * I/O completion callback function.
+		 * Signal whoever is waiting that this
+		 * request is complete.
+		 */
+		complete(io_request_completion);
+	}
+
+	isci_host_can_dequeue(isci_host, 1);
+}
+
+/**
+ * isci_request_io_request_get_transfer_length() - This function is called by
+ *    the sci core to retrieve the transfer length for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * length of transfer for specified request.
+ */
+u32 isci_request_io_request_get_transfer_length(struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: total_xfer_len: %d\n",
+		__func__,
+		task->total_xfer_len);
+	return task->total_xfer_len;
+}
+
+
+/**
+ * isci_request_io_request_get_data_direction() - This function is called by
+ *    the sci core to retrieve the data direction for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * data direction for specified request.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	SCI_IO_REQUEST_DATA_DIRECTION ret;
+
+	switch (task->data_dir) {
+
+	case DMA_FROM_DEVICE:
+		ret = SCI_IO_REQUEST_DATA_IN;
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: request=%p, FROM_DEVICE\n",
+			__func__,
+			request);
+		break;
+
+	case DMA_TO_DEVICE:
+		ret = SCI_IO_REQUEST_DATA_OUT;
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: request=%p, TO_DEVICE\n",
+			__func__,
+			request);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+	case DMA_NONE:
+	default:
+		ret = SCI_IO_REQUEST_NO_DATA;
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: request=%p, unhandled direction case, "
+			"data_dir=%d\n",
+			__func__,
+			request,
+			task->data_dir);
+		break;
+
+	}
+	return ret;
+}
+
+/**
+ * isci_request_sge_get_address_field() - This function is called by the sci
+ *    core to retrieve the address field contents for a given sge.
+ * @request: This parameter is the isci_request object.
+ * @sge_address: This parameter is the sge.
+ *
+ * physical address in the specified sge.
+ */
+dma_addr_t isci_request_sge_get_address_field(
+	struct isci_request *request,
+	void *sge_address)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	dma_addr_t ret;
+	struct isci_host *isci_host = isci_host_from_sas_ha(
+		task->dev->port->ha);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: request = %p, sge_address = %p\n",
+		__func__,
+		request,
+		sge_address);
+
+	if (task->data_dir == PCI_DMA_NONE)
+		return 0;
+
+	/* the case where num_scatter == 0 is special, in that
+	 * task->scatter is the actual buffer address, not an sgl.
+	 * so a map single is required here.
+	 */
+	if ((task->num_scatter == 0) &&
+	    !sas_protocol_ata(task->task_proto)) {
+		ret = dma_map_single(
+			&isci_host->pdev->dev,
+			task->scatter,
+			task->total_xfer_len,
+			task->data_dir
+			);
+		request->zero_scatter_daddr = ret;
+	} else
+		ret = sg_dma_address(((struct scatterlist *)sge_address));
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: bus address = %lx\n",
+		__func__,
+		(unsigned long)ret);
+
+	return ret;
+}
+
+
+/**
+ * isci_request_sge_get_length_field() - This function is called by the sci
+ *    core to retrieve the length field contents for a given sge.
+ * @request: This parameter is the isci_request object.
+ * @sge_address: This parameter is the sge.
+ *
+ * length field value in the specified sge.
+ */
+u32 isci_request_sge_get_length_field(
+	struct isci_request *request,
+	void *sge_address)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	int ret;
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p, sge_address = %p\n",
+		__func__,
+		request,
+		sge_address);
+
+	if (task->data_dir == PCI_DMA_NONE)
+		return 0;
+
+	/* the case where num_scatter == 0 is special, in that
+	 * task->scatter is the actual buffer address, not an sgl.
+	 * so we return total_xfer_len here.
+	 */
+	if (task->num_scatter == 0)
+		ret = task->total_xfer_len;
+	else
+		ret = sg_dma_len((struct scatterlist *)sge_address);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: len = %d\n",
+		__func__,
+		ret);
+
+	return ret;
+}
+
+
+/**
+ * isci_request_ssp_io_request_get_cdb_address() - This function is called by
+ *    the sci core to retrieve the cdb address for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * cdb address for specified request.
+ */
+void *isci_request_ssp_io_request_get_cdb_address(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request->task->ssp_task.cdb = %p\n",
+		__func__,
+		task->ssp_task.cdb);
+	return task->ssp_task.cdb;
+}
+
+
+/**
+ * isci_request_ssp_io_request_get_cdb_length() - This function is called by
+ *    the sci core to retrieve the cdb length for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * cdb length for specified request.
+ */
+u32 isci_request_ssp_io_request_get_cdb_length(
+	struct isci_request *request)
+{
+	return 16;
+}
+
+
+/**
+ * isci_request_ssp_io_request_get_lun() - This function is called by the sci
+ *    core to retrieve the lun for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * lun for specified request.
+ */
+u32 isci_request_ssp_io_request_get_lun(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+#ifdef DEBUG
+	int i;
+
+	for (i = 0; i < 8; i++)
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: request->task->ssp_task.LUN[%d] = %x\n",
+			__func__, i, request->task->ssp_task.LUN[i]);
+
+#endif
+
+	return task->ssp_task.LUN[0];
+}
+
+
+/**
+ * isci_request_ssp_io_request_get_task_attribute() - This function is called
+ *    by the sci core to retrieve the task attribute for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * task attribute for specified request.
+ */
+u32 isci_request_ssp_io_request_get_task_attribute(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request->task->ssp_task.task_attr = %x\n",
+		__func__,
+		task->ssp_task.task_attr);
+
+	return task->ssp_task.task_attr;
+}
+
+
+/**
+ * isci_request_ssp_io_request_get_command_priority() - This function is called
+ *    by the sci core to retrieve the command priority for a given request.
+ * @request: This parameter is the isci_request object.
+ *
+ * command priority for specified request.
+ */
+u32 isci_request_ssp_io_request_get_command_priority(
+	struct isci_request *request)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request->task->ssp_task.task_prio = %x\n",
+		__func__,
+		task->ssp_task.task_prio);
+
+	return task->ssp_task.task_prio;
+}
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
new file mode 100644
index 0000000..5079d4a
--- /dev/null
+++ b/drivers/scsi/isci/request.h
@@ -0,0 +1,429 @@
+/*
+ * 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(_ISCI_REQUEST_H_)
+#define _ISCI_REQUEST_H_
+
+#include "isci.h"
+
+/**
+ * struct isci_request_status - This enum defines the possible states of an I/O
+ *    request.
+ *
+ *
+ */
+enum isci_request_status {
+	unallocated = 0x00,
+	allocated   = 0x01,
+	started     = 0x02,
+	completed   = 0x03,
+	aborting    = 0x04,
+	aborted     = 0x05,
+	terminating = 0x06
+};
+
+enum task_type {
+	io_task  = 0,
+	tmf_task = 1
+};
+
+/**
+ * struct isci_request - This class represents the request object used to track
+ *    IO, smp and TMF request internal. It wraps the SCIC request object.
+ *
+ *
+ */
+struct isci_request {
+
+	struct scic_sds_request *sci_request_handle;
+
+	enum isci_request_status status;
+	enum task_type ttype;
+	unsigned short io_tag;
+	bool complete_in_target;
+
+	union ttype_ptr_union {
+		struct sas_task *io_task_ptr;   /* When ttype==io_task  */
+		struct isci_tmf *tmf_task_ptr;  /* When ttype==tmf_task */
+	} ttype_ptr;
+	struct isci_host *isci_host;
+	struct isci_remote_device *isci_device;
+	/* For use in the requests_to_{complete|abort} lists: */
+	struct list_head completed_node;
+	/* For use in the reqs_in_process list: */
+	struct list_head dev_node;
+	void *sci_request_mem_ptr;
+	spinlock_t state_lock;
+	dma_addr_t request_daddr;
+	dma_addr_t zero_scatter_daddr;
+
+	unsigned int num_sg_entries;                    /* returned by pci_alloc_sg */
+	unsigned int request_alloc_size;                /* size of block from dma_pool_alloc */
+
+	/** Note: "io_request_completion" is completed in two different ways
+	 * depending on whether this is a TMF or regular request.
+	 * - TMF requests are completed in the thread that started them;
+	 * - regular requests are completed in the request completion callback
+	 *   function.
+	 * This difference in operation allows the aborter of a TMF request
+	 * to be sure that once the TMF request completes, the I/O that the
+	 * TMF was aborting is guaranteed to have completed.
+	 */
+	struct completion *io_request_completion;
+};
+
+/**
+ * This function gets the status of the request object.
+ * @request: This parameter points to the isci_request object
+ *
+ * status of the object as a isci_request_status enum.
+ */
+static inline
+enum isci_request_status isci_request_get_state(
+	struct isci_request *isci_request)
+{
+	BUG_ON(isci_request == NULL);
+
+	/*probably a bad sign...	*/
+	if (isci_request->status == unallocated)
+		dev_warn(&isci_request->isci_host->pdev->dev,
+			 "%s: isci_request->status == unallocated\n",
+			 __func__);
+
+	return isci_request->status;
+}
+
+
+/**
+ * isci_request_change_state() - This function sets the status of the request
+ *    object.
+ * @request: This parameter points to the isci_request object
+ * @status: This Parameter is the new status of the object
+ *
+ */
+static inline enum isci_request_status isci_request_change_state(
+	struct isci_request *isci_request,
+	enum isci_request_status status)
+{
+	enum isci_request_status old_state;
+	unsigned long flags;
+
+	dev_dbg(&isci_request->isci_host->pdev->dev,
+		"%s: isci_request = %p, state = 0x%x\n",
+		__func__,
+		isci_request,
+		status);
+
+	BUG_ON(isci_request == NULL);
+
+	spin_lock_irqsave(&isci_request->state_lock, flags);
+	old_state = isci_request->status;
+	isci_request->status = status;
+	spin_unlock_irqrestore(&isci_request->state_lock, flags);
+
+	return old_state;
+}
+
+/**
+ * isci_request_change_started_to_newstate() - This function sets the status of
+ *    the request object.
+ * @request: This parameter points to the isci_request object
+ * @status: This Parameter is the new status of the object
+ *
+ * state previous to any change.
+ */
+static inline enum isci_request_status isci_request_change_started_to_newstate(
+	struct isci_request *isci_request,
+	struct completion *completion_ptr,
+	enum isci_request_status newstate)
+{
+	enum isci_request_status old_state;
+	unsigned long flags;
+
+	BUG_ON(isci_request == NULL);
+
+	spin_lock_irqsave(&isci_request->state_lock, flags);
+
+	old_state = isci_request->status;
+
+	if (old_state == started) {
+		BUG_ON(isci_request->io_request_completion != NULL);
+
+		isci_request->io_request_completion = completion_ptr;
+		isci_request->status = newstate;
+	}
+	spin_unlock_irqrestore(&isci_request->state_lock, flags);
+
+	dev_dbg(&isci_request->isci_host->pdev->dev,
+		"%s: isci_request = %p, old_state = 0x%x\n",
+		__func__,
+		isci_request,
+		old_state);
+
+	return old_state;
+}
+
+/**
+ * isci_request_change_started_to_aborted() - This function sets the status of
+ *    the request object.
+ * @request: This parameter points to the isci_request object
+ * @completion_ptr: This parameter is saved as the kernel completion structure
+ *    signalled when the old request completes.
+ *
+ * state previous to any change.
+ */
+static inline enum isci_request_status isci_request_change_started_to_aborted(
+	struct isci_request *isci_request,
+	struct completion *completion_ptr)
+{
+	return isci_request_change_started_to_newstate(
+		       isci_request, completion_ptr, aborted
+		       );
+}
+/**
+ * isci_request_free() - This function frees the request object.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @isci_request: This parameter points to the isci_request object
+ *
+ */
+static inline void isci_request_free(
+	struct isci_host *isci_host,
+	struct isci_request *isci_request)
+{
+	BUG_ON(isci_request == NULL);
+
+	/* release the dma memory if we fail. */
+	dma_pool_free(isci_host->dma_pool, isci_request,
+		      isci_request->request_daddr);
+}
+
+
+/* #define ISCI_REQUEST_VALIDATE_ACCESS
+ */
+
+#ifdef ISCI_REQUEST_VALIDATE_ACCESS
+
+static inline
+struct sas_task *isci_request_access_task(struct isci_request *isci_request)
+{
+	BUG_ON(isci_request->ttype != io_task);
+	return isci_request->ttype_ptr.io_task_ptr;
+}
+
+static inline
+struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request)
+{
+	BUG_ON(isci_request->ttype != tmf_task);
+	return isci_request->ttype_ptr.tmf_task_ptr;
+}
+
+#else  /* not ISCI_REQUEST_VALIDATE_ACCESS */
+
+#define isci_request_access_task(RequestPtr) \
+	((RequestPtr)->ttype_ptr.io_task_ptr)
+
+#define isci_request_access_tmf(RequestPtr)  \
+	((RequestPtr)->ttype_ptr.tmf_task_ptr)
+
+#endif /* not ISCI_REQUEST_VALIDATE_ACCESS */
+
+
+int isci_request_alloc_tmf(
+	struct isci_host *isci_host,
+	struct isci_tmf *isci_tmf,
+	struct isci_request **isci_request,
+	struct isci_remote_device *isci_device,
+	gfp_t gfp_flags);
+
+
+int isci_request_execute(
+	struct isci_host *isci_host,
+	struct sas_task *task,
+	struct isci_request **request,
+	gfp_t gfp_flags);
+
+/**
+ * isci_request_unmap_sgl() - This function unmaps the DMA address of a given
+ *    sgl
+ * @request: This parameter points to the isci_request object
+ * @*pdev: This Parameter is the pci_device struct for the controller
+ *
+ */
+static inline void isci_request_unmap_sgl(
+	struct isci_request *request,
+	struct pci_dev *pdev)
+{
+	struct sas_task *task = isci_request_access_task(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p, task = %p,\n"
+		"task->data_dir = %d, is_sata = %d\n ",
+		__func__,
+		request,
+		task,
+		task->data_dir,
+		sas_protocol_ata(task->task_proto));
+
+	if ((task->data_dir != PCI_DMA_NONE) &&
+	    !sas_protocol_ata(task->task_proto)) {
+		if (task->num_scatter == 0)
+			/* 0 indicates a single dma address */
+			dma_unmap_single(
+				&pdev->dev,
+				request->zero_scatter_daddr,
+				task->total_xfer_len,
+				task->data_dir
+				);
+
+		else  /* unmap the sgl dma addresses */
+			dma_unmap_sg(
+				&pdev->dev,
+				task->scatter,
+				request->num_sg_entries,
+				task->data_dir
+				);
+	}
+}
+
+
+void isci_request_io_request_complete(
+	struct isci_host *isci_host,
+	struct isci_request *request,
+	enum sci_io_status completion_status);
+
+u32 isci_request_io_request_get_transfer_length(
+	struct isci_request *request);
+
+SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction(
+	struct isci_request *request);
+
+/**
+ * isci_request_io_request_get_next_sge() - This function is called by the sci
+ *    core to retrieve the next sge for a given request.
+ * @request: This parameter is the isci_request object.
+ * @current_sge_address: This parameter is the last sge retrieved by the sci
+ *    core for this request.
+ *
+ * pointer to the next sge for specified request.
+ */
+static inline void *isci_request_io_request_get_next_sge(
+	struct isci_request *request,
+	void *current_sge_address)
+{
+	struct sas_task *task = isci_request_access_task(request);
+	void *ret = NULL;
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p, "
+		"current_sge_address = %p, "
+		"num_scatter = %d\n",
+		__func__,
+		request,
+		current_sge_address,
+		task->num_scatter);
+
+	if (!current_sge_address)	/* First time through.. */
+		ret = task->scatter;    /* always task->scatter */
+	else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
+		ret = NULL;              /* there is only one element. */
+	else
+		ret = sg_next(current_sge_address);     /* sg_next returns NULL
+							 * for the last element
+							 */
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: next sge address = %p\n",
+		__func__,
+		ret);
+
+	return ret;
+}
+
+dma_addr_t isci_request_sge_get_address_field(
+	struct isci_request *request,
+	void *sge_address);
+
+u32 isci_request_sge_get_length_field(
+	struct isci_request *request,
+	void *sge_address);
+
+void *isci_request_ssp_io_request_get_cdb_address(
+	struct isci_request *request);
+
+u32 isci_request_ssp_io_request_get_cdb_length(
+	struct isci_request *request);
+
+u32  isci_request_ssp_io_request_get_lun(
+	struct isci_request *request);
+
+u32 isci_request_ssp_io_request_get_task_attribute(
+	struct isci_request *request);
+
+u32 isci_request_ssp_io_request_get_command_priority(
+	struct isci_request *request);
+
+
+
+
+
+void isci_terminate_pending_requests(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	enum isci_request_status new_request_state);
+
+
+
+
+#endif /* !defined(_ISCI_REQUEST_H_) */
diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c
new file mode 100644
index 0000000..19b0eea
--- /dev/null
+++ b/drivers/scsi/isci/sata.c
@@ -0,0 +1,356 @@
+/*
+ * 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 "isci.h"
+#include "scic_remote_device.h"
+#include "scic_sds_remote_device.h"
+#include "scic_io_request.h"
+#include "scic_task_request.h"
+#include "task.h"
+#include "request.h"
+#include "sata.h"
+#include "intel_sat.h"
+#include "intel_ata.h"
+
+static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf);
+
+
+/**
+ * isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from
+ *    the core and copies the fis from the task into it.
+ * @task: This parameter is a pointer to the task struct from libsas.
+ *
+ * pointer to the host_to_dev_fis from the core request object.
+ */
+struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task)
+{
+	struct isci_request *request = task->lldd_task;
+	struct host_to_dev_fis *register_fis =
+		scic_stp_io_request_get_h2d_reg_address(
+			request->sci_request_handle
+			);
+
+	memcpy(
+		(u8 *)register_fis,
+		(u8 *)&task->ata_task.fis,
+		sizeof(struct host_to_dev_fis)
+		);
+
+	if (!task->ata_task.device_control_reg_update)
+		register_fis->flags |= 0x80;
+
+	register_fis->flags &= 0xF0;
+
+	return register_fis;
+}
+
+/**
+ * isci_sata_is_task_ncq() - This function determines if the given stp task is
+ *    a ncq request.
+ * @task: This parameter is a pointer to the task struct from libsas.
+ *
+ * true if the task is ncq
+ */
+bool isci_sata_is_task_ncq(struct sas_task *task)
+{
+	struct ata_queued_cmd *qc = task->uldd_task;
+
+	bool ret = (qc &&
+		    (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
+		     qc->tf.command == ATA_CMD_FPDMA_READ));
+
+	return ret;
+}
+
+/**
+ * isci_sata_set_ncq_tag() - This function sets the ncq tag field in the
+ *    host_to_dev_fis equal to the tag in the queue command in the task.
+ * @task: This parameter is a pointer to the task struct from libsas.
+ * @register_fis: This parameter is a pointer to the host_to_dev_fis from the
+ *    core request object.
+ *
+ */
+void isci_sata_set_ncq_tag(
+	struct host_to_dev_fis *register_fis,
+	struct sas_task *task)
+{
+	struct ata_queued_cmd *qc = task->uldd_task;
+	struct isci_request *request = task->lldd_task;
+
+	register_fis->sector_count = qc->tag << 3;
+	scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag);
+}
+
+/**
+ * isci_request_process_stp_response() - This function sets the status and
+ *    response, in the task struct, from the request object for the upper layer
+ *    driver.
+ * @sas_task: This parameter is the task struct from the upper layer driver.
+ * @response_buffer: This parameter points to the response of the completed
+ *    request.
+ *
+ * none.
+ */
+void isci_request_process_stp_response(
+	struct sas_task *task,
+	void *response_buffer)
+{
+	struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer;
+	struct task_status_struct *ts = &task->task_status;
+	struct ata_task_resp *resp = (void *)&ts->buf[0];
+
+	resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6));
+	memcpy(&resp->ending_fis[0], response_buffer + 16, 24);
+	ts->buf_valid_size = sizeof(*resp);
+
+	/**
+	 * If the device fault bit is set in the status register, then
+	 * set the sense data and return.
+	 */
+	if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+		ts->stat = SAS_PROTO_RESPONSE;
+	else
+		ts->stat = SAM_STAT_GOOD;
+
+	ts->resp = SAS_TASK_COMPLETE;
+}
+
+/**
+ * isci_sata_get_sat_protocol() - retrieve the sat protocol for the request
+ * @isci_request: ata request
+ *
+ * Note: temporary implementation until expert mode removes the callback
+ *
+ */
+u8 isci_sata_get_sat_protocol(struct isci_request *isci_request)
+{
+	struct sas_task *task;
+	struct domain_device *dev;
+
+	dev_dbg(&isci_request->isci_host->pdev->dev,
+		"%s: isci_request = %p, ttype = %d\n",
+		__func__, isci_request, isci_request->ttype);
+
+	if (tmf_task == isci_request->ttype) {
+		struct isci_tmf *tmf = isci_request_access_tmf(isci_request);
+
+		return isci_sata_get_management_task_protocol(tmf);
+	}
+
+	task = isci_request_access_task(isci_request);
+	dev = task->dev;
+
+	if (!sas_protocol_ata(task->task_proto)) {
+		WARN(1, "unhandled task protocol\n");
+		return SAT_PROTOCOL_NON_DATA;
+	}
+
+	if (task->data_dir == DMA_NONE)
+		return SAT_PROTOCOL_NON_DATA;
+
+	/* the "_IN" protocol types are equivalent to their "_OUT"
+	 * analogs as far as the core is concerned
+	 */
+	if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
+		if (task->ata_task.dma_xfer)
+			return SAT_PROTOCOL_PACKET_DMA_DATA_IN;
+		else
+			return SAT_PROTOCOL_PACKET_PIO_DATA_IN;
+	}
+
+	if (task->ata_task.use_ncq)
+		return SAT_PROTOCOL_FPDMA;
+
+	if (task->ata_task.dma_xfer)
+		return SAT_PROTOCOL_UDMA_DATA_IN;
+	else
+		return SAT_PROTOCOL_PIO_DATA_IN;
+}
+
+static u8 isci_sata_get_management_task_protocol(
+	struct isci_tmf *tmf)
+{
+	u8 ret = 0;
+
+	pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code);
+
+	if ((tmf->tmf_code == isci_tmf_sata_srst_high) ||
+	    (tmf->tmf_code == isci_tmf_sata_srst_low)) {
+		pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__);
+		ret = SAT_PROTOCOL_SOFT_RESET;
+	}
+
+	return ret;
+}
+
+enum sci_status isci_sata_management_task_request_build(
+	struct isci_request *isci_request)
+{
+	struct isci_tmf *isci_tmf;
+	enum sci_status status;
+
+	if (tmf_task != isci_request->ttype)
+		return SCI_FAILURE;
+
+	isci_tmf = isci_request_access_tmf(isci_request);
+
+	switch (isci_tmf->tmf_code) {
+
+	case isci_tmf_sata_srst_high:
+	case isci_tmf_sata_srst_low:
+	{
+		struct host_to_dev_fis *register_fis =
+			scic_stp_io_request_get_h2d_reg_address(
+				isci_request->sci_request_handle
+				);
+
+		memset(register_fis, 0, sizeof(*register_fis));
+
+		register_fis->fis_type  =  0x27;
+		register_fis->flags     &= ~0x80;
+		register_fis->flags     &= 0xF0;
+		if (isci_tmf->tmf_code == isci_tmf_sata_srst_high)
+			register_fis->control |= ATA_SRST;
+		else
+			register_fis->control &= ~ATA_SRST;
+		break;
+	}
+	/* other management commnd go here... */
+	default:
+		return SCI_FAILURE;
+	}
+
+	/* core builds the protocol specific request
+	 *  based on the h2d fis.
+	 */
+	status = scic_task_request_construct_sata(
+		isci_request->sci_request_handle
+		);
+
+	return status;
+}
+
+/**
+ * isci_task_send_lu_reset_sata() - This function is called by of the SAS
+ *    Domain Template functions. This is one of the Task Management functoins
+ *    called by libsas, to reset the given SAS lun. Note the assumption that
+ *    while this call is executing, no I/O will be sent by the host to the
+ *    device.
+ * @lun: This parameter specifies the lun to be reset.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_send_lu_reset_sata(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	u8 *lun)
+{
+	struct isci_tmf tmf;
+	int ret = TMF_RESP_FUNC_FAILED;
+	unsigned long flags;
+
+	/* Send the initial SRST to the target */
+	#define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */
+	isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high,
+			    NULL, NULL
+			    );
+
+	ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
+
+	if (ret != TMF_RESP_FUNC_COMPLETE) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: Assert SRST failed (%p) = %x",
+			 __func__,
+			 isci_device,
+			 ret);
+
+		/* Return the failure so that the LUN reset is escalated
+		 * to a target reset.
+		 */
+		goto out;
+	}
+
+	/* Leave SRST high for a bit. */
+	#define ISCI_SRST_ASSERT_DELAY 100 /* usecs */
+	scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY);
+
+	/* Deassert SRST. */
+	isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low,
+			    NULL, NULL
+			    );
+	ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
+
+	if (ret == TMF_RESP_FUNC_COMPLETE)
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: SATA LUN reset passed (%p)\n",
+			__func__,
+			isci_device);
+	else
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: Deassert SRST failed (%p)=%x\n",
+			 __func__,
+			 isci_device,
+			 ret);
+
+ out:
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	/* Resume the device. */
+	scic_sds_remote_device_resume(isci_device->sci_device_handle);
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	return ret;
+}
diff --git a/drivers/scsi/isci/sata.h b/drivers/scsi/isci/sata.h
new file mode 100644
index 0000000..b6ba25b
--- /dev/null
+++ b/drivers/scsi/isci/sata.h
@@ -0,0 +1,83 @@
+/*
+ * 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_sat.h"
+
+
+
+struct host_to_dev_fis *isci_sata_task_to_fis_copy(
+	struct sas_task *task);
+
+bool isci_sata_is_task_ncq(
+	struct sas_task *task);
+
+void isci_sata_set_ncq_tag(
+	struct host_to_dev_fis *register_fis,
+	struct sas_task *task);
+
+void isci_request_process_stp_response(
+	struct sas_task *task,
+	void *response_buffer);
+
+u8 isci_sata_get_sat_protocol(
+	struct isci_request *isci_request);
+
+enum sci_status isci_sata_management_task_request_build(
+	struct isci_request *isci_request);
+
+int isci_task_send_lu_reset_sata(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	u8 *lun);
diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h
new file mode 100644
index 0000000..e1020ee
--- /dev/null
+++ b/drivers/scsi/isci/sci_environment.h
@@ -0,0 +1,112 @@
+/*
+ * 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_ENVIRONMENT_H_
+#define _SCI_ENVIRONMENT_H_
+
+#include "isci.h"
+
+struct scic_sds_controller;
+struct scic_sds_phy;
+struct scic_sds_port;
+struct scic_sds_remote_device;
+
+static inline struct device *scic_to_dev(struct scic_sds_controller *scic)
+{
+	struct isci_host *isci_host = sci_object_get_association(scic);
+
+	return &isci_host->pdev->dev;
+}
+
+static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)
+{
+	struct isci_phy *iphy = sci_object_get_association(sci_phy);
+
+	if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
+		return NULL;
+
+	return &iphy->isci_port->isci_host->pdev->dev;
+}
+
+static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port)
+{
+	struct isci_port *iport = sci_object_get_association(sci_port);
+
+	if (!iport || !iport->isci_host)
+		return NULL;
+
+	return &iport->isci_host->pdev->dev;
+}
+
+static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev)
+{
+	struct isci_remote_device *idev = sci_object_get_association(sci_dev);
+
+	if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
+		return NULL;
+
+	return &idev->isci_port->isci_host->pdev->dev;
+}
+
+enum {
+	ISCI_SI_REVA0,
+	ISCI_SI_REVA2,
+	ISCI_SI_REVB0,
+};
+
+extern int isci_si_rev;
+
+
+#endif
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
new file mode 100644
index 0000000..5e6f558
--- /dev/null
+++ b/drivers/scsi/isci/task.c
@@ -0,0 +1,1691 @@
+/*
+ * 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/completion.h>
+#include "scic_task_request.h"
+#include "scic_remote_device.h"
+#include "scic_io_request.h"
+#include "scic_sds_remote_device.h"
+#include "scic_sds_remote_node_context.h"
+#include "isci.h"
+#include "request.h"
+#include "sata.h"
+#include "task.h"
+
+
+/**
+ * isci_task_execute_task() - This function is one of the SAS Domain Template
+ *    functions. This function is called by libsas to send a task down to
+ *    hardware.
+ * @task: This parameter specifies the SAS task to send.
+ * @num: This parameter specifies the number of tasks to queue.
+ * @gfp_flags: This parameter specifies the context of this call.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
+{
+	struct isci_host *isci_host;
+	struct isci_request *request = NULL;
+	struct isci_remote_device *device;
+	unsigned long flags;
+	unsigned long quiesce_flags = 0;
+	int ret;
+	enum sci_status status;
+
+
+	dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num);
+
+	if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+
+		isci_task_complete_for_upper_layer(
+			task,
+			SAS_TASK_UNDELIVERED,
+			SAM_STAT_TASK_ABORTED,
+			isci_perform_normal_io_completion
+			);
+
+		return 0;  /* The I/O was accepted (and failed). */
+	}
+	if ((task->dev == NULL) || (task->dev->port == NULL)) {
+
+		/* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer
+		 * removes the target.
+		 */
+		isci_task_complete_for_upper_layer(
+			task,
+			SAS_TASK_UNDELIVERED,
+			SAS_DEVICE_UNKNOWN,
+			isci_perform_normal_io_completion
+			);
+		return 0;  /* The I/O was accepted (and failed). */
+	}
+	isci_host = isci_host_from_sas_ha(task->dev->port->ha);
+
+	/* Check if we have room for more tasks */
+	ret = isci_host_can_queue(isci_host, num);
+
+	if (ret) {
+		dev_warn(task->dev->port->ha->dev, "%s: queue full\n", __func__);
+		return ret;
+	}
+
+	do {
+		dev_dbg(task->dev->port->ha->dev,
+			"task = %p, num = %d; dev = %p; cmd = %p\n",
+			    task, num, task->dev, task->uldd_task);
+
+		if ((task->dev == NULL) || (task->dev->port == NULL)) {
+			dev_warn(task->dev->port->ha->dev,
+				 "%s: task %p's port or dev == NULL!\n",
+				 __func__, task);
+
+			/* Indicate SAS_TASK_UNDELIVERED, so that the scsi
+			 * midlayer removes the target.
+			 */
+			isci_task_complete_for_upper_layer(
+				task,
+				SAS_TASK_UNDELIVERED,
+				SAS_DEVICE_UNKNOWN,
+				isci_perform_normal_io_completion
+				);
+			/* We don't have a valid host reference, so we
+			 * can't control the host queueing condition.
+			 */
+			continue;
+		}
+
+		device = isci_dev_from_domain_dev(task->dev);
+
+		isci_host = isci_host_from_sas_ha(task->dev->port->ha);
+
+		/* check if the controller hasn't started or if the device
+		 * is ready but not accepting IO.
+		 */
+		if (device) {
+
+			spin_lock_irqsave(&device->host_quiesce_lock,
+					  quiesce_flags);
+		}
+		/* From this point onward, any process that needs to guarantee
+		 * that there is no kernel I/O being started will have to wait
+		 * for the quiesce spinlock.
+		 */
+
+		if (isci_host_get_state(isci_host) == isci_starting ||
+		    (device && ((isci_remote_device_get_state(device) == isci_ready) ||
+		    (isci_remote_device_get_state(device) == isci_host_quiesce)))) {
+
+			/* Forces a retry from scsi mid layer. */
+			dev_warn(task->dev->port->ha->dev,
+				 "%s: task %p: isci_host->status = %d, "
+				 "device = %p\n",
+				 __func__,
+				 task,
+				 isci_host_get_state(isci_host),
+				 device);
+
+			if (device)
+				dev_dbg(task->dev->port->ha->dev,
+					"%s: device->status = 0x%x\n",
+					__func__,
+					isci_remote_device_get_state(device));
+
+			/* Indicate QUEUE_FULL so that the scsi midlayer
+			 * retries.
+			 */
+			isci_task_complete_for_upper_layer(
+				task,
+				SAS_TASK_COMPLETE,
+				SAS_QUEUE_FULL,
+				isci_perform_normal_io_completion
+				);
+			isci_host_can_dequeue(isci_host, 1);
+		}
+		/* the device is going down... */
+		else if (!device || (isci_ready_for_io != isci_remote_device_get_state(device))) {
+
+			dev_dbg(task->dev->port->ha->dev,
+				"%s: task %p: isci_host->status = %d, "
+				"device = %p\n",
+				__func__,
+				task,
+				isci_host_get_state(isci_host),
+				device);
+
+			if (device)
+				dev_dbg(task->dev->port->ha->dev,
+					"%s: device->status = 0x%x\n",
+					__func__,
+					isci_remote_device_get_state(device));
+
+			/* Indicate SAS_TASK_UNDELIVERED, so that the scsi
+			 * midlayer removes the target.
+			 */
+			isci_task_complete_for_upper_layer(
+				task,
+				SAS_TASK_UNDELIVERED,
+				SAS_DEVICE_UNKNOWN,
+				isci_perform_normal_io_completion
+				);
+			isci_host_can_dequeue(isci_host, 1);
+
+		} else {
+			/* build and send the request. */
+			status = isci_request_execute(isci_host, task, &request,
+						      gfp_flags);
+
+			if (status == SCI_SUCCESS) {
+				spin_lock_irqsave(&task->task_state_lock, flags);
+				task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+				spin_unlock_irqrestore(&task->task_state_lock, flags);
+			} else {
+				/* Indicate QUEUE_FULL so that the scsi
+				 * midlayer retries. if the request
+				 * failed for remote device reasons,
+				 * it gets returned as
+				 * SAS_TASK_UNDELIVERED next time
+				 * through.
+				 */
+				isci_task_complete_for_upper_layer(
+						task,
+						SAS_TASK_COMPLETE,
+						SAS_QUEUE_FULL,
+						isci_perform_normal_io_completion
+						);
+				isci_host_can_dequeue(isci_host, 1);
+			}
+		}
+		if (device) {
+			spin_unlock_irqrestore(&device->host_quiesce_lock,
+					       quiesce_flags
+					       );
+		}
+		task = list_entry(task->list.next, struct sas_task, list);
+	} while (--num > 0);
+	return 0;
+}
+
+
+
+/**
+ * isci_task_request_build() - This function builds the task request object.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @request: This parameter points to the isci_request object allocated in the
+ *    request construct function.
+ * @tmf: This parameter is the task management struct to be built
+ *
+ * SCI_SUCCESS on successfull completion, or specific failure code.
+ */
+static enum sci_status isci_task_request_build(
+	struct isci_host *isci_host,
+	struct isci_request **isci_request,
+	struct isci_tmf *isci_tmf)
+{
+	struct scic_sds_remote_device *sci_device;
+	enum sci_status status = SCI_FAILURE;
+	struct isci_request *request;
+	struct isci_remote_device *isci_device;
+/*	struct sci_sas_identify_address_frame_protocols dev_protocols; */
+	struct smp_discover_response_protocols dev_protocols;
+
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_tmf = %p\n", __func__, isci_tmf);
+
+	isci_device = isci_tmf->device;
+	sci_device = isci_device->sci_device_handle;
+
+	/* do common allocation and init of request object. */
+	status = isci_request_alloc_tmf(
+		isci_host,
+		isci_tmf,
+		&request,
+		isci_device,
+		GFP_ATOMIC
+		);
+
+	if (status != SCI_SUCCESS)
+		goto out;
+
+	/* let the core do it's construct. */
+	status = scic_task_request_construct(
+		isci_host->core_controller,
+		sci_device,
+		SCI_CONTROLLER_INVALID_IO_TAG,
+		request,
+		request->sci_request_mem_ptr,
+		&request->sci_request_handle
+		);
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: scic_task_request_construct failed - "
+			 "status = 0x%x\n",
+			 __func__,
+			 status);
+		goto errout;
+	}
+
+	sci_object_set_association(
+		request->sci_request_handle,
+		request
+		);
+
+	scic_remote_device_get_protocols(
+		sci_device,
+		&dev_protocols
+		);
+
+	/* let the core do it's protocol
+	 * specific construction.
+	 */
+	if (dev_protocols.u.bits.attached_ssp_target) {
+
+		isci_tmf->proto = SAS_PROTOCOL_SSP;
+		status = scic_task_request_construct_ssp(
+			request->sci_request_handle
+			);
+		if (status != SCI_SUCCESS)
+			goto errout;
+	}
+
+	if (dev_protocols.u.bits.attached_stp_target) {
+
+		isci_tmf->proto = SAS_PROTOCOL_SATA;
+		status = isci_sata_management_task_request_build(request);
+
+		if (status != SCI_SUCCESS)
+			goto errout;
+	}
+
+	goto out;
+
+ errout:
+
+	/* release the dma memory if we fail. */
+	isci_request_free(isci_host, request);
+	request = NULL;
+
+ out:
+	*isci_request = request;
+	return status;
+}
+
+/**
+ * isci_tmf_timeout_cb() - This function is called as a kernel callback when
+ *    the timeout period for the TMF has expired.
+ *
+ *
+ */
+static void isci_tmf_timeout_cb(void *tmf_request_arg)
+{
+	struct isci_request *request = (struct isci_request *)tmf_request_arg;
+	struct isci_tmf *tmf = isci_request_access_tmf(request);
+	enum sci_status status;
+
+	BUG_ON(request->ttype != tmf_task);
+
+	/* This task management request has timed-out.  Terminate the request
+	 * so that the request eventually completes to the requestor in the
+	 * request completion callback path.
+	 */
+	/* Note - the timer callback function itself has provided spinlock
+	 * exclusion from the start and completion paths.  No need to take
+	 * the request->isci_host->scic_lock here.
+	 */
+
+	if (tmf->timeout_timer != NULL) {
+		/* Call the users callback, if any. */
+		if (tmf->cb_state_func != NULL)
+			tmf->cb_state_func(isci_tmf_timed_out, tmf,
+					   tmf->cb_data);
+
+		/* Terminate the TMF transmit request. */
+		status = scic_controller_terminate_request(
+			request->isci_host->core_controller,
+			request->isci_device->sci_device_handle,
+			request->sci_request_handle
+			);
+
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: tmf_request = %p; tmf = %p; status = %d\n",
+			__func__, request, tmf, status);
+	} else
+		dev_dbg(&request->isci_host->pdev->dev,
+			"%s: timer already canceled! "
+			"tmf_request = %p; tmf = %p\n",
+			__func__, request, tmf);
+
+	/* No need to unlock since the caller to this callback is doing it for
+	 * us.
+	 * request->isci_host->scic_lock
+	 */
+}
+
+/**
+ * isci_task_execute_tmf() - This function builds and sends a task request,
+ *    then waits for the completion.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @tmf: This parameter is the pointer to the task management structure for
+ *    this request.
+ * @timeout_ms: This parameter specifies the timeout period for the task
+ *    management request.
+ *
+ * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes
+ * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED.
+ */
+int isci_task_execute_tmf(
+	struct isci_host *isci_host,
+	struct isci_tmf *tmf,
+	unsigned long timeout_ms)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	enum sci_status status = SCI_FAILURE;
+	struct scic_sds_remote_device *sci_device;
+	struct isci_remote_device *isci_device = tmf->device;
+	struct isci_request *request;
+	int ret = TMF_RESP_FUNC_FAILED;
+	unsigned long flags;
+
+	/* sanity check, return TMF_RESP_FUNC_FAILED
+	 * if the device is not there and ready.
+	 */
+	if (!isci_device ||
+	    ((isci_ready_for_io != isci_remote_device_get_state(isci_device)) &&
+	    (isci_host_quiesce != isci_remote_device_get_state(isci_device)))) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: isci_device = %p not ready (%d)\n",
+			__func__,
+			isci_device,
+			isci_remote_device_get_state(isci_device));
+		return TMF_RESP_FUNC_FAILED;
+	} else
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: isci_device = %p\n",
+			__func__, isci_device);
+
+	sci_device = isci_device->sci_device_handle;
+
+	/* Assign the pointer to the TMF's completion kernel wait structure. */
+	tmf->complete = &completion;
+
+	isci_task_request_build(
+		isci_host,
+		&request,
+		tmf
+		);
+
+	if (!request) {
+		dev_warn(&isci_host->pdev->dev,
+			"%s: isci_task_request_build failed\n",
+			__func__);
+		return TMF_RESP_FUNC_FAILED;
+	}
+
+	/* Allocate the TMF timeout timer. */
+	tmf->timeout_timer = isci_timer_create(
+		&isci_host->timer_list_struct,
+		isci_host,
+		request,
+		isci_tmf_timeout_cb
+		);
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	/* Start the timer. */
+	if (tmf->timeout_timer)
+		isci_timer_start(tmf->timeout_timer, timeout_ms);
+	else
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: isci_timer_create failed!!!!\n",
+			 __func__);
+
+	/* start the TMF io. */
+	status = scic_controller_start_task(
+		isci_host->core_controller,
+		sci_device,
+		request->sci_request_handle,
+		SCI_CONTROLLER_INVALID_IO_TAG
+		);
+
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: start_io failed - status = 0x%x, request = %p\n",
+			 __func__,
+			 status,
+			 request);
+		goto cleanup_request;
+	}
+
+	/* Call the users callback, if any. */
+	if (tmf->cb_state_func != NULL)
+		tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data);
+
+	/* Change the state of the TMF-bearing request to "started". */
+	isci_request_change_state(request, started);
+
+	/* add the request to the remote device request list. */
+	list_add(&request->dev_node, &isci_device->reqs_in_process);
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	/* Wait for the TMF to complete, or a timeout. */
+	wait_for_completion(&completion);
+
+	isci_print_tmf(tmf);
+
+	if (tmf->status == SCI_SUCCESS)
+		ret =  TMF_RESP_FUNC_COMPLETE;
+	else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: tmf.status == "
+			"SCI_FAILURE_IO_RESPONSE_VALID\n",
+			__func__);
+		ret =  TMF_RESP_FUNC_COMPLETE;
+	}
+	/* Else - leave the default "failed" status alone. */
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: completed request = %p\n",
+		__func__,
+		request);
+
+	if (request->io_request_completion != NULL) {
+
+		/* The fact that this is non-NULL for a TMF request
+		 * means there is a thread waiting for this TMF to
+		 * finish.
+		 */
+		complete(request->io_request_completion);
+	}
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+ cleanup_request:
+
+	/* Clean up the timer if needed. */
+	if (tmf->timeout_timer) {
+		isci_timer_stop(tmf->timeout_timer);
+		isci_timer_free(&isci_host->timer_list_struct,
+				tmf->timeout_timer);
+		tmf->timeout_timer = NULL;
+	}
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	isci_request_free(isci_host, request);
+
+	return ret;
+}
+
+void isci_task_build_tmf(
+	struct isci_tmf *tmf,
+	struct isci_remote_device *isci_device,
+	enum isci_tmf_function_codes code,
+	void (*tmf_sent_cb)(enum isci_tmf_cb_state,
+			    struct isci_tmf *,
+			    void *),
+	void *cb_data)
+{
+	dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
+		"%s: isci_device = %p\n", __func__, isci_device);
+
+	memset(tmf, 0, sizeof(*tmf));
+
+	tmf->device        = isci_device;
+	tmf->tmf_code      = code;
+	tmf->timeout_timer = NULL;
+	tmf->cb_state_func = tmf_sent_cb;
+	tmf->cb_data       = cb_data;
+}
+
+static struct isci_request *isci_task_get_request_from_task(
+	struct sas_task *task,
+	struct isci_host **isci_host,
+	struct isci_remote_device **isci_device)
+{
+
+	struct isci_request *request = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
+
+	request = task->lldd_task;
+
+	/* If task is already done, the request isn't valid */
+	if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
+	    (task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
+	    (request != NULL)) {
+
+		if (isci_host != NULL)
+			*isci_host = request->isci_host;
+
+		if (isci_device != NULL)
+			*isci_device = request->isci_device;
+	}
+
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+	return request;
+}
+
+/**
+ * isci_task_validate_request_to_abort() - This function checks the given I/O
+ *    against the "started" state.  If the request is still "started", it's
+ *    state is changed to aborted. NOTE: isci_host->scic_lock MUST BE HELD
+ *    BEFORE CALLING THIS FUNCTION.
+ * @isci_request: This parameter specifies the request object to control.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @isci_device: This is the device to which the request is pending.
+ * @aborted_io_completion: This is a completion structure that will be added to
+ *    the request in case it is changed to aborting; this completion is
+ *    triggered when the request is fully completed.
+ *
+ * Either "started" on successful change of the task status to "aborted", or
+ * "unallocated" if the task cannot be controlled.
+ */
+static enum isci_request_status isci_task_validate_request_to_abort(
+	struct isci_request *isci_request,
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	struct completion *aborted_io_completion)
+{
+	enum isci_request_status old_state = unallocated;
+
+	/* Only abort the task if it's in the
+	 *  device's request_in_process list
+	 */
+	if (isci_request && !list_empty(&isci_request->dev_node)) {
+		old_state = isci_request_change_started_to_aborted(
+			isci_request, aborted_io_completion);
+
+		/* Only abort requests in the started state. */
+		if (old_state != started)
+			old_state = unallocated;
+	}
+
+	return old_state;
+}
+
+static void isci_request_cleanup_completed_loiterer(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	struct isci_request *isci_request)
+{
+	struct sas_task *task = isci_request_access_task(isci_request);
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device=%p, request=%p, task=%p\n",
+		__func__, isci_device, isci_request,
+		isci_request->ttype_ptr.io_task_ptr);
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+	list_del_init(&isci_request->dev_node);
+	if (task != NULL)
+		task->lldd_task = NULL;
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	isci_request_free(isci_host, isci_request);
+}
+/**
+ * isci_terminate_request_core() - This function will terminate the given
+ *    request, and wait for it to complete.  This function must only be called
+ *    from a thread that can wait.  Note that the request is terminated and
+ *    completed (back to the host, if started there).
+ * @isci_host: This SCU.
+ * @isci_device: The target.
+ * @isci_request: The I/O request to be terminated.
+ *
+ *
+ */
+static void isci_terminate_request_core(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	struct isci_request *isci_request,
+	struct completion *request_completion)
+{
+	enum sci_status status                 = SCI_SUCCESS;
+	bool was_terminated         = false;
+	bool needs_cleanup_handling = false;
+	enum isci_request_status request_status;
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: device = %p; request = %p\n",
+		__func__, isci_device, isci_request);
+
+	/* Peek at the current status of the request.  This will tell
+	 * us if there was special handling on the request such that it
+	 * needs to be detached and freed here.
+	 */
+	spin_lock_irqsave(&isci_request->state_lock, flags);
+	request_status = isci_request_get_state(isci_request);
+
+	/* TMFs are in their own thread */
+	if ((isci_request->ttype == io_task) &&
+	    ((request_status == aborted) ||
+	     (request_status == aborting) ||
+	     (request_status == terminating)))
+		/* The completion routine won't free a request in
+		 * the aborted/aborting/terminating state, so we do
+		 * it here.
+		 */
+		needs_cleanup_handling = true;
+
+	spin_unlock_irqrestore(&isci_request->state_lock, flags);
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+	/* Make sure the request wasn't just sitting around signalling
+	 * device condition (if the request handle is NULL, then the
+	 * request completed but needed additional handling here).
+	 */
+	if (isci_request->sci_request_handle != NULL) {
+		was_terminated = true;
+		status = scic_controller_terminate_request(
+			isci_host->core_controller,
+			isci_device->sci_device_handle,
+			isci_request->sci_request_handle
+			);
+	}
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	/*
+	 * The only time the request to terminate will
+	 * fail is when the io request is completed and
+	 * being aborted.
+	 */
+	if (status != SCI_SUCCESS)
+		dev_err(&isci_host->pdev->dev,
+			"%s: scic_controller_terminate_request"
+			" returned = 0x%x\n",
+			__func__,
+			status);
+	else {
+		if (was_terminated) {
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: before completion wait (%p)\n",
+				__func__,
+				request_completion);
+
+			/* Wait here for the request to complete. */
+			wait_for_completion(request_completion);
+
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: after completion wait (%p)\n",
+				__func__,
+				request_completion);
+		}
+
+		if (needs_cleanup_handling)
+			isci_request_cleanup_completed_loiterer(
+				isci_host, isci_device, isci_request
+				);
+	}
+}
+static void isci_terminate_request(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	struct isci_request *isci_request,
+	enum isci_request_status new_request_state)
+{
+	enum isci_request_status old_state;
+
+	DECLARE_COMPLETION_ONSTACK(request_completion);
+	unsigned long flags;
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	/* Change state to "new_request_state" if it is currently "started" */
+	old_state = isci_request_change_started_to_newstate(
+		isci_request,
+		&request_completion,
+		new_request_state
+		);
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	if (old_state == started)
+		/* This request was not already being aborted. If it had been,
+		 * then the aborting I/O (ie. the TMF request) would not be in
+		 * the aborting state, and thus would be terminated here.  Note
+		 * that since the TMF completion's call to the kernel function
+		 * "complete()" does not happen until the pending I/O request
+		 * terminate fully completes, we do not have to implement a
+		 * special wait here for already aborting requests - the
+		 * termination of the TMF request will force the request
+		 * to finish it's already started terminate.
+		 */
+		isci_terminate_request_core(isci_host, isci_device,
+					    isci_request, &request_completion);
+}
+
+/**
+ * isci_terminate_pending_requests() - This function will change the all of the
+ *    requests on the given device's state to "aborting", will terminate the
+ *    requests, and wait for them to complete.  This function must only be
+ *    called from a thread that can wait.  Note that the requests are all
+ *    terminated and completed (back to the host, if started there).
+ * @isci_host: This parameter specifies SCU.
+ * @isci_device: This parameter specifies the target.
+ *
+ *
+ */
+void isci_terminate_pending_requests(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	enum isci_request_status new_request_state)
+{
+	struct isci_request *isci_request;
+	struct sas_task *task;
+	bool done = false;
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_device = %p (new request state = %d)\n",
+		__func__, isci_device, new_request_state);
+
+	#define ISCI_TERMINATE_SHOW_PENDING_REQUESTS
+	#ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS
+	{
+		struct isci_request *request;
+
+		/* Only abort the task if it's in the
+		 * device's request_in_process list
+		 */
+		list_for_each_entry(request,
+				    &isci_device->reqs_in_process,
+				    dev_node)
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: isci_device = %p; request is on "
+				"reqs_in_process list: %p\n",
+				__func__, isci_device, request);
+	}
+	#endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */
+
+	/* Clean up all pending requests. */
+	do {
+		spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+		if (list_empty(&isci_device->reqs_in_process)) {
+
+			done = true;
+			spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: isci_device = %p; done.\n",
+				__func__, isci_device);
+		} else {
+			/* The list was not empty - grab the first request. */
+			isci_request = list_first_entry(
+				&isci_device->reqs_in_process,
+				struct isci_request, dev_node
+				);
+			/* Note that we are not expecting to have to control
+			 * the target to abort the request.
+			 */
+			isci_request->complete_in_target = true;
+
+			spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+			/* Get the libsas task reference. */
+			task = isci_request_access_task(isci_request);
+
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: isci_device=%p request=%p; task=%p\n",
+				__func__, isci_device, isci_request, task);
+
+			/* Mark all still pending I/O with the selected next
+			 * state.
+			 */
+			isci_terminate_request(isci_host, isci_device,
+					       isci_request, new_request_state
+					       );
+
+			/* Set the 'done' state on the task. */
+			if (task)
+				isci_task_all_done(task);
+		}
+	} while (!done);
+}
+
+/**
+ * isci_task_send_lu_reset_sas() - This function is called by of the SAS Domain
+ *    Template functions.
+ * @lun: This parameter specifies the lun to be reset.
+ *
+ * status, zero indicates success.
+ */
+static int isci_task_send_lu_reset_sas(
+	struct isci_host *isci_host,
+	struct isci_remote_device *isci_device,
+	u8 *lun)
+{
+	struct isci_tmf tmf;
+	int ret = TMF_RESP_FUNC_FAILED;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_host = %p, isci_device = %p\n",
+		__func__, isci_host, isci_device);
+	/* Send the LUN reset to the target.  By the time the call returns,
+	 * the TMF has fully exected in the target (in which case the return
+	 * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or
+	 * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED").
+	 */
+	isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_lun_reset, NULL,
+			    NULL);
+
+	#define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */
+	ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_LU_RESET_TIMEOUT_MS);
+
+	if (ret == TMF_RESP_FUNC_COMPLETE)
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: %p: TMF_LU_RESET passed\n",
+			__func__, isci_device);
+	else
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: %p: TMF_LU_RESET failed (%x)\n",
+			__func__, isci_device, ret);
+
+	return ret;
+}
+
+/**
+ * isci_task_lu_reset() - This function is one of the SAS Domain Template
+ *    functions. This is one of the Task Management functoins called by libsas,
+ *    to reset the given lun. Note the assumption that while this call is
+ *    executing, no I/O will be sent by the host to the device.
+ * @lun: This parameter specifies the lun to be reset.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_lu_reset(
+	struct domain_device *domain_device,
+	u8 *lun)
+{
+	struct isci_host *isci_host = NULL;
+	struct isci_remote_device *isci_device = NULL;
+	int ret;
+	bool device_stopping = false;
+
+	if (domain_device == NULL) {
+		pr_warn("%s: domain_device == NULL\n", __func__);
+		return TMF_RESP_FUNC_FAILED;
+	}
+
+	isci_device = isci_dev_from_domain_dev(domain_device);
+
+	if (domain_device->port != NULL)
+		isci_host = isci_host_from_sas_ha(domain_device->port->ha);
+
+	pr_debug("%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
+		 __func__, domain_device, isci_host, isci_device);
+
+	if (isci_device != NULL)
+		device_stopping = (isci_device->status == isci_stopping)
+				  || (isci_device->status == isci_stopped);
+
+	/* If there is a device reset pending on any request in the
+	 * device's list, fail this LUN reset request in order to
+	 * escalate to the device reset.
+	 */
+	if ((isci_device == NULL) ||
+	    (isci_host == NULL) ||
+	    ((isci_host != NULL) &&
+	     (isci_device != NULL) &&
+	     (device_stopping ||
+	      (isci_device_is_reset_pending(isci_host, isci_device))))) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: No dev (%p), no host (%p), or "
+			 "RESET PENDING: domain_device=%p\n",
+			 __func__, isci_device, isci_host, domain_device);
+		return TMF_RESP_FUNC_FAILED;
+	}
+
+	/* Stop I/O to the remote device. */
+	isci_device_set_host_quiesce_lock_state(isci_device, true);
+
+	/* Send the task management part of the reset. */
+	if (sas_protocol_ata(domain_device->tproto)) {
+		ret = isci_task_send_lu_reset_sata(
+			isci_host, isci_device, lun
+			);
+	} else
+		ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun);
+
+	/* If the LUN reset worked, all the I/O can now be terminated. */
+	if (ret == TMF_RESP_FUNC_COMPLETE)
+		/* Terminate all I/O now. */
+		isci_terminate_pending_requests(isci_host,
+						isci_device,
+						terminating);
+
+	/* Resume I/O to the remote device. */
+	isci_device_set_host_quiesce_lock_state(isci_device, false);
+
+	return ret;
+}
+
+
+/*	 int (*lldd_clear_nexus_port)(struct asd_sas_port *); */
+int isci_task_clear_nexus_port(struct asd_sas_port *port)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+
+
+int isci_task_clear_nexus_ha(struct sas_ha_struct *ha)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+int isci_task_I_T_nexus_reset(struct domain_device *dev)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+
+/* Task Management Functions. Must be called from process context.	 */
+
+/**
+ * isci_abort_task_process_cb() - This is a helper function for the abort task
+ *    TMF command.  It manages the request state with respect to the successful
+ *    transmission / completion of the abort task request.
+ * @cb_state: This parameter specifies when this function was called - after
+ *    the TMF request has been started and after it has timed-out.
+ * @tmf: This parameter specifies the TMF in progress.
+ *
+ *
+ */
+static void isci_abort_task_process_cb(
+	enum isci_tmf_cb_state cb_state,
+	struct isci_tmf *tmf,
+	void *cb_data)
+{
+	struct isci_request *old_request;
+
+	old_request = (struct isci_request *)cb_data;
+
+	dev_dbg(&old_request->isci_host->pdev->dev,
+		"%s: tmf=%p, old_request=%p\n",
+		__func__, tmf, old_request);
+
+	switch (cb_state) {
+
+	case isci_tmf_started:
+		/* The TMF has been started.  Nothing to do here, since the
+		 * request state was already set to "aborted" by the abort
+		 * task function.
+		 */
+		BUG_ON(old_request->status != aborted);
+		break;
+
+	case isci_tmf_timed_out:
+
+		/* Set the task's state to "aborting", since the abort task
+		 * function thread set it to "aborted" (above) in anticipation
+		 * of the task management request working correctly.  Since the
+		 * timeout has now fired, the TMF request failed.  We set the
+		 * state such that the request completion will indicate the
+		 * device is no longer present.
+		 */
+		isci_request_change_state(old_request, aborting);
+		break;
+
+	default:
+		dev_err(&old_request->isci_host->pdev->dev,
+			"%s: Bad cb_state (%d): tmf=%p, old_request=%p\n",
+			__func__, cb_state, tmf, old_request);
+		break;
+	}
+}
+
+/**
+ * isci_task_abort_task() - This function is one of the SAS Domain Template
+ *    functions. This function is called by libsas to abort a specified task.
+ * @task: This parameter specifies the SAS task to abort.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_abort_task(struct sas_task *task)
+{
+	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
+	struct isci_request *old_request = NULL;
+	struct isci_remote_device *isci_device = NULL;
+	struct isci_host *isci_host = NULL;
+	struct isci_tmf tmf;
+	int ret = TMF_RESP_FUNC_FAILED;
+	unsigned long flags;
+	bool any_dev_reset, device_stopping;
+
+	/* Get the isci_request reference from the task.  Note that
+	 * this check does not depend on the pending request list
+	 * in the device, because tasks driving resets may land here
+	 * after completion in the core.
+	 */
+	old_request = isci_task_get_request_from_task(task, &isci_host,
+						      &isci_device);
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: task = %p\n", __func__, task);
+
+	/* Check if the device has been / is currently being removed.
+	 * If so, no task management will be done, and the I/O will
+	 * be terminated.
+	 */
+	device_stopping = (isci_device->status == isci_stopping)
+			  || (isci_device->status == isci_stopped);
+
+#ifdef NOMORE
+	/* This abort task function is the first stop of the libsas error
+	 * handler thread. Since libsas is executing in a thread with a
+	 * referernce to the "task" parameter, that task cannot be completed
+	 * directly back to the upper layers.  In order to make sure that
+	 * the task is managed correctly if this abort task fails, set the
+	 * "SAS_TASK_STATE_ABORTED" bit now such that completions up the
+	 * stack will be intercepted and only allowed to happen in the
+	 * libsas SCSI error handler thread.
+	 */
+	spin_lock_irqsave(&task->task_state_lock, flags);
+	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+#endif  /* NOMORE */
+
+	/* This version of the driver will fail abort requests for
+	 * SATA/STP.  Failing the abort request this way will cause the
+	 * SCSI error handler thread to escalate to LUN reset
+	 */
+	if (sas_protocol_ata(task->task_proto) && !device_stopping) {
+		dev_warn(&isci_host->pdev->dev,
+			    " task %p is for a STP/SATA device;"
+			    " returning TMF_RESP_FUNC_FAILED\n"
+			    " to cause a LUN reset...\n", task);
+		return TMF_RESP_FUNC_FAILED;
+	}
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: old_request == %p\n", __func__, old_request);
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
+
+	/* Don't do resets to stopping devices. */
+	if (device_stopping)
+		task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
+
+	/* See if there is a pending device reset for this device. */
+	any_dev_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
+
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+	if ((isci_device != NULL) && !device_stopping)
+		any_dev_reset = any_dev_reset
+				|| isci_device_is_reset_pending(isci_host,
+								isci_device
+								);
+
+	/* If the extraction of the request reference from the task
+	 * failed, then the request has been completed (or if there is a
+	 * pending reset then this abort request function must be failed
+	 * in order to escalate to the target reset).
+	 */
+	if ((old_request == NULL) ||
+	    ((old_request != NULL) &&
+	     (old_request->sci_request_handle == NULL) &&
+	     (old_request->complete_in_target)) ||
+	     any_dev_reset) {
+
+		spin_lock_irqsave(&task->task_state_lock, flags);
+
+		/* If the device reset task flag is set, fail the task
+		 * management request.  Otherwise, the original request
+		 * has completed.
+		 */
+		if (any_dev_reset) {
+
+			/* Turn off the task's DONE to make sure this
+			 * task is escalated to a target reset.
+			 */
+			task->task_state_flags &= ~SAS_TASK_STATE_DONE;
+
+			/* Fail the task management request in order to
+			 * escalate to the target reset.
+			 */
+			ret = TMF_RESP_FUNC_FAILED;
+
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: Failing task abort in order to "
+				"escalate to target reset because\n"
+				"SAS_TASK_NEED_DEV_RESET is set for "
+				"task %p on dev %p\n",
+				__func__, task, isci_device);
+
+		} else {
+			ret = TMF_RESP_FUNC_COMPLETE;
+
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: abort task not needed for %p\n",
+				__func__, task);
+
+			/* The request has already completed and there
+			 * is nothing to do here other than to set the task
+			 * done bit, and indicate that the task abort function
+			 * was sucessful.
+			 */
+			isci_set_task_doneflags(task);
+
+			/* Set the abort bit to make sure that libsas sticks the
+			 * task in the completed task queue.
+			 */
+/*			task->task_state_flags |= SAS_TASK_STATE_ABORTED; */
+
+			/* Check for the situation where the request was
+			 * left around on the device list but the
+			 * request already completed.
+			 */
+			if (old_request && !old_request->sci_request_handle) {
+
+				isci_request_cleanup_completed_loiterer(
+					isci_host, isci_device, old_request
+					);
+			}
+		}
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+		return ret;
+	}
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	/* Sanity check the request status, and set the I/O kernel completion
+	 * struct that will be triggered when the request completes.
+	 */
+	if (isci_task_validate_request_to_abort(
+		    old_request,
+		    isci_host,
+		    isci_device,
+		    &aborted_io_completion)
+	    == unallocated) {
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: old_request not valid for device = %p\n",
+			__func__,
+			isci_device);
+		old_request = NULL;
+	}
+
+	if (!old_request) {
+
+		/* There is no isci_request attached to the sas_task.
+		 * It must have been completed and detached.
+		 */
+		dev_dbg(&isci_host->pdev->dev,
+			"%s: old_request == NULL\n",
+			__func__);
+
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+		/* Set the state on the task. */
+		isci_task_all_done(task);
+
+		return TMF_RESP_FUNC_COMPLETE;
+	}
+	if (task->task_proto == SAS_PROTOCOL_SMP || device_stopping) {
+
+		if (device_stopping)
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: device is stopping, thus no TMF\n",
+				__func__);
+		else
+			dev_dbg(&isci_host->pdev->dev,
+				"%s: request is SMP, thus no TMF\n",
+				__func__);
+
+		old_request->complete_in_target = true;
+
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+		/* Set the state on the task. */
+		isci_task_all_done(task);
+
+		ret = TMF_RESP_FUNC_COMPLETE;
+
+		/* Stopping and SMP devices are not sent a TMF, and are not
+		 * reset, but the outstanding I/O request is terminated here.
+		 *
+		 * Clean up the request on our side, and wait for the aborted
+		 * I/O to complete.
+		 */
+		isci_terminate_request_core(isci_host, isci_device, old_request,
+					    &aborted_io_completion);
+	} else {
+		/* Fill in the tmf stucture */
+		isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort,
+				    isci_abort_task_process_cb, old_request);
+
+		tmf.io_tag = scic_io_request_get_io_tag(
+			old_request->sci_request_handle
+			);
+
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */
+		ret = isci_task_execute_tmf(isci_host, &tmf,
+					    ISCI_ABORT_TASK_TIMEOUT_MS);
+
+		if (ret == TMF_RESP_FUNC_COMPLETE) {
+			old_request->complete_in_target = true;
+
+			/* Clean up the request on our side, and wait for the aborted I/O to
+			 * complete.
+			 */
+			isci_terminate_request_core(isci_host, isci_device, old_request,
+						    &aborted_io_completion);
+
+			/* Set the state on the task. */
+			isci_task_all_done(task);
+		} else
+			dev_err(&isci_host->pdev->dev,
+				"%s: isci_task_send_tmf failed\n",
+				__func__);
+	}
+
+	return ret;
+}
+
+/**
+ * isci_task_abort_task_set() - This function is one of the SAS Domain Template
+ *    functions. This is one of the Task Management functoins called by libsas,
+ *    to abort all task for the given lun.
+ * @d_device: This parameter specifies the domain device associated with this
+ *    request.
+ * @lun: This parameter specifies the lun associated with this request.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_abort_task_set(
+	struct domain_device *d_device,
+	u8 *lun)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+
+/**
+ * isci_task_clear_aca() - This function is one of the SAS Domain Template
+ *    functions. This is one of the Task Management functoins called by libsas.
+ * @d_device: This parameter specifies the domain device associated with this
+ *    request.
+ * @lun: This parameter specifies the lun	 associated with this request.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_clear_aca(
+	struct domain_device *d_device,
+	u8 *lun)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+
+
+/**
+ * isci_task_clear_task_set() - This function is one of the SAS Domain Template
+ *    functions. This is one of the Task Management functoins called by libsas.
+ * @d_device: This parameter specifies the domain device associated with this
+ *    request.
+ * @lun: This parameter specifies the lun	 associated with this request.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_clear_task_set(
+	struct domain_device *d_device,
+	u8 *lun)
+{
+	return TMF_RESP_FUNC_FAILED;
+}
+
+
+/**
+ * isci_task_query_task() - This function is implemented to cause libsas to
+ *    correctly escalate the failed abort to a LUN or target reset (this is
+ *    because sas_scsi_find_task libsas function does not correctly interpret
+ *    all return codes from the abort task call).  When TMF_RESP_FUNC_SUCC is
+ *    returned, libsas turns this into a LUN reset; when FUNC_FAILED is
+ *    returned, libsas will turn this into a target reset
+ * @task: This parameter specifies the sas task being queried.
+ * @lun: This parameter specifies the lun associated with this request.
+ *
+ * status, zero indicates success.
+ */
+int isci_task_query_task(
+	struct sas_task *task)
+{
+	/* See if there is a pending device reset for this device. */
+	if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
+		return TMF_RESP_FUNC_FAILED;
+	else
+		return TMF_RESP_FUNC_SUCC;
+}
+
+/**
+ * isci_task_request_complete() - This function is called by the sci core when
+ *    an task request completes.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @request: This parameter is the completed isci_request object.
+ * @completion_status: This parameter specifies the completion status from the
+ *    sci core.
+ *
+ * none.
+ */
+void isci_task_request_complete(
+	struct isci_host *isci_host,
+	struct isci_request *request,
+	enum sci_task_status completion_status)
+{
+	struct isci_remote_device *isci_device = request->isci_device;
+	enum isci_request_status old_state;
+	struct isci_tmf *tmf = isci_request_access_tmf(request);
+	struct completion *tmf_complete;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: request = %p, status=%d\n",
+		__func__, request, completion_status);
+
+	old_state = isci_request_change_state(request, completed);
+
+	tmf->status = completion_status;
+	request->complete_in_target = true;
+
+	if (SAS_PROTOCOL_SSP == tmf->proto) {
+
+		memcpy(&tmf->resp.resp_iu,
+		       scic_io_request_get_response_iu_address(
+			       request->sci_request_handle
+			       ),
+		       sizeof(struct sci_ssp_response_iu));
+
+	} else if (SAS_PROTOCOL_SATA == tmf->proto) {
+
+		memcpy(&tmf->resp.d2h_fis,
+		       scic_stp_io_request_get_d2h_reg_address(
+			       request->sci_request_handle
+			       ),
+		       sizeof(struct sata_fis_reg_d2h)
+		       );
+	}
+
+	/* Manage the timer if it is still running. */
+	if (tmf->timeout_timer) {
+
+		isci_timer_stop(tmf->timeout_timer);
+		isci_timer_free(&isci_host->timer_list_struct,
+				tmf->timeout_timer);
+		tmf->timeout_timer = NULL;
+	}
+
+	/* PRINT_TMF( ((struct isci_tmf *)request->task)); */
+	tmf_complete = tmf->complete;
+
+	scic_controller_complete_task(
+		isci_host->core_controller,
+		isci_device->sci_device_handle,
+		request->sci_request_handle
+		);
+	/* NULL the request handle to make sure it cannot be terminated
+	 *  or completed again.
+	 */
+	request->sci_request_handle = NULL;
+
+	isci_request_change_state(request, unallocated);
+	list_del_init(&request->dev_node);
+
+	/* The task management part completes last. */
+	complete(tmf_complete);
+}
+
+
+/**
+ * isci_task_ssp_request_get_lun() - This function is called by the sci core to
+ *    retrieve the lun for a given task request.
+ * @request: This parameter is the isci_request object.
+ *
+ * lun for specified task request.
+ */
+u32 isci_task_ssp_request_get_lun(struct isci_request *request)
+{
+	struct isci_tmf *isci_tmf = isci_request_access_tmf(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: lun = %d\n", __func__, isci_tmf->lun[0]);
+/* @todo: build lun from array of bytes to 32 bit */
+	return isci_tmf->lun[0];
+}
+
+/**
+ * isci_task_ssp_request_get_function() - This function is called by the sci
+ *    core to retrieve the function for a given task request.
+ * @request: This parameter is the isci_request object.
+ *
+ * function code for specified task request.
+ */
+u8 isci_task_ssp_request_get_function(struct isci_request *request)
+{
+	struct isci_tmf *isci_tmf = isci_request_access_tmf(request);
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: func = %d\n", __func__, isci_tmf->tmf_code);
+
+	return isci_tmf->tmf_code;
+}
+
+/**
+ * isci_task_ssp_request_get_io_tag_to_manage() - This function is called by
+ *    the sci core to retrieve the io tag for a given task request.
+ * @request: This parameter is the isci_request object.
+ *
+ * io tag for specified task request.
+ */
+u16 isci_task_ssp_request_get_io_tag_to_manage(struct isci_request *request)
+{
+	u16 io_tag = SCI_CONTROLLER_INVALID_IO_TAG;
+
+	if (tmf_task == request->ttype) {
+		struct isci_tmf *tmf = isci_request_access_tmf(request);
+		io_tag = tmf->io_tag;
+	}
+
+	dev_dbg(&request->isci_host->pdev->dev,
+		"%s: request = %p, io_tag = %d\n",
+		__func__, request, io_tag);
+
+	return io_tag;
+}
+
+/**
+ * isci_task_ssp_request_get_response_data_address() - This function is called
+ *    by the sci core to retrieve the response data address for a given task
+ *    request.
+ * @request: This parameter is the isci_request object.
+ *
+ * response data address for specified task request.
+ */
+void *isci_task_ssp_request_get_response_data_address(
+	struct isci_request *request)
+{
+	struct isci_tmf *isci_tmf = isci_request_access_tmf(request);
+
+	return &isci_tmf->resp.resp_iu;
+}
+
+/**
+ * isci_task_ssp_request_get_response_data_length() - This function is called
+ *    by the sci core to retrieve the response data length for a given task
+ *    request.
+ * @request: This parameter is the isci_request object.
+ *
+ * response data length for specified task request.
+ */
+u32 isci_task_ssp_request_get_response_data_length(
+	struct isci_request *request)
+{
+	struct isci_tmf *isci_tmf = isci_request_access_tmf(request);
+
+	return sizeof(isci_tmf->resp.resp_iu);
+}
+
+/**
+ * isci_bus_reset_handler() - This function performs a target reset of the
+ *    device referenced by "cmd'.  This function is exported through the
+ *    "struct scsi_host_template" structure such that it is called when an I/O
+ *    recovery process has escalated to a target reset. Note that this function
+ *    is called from the scsi error handler event thread, so may block on calls.
+ * @scsi_cmd: This parameter specifies the target to be reset.
+ *
+ * SUCCESS if the reset process was successful, else FAILED.
+ */
+int isci_bus_reset_handler(struct scsi_cmnd *cmd)
+{
+	unsigned long flags = 0;
+	struct isci_host *isci_host = NULL;
+	enum sci_status status;
+	int base_status;
+	struct isci_remote_device *isci_dev
+		= isci_dev_from_domain_dev(
+		sdev_to_domain_dev(cmd->device));
+
+	dev_dbg(&cmd->device->sdev_gendev,
+		"%s: cmd %p, isci_dev %p\n",
+		__func__, cmd, isci_dev);
+
+	if (!isci_dev) {
+		dev_warn(&cmd->device->sdev_gendev,
+			 "%s: isci_dev is GONE!\n",
+			 __func__);
+
+		return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */
+	}
+
+	if (isci_dev->isci_port != NULL)
+		isci_host = isci_dev->isci_port->isci_host;
+
+	if (isci_host != NULL)
+		spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	status = scic_remote_device_reset(isci_dev->sci_device_handle);
+	if (status != SCI_SUCCESS) {
+
+		if (isci_host != NULL)
+			spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+		scmd_printk(KERN_WARNING, cmd,
+			    "%s: scic_remote_device_reset(%p) returned %d!\n",
+			    __func__, isci_dev, status);
+
+		return TMF_RESP_FUNC_FAILED;
+	}
+	if (isci_host != NULL)
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	/* Stop I/O to the remote device. */
+	isci_device_set_host_quiesce_lock_state(isci_dev, true);
+
+	/* Make sure all pending requests are able to be fully terminated. */
+	isci_device_clear_reset_pending(isci_dev);
+
+	/* Terminate in-progress I/O now. */
+	isci_remote_device_nuke_requests(isci_dev);
+
+	/* Call into the libsas default handler (which calls sas_phy_reset). */
+	base_status = sas_eh_bus_reset_handler(cmd);
+
+	if (base_status != SUCCESS) {
+
+		/* There can be cases where the resets to individual devices
+		 * behind an expander will fail because of an unplug of the
+		 * expander itself.
+		 */
+		scmd_printk(KERN_WARNING, cmd,
+			    "%s: sas_eh_bus_reset_handler(%p) returned %d!\n",
+			    __func__, cmd, base_status);
+	}
+
+	/* WHAT TO DO HERE IF sas_phy_reset FAILS? */
+
+	if (isci_host != NULL)
+		spin_lock_irqsave(&isci_host->scic_lock, flags);
+	status
+		= scic_remote_device_reset_complete(isci_dev->sci_device_handle);
+
+	if (isci_host != NULL)
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	if (status != SCI_SUCCESS) {
+		scmd_printk(KERN_WARNING, cmd,
+			    "%s: scic_remote_device_reset_complete(%p) "
+			    "returned %d!\n",
+			    __func__, isci_dev, status);
+	}
+	/* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */
+
+	dev_dbg(&cmd->device->sdev_gendev,
+		"%s: cmd %p, isci_dev %p complete.\n",
+		__func__, cmd, isci_dev);
+
+	/* Resume I/O to the remote device. */
+	isci_device_set_host_quiesce_lock_state(isci_dev, false);
+
+	return TMF_RESP_FUNC_COMPLETE;
+}
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
new file mode 100644
index 0000000..ced6a8b
--- /dev/null
+++ b/drivers/scsi/isci/task.h
@@ -0,0 +1,368 @@
+/*
+ * 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(_ISCI_TASK_H_)
+#define _ISCI_TASK_H_
+
+struct isci_request;
+struct isci_host;
+
+/**
+ * enum isci_tmf_cb_state - This enum defines the possible states in which the
+ *    TMF callback function is invoked during the TMF execution process.
+ *
+ *
+ */
+enum isci_tmf_cb_state {
+
+	isci_tmf_init_state = 0,
+	isci_tmf_started,
+	isci_tmf_timed_out
+};
+
+/**
+ * enum isci_tmf_function_codes - This enum defines the possible preparations
+ *    of task management requests.
+ *
+ *
+ */
+enum isci_tmf_function_codes {
+
+	isci_tmf_func_none      = 0,
+	isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
+	isci_tmf_ssp_lun_reset  = TMF_LU_RESET,
+	isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */
+	isci_tmf_sata_srst_low  = TMF_LU_RESET + 0x101  /* Non SCSI */
+};
+/**
+ * struct isci_tmf - This class represents the task management object which
+ *    acts as an interface to libsas for processing task management requests
+ *
+ *
+ */
+struct isci_tmf {
+
+	struct completion *complete;
+	enum sas_protocol proto;
+	union {
+		struct sci_ssp_response_iu resp_iu;
+		struct dev_to_host_fis d2h_fis;
+	}                            resp;
+	unsigned char lun[8];
+	u16 io_tag;
+	struct isci_remote_device *device;
+	enum isci_tmf_function_codes tmf_code;
+	int status;
+
+	struct isci_timer *timeout_timer;
+
+	/* The optional callback function allows the user process to
+	 * track the TMF transmit / timeout conditions.
+	 */
+	void (*cb_state_func)(
+		enum isci_tmf_cb_state,
+		struct isci_tmf *, void *);
+	void *cb_data;
+
+};
+
+static inline void isci_print_tmf(
+	struct isci_tmf *tmf)
+{
+	if (SAS_PROTOCOL_SATA == tmf->proto)
+		dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+			"%s: status = %x\n"
+			"tmf->resp.d2h_fis.status = %x\n"
+			"tmf->resp.d2h_fis.error = %x\n",
+			__func__,
+			tmf->status,
+			tmf->resp.d2h_fis.status,
+			tmf->resp.d2h_fis.error);
+	else
+		dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+			"%s: status = %x\n"
+			"tmf->resp.resp_iu.data_present = %x\n"
+			"tmf->resp.resp_iu.status = %x\n"
+			"tmf->resp.resp_iu.data_length = %x\n"
+			"tmf->resp.resp_iu.data[0] = %x\n"
+			"tmf->resp.resp_iu.data[1] = %x\n"
+			"tmf->resp.resp_iu.data[2] = %x\n"
+			"tmf->resp.resp_iu.data[3] = %x\n",
+			__func__,
+			tmf->status,
+			tmf->resp.resp_iu.data_present,
+			tmf->resp.resp_iu.status,
+			(tmf->resp.resp_iu.response_data_length[0] << 24) +
+			(tmf->resp.resp_iu.response_data_length[1] << 16) +
+			(tmf->resp.resp_iu.response_data_length[2] << 8) +
+			tmf->resp.resp_iu.response_data_length[3],
+			tmf->resp.resp_iu.data[0],
+			tmf->resp.resp_iu.data[1],
+			tmf->resp.resp_iu.data[2],
+			tmf->resp.resp_iu.data[3]);
+}
+
+
+int isci_task_execute_task(
+	struct sas_task *task,
+	int num,
+	gfp_t gfp_flags);
+
+int isci_task_abort_task(
+	struct sas_task *task);
+
+int isci_task_abort_task_set(
+	struct domain_device *d_device,
+	u8 *lun);
+
+int isci_task_clear_aca(
+	struct domain_device *d_device,
+	u8 *lun);
+
+int isci_task_clear_task_set(
+	struct domain_device *d_device,
+	u8 *lun);
+
+int isci_task_query_task(
+	struct sas_task *task);
+
+int isci_task_lu_reset(
+	struct domain_device *d_device,
+	u8 *lun);
+
+int isci_task_clear_nexus_port(
+	struct asd_sas_port *port);
+
+int isci_task_clear_nexus_ha(
+	struct sas_ha_struct *ha);
+
+int isci_task_I_T_nexus_reset(
+	struct domain_device *d_device);
+
+void isci_task_request_complete(
+	struct isci_host *isci_host,
+	struct isci_request *request,
+	enum sci_task_status completion_status);
+
+u16 isci_task_ssp_request_get_io_tag_to_manage(
+	struct isci_request *request);
+
+u8 isci_task_ssp_request_get_function(
+	struct isci_request *request);
+
+u32 isci_task_ssp_request_get_lun(
+	struct isci_request *request);
+
+void *isci_task_ssp_request_get_response_data_address(
+	struct isci_request *request);
+
+u32 isci_task_ssp_request_get_response_data_length(
+	struct isci_request *request);
+
+int isci_queuecommand(
+	struct scsi_cmnd *scsi_cmd,
+	void (*donefunc)(struct scsi_cmnd *));
+
+int isci_bus_reset_handler(struct scsi_cmnd *cmd);
+
+void isci_task_build_tmf(
+	struct isci_tmf *tmf,
+	struct isci_remote_device *isci_device,
+	enum isci_tmf_function_codes code,
+	void (*tmf_sent_cb)(
+		enum isci_tmf_cb_state,
+		struct isci_tmf *, void *),
+	void *cb_data);
+
+int isci_task_execute_tmf(
+	struct isci_host *isci_host,
+	struct isci_tmf *tmf,
+	unsigned long timeout_ms);
+
+/**
+ * enum isci_completion_selection - This enum defines the possible actions to
+ *    take with respect to a given request's notification back to libsas.
+ *
+ *
+ */
+enum isci_completion_selection {
+
+	isci_perform_normal_io_completion,      /* Normal notify (task_done) */
+	isci_perform_aborted_io_completion,     /* No notification.   */
+	isci_perform_error_io_completion        /* Use sas_task_abort */
+};
+
+static inline void isci_set_task_doneflags(
+	struct sas_task *task)
+{
+	/* Since no futher action will be taken on this task,
+	 * make sure to mark it complete from the lldd perspective.
+	 */
+	task->task_state_flags |= SAS_TASK_STATE_DONE;
+	task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+	task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+}
+/**
+ * isci_task_all_done() - This function clears the task bits to indicate the
+ *    LLDD is done with the task.
+ *
+ *
+ */
+static inline void isci_task_all_done(
+	struct sas_task *task)
+{
+	unsigned long flags;
+
+	/* Since no futher action will be taken on this task,
+	 * make sure to mark it complete from the lldd perspective.
+	 */
+	spin_lock_irqsave(&task->task_state_lock, flags);
+	isci_set_task_doneflags(task);
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+}
+
+/**
+ * isci_task_set_completion_status() - This function sets the completion status
+ *    for the request.
+ * @task: This parameter is the completed request.
+ * @response: This parameter is the response code for the completed task.
+ * @status: This parameter is the status code for the completed task.
+ *
+ * none.
+ */
+static inline void isci_task_set_completion_status(
+	struct sas_task *task,
+	enum service_response response,
+	enum exec_status status,
+	enum isci_completion_selection task_notification_selection)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
+
+	task->task_status.resp = response;
+	task->task_status.stat = status;
+
+	/* Don't set DONE (or clear AT_INITIATOR) for any task going into the
+	 * error path, because the EH interprets that as a handled error condition.
+	 * Also don't take action if there is a reset pending.
+	 */
+	if ((task_notification_selection != isci_perform_error_io_completion)
+	    && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
+		isci_set_task_doneflags(task);
+
+	spin_unlock_irqrestore(&task->task_state_lock, flags);
+}
+/**
+ * isci_task_complete_for_upper_layer() - This function completes the request
+ *    to the upper layer driver.
+ * @host: This parameter is a pointer to the host on which the the request
+ *    should be queued (either as an error or success).
+ * @request: This parameter is the completed request.
+ * @response: This parameter is the response code for the completed task.
+ * @status: This parameter is the status code for the completed task.
+ *
+ * none.
+ */
+static inline void isci_task_complete_for_upper_layer(
+	struct sas_task *task,
+	enum service_response response,
+	enum exec_status status,
+	enum isci_completion_selection task_notification_selection)
+{
+	isci_task_set_completion_status(task, response, status,
+					 task_notification_selection);
+
+
+	/* Tasks aborted specifically by a call to the lldd_abort_task
+	 * function should not be completed to the host in the regular path.
+	 */
+	switch (task_notification_selection) {
+	case isci_perform_normal_io_completion:
+		/* Normal notification (task_done) */
+		dev_dbg(task->dev->port->ha->dev,
+			"%s: Normal - task = %p, response=%d, status=%d\n",
+			__func__, task, response, status);
+		task->task_done(task);
+		task->lldd_task = NULL;
+		break;
+
+	case isci_perform_aborted_io_completion:
+		/* No notification because this request is already in the
+		 * abort path.
+		 */
+		dev_warn(task->dev->port->ha->dev,
+			 "%s: Aborted - task = %p, response=%d, status=%d\n",
+			 __func__, task, response, status);
+		break;
+
+	case isci_perform_error_io_completion:
+		/* Use sas_task_abort */
+		dev_warn(task->dev->port->ha->dev,
+			 "%s: Error - task = %p, response=%d, status=%d\n",
+			 __func__, task, response, status);
+		sas_task_abort(task);
+		break;
+
+	default:
+		dev_warn(task->dev->port->ha->dev,
+			 "%s: isci task notification default case!",
+			 __func__);
+		sas_task_abort(task);
+		break;
+	}
+}
+
+#endif /* !defined(_SCI_TASK_H_) */
diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c
new file mode 100644
index 0000000..ca72308
--- /dev/null
+++ b/drivers/scsi/isci/timers.c
@@ -0,0 +1,319 @@
+/*
+ * 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 "isci.h"
+#include "timers.h"
+
+
+/**
+ * isci_timer_list_construct() - This method contrucst the SCI Timer List
+ *    object used by the SCI Module class. The construction process involves
+ *    creating isci_timer objects and adding them to the SCI Timer List
+ *    object's list member. The number of isci_timer objects is determined by
+ *    the timer_list_size parameter.
+ * @isci_timer_list: This parameter points to the SCI Timer List object being
+ *    constructed. The calling routine is responsible for allocating the memory
+ *    for isci_timer_list and initializing the timer list_head member of
+ *    isci_timer_list.
+ * @timer_list_size: This parameter specifies the number of isci_timer objects
+ *    contained by the SCI Timer List. which this timer is to be associated.
+ *
+ * This method returns an error code indicating sucess or failure. The user
+ * should check for possible memory allocation error return otherwise, a zero
+ * indicates success.
+ */
+int isci_timer_list_construct(
+	struct isci_timer_list *isci_timer_list,
+	int timer_list_size)
+{
+	struct isci_timer *isci_timer;
+	int i;
+	int err = 0;
+
+
+	for (i = 0; i < timer_list_size; i++) {
+
+		isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL);
+
+		if (!isci_timer) {
+
+			err = -ENOMEM;
+			break;
+		}
+		isci_timer->used = 0;
+		isci_timer->stopped = 1;
+		isci_timer->parent = isci_timer_list;
+		list_add(&isci_timer->node, &isci_timer_list->timers);
+	}
+
+	return 0;
+
+}
+
+
+/**
+ * isci_timer_list_destroy() - This method destroys the SCI Timer List object
+ *    used by the SCI Module class. The destruction  process involves freeing
+ *    memory allocated for isci_timer objects on the SCI Timer List object's
+ *    timers list_head member. If any isci_timer objects are mark as "in use",
+ *    they are not freed and the function returns an error code of -EBUSY.
+ * @isci_timer_list: This parameter points to the SCI Timer List object being
+ *    destroyed.
+ *
+ * This method returns an error code indicating sucess or failure. The user
+ * should check for possible -EBUSY error return, in the event of one or more
+ * isci_timers still "in use", otherwise, a zero indicates success.
+ */
+int isci_timer_list_destroy(
+	struct isci_timer_list *isci_timer_list)
+{
+	struct isci_timer *timer, *tmp;
+
+	list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) {
+		isci_timer_free(isci_timer_list, timer);
+		list_del(&timer->node);
+		kfree(timer);
+	}
+	return 0;
+}
+
+
+
+static void isci_timer_restart(struct isci_timer *isci_timer)
+{
+	struct timer_list *timer =
+		&isci_timer->timer;
+	unsigned long timeout;
+
+	dev_dbg(&isci_timer->isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, isci_timer);
+
+	isci_timer->restart = 0;
+	isci_timer->stopped = 0;
+	timeout = isci_timer->timeout_value;
+	timeout = (timeout * HZ) / 1000;
+	timeout = timeout ? timeout : 1;
+	mod_timer(timer, jiffies + timeout);
+}
+
+/**
+ * This method pulls an isci_timer object off of the list for the SCI Timer
+ *    List object specified, marks the isci_timer as "in use" and initializes
+ *    it with user callback function and cookie data. The timer is not start at
+ *    this time, just reserved for the user.
+ * @isci_timer_list: This parameter points to the SCI Timer List from which the
+ *    timer is reserved.
+ * @cookie: This parameter specifies a piece of information that the user must
+ *    retain.  This cookie is to be supplied by the user anytime a timeout
+ *    occurs for the created timer.
+ * @timer_callback: This parameter specifies the callback method to be invoked
+ *    whenever the timer expires.
+ *
+ * This method returns a pointer to an isci_timer object reserved from the SCI
+ * Timer List.  The pointer will be utilized for all further interactions
+ * relating to this timer.
+ */
+
+static void timer_function(unsigned long data)
+{
+
+	struct isci_timer *timer     = (struct isci_timer *)data;
+	struct isci_host *isci_host = timer->isci_host;
+	unsigned long flags;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, timer);
+
+	if (isci_stopped == isci_host_get_state(isci_host)) {
+		timer->stopped = 1;
+		return;
+	}
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	if (!timer->stopped) {
+		timer->stopped = 1;
+		timer->timer_callback(timer->cookie);
+
+		if (timer->restart)
+			isci_timer_restart(timer);
+	}
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+}
+
+
+struct isci_timer *isci_timer_create(
+	struct isci_timer_list *isci_timer_list,
+	struct isci_host *isci_host,
+	void *cookie,
+	void (*timer_callback)(void *))
+{
+
+	struct timer_list *timer;
+	struct isci_timer *isci_timer;
+	struct list_head *timer_list =
+		&isci_timer_list->timers;
+	unsigned long flags;
+
+	spin_lock_irqsave(&isci_host->scic_lock, flags);
+
+	if (list_empty(timer_list)) {
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+		return NULL;
+	}
+
+	isci_timer = list_entry(timer_list->next, struct isci_timer, node);
+
+	if (isci_timer->used) {
+		spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+		return NULL;
+	}
+	isci_timer->used = 1;
+	isci_timer->stopped = 1;
+	list_move_tail(&isci_timer->node, timer_list);
+
+	spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+
+	timer = &isci_timer->timer;
+	timer->data = (unsigned long)isci_timer;
+	timer->function = timer_function;
+	isci_timer->cookie = cookie;
+	isci_timer->timer_callback = timer_callback;
+	isci_timer->isci_host = isci_host;
+
+	dev_dbg(&isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, isci_timer);
+
+	return isci_timer;
+}
+
+/**
+ * isci_timer_free() - This method frees the isci_timer, marking it "free to
+ *    use", then places its back at the head of the timers list for the SCI
+ *    Timer List object specified.
+ * @isci_timer_list: This parameter points to the SCI Timer List from which the
+ *    timer is reserved.
+ * @isci_timer: This parameter specifies the timer to be freed.
+ *
+ */
+void isci_timer_free(
+	struct isci_timer_list *isci_timer_list,
+	struct isci_timer *isci_timer)
+{
+	struct list_head *timer_list = &isci_timer_list->timers;
+
+	dev_dbg(&isci_timer->isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, isci_timer);
+
+	if (list_empty(timer_list))
+		return;
+
+	isci_timer->used = 0;
+	list_move(&isci_timer->node, timer_list);
+
+	if (!isci_timer->stopped) {
+		del_timer(&isci_timer->timer);
+		isci_timer->stopped = 1;
+	}
+}
+
+/**
+ * isci_timer_start() - This method starts the specified isci_timer, with the
+ *    specified timeout value.
+ * @isci_timer: This parameter specifies the timer to be started.
+ * @timeout: This parameter specifies the timeout, in milliseconds, after which
+ *    the associated callback function will be called.
+ *
+ */
+void isci_timer_start(
+	struct isci_timer *isci_timer,
+	unsigned long timeout)
+{
+	struct timer_list *timer = &isci_timer->timer;
+
+	dev_dbg(&isci_timer->isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, isci_timer);
+
+	isci_timer->timeout_value = timeout;
+	init_timer(timer);
+	timeout = (timeout * HZ) / 1000;
+	timeout = timeout ? timeout : 1;
+
+	timer->expires = jiffies + timeout;
+	timer->data = (unsigned long)isci_timer;
+	timer->function = timer_function;
+	isci_timer->stopped = 0;
+	isci_timer->restart = 0;
+	add_timer(timer);
+}
+
+/**
+ * isci_timer_stop() - This method stops the supplied isci_timer.
+ * @isci_timer: This parameter specifies the isci_timer to be stopped.
+ *
+ */
+void isci_timer_stop(struct isci_timer *isci_timer)
+{
+	dev_dbg(&isci_timer->isci_host->pdev->dev,
+		"%s: isci_timer = %p\n", __func__, isci_timer);
+
+	if (isci_timer->stopped)
+		return;
+
+	isci_timer->stopped = 1;
+
+	del_timer(&isci_timer->timer);
+}
diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h
new file mode 100644
index 0000000..ca5c215
--- /dev/null
+++ b/drivers/scsi/isci/timers.h
@@ -0,0 +1,126 @@
+/*
+ * 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(_SCI_TIMER_H_)
+#define _SCI_TIMER_H_
+
+#include <linux/timer.h>
+#include <linux/types.h>
+
+/***************************************************
+ * isci_timer
+ ***************************************************
+ */
+/**
+ * struct isci_timer_list - This class is the container for all isci_timer
+ *    objects
+ *
+ *
+ */
+struct isci_timer_list {
+
+	struct list_head timers;
+};
+
+/**
+ * struct isci_timer - This class represents the timer object used by SCIC. It
+ *    wraps the Linux timer_list object.
+ *
+ *
+ */
+struct isci_timer {
+	int used;
+	int stopped;
+	int restart;
+	int timeout_value;
+	void *cookie;
+	void (*timer_callback)(void *);
+	struct list_head node;
+	struct timer_list timer;
+	struct isci_timer_list *parent;
+	struct isci_host *isci_host;
+};
+
+#define to_isci_timer(t)	\
+	container_of(t, struct isci_timer, timer);
+
+int isci_timer_list_construct(
+	struct isci_timer_list *isci_timer_list,
+	int timer_list_size);
+
+
+int isci_timer_list_destroy(
+	struct isci_timer_list *isci_timer_list);
+
+struct isci_timer *isci_timer_create(
+	struct isci_timer_list *isci_timer_list,
+	struct isci_host *isci_host,
+	void *cookie,
+	void (*timer_callback)(void *));
+
+void isci_timer_free(
+	struct isci_timer_list *isci_timer_list,
+	struct isci_timer *isci_timer);
+
+void isci_timer_start(
+	struct isci_timer *isci_timer,
+	unsigned long timeout);
+
+void isci_timer_stop(
+	struct isci_timer *isci_timer);
+
+
+#endif /* !defined (_SCI_TIMER_H_) */
+
diff --git a/firmware/Makefile b/firmware/Makefile
index 0d15a3d..5f43bfb 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -82,6 +82,7 @@
 fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
 fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
 				      advansys/3550.bin advansys/38C0800.bin
+fw-shipped-$(CONFIG_SCSI_ISCI) += isci/isci_firmware.bin
 fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
 					 qlogic/12160.bin
 fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex
new file mode 100644
index 0000000..9fc9e60
--- /dev/null
+++ b/firmware/isci/isci_firmware.bin.ihex
@@ -0,0 +1,11 @@
+:1000000023534355204D4147494323000100010834
+:1000100001000000020000000400000008000000D1
+:1000200001000000020000000400000008000000C1
+:1000300002080300000003000000030000000300AA
+:1000400000000300000003000000030000000300A4
+:1000500000000308000000F0FFFFCF5F000000F188
+:10006000FFFFCF5F000000F2FFFFCF5F000000F353
+:10007000FFFFCF5F000000F4FFFFCF5F000000F53F
+:10008000FFFFCF5F000000F6FFFFCF5F000000F72B
+:05009000FFFFCF5FFF40
+:00000001FF