diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index f409470e0eae970cc258d075935d31d8c99407a7..eb923db2651a28faa2c4883318e81abc8f90ed21 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -30,25 +30,25 @@ Frequency  : rare on shutdown ost
 Bugzilla   : 13196
 Description: Don't allow skipping OSTs if index has been specified.
 Details    : Don't allow skipping OSTs if index has been specified, make locking
-             in internal create lots better.
+	     in internal create lots better.
 
 Severity   : normal
 Bugzilla   : 14421
 Description: ASSERTION(!PageDirty(page)) failed
 Details    : Wrong check could lead to an assertion failure under specific 
-             load patterns.
+	     load patterns.
 
 Severity   : normal
 Bugzilla   : 12228
 Description: LBUG in ptlrpc_check_set() bad phase ebc0de00
 Details    : access to bitfield in structure is always rounded to long 
-             and this produce problem with not atomic change any bit.
+	     and this produce problem with not atomic change any bit.
 
 Severity   : normal
 Bugzilla   : 13647
 Description: Lustre make rpms failed.
 Details    : Remove ldiskfs spec file to avoids rpmbuild be confused when
-             builds Lustre rpms from tarball.
+	     builds Lustre rpms from tarball.
 
 Severity   : enhancement
 Bugzilla   : 14498
@@ -58,9 +58,9 @@ Severity   : normal
 Frequency  : rare on shutdown ost
 Bugzilla   : 14608
 Description: If llog cancel was not send before clean_exports phase, this can
-             produce deadlock in llog code.
+	     produce deadlock in llog code.
 Details    : If llog thread has last reference to obd and call class_import_put
-             this produce deadlock because llog_cleanup_commit_master wait when
+	     this produce deadlock because llog_cleanup_commit_master wait when
 	     last llog_commit_thread exited, but this never success because was 
 	     called from llog_commit_thread.
 
@@ -91,7 +91,7 @@ Bugzilla   : 12702
 Frequency  : rare, in recovery and (or) destroy lovobjid file.
 Description: rewrite lov objid code.
 Details    : Cleanup for lov objid code, remove scability problems and wrong
-             locking. Fix sending last_id into ost.
+	     locking. Fix sending last_id into ost.
 
 Severity   : enhancement
 Bugzilla   : 14388
@@ -107,8 +107,8 @@ Bugzilla   : 14260
 Frequency  : rare, at shutdown
 Description: access already free / zero obd_namespace.
 Details    : if client_disconnect_export was called without force flag set,
-             and exist connect request in flight, this can produce access to
-	     NULL pointer (or already free pointer) when connect_interpret 
+	     and exist connect request in flight, this can produce access to
+	     NULL pointer (or already free pointer) when connect_interpret
 	     store ocd flags in obd_namespace.
 
 Severity   : minor
@@ -116,7 +116,7 @@ Bugzilla   : 14418
 Frequency  : only at startup
 Description: not alloc memory with spinlock held.
 Details    : allocation memory with GFP_KERNEL can produce sleep deadlock,
-             if any spinlock held.
+	     if any spinlock held.
 
 Severity   : major
 Frequency  : always
@@ -128,7 +128,7 @@ Severity   : normal
 Bugzilla   : 11791
 Description: Inconsistent usage of lustre_pack_reply()
 Details    : Standardize the usage of lustre_pack_reply() such that it
-             always generate a CERROR on failure.
+	     always generate a CERROR on failure.
 
 Severity   : normal
 Frequency  : very rare
@@ -157,11 +157,11 @@ Description: Update to RHEL4 kernel-2.6.9-55.0.12.EL.
 Severity   : enhancement
 Bugzilla   : 13690
 Description: Build SLES10 patchless client fails
-Details    : The configure was broken by run ./configure with 
+Details    : The configure was broken by run ./configure with
 	     --with-linux-obj=.... argument for patchless client. When the
 	     configure use --with-linux-obj, the LINUXINCLUDE= -Iinclude
-	     can't search header adequately. Use absolute path such as 
-	     -I($LINUX)/include instead. 
+	     can't search header adequately. Use absolute path such as
+	     -I($LINUX)/include instead.
 
 Severity   : enhancement
 Bugzilla   : 11622
@@ -184,7 +184,7 @@ Bugzilla   : 13888
 Description: interrupt oig_wait produce painc on resend.
 Details    : brw_redo_request can be used for resend requests from ptlrpcd and
 	     private set, and this produce situation when rq_ptlrpcd_data not
-	     copyed to new allocated request and triggered LBUG on assert 
+	     copyed to new allocated request and triggered LBUG on assert
 	     req->rq_ptlrpcd_data != NULL. But this member used only for wakeup
 	     ptlrpcd set if request is changed and can be safety changed to use
 	     rq_set directly.
@@ -200,7 +200,7 @@ Details    : Change the structure of stats under obdfilter and mds to
 			|   + uuids
 			+- nid#2...
 			+- clear
-	     The "uuid"s file would list the uuids of _active_ exports. 
+	     The "uuid"s file would list the uuids of _active_ exports.
 	     And the clear entry is to clear all stats and stale nids.
 
 Severity   : normal
@@ -234,21 +234,21 @@ Severity   : normal
 Bugzilla   : 12749
 Description: Root Squash Functionality
 Details    : Implementation of NFS-like root squash capability. Specifically,
-             don't allow someone with root access on a client node to be able
-             to manipulate files owned by root on a server node.
+	     don't allow someone with root access on a client node to be able
+	     to manipulate files owned by root on a server node.
 
 Severity   : normal
 Bugzilla   : 10718
 Description: Slow trucate/writes to huge files at high offsets.
 Details    : Directly associate cached pages to lock that protect those pages,
-             this allows us to quickly find what pages to write and remove
+	     this allows us to quickly find what pages to write and remove
 	     once lock callback is received.
 
 Severity   : normal
 Bugzilla   : 14379
 Description: Too many locks accumulating on client during NFS usage
 Details    : mds_open improperly used accmode to find out access mode to a
-             file. Also mdc_intent_lock logic to find out if we already have
+	     file. Also mdc_intent_lock logic to find out if we already have
 	     lock similar to just received was flawed since introduction of
 	     skiplists - locks are now added to the front of the granted
 	     queue.
@@ -268,10 +268,10 @@ Details    : Console messages can now be disabled via lnet.printk.
 
 Severity   : normal
 Bugzilla   : 14614
-Description: User code with malformed file open parameter crashes client node 
+Description: User code with malformed file open parameter crashes client node
 Details    : Before packing join_file req, all the related reference should be
-             checked carefully in case some malformed flags cause fake
-	     join_file req on client.
+	     checked carefully in case some malformed flags cause fake join_file
+	     req on client.
 
 Severity   : normal
 Frequency  : always
@@ -313,6 +313,15 @@ Details    : A lot of unlink operations with concurrent I/O can lead to a
 	     max_rpcs_in_flight per OSC and LDLM_FL_DISCARD_DATA blocking
 	     callbacks are processed in priority.
 
+Severity   : normal
+Frequency  : RHEL4 only
+Bugzilla   : 14618
+Description: mkfs is very slow on IA64/RHEL4
+Details    : A performance regression has been discovered in the MPT Fusion
+	     driver between versions 3.02.73rh and 3.02.99.00rh. As a
+	     consequence, we have downgraded the MPT Fusion driver in the RHEL4
+	     kernel from 3.02.99.00 to 3.02.73 until this problem is fixed.
+
 --------------------------------------------------------------------------------
 
 2007-12-07         Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch b/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7bb3440921a9a3aca5c919f88a128fbcd920c848
--- /dev/null
+++ b/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch
@@ -0,0 +1,27949 @@
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c	1970-01-01 01:00:00.000000000 +0100
+@@ -1,5894 +0,0 @@
+-#define MPT_CSMI_DESCRIPTION "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
+-#define csmisas_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
+-
+-static int csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
+-    u8 VolumeId, pMpiRaidActionReply_t reply);
+-static u8  map_sas_status_to_csmi(u8 mpi_sas_status);
+-
+-/**
+- * reverse_byte_order64
+- *
+- * @data64
+- *
+- **/
+-static u64
+-reverse_byte_order64(u64 data64)
+-{
+-	int i;
+-	u64 rc;
+-	u8  *inWord = (u8*)&data64, *outWord = (u8*)&rc;
+-
+-	for (i = 0 ; i < 8 ; i++)
+-		outWord[i] = inWord[7-i];
+-
+-	return rc;
+-}
+-
+-/**
+- * csmisas_is_sata
+- *
+- * @phys_disk
+- *
+- **/
+-static int
+-csmisas_is_sata(RaidPhysDiskPage0_t *phys_disk)
+-{
+-	if ((phys_disk->ExtDiskIdentifier[0] == 'A') &&
+-	    (phys_disk->ExtDiskIdentifier[1] == 'T') &&
+-	    (phys_disk->ExtDiskIdentifier[2] == 'A'))
+-		return 1;
+-	else
+-		return 0;
+-}
+-
+-/**
+- * csmisas_is_end_device
+- *
+- * @attached
+- *
+- **/
+-static inline int
+-csmisas_is_end_device(struct mptsas_devinfo * attached)
+-{
+-	if ((attached->sas_address) &&
+-	    (attached->device_info &
+-	    MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+-	    ((attached->device_info &
+-	    MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+-	    (attached->device_info &
+-	    MPI_SAS_DEVICE_INFO_STP_TARGET) |
+-	    (attached->device_info &
+-	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+-		return 1;
+-	else
+-		return 0;
+-}
+-
+-/**
+- * csmisas_is_phys_disk
+- *
+- * returns (1) success (0) fail - not a phys disk
+- **/
+-int
+-csmisas_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
+-{
+-	struct inactive_raid_component_info *component_info;
+-	int i;
+-	int rc = 0;
+-
+-	if (!ioc->raid_data.pIocPg3)
+-		goto out;
+-	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-			rc = 1;
+-			goto out;
+-		}
+-	}
+-
+-	/*
+-	 * Check inactive list for matching phys disks
+-	 */
+-	if (list_empty(&ioc->raid_data.inactive_list))
+-		goto out;
+-
+-	down(&ioc->raid_data.inactive_list_mutex);
+-	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+-	    list) {
+-		if ((component_info->d.PhysDiskID == id) &&
+-		    (component_info->d.PhysDiskBus == channel))
+-			rc = 1;
+-	}
+-	up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-	return rc;
+-}
+-
+-/**
+- * csmisas_raid_id_to_num
+- *
+- * Obtains the phys disk num for given H:C:T nexus
+- *
+- * input (channel/id)
+- * output (phys disk number - used by SCSI_IO_PASSTHRU to access hidden component)
+- *
+- * returns - signed return means failure
+- **/
+-s8
+-csmisas_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct inactive_raid_component_info *component_info;
+-	int i;
+-	s8 rc = -ENXIO;
+-
+-	if (!ioc->raid_data.pIocPg3)
+-		goto out;
+-	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-			rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+-			goto out;
+-		}
+-	}
+-
+-	/*
+-	 * Check inactive list for matching phys disks
+-	 */
+-	if (list_empty(&ioc->raid_data.inactive_list))
+-		goto out;
+-
+-	down(&ioc->raid_data.inactive_list_mutex);
+-	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+-	    list) {
+-		if ((component_info->d.PhysDiskID == id) &&
+-		    (component_info->d.PhysDiskBus == channel))
+-			rc = component_info->d.PhysDiskNum;
+-	}
+-	up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-	return rc;
+-}
+-
+-/**
+- * csmisas_get_device_component_by_os
+- *
+- * Obtain device component object by operating system mapping
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct sas_device_info *sas_info, *p;
+-
+-	sas_info = NULL;
+-
+-	down(&ioc->sas_device_info_mutex);
+-	list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-		if (p->os.channel == channel && p->os.id == id) {
+-			sas_info = p;
+-			goto out;
+-		}
+-	}
+-
+- out:
+-	up(&ioc->sas_device_info_mutex);
+-	return sas_info;
+-}
+-
+-/**
+- * csmisas_get_device_component
+- *
+- * Obtain device component object by firmware system mapping
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct sas_device_info *sas_info, *p;
+-
+-	sas_info = NULL;
+-
+-	down(&ioc->sas_device_info_mutex);
+-	list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-		if (p->fw.channel == channel && p->fw.id == id) {
+-			sas_info = p;
+-			goto out;
+-		}
+-	}
+-
+- out:
+-	up(&ioc->sas_device_info_mutex);
+-	return sas_info;
+-}
+-
+-
+-/**
+- * csmisas_get_device_component_by_sas_addr
+- *
+- * Obtain device component object by sas address
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_sas_addr(MPT_ADAPTER *ioc, u64 sas_address)
+-{
+-	struct sas_device_info *sas_info, *p;
+-
+-	sas_info = NULL;
+-
+-	down(&ioc->sas_device_info_mutex);
+-	list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-		dcsmisasprintk((KERN_ERR
+-		    ":%s()"
+-		    " looking for SASAddress=%llX entry SASAddress=%llX\n",
+-		    __FUNCTION__, sas_address, p->sas_address));
+-		if (p->sas_address == sas_address) {
+-			sas_info = p;
+-			dcsmisasprintk((KERN_ERR
+-				":%s()"
+-				" found SASAddress=%llX\n",
+-				__FUNCTION__, sas_address));
+-			goto out;
+-		}
+-	}
+-
+- out:
+-	up(&ioc->sas_device_info_mutex);
+-	return sas_info;
+-}
+-
+-/**
+- * csmisas_send_command_wait
+- *
+- * Send mf to firmware
+- *
+- * @ioc
+- * @mf
+- * @timeout - timeout
+- *
+- *	Return: 0 for success
+- *	non-zero, failure
+- **/
+-static int
+-csmisas_send_command_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout)
+-{
+-	int rc;
+-	int mf_timeout;
+-
+-	mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-	ioc->ioctl->wait_done = 0;
+-	rc = 0;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-	ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout);
+-	ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
+-	ADD_TIMER(&ioc->ioctl->timer);
+-#endif
+-
+-	mpt_put_msg_frame(mptctl_id, ioc, mf);
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-	WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done);
+-#else
+-	if ((wait_event_timeout(mptctl_wait,
+-	    ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) &&
+-	    ioc->ioctl->wait_done != 1 ) {
+-		mpt_free_msg_frame(ioc, mf);
+-		mptctl_timeout_expired(ioc->ioctl);
+-		rc = -1;
+-	}
+-#endif
+-
+-	if (rc != 0)
+-		dfailprintk((KERN_ERR "%s@%d::%s() - "
+-		    "%s IOCTL timeout (%d)\n",
+-		    __FILE__, __LINE__, __FUNCTION__,
+-		    ioc->name, mf_timeout));
+-
+-	return rc;
+-}
+-
+-/**
+- * csmisas_send_handshake_wait
+- *
+- * Handshake a mf to firmware
+- *
+- * @ioc
+- * @mf
+- * @mf_size
+- * @timeout - timeout
+- *
+- *	Return: 0 for success
+- *	non-zero, failure
+- **/
+-static int
+-csmisas_send_handshake_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout)
+-{
+-	int rc;
+-	int mf_timeout;
+-
+-	mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-	ioc->ioctl->wait_done = 0;
+-	rc = 0;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-	ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout);
+-	ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
+-	ADD_TIMER(&ioc->ioctl->timer);
+-#endif
+-
+-	rc = mpt_send_handshake_request(mptctl_id, ioc,
+-	    sizeof(SCSITaskMgmt_t), (u32*)mf,timeout, CAN_SLEEP);
+-	if (rc != 0)
+-		return rc;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-	WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done);
+-#else
+-	if ((wait_event_timeout(mptctl_wait,
+-	    ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) &&
+-	    ioc->ioctl->wait_done != 1 ) {
+-		mpt_free_msg_frame(ioc, mf);
+-		mptctl_timeout_expired(ioc->ioctl);
+-		rc = -1;
+-	}
+-#endif
+-
+-	if (rc != 0)
+-		dfailprintk((KERN_ERR "%s@%d::%s() - "
+-		    "%s IOCTL timeout (%d)\n", __FILE__, __LINE__,
+-		    __FUNCTION__, ioc->name, mf_timeout));
+-
+-	return rc;
+-}
+-
+-/**
+- *	csmisas_get_manufacture_pg0 - Manufacturing Page 0.
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@mfgPage0: read only info set at manufacturing time
+- *
+- *	Return: 0 for success
+- *	-ENOMEM if no memory available
+- *		-EPERM if not allowed due to ISR context
+- *		-EAGAIN if no msg frames currently available
+- *		-EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_manufacture_pg0(MPT_ADAPTER *ioc, ManufacturingPage0_t *mfgPage0)
+-{
+-
+-	ConfigPageHeader_t	 hdr;
+-	CONFIGPARMS		 cfg;
+-	ManufacturingPage0_t	 *buffer = NULL;
+-	dma_addr_t		 dma_handle;
+-	int			 data_sz;
+-	int			 rc;
+-
+-	/*
+-	 * Get Manufacturing Page 0 header
+-	 */
+-	data_sz = 0;
+-	hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
+-	hdr.PageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.pageAddr = 0;
+-	cfg.timeout = 0;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_manufacture_pg0_out;
+-
+-	if (hdr.PageLength == 0) {
+-		rc = -EFAULT;
+-		goto get_manufacture_pg0_out;
+-	}
+-
+-	data_sz = hdr.PageLength * 4;
+-	buffer = (ManufacturingPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-		data_sz, &dma_handle);
+-	if (!buffer) {
+-		rc = -ENOMEM;
+-		goto get_manufacture_pg0_out;
+-	}
+-
+-	memset((u8 *)buffer, 0, data_sz);
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_manufacture_pg0_out;
+-
+-	strncpy(mfgPage0->ChipName, buffer->ChipName, 16);
+-	strncpy(mfgPage0->ChipRevision, buffer->ChipRevision, 8);
+-	strncpy(mfgPage0->BoardName, buffer->BoardName, 16);
+-	strncpy(mfgPage0->BoardAssembly, buffer->BoardAssembly, 16);
+-	strncpy(mfgPage0->BoardTracerNumber, buffer->BoardTracerNumber, 16);
+-
+-	dcsmisasprintk(("ChipName=%s\n",buffer->ChipName));
+-	dcsmisasprintk(("ChipRevision=%s\n",buffer->ChipRevision));
+-	dcsmisasprintk(("BoardName=%s\n",buffer->BoardName));
+-	dcsmisasprintk(("BoardAssembly=%s\n",buffer->BoardAssembly));
+-	dcsmisasprintk(("BoardTracerNumber=%s\n",buffer->BoardTracerNumber));
+-
+- get_manufacture_pg0_out:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, data_sz,
+-		    (u8 *) buffer, dma_handle);
+-
+-
+-	return rc;
+-}
+-
+-/**
+- *	csmisas_get_number_hotspares - returns num hot spares in this ioc
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *
+- *	Return: number of hotspares
+- *
+- **/
+-static int
+-csmisas_get_number_hotspares(MPT_ADAPTER *ioc)
+-{
+-	ConfigPageHeader_t	 hdr;
+-	CONFIGPARMS		 cfg;
+-	IOCPage5_t		 *buffer = NULL;
+-	dma_addr_t		 dma_handle;
+-	int			 data_sz;
+-	int			 rc;
+-
+-	memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-	memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-	rc = 0;
+-	data_sz = 0;
+-	hdr.PageNumber = 5;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto get_ioc_pg5;
+-
+-	if (hdr.PageLength == 0)
+-		goto get_ioc_pg5;
+-
+-	data_sz = hdr.PageLength * 4;
+-	buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-		data_sz, &dma_handle);
+-	if (!buffer)
+-		goto get_ioc_pg5;
+-
+-	memset((u8 *)buffer, 0, data_sz);
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto get_ioc_pg5;
+-
+-	rc = buffer->NumHotSpares;
+-
+- get_ioc_pg5:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, data_sz,
+-		    (u8 *) buffer, dma_handle);
+-
+-	return rc;
+-}
+-
+-
+-/**
+- *	csmisas_get_ioc_pg5 - ioc Page 5 hot spares
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@pIocPage5: ioc page 5
+- *	@data_size: expected data size(units=bytes)
+- *
+- *	Return: 0 for success
+- *	-ENOMEM if no memory available
+- *		-EPERM if not allowed due to ISR context
+- *		-EAGAIN if no msg frames currently available
+- *		-EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5, int data_size)
+-{
+-	ConfigPageHeader_t	 hdr;
+-	CONFIGPARMS		 cfg;
+-	IOCPage5_t		 *buffer = NULL;
+-	dma_addr_t		 dma_handle;
+-	int			 data_sz;
+-	int			 rc;
+-
+-	memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-	memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-	rc = 0;
+-	data_sz = 0;
+-	hdr.PageNumber = 5;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	if (hdr.PageLength == 0) {
+-		rc = -EFAULT;
+-		goto get_ioc_pg5;
+-	}
+-
+-	data_sz = hdr.PageLength * 4;
+-	buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-		data_sz, &dma_handle);
+-	if (!buffer) {
+-		rc = -ENOMEM;
+-		goto get_ioc_pg5;
+-	}
+-
+-	memset((u8 *)buffer, 0, data_sz);
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	memcpy(iocPage5, buffer, data_size);
+-
+- get_ioc_pg5:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, data_sz,
+-		    (u8 *) buffer, dma_handle);
+-
+-	return rc;
+-}
+-
+-/**
+- *	csmisas_sas_device_pg0 - sas device page 0
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@mptsas_devinfo: structure found in mptsas.h
+- *	@form, @form_specific - defines the Page Address field in the config page
+- *		(pls refer to chapter 5.1 in the mpi spec)
+- *
+- *	Return: 0 for success
+- *	-ENOMEM if no memory available
+- *		-EPERM if not allowed due to ISR context
+- *		-EAGAIN if no msg frames currently available
+- *		-EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+-		u32 form, u32 form_specific)
+-{
+-	ConfigExtendedPageHeader_t hdr;
+-	CONFIGPARMS cfg;
+-	SasDevicePage0_t *buffer;
+-	dma_addr_t dma_handle;
+-	u64 sas_address;
+-	int rc;
+-
+-	rc = 0;
+-	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.pageAddr = form + form_specific;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = 10;
+-
+-	memset(device_info, 0, sizeof(struct mptsas_devinfo));
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto out;
+-
+-	if (!hdr.ExtPageLength) {
+-		rc = -ENXIO;
+-		goto out;
+-	}
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev,
+-	    hdr.ExtPageLength * 4, &dma_handle);
+-	if (!buffer) {
+-		rc = -ENOMEM;
+-		goto out;
+-	}
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto out_free_consistent;
+-
+-	device_info->handle = le16_to_cpu(buffer->DevHandle);
+-	device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
+-	device_info->handle_enclosure =
+-	    le16_to_cpu(buffer->EnclosureHandle);
+-	device_info->slot = le16_to_cpu(buffer->Slot);
+-	device_info->phy_id = buffer->PhyNum;
+-	device_info->port_id = buffer->PhysicalPort;
+-	device_info->id = buffer->TargetID;
+-	device_info->channel = buffer->Bus;
+-	memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
+-	device_info->sas_address = le64_to_cpu(sas_address);
+-	device_info->device_info =
+-	    le32_to_cpu(buffer->DeviceInfo);
+-
+- out_free_consistent:
+-	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-			    buffer, dma_handle);
+- out:
+-	return rc;
+-}
+-
+-/**
+- * Routine for the CSMI Sas Get Driver Info command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_driver_info(unsigned long arg)
+-{
+-
+-	CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_DRIVER_INFO_BUFFER	karg;
+-	MPT_ADAPTER	*ioc = NULL;
+-	int		iocnum;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-	      "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Fill in the data and return the structure to the calling
+-	 * program
+-	 */
+-	memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
+-	    sizeof(MPT_MISCDEV_BASENAME));
+-	memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
+-	    sizeof(MPT_CSMI_DESCRIPTION));
+-
+-	karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
+-	karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
+-	karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
+-	karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
+-
+-	karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
+-	karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-		sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		   "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_cntlr_config(unsigned long arg)
+-{
+-
+-	CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_CNTLR_CONFIG_BUFFER	karg;
+-	MPT_ADAPTER	*ioc = NULL;
+-	int		iocnum;
+-	int		ii,msize,psize;
+-	unsigned int 	reg;
+-	u32      	l;
+-	ManufacturingPage0_t mfgPage0;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-	     "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-	      "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Clear the struct before filling in data. */
+-	memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
+-
+-	/* Fill in the data and return the structure to the calling
+-	 * program
+-	 */
+-
+-	/* Get Base IO and Mem Mapped Addresses. */
+-msize = psize = 0;
+-for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
+-		reg = PCI_BASE_ADDRESS_0 + (ii << 2);
+-		pci_read_config_dword(ioc->pcidev, reg, &l);
+-
+-		if ((l & PCI_BASE_ADDRESS_SPACE) ==
+-                       PCI_BASE_ADDRESS_SPACE_MEMORY) {
+-		    if(msize)
+-                         continue;
+-	            msize=1;
+-		karg.Configuration.BaseMemoryAddress.uLowPart =
+-			    l & PCI_BASE_ADDRESS_MEM_MASK;
+-
+-		if ((l & (PCI_BASE_ADDRESS_SPACE |
+-                   PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+-                   == (PCI_BASE_ADDRESS_SPACE_MEMORY |
+-                   PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+-                     pci_read_config_dword(ioc->pcidev, reg+4, &l);
+-                     karg.Configuration.BaseMemoryAddress.uHighPart = l;
+-                  }
+-               }
+-
+-
+-                  else {
+-		        if(psize)
+-                       continue;
+-                       psize=1;
+-			karg.Configuration.uBaseIoAddress =
+-			    l & PCI_BASE_ADDRESS_IO_MASK;
+-		}
+-
+-	}
+-
+-	karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
+-	    (ioc->pcidev->subsystem_vendor);
+-
+-	karg.Configuration.usSlotNumber =
+-	    (ioc->pci_slot_number = 0xff) ?
+-	    SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
+-	karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
+-	karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
+-	karg.Configuration.BusAddress.PciAddress.bBusNumber =
+-	    ioc->pcidev->bus->number;
+-	karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
+-	    PCI_SLOT(ioc->pcidev->devfn);
+-	karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
+-	    PCI_FUNC(ioc->pcidev->devfn);
+-	karg.Configuration.BusAddress.PciAddress.bReserved = 0;
+-	if (!csmisas_get_manufacture_pg0(ioc, &mfgPage0))
+-		memcpy( &karg.Configuration.szSerialNumber,
+-		    mfgPage0.BoardTracerNumber, 16 );
+-	karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
+-	karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
+-	karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
+-	karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
+-	karg.Configuration.usBIOSMajorRevision =
+-	    (ioc->biosVersion & 0xFF000000) >> 24;
+-	karg.Configuration.usBIOSMinorRevision =
+-	    (ioc->biosVersion & 0x00FF0000) >> 16;
+-	karg.Configuration.usBIOSBuildRevision =
+-	    (ioc->biosVersion & 0x0000FF00) >> 8;
+-	karg.Configuration.usBIOSReleaseRevision =
+-	    (ioc->biosVersion & 0x000000FF);
+-	karg.Configuration.uControllerFlags = CSMI_SAS_CNTLR_SAS_HBA |
+-	    CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE |
+-	    CSMI_SAS_CNTLR_FWD_SRESET ;
+-
+-	/*
+-	 * Enabling CSMI_SAS_CNTLR_SAS_RAID bit when IR fw detected
+-	 */
+-	if (ioc->ir_firmware)
+-		karg.Configuration.uControllerFlags |= CSMI_SAS_CNTLR_SAS_RAID;
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* All Rrom entries will be zero. Skip them. */
+-	/* bReserved will also be zeros. */
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-		sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		"Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Controller Status command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_cntlr_status(unsigned long arg)
+-{
+-
+-	CSMI_SAS_CNTLR_STATUS_BUFFER  __user *uarg = (void __user *) arg;
+-	MPT_ADAPTER		*ioc = NULL;
+-	CSMI_SAS_CNTLR_STATUS_BUFFER	karg;
+-	int			iocnum;
+-	int			rc;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-	     "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Fill in the data and return the structure to the calling
+-	 * program
+-	 */
+-
+-	rc = mpt_GetIocState(ioc, 1);
+-	switch (rc) {
+-	case MPI_IOC_STATE_OPERATIONAL:
+-		karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_GOOD;
+-		karg.Status.uOfflineReason = 0;
+-		break;
+-
+-	case MPI_IOC_STATE_FAULT:
+-		karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
+-		karg.Status.uOfflineReason = 0;
+-		break;
+-
+-	case MPI_IOC_STATE_RESET:
+-	case MPI_IOC_STATE_READY:
+-	default:
+-		karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_OFFLINE;
+-		karg.Status.uOfflineReason =
+-		    CSMI_SAS_OFFLINE_REASON_INITIALIZING;
+-		break;
+-	}
+-
+-	memset(&karg.Status.bReserved, 0, 28);
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-		sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		    "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Phy Info command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_phy_info(unsigned long arg)
+-{
+-	CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_PHY_INFO_BUFFER  karg;
+-	MPT_ADAPTER		*ioc = NULL;
+-	ConfigExtendedPageHeader_t  hdr;
+-	CONFIGPARMS		cfg;
+-	SasIOUnitPage0_t	*sasIoUnitPg0;
+-	dma_addr_t		sasIoUnitPg0_dma;
+-	int			sasIoUnitPg0_data_sz;
+-	SasPhyPage0_t		*sasPhyPg0;
+-	dma_addr_t		sasPhyPg0_dma;
+-	int			sasPhyPg0_data_sz;
+-	u16			protocol;
+-	int			iocnum;
+-	int			rc;
+-	int			ii;
+-	u64			sas_address;
+-	struct mptsas_devinfo	device_info;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-	sasIoUnitPg0=NULL;
+-	sasPhyPg0=NULL;
+-	sasIoUnitPg0_data_sz=0;
+-	sasPhyPg0_data_sz=0;
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		"Unable to read in csmisas_get_phy_info_buffer struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Fill in the data and return the structure to the calling
+-	 * program
+-	 */
+-	memset(&karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO));
+-
+-	/* Issue a config request to get the number of phys
+-	 */
+-	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((
+-		    ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto sas_get_phy_info_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto sas_get_phy_info_exit;
+-	}
+-
+-	sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
+-	rc = -ENOMEM;
+-
+-	sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-	    sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
+-
+-	if (!sasIoUnitPg0) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto sas_get_phy_info_exit;
+-	}
+-
+-	memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
+-	cfg.physAddr = sasIoUnitPg0_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((
+-		    ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto sas_get_phy_info_exit;
+-	}
+-
+-	/* Number of Phys. */
+-	karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
+-
+-	/* Fill in information for each phy. */
+-	for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) {
+-
+-/* EDM : dump IO Unit Page 0 data*/
+-		dcsmisasprintk(("---- IO UNIT PAGE 0 ------------\n"));
+-		dcsmisasprintk(("Handle=0x%X\n",
+-		    le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
+-		dcsmisasprintk(("Controller Handle=0x%X\n",
+-		    le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
+-		dcsmisasprintk(("Port=0x%X\n",
+-		    sasIoUnitPg0->PhyData[ii].Port));
+-		dcsmisasprintk(("Port Flags=0x%X\n",
+-		    sasIoUnitPg0->PhyData[ii].PortFlags));
+-		dcsmisasprintk(("PHY Flags=0x%X\n",
+-		    sasIoUnitPg0->PhyData[ii].PhyFlags));
+-		dcsmisasprintk(("Negotiated Link Rate=0x%X\n",
+-		    sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
+-		dcsmisasprintk(("Controller PHY Device Info=0x%X\n",
+-		    le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
+-		dcsmisasprintk(("DiscoveryStatus=0x%X\n",
+-		    le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
+-		dcsmisasprintk(("\n"));
+-/* EDM : debug data */
+-
+-		/* PHY stuff. */
+-		karg.Information.Phy[ii].bPortIdentifier =
+-		    sasIoUnitPg0->PhyData[ii].Port;
+-
+-		/* Get the negotiated link rate for the phy. */
+-		switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
+-
+-		case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
+-			karg.Information.Phy[ii].bNegotiatedLinkRate =
+-			    CSMI_SAS_PHY_DISABLED;
+-			break;
+-
+-		case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
+-			karg.Information.Phy[ii].bNegotiatedLinkRate =
+-			    CSMI_SAS_LINK_RATE_FAILED;
+-			break;
+-
+-		case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
+-			break;
+-
+-		case MPI_SAS_IOUNIT0_RATE_1_5:
+-			karg.Information.Phy[ii].bNegotiatedLinkRate =
+-			    CSMI_SAS_LINK_RATE_1_5_GBPS;
+-			break;
+-
+-		case MPI_SAS_IOUNIT0_RATE_3_0:
+-			karg.Information.Phy[ii].bNegotiatedLinkRate =
+-			    CSMI_SAS_LINK_RATE_3_0_GBPS;
+-			break;
+-
+-		case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
+-		default:
+-			karg.Information.Phy[ii].bNegotiatedLinkRate =
+-			    CSMI_SAS_LINK_RATE_UNKNOWN;
+-			break;
+-		}
+-
+-		if (sasIoUnitPg0->PhyData[ii].PortFlags &
+-		    MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
+-			karg.Information.Phy[ii].bAutoDiscover =
+-			    CSMI_SAS_DISCOVER_IN_PROGRESS;
+-		} else {
+-			karg.Information.Phy[ii].bAutoDiscover =
+-			    CSMI_SAS_DISCOVER_COMPLETE;
+-		}
+-
+-		/* Issue a config request to get
+-		 * phy information.
+-		 */
+-		hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+-		hdr.ExtPageLength = 0;
+-		hdr.PageNumber = 0;
+-		hdr.Reserved1 = 0;
+-		hdr.Reserved2 = 0;
+-		hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-		hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-		cfg.cfghdr.ehdr = &hdr;
+-		cfg.physAddr = -1;
+-		cfg.pageAddr = ii;
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-		cfg.dir = 0;	/* read */
+-		cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-		if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
+-			dcsmisasprintk((": rc=%x\n",rc));
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto sas_get_phy_info_exit;
+-		}
+-
+-		if (hdr.ExtPageLength == 0) {
+-			dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto sas_get_phy_info_exit;
+-		}
+-
+-		sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
+-		rc = -ENOMEM;
+-
+-		sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
+-		    ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
+-
+-		if (! sasPhyPg0) {
+-			dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto sas_get_phy_info_exit;
+-		}
+-
+-		memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
+-		cfg.physAddr = sasPhyPg0_dma;
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-		if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
+-			dcsmisasprintk((": rc=%x\n",rc));
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-			    (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-			goto sas_get_phy_info_exit;
+-		}
+-
+-/* EDM : dump PHY Page 0 data*/
+-		memcpy(&sas_address, &sasPhyPg0->SASAddress, sizeof(u64));
+-		dcsmisasprintk(("---- SAS PHY PAGE 0 ------------\n"));
+-		dcsmisasprintk(("Handle=0x%X\n",
+-		    le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
+-		dcsmisasprintk(("SAS Address=0x%llX\n",
+-		    (unsigned long long)sas_address));
+-		dcsmisasprintk(("Attached PHY Identifier=0x%X\n",
+-		    sasPhyPg0->AttachedPhyIdentifier));
+-		dcsmisasprintk(("Attached Device Info=0x%X\n",
+-		    le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
+-		dcsmisasprintk(("Programmed Link Rate=0x%X\n",
+-		    sasPhyPg0->ProgrammedLinkRate));
+-		dcsmisasprintk(("Hardware Link Rate=0x%X\n",
+-		    sasPhyPg0->HwLinkRate));
+-		dcsmisasprintk(("Change Count=0x%X\n",
+-		    sasPhyPg0->ChangeCount));
+-		dcsmisasprintk(("PHY Info=0x%X\n",
+-		    le32_to_cpu(sasPhyPg0->PhyInfo)));
+-		dcsmisasprintk(("\n"));
+-/* EDM : debug data */
+-
+-		/* save the data */
+-
+-		/* Set Max hardware link rate.
+-		 * This value is hard coded
+-		 * because the HW link rate
+-		 * is currently being
+-		 * overwritten in FW.
+-		 */
+-
+-		/* Set Max hardware link rate. */
+-		switch (sasPhyPg0->HwLinkRate &
+-		    MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+-
+-		case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
+-			karg.Information.Phy[ii].bMaximumLinkRate =
+-			    CSMI_SAS_LINK_RATE_1_5_GBPS;
+-			break;
+-
+-		case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+-			karg.Information.Phy[ii].bMaximumLinkRate =
+-			    CSMI_SAS_LINK_RATE_3_0_GBPS;
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		/* Set Max programmed link rate. */
+-		switch (sasPhyPg0->ProgrammedLinkRate &
+-		    MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+-
+-		case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
+-			karg.Information.Phy[ii].bMaximumLinkRate |=
+-			    (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
+-			break;
+-
+-		case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+-			karg.Information.Phy[ii].bMaximumLinkRate |=
+-			    (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		/* Set Min hardware link rate. */
+-		switch (sasPhyPg0->HwLinkRate &
+-		    MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
+-
+-		case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
+-			karg.Information.Phy[ii].bMinimumLinkRate =
+-			    CSMI_SAS_LINK_RATE_1_5_GBPS;
+-			break;
+-
+-		case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+-			karg.Information.Phy[ii].bMinimumLinkRate =
+-			    CSMI_SAS_LINK_RATE_3_0_GBPS;
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		/* Set Min programmed link rate. */
+-		switch (sasPhyPg0->ProgrammedLinkRate &
+-		    MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
+-
+-		case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
+-			karg.Information.Phy[ii].bMinimumLinkRate |=
+-			    (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
+-			break;
+-
+-		case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+-			karg.Information.Phy[ii].bMinimumLinkRate |=
+-			    (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		karg.Information.Phy[ii].bPhyChangeCount = sasPhyPg0->ChangeCount;
+-		if( sasPhyPg0->PhyInfo & MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY )
+-			karg.Information.Phy[ii].bPhyFeatures = CSMI_SAS_PHY_VIRTUAL_SMP;
+-
+-		/* Fill in Attached Device
+-		 * Initiator Port Protocol.
+-		 * Bits 6:3
+-		 * More than one bit can be set.
+-		 */
+-		protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
+-		karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
+-		      karg.Information.Phy[ii].Attached.bInitiatorPortProtocol =
+-			    CSMI_SAS_PROTOCOL_SSP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
+-		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_STP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
+-		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SMP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
+-		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SATA;
+-
+-		/* Fill in Phy Target Port
+-		 * Protocol. Bits 10:7
+-		 * More than one bit can be set.
+-		 */
+-		protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
+-		karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+-			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SSP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
+-			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_STP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
+-			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SMP;
+-		if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+-			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SATA;
+-
+-
+-		/* Fill in Attached device type */
+-		switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
+-		    MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+-
+-		case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+-			karg.Information.Phy[ii].Attached.bDeviceType =
+-			    CSMI_SAS_NO_DEVICE_ATTACHED;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_END_DEVICE:
+-			karg.Information.Phy[ii].Attached.bDeviceType =
+-			    CSMI_SAS_END_DEVICE;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+-			karg.Information.Phy[ii].Attached.bDeviceType =
+-			    CSMI_SAS_EDGE_EXPANDER_DEVICE;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+-			karg.Information.Phy[ii].Attached.bDeviceType =
+-			    CSMI_SAS_FANOUT_EXPANDER_DEVICE;
+-			break;
+-		}
+-
+-		/* Identify Info. */
+-		switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
+-		    MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+-
+-		case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+-			karg.Information.Phy[ii].Identify.bDeviceType =
+-			    CSMI_SAS_NO_DEVICE_ATTACHED;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_END_DEVICE:
+-			karg.Information.Phy[ii].Identify.bDeviceType =
+-			    CSMI_SAS_END_DEVICE;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+-			karg.Information.Phy[ii].Identify.bDeviceType =
+-			    CSMI_SAS_EDGE_EXPANDER_DEVICE;
+-			break;
+-
+-		case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+-			karg.Information.Phy[ii].Identify.bDeviceType =
+-			    CSMI_SAS_FANOUT_EXPANDER_DEVICE;
+-			break;
+-		}
+-
+-		/* Fill in Phy Initiator Port Protocol. Bits 6:3
+-		 * More than one bit can be set, fall through cases.
+-		 */
+-		protocol = le32_to_cpu(
+-		    sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x78;
+-		karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
+-		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SSP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
+-		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_STP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
+-		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SMP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
+-		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SATA;
+-
+-		/* Fill in Phy Target Port Protocol. Bits 10:7
+-		 * More than one bit can be set, fall through cases.
+-		 */
+-		protocol = le32_to_cpu(
+-		    sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x780;
+-		karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
+-			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SSP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
+-			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_STP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
+-			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SMP;
+-		if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
+-			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-			    CSMI_SAS_PROTOCOL_SATA;
+-
+-		/* Setup SAS Address for the attached device */
+-		if (sasPhyPg0->AttachedDevHandle) {
+-			sas_address = reverse_byte_order64(sas_address);
+-			memcpy(karg.Information.Phy[ii].Attached.bSASAddress,
+-			    &sas_address, sizeof(u64));
+-			karg.Information.Phy[ii].Attached.bPhyIdentifier =
+-			    sasPhyPg0->AttachedPhyIdentifier;
+-		}
+-
+-		/* Setup SAS Address for the parent device */
+-		csmisas_sas_device_pg0(ioc, &device_info,
+-		    (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+-		    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+-		    sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
+-		sas_address = reverse_byte_order64(device_info.sas_address);
+-		memcpy(karg.Information.Phy[ii].Identify.bSASAddress,
+-		    &sas_address, sizeof(u64));
+-		karg.Information.Phy[ii].Identify.bPhyIdentifier = ii;
+-
+-		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-	}
+-
+-sas_get_phy_info_exit:
+-
+-	if (sasIoUnitPg0)
+-		pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
+-		    (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		    "Unable to write out csmisas_get_phy_info_buffer @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set PHY Info command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_phy_info(unsigned long arg)
+-{
+-	CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_SET_PHY_INFO_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-/* TODO - implement IOCTL here */
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-	dcsmisasprintk((": not implemented\n"));
+-
+-// cim_set_phy_info_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_set_phy_info @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_scsi_address(unsigned long arg)
+-{
+-	CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_GET_SCSI_ADDRESS_BUFFER	 karg;
+-	MPT_ADAPTER		*ioc = NULL;
+-	int			iocnum;
+-	u64			sas_address;
+-	struct sas_device_info	*sas_info;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg,
+-	    sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-	      "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* reverse byte order the sas address */
+-	memcpy(&sas_address, karg.bSASAddress, sizeof(u64));
+-	sas_address = reverse_byte_order64(sas_address);
+-
+-	/* Search the list for the matching SAS address. */
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
+-	karg.bPathId = 0;
+-	karg.bTargetId = 0;
+-	karg.bLun = 0;
+-
+-	sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-	if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-		goto csmisas_get_scsi_address_exit;
+-
+-	karg.bPathId = sas_info->os.channel;
+-	karg.bTargetId = sas_info->os.id;
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- csmisas_get_scsi_address_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to write out csmi_sas_get_scsi_address @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_sata_signature(unsigned long arg)
+-{
+-	CSMI_SAS_SATA_SIGNATURE_BUFFER  __user *uarg = (void __user *) arg;
+-	CSMI_SAS_SATA_SIGNATURE_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-	int				rc, jj;
+-	ConfigExtendedPageHeader_t	hdr;
+-	CONFIGPARMS			cfg;
+-	SasPhyPage0_t			*sasPhyPg0;
+-	dma_addr_t			sasPhyPg0_dma;
+-	int				sasPhyPg0_data_sz;
+-	SasDevicePage1_t		*sasDevicePg1;
+-	dma_addr_t			sasDevicePg1_dma;
+-	int				sasDevicePg1_data_sz;
+-	u8				phyId;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-	sasPhyPg0=NULL;
+-	sasPhyPg0_data_sz=0;
+-	sasDevicePg1=NULL;
+-	sasDevicePg1_data_sz=0;
+-
+-	if (copy_from_user(&karg, uarg,
+-	     sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_sata_signature struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-	    "%s::%s() @%d - ioc%d not found!\n",
+-		     __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	phyId = karg.Signature.bPhyIdentifier;
+-	if (phyId >= ioc->num_ports) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
+-		dcsmisasprintk((": phyId >= ioc->num_ports\n"));
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	/* Default to success.*/
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Issue a config request to get the devHandle of the attached device
+-	 */
+-
+-	/* Issue a config request to get phy information. */
+-	hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = phyId;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-
+-	sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
+-	rc = -ENOMEM;
+-
+-	sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-	    sasPhyPg0_data_sz, &sasPhyPg0_dma);
+-
+-	if (! sasPhyPg0) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
+-	cfg.physAddr = sasPhyPg0_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	/* Make sure a SATA device is attached. */
+-	if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
+-	    MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
+-		dcsmisasprintk((": NOT A SATA DEVICE\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	/* Get device page 1 for FIS  signature. */
+-	hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 1 /* page number 1 */;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-
+-	cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+-	    MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
+-	    le16_to_cpu(sasPhyPg0->AttachedDevHandle));
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
+-	rc = -ENOMEM;
+-
+-	sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
+-	    (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
+-
+-	if (! sasDevicePg1) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-	memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
+-	cfg.physAddr = sasDevicePg1_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sata_signature_exit;
+-	}
+-
+-/* EDM : dump Device Page 1 data*/
+-	dcsmisasprintk(("---- SAS DEVICE PAGE 1 ---------\n"));
+-	dcsmisasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle));
+-	dcsmisasprintk(("SAS Address="));
+-	for(jj=0;jj<8;jj++)
+-		dcsmisasprintk(("%02x ",
+-		((u8 *)&sasDevicePg1->SASAddress)[jj]));
+-	dcsmisasprintk(("\n"));
+-	dcsmisasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID));
+-	dcsmisasprintk(("Bus=0x%x\n",sasDevicePg1->Bus));
+-	dcsmisasprintk(("Initial Reg Device FIS="));
+-	for(jj=0;jj<20;jj++)
+-		dcsmisasprintk(("%02x ",
+-		((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
+-	dcsmisasprintk(("\n\n"));
+-/* EDM : debug data */
+-
+-	memcpy(karg.Signature.bSignatureFIS,
+-		sasDevicePg1->InitialRegDeviceFIS,20);
+-
+- cim_sata_signature_exit:
+-
+-	if (sasPhyPg0)
+-		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-
+-	if (sasDevicePg1)
+-		pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
+-		    (u8 *) sasDevicePg1, sasDevicePg1_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to write out csmi_sas_sata_signature @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_device_address(unsigned long arg)
+-{
+-	CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER	 karg;
+-	MPT_ADAPTER		*ioc = NULL;
+-	int			iocnum;
+-	struct sas_device_info	*sas_info;
+-	u64			sas_address;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg,
+-	    sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-	   "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-	    "%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
+-	memset(karg.bSASAddress, 0, sizeof(u64));
+-	memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
+-
+-	/* Search the list for the matching SAS address. */
+-	sas_info = csmisas_get_device_component_by_os(ioc, karg.bPathId,
+-	    karg.bTargetId);
+-	if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-		goto csmisas_get_device_address_exit;
+-
+-	sas_address = reverse_byte_order64(sas_info->sas_address);
+-	memcpy(karg.bSASAddress, &sas_address, sizeof(u64));
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- csmisas_get_device_address_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		"Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Link Errors command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_link_errors(unsigned long arg)
+-{
+-	CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_LINK_ERRORS_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t			*mpi_hdr;
+-	int				iocnum;
+-	int				rc;
+-	ConfigExtendedPageHeader_t	hdr;
+-	CONFIGPARMS			cfg;
+-	SasPhyPage1_t			*sasPhyPage1;
+-	dma_addr_t			sasPhyPage1_dma;
+-	int				sasPhyPage1_data_sz;
+-	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
+-	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
+-	u8				phyId;
+-	u16				ioc_status;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-	sasPhyPage1=NULL;
+-	sasPhyPage1_data_sz=0;
+-
+-	if (copy_from_user(&karg, uarg,
+-	     sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmisas_get_link_errors struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-	    "%s::%s() @%d - ioc%d not found!\n",
+-		     __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	phyId = karg.Information.bPhyIdentifier;
+-	if (phyId >= ioc->num_ports) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
+-		dcsmisasprintk((": phyId >= ioc->num_ports\n"));
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-	/* Default to success.*/
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Issue a config request to get the devHandle of the attached device
+-	 */
+-
+-	/* Issue a config request to get phy information. */
+-	hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 1 /* page number 1*/;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = phyId;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-
+-	sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
+-	rc = -ENOMEM;
+-
+-	sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
+-	    sasPhyPage1_data_sz, &sasPhyPage1_dma);
+-
+-	if (! sasPhyPage1) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-	memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
+-	cfg.physAddr = sasPhyPage1_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		/* Don't check if this failed.  Already in a
+-		 * failure case.
+-		 */
+-		dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
+-		dcsmisasprintk((": rc=%x\n",rc));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-/* EDM : dump PHY Page 1 data*/
+-	dcsmisasprintk(("---- SAS PHY PAGE 1 ------------\n"));
+-	dcsmisasprintk(("Invalid Dword Count=0x%x\n",
+-	    sasPhyPage1->InvalidDwordCount));
+-	dcsmisasprintk(("Running Disparity Error Count=0x%x\n",
+-	    sasPhyPage1->RunningDisparityErrorCount));
+-	dcsmisasprintk(("Loss Dword Synch Count=0x%x\n",
+-	    sasPhyPage1->LossDwordSynchCount));
+-	dcsmisasprintk(("PHY Reset Problem Count=0x%x\n",
+-	    sasPhyPage1->PhyResetProblemCount));
+-	dcsmisasprintk(("\n\n"));
+-/* EDM : debug data */
+-
+-	karg.Information.uInvalidDwordCount =
+-		le32_to_cpu(sasPhyPage1->InvalidDwordCount);
+-	karg.Information.uRunningDisparityErrorCount =
+-		le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
+-	karg.Information.uLossOfDwordSyncCount =
+-		le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
+-	karg.Information.uPhyResetProblemCount =
+-		le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
+-
+-	if (karg.Information.bResetCounts ==
+-	    CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-	/* Clear Error log
+-	 *
+-	 * Issue IOUNIT Control Reqeust Message
+-	 */
+-
+-	/* Get a MF for this command.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-        }
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+-	memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+-	sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+-	sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+-	sasIoUnitCntrReq->PhyNum = phyId;
+-	sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
+-
+-	if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_link_errors_exit;
+-	}
+-
+-	/* process the completed Reply Message Frame */
+-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-		sasIoUnitCntrReply =
+-		    (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
+-		ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
+-		    & MPI_IOCSTATUS_MASK;
+-
+-		if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
+-			dcsmisasprintk((": SAS IO Unit Control: "));
+-			dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-			    sasIoUnitCntrReply->IOCStatus,
+-			    sasIoUnitCntrReply->IOCLogInfo));
+-		}
+-	}
+-
+- cim_get_link_errors_exit:
+-
+-	if (sasPhyPage1)
+-		pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
+-		    (u8 *) sasPhyPage1, sasPhyPage1_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to write out csmisas_get_link_errors @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS SMP Passthru command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_smp_passthru(unsigned long arg)
+-{
+-	CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-	MPT_ADAPTER			*ioc;
+-	CSMI_SAS_SMP_PASSTHRU_BUFFER	 karg;
+-	pSmpPassthroughRequest_t	smpReq;
+-	pSmpPassthroughReply_t		smpReply;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t			*mpi_hdr;
+-	char				*psge;
+-	int				iocnum, flagsLength;
+-	void *				request_data;
+-	dma_addr_t			request_data_dma;
+-	u32				request_data_sz;
+-	void *				response_data;
+-	dma_addr_t			response_data_dma;
+-	u32				response_data_sz;
+-	u16				ioc_status;
+-	u64				sas_address;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	request_data = NULL;
+-	response_data = NULL;
+-	response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
+-	request_data_sz  = karg.Parameters.uRequestLength;
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Make sure the adapter is not being reset. */
+-	if (!ioc->ioctl) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		    "No memory available during driver init.\n",
+-		    __FILE__, __LINE__,__FUNCTION__);
+-		return -ENOMEM;
+-	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
+-		printk(KERN_ERR "%s@%d::%s - "
+-		    "Busy with IOC Reset \n",
+-		    __FILE__, __LINE__,__FUNCTION__);
+-		return -EBUSY;
+-	}
+-
+-	/* Default to success.*/
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Do some error checking on the request. */
+-	if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	/* Get a free request frame and save the message context.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_smp_passthru_exit;
+-        }
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	smpReq = (pSmpPassthroughRequest_t ) mf;
+-
+-	memset(smpReq,0,ioc->req_sz);
+-
+-	memcpy(&sas_address, karg.Parameters.bDestinationSASAddress,
+-	    sizeof(u64));
+-	sas_address = cpu_to_le64(reverse_byte_order64(sas_address));
+-	memcpy(&smpReq->SASAddress, &sas_address, sizeof(u64));
+-
+-	/* Fill in smp request. */
+-	smpReq->PhysicalPort = karg.Parameters.bPortIdentifier;
+-	smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
+-	smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
+-	smpReq->ConnectionRate = karg.Parameters.bConnectionRate;
+-	smpReq->MsgContext = mpi_hdr->MsgContext;
+-	smpReq->Reserved2 = 0;
+-	smpReq->Reserved3 = 0;
+-
+-	/*
+-	 * Prepare the necessary pointers to run
+-	 * through the SGL generation
+-	 */
+-
+-	psge = (char *)&smpReq->SGL;
+-
+-	/* setup the *Request* payload SGE */
+-	flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-		MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+-		MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+-		MPI_SGE_FLAGS_HOST_TO_IOC |
+-		MPI_SGE_FLAGS_END_OF_BUFFER;
+-
+-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+-		flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+-	}
+-	flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+-	flagsLength |= request_data_sz;
+-
+-	request_data = pci_alloc_consistent(
+-	    ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-	if (!request_data) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		mpt_free_msg_frame(ioc, mf);
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	mpt_add_sge(psge, flagsLength, request_data_dma);
+-	psge += (sizeof(u32) + sizeof(dma_addr_t));
+-
+-	memcpy(request_data,&karg.Parameters.Request,request_data_sz);
+-
+-	/* setup the *Response* payload SGE */
+-	response_data = pci_alloc_consistent(
+-	    ioc->pcidev, response_data_sz, &response_data_dma);
+-
+-	if (!response_data) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		mpt_free_msg_frame(ioc, mf);
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-		MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+-		MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+-		MPI_SGE_FLAGS_IOC_TO_HOST |
+-		MPI_SGE_FLAGS_END_OF_BUFFER;
+-
+-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+-		flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+-	}
+-
+-	flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+-	flagsLength |= response_data_sz;
+-
+-	mpt_add_sge(psge, flagsLength, response_data_dma);
+-
+-	if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
+-		dcsmisasprintk((": SMP Passthru: oh no, there is no reply!!"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	/* process the completed Reply Message Frame */
+-	smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame;
+-	ioc_status = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-	if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
+-	    (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		dcsmisasprintk((": SMP Passthru: "));
+-		dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
+-		    le16_to_cpu(smpReply->IOCStatus),
+-		    le32_to_cpu(smpReply->IOCLogInfo),
+-		    smpReply->SASStatus));
+-		goto cim_smp_passthru_exit;
+-	}
+-
+-	karg.Parameters.bConnectionStatus =
+-	    map_sas_status_to_csmi(smpReply->SASStatus);
+-
+-
+-	if (le16_to_cpu(smpReply->ResponseDataLength)) {
+-		karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
+-		memcpy(&karg.Parameters.Response,
+-		    response_data, le16_to_cpu(smpReply->ResponseDataLength));
+-	}
+-
+- cim_smp_passthru_exit:
+-
+-	if (request_data)
+-		pci_free_consistent(ioc->pcidev, request_data_sz,
+-		    (u8 *)request_data, request_data_dma);
+-
+-	if (response_data)
+-		pci_free_consistent(ioc->pcidev, response_data_sz,
+-		    (u8 *)response_data, response_data_dma);
+-
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_smp_passthru @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk((": %s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS SSP Passthru command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int csmisas_ssp_passthru(unsigned long arg)
+-{
+-	CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_SSP_PASSTHRU_BUFFER	 karg_hdr, * karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	pSCSIIORequest_t		pScsiRequest;
+-	pSCSIIOReply_t			pScsiReply;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t 			*mpi_hdr;
+-	int				iocnum,ii;
+-	u64				sas_address;
+-	u16				req_idx;
+-	char				*psge;
+-	int				flagsLength;
+-	void *				request_data;
+-	dma_addr_t			request_data_dma;
+-	u32				request_data_sz;
+-	int				malloc_data_sz;
+-	int				memory_pages;
+-	u16				ioc_status;
+-	u8 				volume_id;
+-	u8				volume_bus;
+-	u8				is_hidden_raid_component;
+-	u8				channel;
+-	u8				id;
+-	struct sas_device_info		*sas_info;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	request_data = NULL;
+-	request_data_sz = karg_hdr.Parameters.uDataLength;
+-	channel = 0;
+-	id = 0;
+-	volume_id = 0;
+-	volume_bus = 0;
+-	is_hidden_raid_component = 0;
+-
+-	malloc_data_sz = (request_data_sz +
+-	    offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer));
+-	memory_pages = get_order(malloc_data_sz);
+-	karg = (CSMI_SAS_SSP_PASSTHRU_BUFFER *)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!karg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to malloc SAS_SSP_PASSTHRU_BUFFER "
+-			"malloc_data_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			malloc_data_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-
+-	dcsmisasprintk((KERN_ERR "%s@%d::%s() - "
+-			"malloc'ed SAS_SSP_PASSTHRU_BUFFER "
+-			"malloc_data_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			malloc_data_sz, memory_pages));
+-
+-	memset(karg, 0, sizeof(*karg));
+-
+-	if (copy_from_user(karg, uarg, request_data_sz +
+-	    offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	/*
+-	 * some checks of the incoming frame
+-	 */
+-	if ( offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer) +
+-	    request_data_sz - sizeof(IOCTL_HEADER) >
+-	    karg->IoctlHeader.Length ) {
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s()"
+-		    " @%d - expected datalen incorrect!\n",
+-		    __FILE__, __FUNCTION__, __LINE__));
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s()"
+-		    " @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	/* Default to success.
+-	 */
+-	karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Neither a phy nor a port has been selected.
+-	 */
+-	if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
+-		(karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s()"
+-		    " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
+-		    __FILE__, __FUNCTION__, __LINE__));
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	/* A phy has been selected. Verify that it's valid.
+-	 */
+-	if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-
+-		/* Is the phy in range? */
+-		if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
+-			dcsmisasprintk((": phyId >= ioc->num_ports (%d %d)\n",
+-			    karg->Parameters.bPhyIdentifier,
+-			    ioc->num_ports));
+-			karg->IoctlHeader.ReturnCode =
+-			    CSMI_SAS_PHY_DOES_NOT_EXIST;
+-			goto cim_ssp_passthru_exit;
+-		}
+-	}
+-
+-	if(karg->Parameters.bAdditionalCDBLength) {
+-	/* TODO - SCSI IO (32) Request Message support
+-	 */
+-		dcsmisasprintk((": greater than 16-byte cdb is not supported!\n"));
+-		karg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	/* we will use SAS address to resolve the scsi adddressing
+-	 */
+-	memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
+-	    sizeof(u64));
+-	sas_address = reverse_byte_order64(sas_address);
+-
+-	/* Search the list for the matching SAS address.
+-	 */
+-	sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-	if (!sas_info || sas_info->is_cached) {
+-		/*
+-		 *Invalid SAS address
+-		 */
+-		karg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s()"
+-		    " @%d - couldn't find associated SASAddress=%llX!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, sas_address));
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	id = sas_info->fw.id;
+-	channel = sas_info->fw.channel;
+-
+-	if (csmisas_is_phys_disk(ioc, channel, id)) {
+-		id = csmisas_raid_id_to_num(ioc, channel, id);
+-		channel = 0;
+-		is_hidden_raid_component = 1;
+-	}
+-
+-	/* Get a free request frame and save the message context.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_ssp_passthru_exit;
+-        }
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	pScsiRequest = (pSCSIIORequest_t) mf;
+-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-	memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
+-
+-	/* Fill in SCSI IO (16) request.
+-	 */
+-
+-	pScsiRequest->Function = (is_hidden_raid_component == 1) ?
+-	    MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
+-	pScsiRequest->TargetID = id;
+-	pScsiRequest->Bus = channel;
+-	memcpy(pScsiRequest->LUN, &karg->Parameters.bLun, 8);
+-	pScsiRequest->CDBLength = karg->Parameters.bCDBLength;
+-	pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
+-	pScsiRequest->MsgContext = mpi_hdr->MsgContext;
+-	memcpy(pScsiRequest->CDB, karg->Parameters.bCDB,
+-	    pScsiRequest->CDBLength);
+-
+-	#if defined(MPT_DEBUG_CSMISAS)
+-	{
+-	int k;
+-		printk("\tchannel=%d id=%d ", sas_info->fw.channel,
+-		    sas_info->fw.id);
+-		if (is_hidden_raid_component)
+-			printk("num_id=%d ", id);
+-		printk("\n");
+-		printk("\tcdb_len = %d data_len=%d\n",
+-		    pScsiRequest->CDBLength, request_data_sz);
+-		printk("\t");
+-		for (k = 0; k < pScsiRequest->CDBLength; ++k)
+-			printk(" %02x", pScsiRequest->CDB[k]);
+-		printk("\n");
+-	}
+-	#endif
+-
+-	/* direction
+-	 */
+-	if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
+-		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-	} else if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
+-		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
+-	} else if ((karg->Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
+-	    (!karg->Parameters.uDataLength)) {
+-		/* no data transfer
+-		 */
+-		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
+-	} else {
+-		/* no direction specified
+-		 */
+-		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-		pScsiRequest->MsgFlags =
+-		    MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
+-	}
+-
+-	pScsiRequest->MsgFlags |= mpt_msg_flags();
+-	/* task attributes
+-	 */
+-	if((karg->Parameters.uFlags && 0xFF) == 0) {
+-		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
+-	} else if (karg->Parameters.uFlags &
+-	    CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
+-		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
+-	} else if (karg->Parameters.uFlags &
+-	    CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
+-		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
+-	} else if (karg->Parameters.uFlags &
+-	    CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
+-		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
+-	} else {
+-		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
+-	}
+-
+-	/* setup sense
+-	 */
+-	pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
+-	pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
+-	    (req_idx * MPT_SENSE_BUFFER_ALLOC));
+-
+-	/* setup databuffer sg, assuming we fit everything one contiguous buffer
+-	 */
+-	psge = (char *)&pScsiRequest->SGL;
+-
+-	if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
+-		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+-	} else if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
+-		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
+-	}else {
+-		flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-				MPI_SGE_FLAGS_DIRECTION |
+-				mpt_addr_size() )
+-				<< MPI_SGE_FLAGS_SHIFT;
+-	}
+-	flagsLength |= request_data_sz;
+-
+-	if ( request_data_sz > 0) {
+-		request_data = pci_alloc_consistent(
+-		    ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-		if (request_data == NULL) {
+-			dcsmisasprintk((": pci_alloc_consistent: FAILED "
+-			    "request_data_sz=%d\n", request_data_sz));
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			mpt_free_msg_frame(ioc, mf);
+-			goto cim_ssp_passthru_exit;
+-		}
+-
+-		mpt_add_sge(psge, flagsLength, request_data_dma);
+-		if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
+-			memcpy(request_data, karg->bDataBuffer, request_data_sz);
+-	} else {
+-		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
+-	}
+-
+-	if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_ssp_passthru_exit;
+-	}
+-
+-	memset(&karg->Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
+-	karg->Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
+-	karg->Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
+-	karg->Status.bStatus = GOOD;
+-	karg->Status.bResponseLength[0] = 0;
+-	karg->Status.bResponseLength[1] = 0;
+-	karg->Status.uDataBytes = request_data_sz;
+-
+-	/* process the completed Reply Message Frame */
+-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-		pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame;
+-		karg->Status.bStatus = pScsiReply->SCSIStatus;
+-		karg->Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
+-		    request_data_sz);
+-		ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-		if (pScsiReply->SCSIState ==
+-		    MPI_SCSI_STATE_AUTOSENSE_VALID) {
+-			karg->Status.bConnectionStatus =
+-			    CSMI_SAS_SSP_SENSE_DATA_PRESENT;
+-			karg->Status.bResponseLength[0] =
+-				(u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
+-			memcpy(karg->Status.bResponse,
+-			    ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount));
+-		} else if(pScsiReply->SCSIState ==
+-		    MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
+-			karg->Status.bDataPresent =
+-			    CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
+-			karg->Status.bResponseLength[0] =
+-				sizeof(pScsiReply->ResponseInfo);
+-			for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
+-				karg->Status.bResponse[ii] =
+-				((u8*)&pScsiReply->ResponseInfo)[
+-				    (sizeof(pScsiReply->ResponseInfo)-1)-ii];
+-			}
+-		} else if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
+-		    (ioc_status !=  MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
+-		    (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			dcsmisasprintk((": SCSI IO : "));
+-			dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-			    pScsiReply->IOCStatus,
+-			    pScsiReply->IOCLogInfo));
+-		}
+-	}
+-
+-	if ((karg->Status.uDataBytes) && (request_data) &&
+-	    (karg->Parameters.uFlags & CSMI_SAS_SSP_READ)) {
+-		if (copy_to_user((char *)uarg->bDataBuffer,
+-		    request_data, karg->Status.uDataBytes)) {
+-			printk(KERN_ERR "%s@%d::%s - "
+-			    "Unable to write data to user %p\n",
+-			    __FILE__, __LINE__,__FUNCTION__,
+-			    (void*)karg->bDataBuffer);
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		}
+-	}
+-
+- cim_ssp_passthru_exit:
+-
+-
+-	if (request_data)
+-		pci_free_consistent(ioc->pcidev, request_data_sz,
+-		    (u8 *)request_data, request_data_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, karg,
+-	    offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_ssp_passthru @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)karg, memory_pages);
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS STP Passthru command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_stp_passthru(unsigned long arg)
+-{
+-	CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_STP_PASSTHRU_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	pSataPassthroughRequest_t  	pSataRequest;
+-	pSataPassthroughReply_t		pSataReply;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t 			*mpi_hdr;
+-	int				iocnum;
+-	u32				data_sz;
+-	u64				sas_address;
+-	u16				req_idx;
+-	char				*psge;
+-	int				flagsLength;
+-	void *				request_data;
+-	dma_addr_t			request_data_dma;
+-	u32				request_data_sz;
+-	u8				channel;
+-	u8				id;
+-	u8 				volume_id;
+-	u8				volume_bus;
+-	struct sas_device_info		*sas_info;
+-	u16				ioc_status;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	request_data=NULL;
+-	request_data_sz = karg.Parameters.uDataLength;
+-	volume_id = 0;
+-	volume_bus = 0;
+-	channel = 0;
+-	id = 0;
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Default to success.
+-	 */
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* Neither a phy nor a port has been selected.
+-	 */
+-	if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
+-		(karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
+-		    __FILE__,__FUNCTION__, __LINE__));
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	/* A phy has been selected. Verify that it's valid.
+-	 */
+-	if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-
+-		/* Is the phy in range? */
+-		if (karg.Parameters.bPhyIdentifier >= ioc->num_ports) {
+-			karg.IoctlHeader.ReturnCode =
+-			    CSMI_SAS_PHY_DOES_NOT_EXIST;
+-			goto cim_stp_passthru_exit;
+-		}
+-	}
+-
+-	/* some checks of the incoming frame
+-	 */
+-	if (request_data_sz > 0xFFFF) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - uDataLength > 0xFFFF!\n",
+-		    __FILE__, __FUNCTION__, __LINE__));
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
+-	    sizeof(IOCTL_HEADER) - sizeof(u8*) +
+-	    request_data_sz;
+-
+-	if ( data_sz > karg.IoctlHeader.Length ) {
+-		karg.IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - expected datalen incorrect!\n",
+-		    __FILE__, __FUNCTION__,__LINE__));
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-
+-	/* we will use SAS address to resolve the scsi adddressing
+-	 */
+-	memcpy(&sas_address, karg.Parameters.bDestinationSASAddress,
+-	    sizeof(u64));
+-	sas_address = reverse_byte_order64(sas_address);
+-
+-	/* Search the list for the matching SAS address.
+-	 */
+-	sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-	if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) {
+-		/*
+-		 *Invalid SAS address
+-		 */
+-		karg.IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s()"
+-		    " @%d - couldn't find associated SASAddress=%llX!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, sas_address));
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	id = sas_info->fw.id;
+-	channel = sas_info->fw.channel;
+-
+-	/* check that this is an STP or SATA target device
+-	 */
+-	if ( !(sas_info->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
+-	     !(sas_info->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
+-		karg.IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	/* Get a free request frame and save the message context.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_stp_passthru_exit;
+-        }
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	pSataRequest = (pSataPassthroughRequest_t) mf;
+-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-	memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
+-
+-	pSataRequest->TargetID = id;
+-	pSataRequest->Bus = channel;
+-	pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
+-	pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags);
+-	pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate;
+-	pSataRequest->MsgContext = mpi_hdr->MsgContext;
+-	pSataRequest->DataLength = cpu_to_le32(request_data_sz);
+-	pSataRequest->MsgFlags = 0;
+-	memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20);
+-
+-	psge = (char *)&pSataRequest->SGL;
+-	if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
+-		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+-	} else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) {
+-		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
+-	}else {
+-		flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-				MPI_SGE_FLAGS_DIRECTION |
+-				mpt_addr_size() )
+-				<< MPI_SGE_FLAGS_SHIFT;
+-	}
+-
+-	flagsLength |= request_data_sz;
+-	if (request_data_sz > 0) {
+-		request_data = pci_alloc_consistent(
+-		    ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-		if (request_data == NULL) {
+-			dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			mpt_free_msg_frame(ioc, mf);
+-			goto cim_stp_passthru_exit;
+-		}
+-
+-		mpt_add_sge(psge, flagsLength, request_data_dma);
+-		if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
+-			if (copy_from_user(request_data,
+-			    karg.bDataBuffer,
+-			    request_data_sz)) {
+-				printk(KERN_ERR
+-				    "%s::%s() @%d - Unable to read user data "
+-				    "struct @ %p\n",
+-				    __FILE__, __FUNCTION__, __LINE__,
+-				    (void*)karg.bDataBuffer);
+-				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-				mpt_free_msg_frame(ioc, mf);
+-				goto cim_stp_passthru_exit;
+-			}
+-		}
+-	} else {
+-		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
+-	}
+-
+-	if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
+-
+-	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
+-		dcsmisasprintk((": STP Passthru: oh no, there is no reply!!"));
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_stp_passthru_exit;
+-	}
+-
+-	/* process the completed Reply Message Frame */
+-	pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame;
+-	ioc_status = le16_to_cpu(pSataReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-	if (ioc_status != MPI_IOCSTATUS_SUCCESS &&
+-	    ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		dcsmisasprintk((": STP Passthru: "));
+-		dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
+-		    le16_to_cpu(pSataReply->IOCStatus),
+-		    le32_to_cpu(pSataReply->IOCLogInfo),
+-		    pSataReply->SASStatus));
+-	}
+-
+-	karg.Status.bConnectionStatus =
+-	    map_sas_status_to_csmi(pSataReply->SASStatus);
+-
+-	memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20);
+-
+-	/*
+-	 * for now, just zero out uSCR array,
+-	 * then copy the one dword returned
+-	 * in the reply frame into uSCR[0]
+-	 */
+-	memset( karg.Status.uSCR, 0, 64);
+-	karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
+-
+-	if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
+-	    (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) {
+-		karg.Status.uDataBytes =
+-		    min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
+-		if (copy_to_user((char *)uarg->bDataBuffer,
+-		    request_data, karg.Status.uDataBytes)) {
+-			printk(KERN_ERR "%s::%s() @%d - "
+-			    "Unable to write data to user %p\n",
+-			    __FILE__, __FUNCTION__, __LINE__,
+-			    (void*)karg.bDataBuffer);
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		}
+-	}
+-
+- cim_stp_passthru_exit:
+-
+-	if (request_data)
+-		pci_free_consistent(ioc->pcidev, request_data_sz,
+-		    (u8 *)request_data, request_data_dma);
+-
+-	/* Copy th data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-	    offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_ssp_passthru @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk((": %s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Firmware Download command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_firmware_download(unsigned long arg)
+-{
+-	CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-	pMpiFwHeader_t			pFwHeader=NULL;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg,
+-		sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_firmware_download struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	/* Default to success.*/
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-	karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
+-	karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
+-
+-	/* some checks of the incoming frame */
+-	if ((karg.Information.uBufferLength +
+-	    sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
+-	    karg.IoctlHeader.Length) {
+-		karg.IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-		goto cim_firmware_download_exit;
+-	}
+-
+-	if ( karg.Information.uDownloadFlags &
+-	    (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-		goto cim_firmware_download_exit;
+-	}
+-
+-	/* now we need to alloc memory so we can pull in the
+-	 * fw image attached to end of incoming packet.
+-	 */
+-	pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
+-	if (!pFwHeader){
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-		goto cim_firmware_download_exit;
+-	}
+-	memset(pFwHeader, 0, sizeof(*pFwHeader));
+-
+-	if (copy_from_user(pFwHeader, uarg->bDataBuffer,
+-		karg.Information.uBufferLength)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in pFwHeader @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
+-	    (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
+-	    (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
+-		// the signature check failed
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-		goto cim_firmware_download_exit;
+-	}
+-
+-	if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
+-	    uarg->bDataBuffer, karg.Information.uBufferLength)
+-	    != 0) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-		karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
+-		goto cim_firmware_download_exit;
+-	}
+-
+-	if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
+-	    (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
+-		if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-			karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
+-		}
+-	}
+-
+- cim_firmware_download_exit:
+-
+-	if(pFwHeader)
+-		kfree(pFwHeader);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_firmware_download @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Info command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_info(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_INFO_BUFFER __user *uarg =  (void __user *) arg;
+-	CSMI_SAS_RAID_INFO_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-	u32				raidFlags;
+-	u8				maxRaidTypes;
+-	u8				maxDrivesPerSet;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-	if (!ioc->raid_data.pIocPg2)
+-		goto csmisas_get_raid_info_out;
+-	karg.Information.uNumRaidSets =
+-	    ioc->raid_data.pIocPg2->NumActiveVolumes;
+-	karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
+-	if( ioc->raid_data.pIocPg6 ) {
+-		// get absolute maximum for all RAID sets
+-		maxDrivesPerSet = ioc->raid_data.pIocPg6->MaxDrivesIS;
+-		maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIM,
+-		    maxDrivesPerSet);
+-		maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIME,
+-		    maxDrivesPerSet);
+-		karg.Information.uMaxDrivesPerSet = maxDrivesPerSet;
+-	}
+-	else
+-		karg.Information.uMaxDrivesPerSet = 8;
+-	// For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
+-	raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
+-	for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
+-		raidFlags &= raidFlags - 1;
+-	karg.Information.bMaxRaidTypes = maxRaidTypes;
+-	// ulMinRaidSetBlocks hard coded to 1MB until available from config page
+-	karg.Information.ulMinRaidSetBlocks.uLowPart = 2048;
+-	karg.Information.ulMinRaidSetBlocks.uHighPart = 0;
+-	karg.Information.ulMaxRaidSetBlocks.uLowPart = 0xffffffff;
+-	if( ioc->raid_data.pIocPg2->CapabilitiesFlags &
+-	    MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING )
+-		karg.Information.ulMaxRaidSetBlocks.uHighPart = 0xffffffff;
+-	else
+-		karg.Information.ulMaxRaidSetBlocks.uHighPart = 0;
+-	karg.Information.uMaxPhysicalDrives =
+-	    ioc->raid_data.pIocPg2->MaxPhysDisks;
+-	karg.Information.uMaxExtents = 1;
+-	karg.Information.uMaxModules = 0;
+-	karg.Information.uMaxTransformationMemory = 0;
+-	karg.Information.uChangeCount = ioc->csmi_change_count;
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-csmisas_get_raid_info_out:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_get_raid_info @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- *	csmisas_do_raid - Format and Issue a RAID volume request message.
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@action: What do be done.
+- *	@PhysDiskNum: Logical target id.
+- *	@VolumeBus: Target locations bus.
+- *	@VolumeId: Volume id
+- *
+- *	Returns: < 0 on a fatal error
+- *		0 on success
+- *
+- *	Remark: Wait to return until reply processed by the ISR.
+- **/
+-static int
+-csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
+-{
+-	MpiRaidActionRequest_t	*pReq;
+-	MpiRaidActionReply_t	*pReply;
+-	MPT_FRAME_HDR		*mf;
+-
+-	/* Get and Populate a free Frame
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		return -EAGAIN;
+-	}
+-	pReq = (MpiRaidActionRequest_t *)mf;
+-	pReq->Action = action;
+-	pReq->Reserved1 = 0;
+-	pReq->ChainOffset = 0;
+-	pReq->Function = MPI_FUNCTION_RAID_ACTION;
+-	pReq->VolumeID = VolumeId;
+-	pReq->VolumeBus = VolumeBus;
+-	pReq->PhysDiskNum = PhysDiskNum;
+-	pReq->MsgFlags = 0;
+-	pReq->Reserved2 = 0;
+-	pReq->ActionDataWord = 0; /* Reserved for this action */
+-	//pReq->ActionDataSGE = 0;
+-
+-	mpt_add_sge((char *)&pReq->ActionDataSGE,
+-		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
+-
+-	if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
+-		return -ENODATA;
+-
+-	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) &&
+-	    (reply != NULL)){
+-		pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame);
+-		memcpy(reply, pReply,
+-			min(ioc->reply_sz,
+-			4*pReply->MsgLength));
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- * csmisas_raid_inq
+- * @ioc = per host instance
+- * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or
+- *  	     MPI_FUNCTION_SCSI_IO_REQUEST
+- * @id = target id
+- * @bus = target bus
+- * @inq_vpd = inquiry data, returned
+- * @inq_vpd_sz = maximum size of inquiry data
+- *
+- * Return = 0(sucess), non-zero(failure)
+- **/
+-static int
+-csmisas_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 bus, u8 id, u8 inq_vpd_page,
+-    u8 * inq_vpd, u32 inq_vpd_sz)
+-{
+-	MPT_FRAME_HDR		*mf = NULL;
+-	MPIHeader_t 		*mpi_hdr;
+-	pSCSIIORequest_t	pScsiRequest;
+-	u16		       	req_idx;
+-	char		    	*psge;
+-	u8 		        inq_vpd_cdb[6];
+-	u8 		        *request_data=NULL;
+-	dma_addr_t	    	request_data_dma;
+-	u32		        request_data_sz;
+-	int		    	rc = 0;
+-
+-	request_data_sz = inq_vpd_sz;
+-
+-	/* fill-in cdb */
+-	memset(inq_vpd_cdb, 0, sizeof(inq_vpd_cdb));
+-	inq_vpd_cdb[0] = 0x12;
+-	if (inq_vpd_page) {
+-		inq_vpd_cdb[1] = 0x01; /* evpd bit */
+-		inq_vpd_cdb[2] = inq_vpd_page;
+-	}
+-	inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
+-	inq_vpd_cdb[4] = (u8)request_data_sz;
+-
+-	/* Get a free request frame and save the message context.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		goto csmisas_raid_inq_exit;
+-	}
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	pScsiRequest = (pSCSIIORequest_t) mf;
+-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-	memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
+-	pScsiRequest->Function = opcode;
+-	pScsiRequest->TargetID = id;
+-	pScsiRequest->Bus = bus;
+-	pScsiRequest->CDBLength = 6;
+-	pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
+-	pScsiRequest->MsgContext = mpi_hdr->MsgContext;
+-	memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
+-	pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-	pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
+-	pScsiRequest->MsgFlags = mpt_msg_flags();
+-
+-	/* setup sense
+-	 */
+-	pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
+-	pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
+-	    (req_idx * MPT_SENSE_BUFFER_ALLOC));
+-
+-	request_data = pci_alloc_consistent(
+-	    ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-	if (request_data == NULL) {
+-		mpt_free_msg_frame(ioc, mf);
+-		rc=-1;
+-		goto csmisas_raid_inq_exit;
+-	}
+-
+-	memset(request_data,0,request_data_sz);
+-	psge = (char *)&pScsiRequest->SGL;
+-	mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) ,
+-	    request_data_dma);
+-
+-	if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) {
+-		rc=-1;
+-		goto csmisas_raid_inq_exit;
+-	}
+-
+-	/* copy the request_data */
+-	memcpy(inq_vpd, request_data, request_data_sz);
+-
+- csmisas_raid_inq_exit:
+-
+-	if (request_data)
+-		pci_free_consistent(ioc->pcidev, request_data_sz,
+-		    request_data, request_data_dma);
+-
+-	return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Config command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_config(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_RAID_CONFIG_BUFFER	 karg,*pKarg=NULL;
+-	CONFIGPARMS		 	cfg;
+-	ConfigPageHeader_t	 	header;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-	u8				volumeID, VolumeBus;
+-	u8				physDiskNum, physDiskNumMax;
+-	int			 	volumepage0sz = 0;
+-	int				physdiskpage0sz = 0, ioc_page5_sz = 0;
+-	dma_addr_t			volume0_dma, physdisk0_dma;
+-	dma_addr_t			ioc_page5_dma = 0;
+-	pRaidVolumePage0_t		pVolume0 = NULL;
+-	pRaidPhysDiskPage0_t		pPhysDisk0 = NULL;
+-	pMpiRaidActionReply_t 		pRaidActionReply = NULL;
+-	u32				device_info = 0;
+-	pIOCPage5_t			pIocPage5 = NULL;
+-	int 				i, idx, csmi_sas_raid_config_buffer_sz;
+-	int				memory_pages;
+-	int				copy_buffer_sz = 0;
+-	u64				totalMaxLBA, tmpTotalMaxLBA;
+-	u64				sas_address;
+-	struct sas_device_info		*sas_info;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmisas_get_raid_config struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
+-	memory_pages = get_order(csmi_sas_raid_config_buffer_sz);
+-	pKarg = (CSMI_SAS_RAID_CONFIG_BUFFER *)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!pKarg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to malloc RAID_CONFIG_BUFFER "
+-			"csmi_sas_raid_config_buffer_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			csmi_sas_raid_config_buffer_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-	memset(pKarg, 0, sizeof(*pKarg));
+-
+-	if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmisas_get_raid_config struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (pKarg->Configuration.uChangeCount != 0 &&
+-		pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Configuration.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	if (!ioc->raid_data.pIocPg2) {
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	/*
+-	 * Check to see if the input uRaidSetIndex is
+-	 * greater than the number of RAID sets
+-	 */
+-	if (pKarg->Configuration.uRaidSetIndex >=
+-	    ioc->raid_data.pIocPg2->NumActiveVolumes) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	/*
+-	 * get RAID Volume Page 0
+-	 */
+-	volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
+-	VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
+-
+-	header.PageVersion = 0;
+-	header.PageLength = 0;
+-	header.PageNumber = 0;
+-	header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-	cfg.cfghdr.hdr = &header;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = (VolumeBus << 8) + volumeID;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	if (header.PageLength == 0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	volumepage0sz = header.PageLength * 4;
+-	pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
+-	    &volume0_dma);
+-	if (!pVolume0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	cfg.physAddr = volume0_dma;
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
+-	    ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
+-	tmpTotalMaxLBA = totalMaxLBA + 1;
+-	do_div(tmpTotalMaxLBA, 2048);
+-	pKarg->Configuration.uCapacity = tmpTotalMaxLBA;
+-	pKarg->Configuration.uStripeSize =
+-		le32_to_cpu(pVolume0->StripeSize)/2;
+-
+-	switch(pVolume0->VolumeType) {
+-	case MPI_RAID_VOL_TYPE_IS:
+-		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
+-		break;
+-	case MPI_RAID_VOL_TYPE_IME:
+-		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
+-		break;
+-	case MPI_RAID_VOL_TYPE_IM:
+-		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
+-		break;
+-	default:
+-		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
+-		break;
+-	}
+-
+-	switch (pVolume0->VolumeStatus.State) {
+-	case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+-		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
+-		break;
+-	case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+-		/* Volume is degraded, check if Resyncing or Inactive */
+-		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
+-		break;
+-	case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+-		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
+-		break;
+-	}
+-
+-	/* check flags */
+-	if (pVolume0->VolumeStatus.Flags &
+-	    MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)
+-		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
+-	else if (pVolume0->VolumeStatus.Flags &
+-	    MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
+-		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
+-
+-	pKarg->Configuration.bInformation = 0;  /* default */
+-	if(pVolume0->VolumeStatus.Flags &
+-	    MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
+-
+-		uint64_t 	* ptrUint64;
+-		uint64_t	totalBlocks64, blocksRemaining64;
+-		uint32_t	totalBlocks32, blocksRemaining32;
+-
+-		/* get percentage complete */
+-		pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
+-		    offsetof(MSG_RAID_ACTION_REPLY,ActionData),
+-		    GFP_KERNEL);
+-
+-		if (!pRaidActionReply){
+-			printk(KERN_ERR "%s@%d::%s() - "
+-			    "Unable to malloc @ %p\n",
+-			    __FILE__, __LINE__, __FUNCTION__,pKarg);
+-			goto cim_get_raid_config_exit;
+-		}
+-		memset(pRaidActionReply, 0, sizeof(*pRaidActionReply));
+-
+-		csmisas_do_raid(ioc,
+-		    MPI_RAID_ACTION_INDICATOR_STRUCT,
+-		    0, VolumeBus, volumeID, pRaidActionReply);
+-
+-		ptrUint64       = (uint64_t *)&pRaidActionReply->ActionData;
+-		totalBlocks64     = *ptrUint64;
+-		ptrUint64++;
+-		blocksRemaining64 = *ptrUint64;
+-		while(totalBlocks64 > 0xFFFFFFFFUL){
+-			totalBlocks64 = totalBlocks64 >> 1;
+-			blocksRemaining64 = blocksRemaining64 >> 1;
+-		}
+-		totalBlocks32 = (uint32_t)totalBlocks64;
+-		blocksRemaining32 = (uint32_t)blocksRemaining64;
+-
+-		if(totalBlocks32)
+-			pKarg->Configuration.bInformation =
+-			    (totalBlocks32 - blocksRemaining32) /
+-			    (totalBlocks32 / 100);
+-
+-		kfree(pRaidActionReply);
+-	}
+-
+-	/* fill-in more information depending on data type */
+-	if (pKarg->Configuration.bDataType ==
+-	    CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
+-		pKarg->Configuration.Data->bLabel[0] = '\0';
+-		pKarg->Configuration.Data->bRaidSetLun[1] = 0;
+-		pKarg->Configuration.Data->bWriteProtection =
+-			CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
+-		pKarg->Configuration.Data->bCacheSetting =
+-			CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
+-		pKarg->Configuration.Data->bCacheRatio = 0;
+-		pKarg->Configuration.Data->usBlockSize = 512;
+-		pKarg->Configuration.Data->ulRaidSetExtentOffset.uLowPart = 0;
+-		pKarg->Configuration.Data->ulRaidSetExtentOffset.uHighPart = 0;
+-		pKarg->Configuration.Data->ulRaidSetBlocks.uLowPart =
+-		    le32_to_cpu(pVolume0->MaxLBA);
+-		pKarg->Configuration.Data->ulRaidSetBlocks.uHighPart =
+-		    le32_to_cpu(pVolume0->MaxLBAHigh);
+-		if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
+-		    pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
+-			pKarg->Configuration.Data->uStripeSizeInBlocks =
+-			    le32_to_cpu(pVolume0->StripeSize);
+-		} else {
+-			pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
+-		}
+-		pKarg->Configuration.Data->uSectorsPerTrack = 128;
+-		for (i=0; i<16; i++) {
+-			// unsupported
+-			pKarg->Configuration.Data->bApplicationScratchPad[i] =
+-			    0xFF;
+-		}
+-		pKarg->Configuration.Data->uNumberOfHeads = 16;
+-
+-		tmpTotalMaxLBA = totalMaxLBA;
+-		do_div(tmpTotalMaxLBA,
+-		    (pKarg->Configuration.Data->uNumberOfHeads *
+-		     pKarg->Configuration.Data->uSectorsPerTrack));
+-		pKarg->Configuration.Data->uNumberOfTracks = tmpTotalMaxLBA;
+-		pKarg->Configuration.bDriveCount = 1;
+-	} else if ( pKarg->Configuration.bDataType ==
+-	    CSMI_SAS_RAID_DATA_DEVICE_ID ) {
+-		/* Send inquiry to get VPD Page 0x83 */
+-		u32 vpd_page_sz;
+-		vpd_page_sz = csmi_sas_raid_config_buffer_sz -
+-		    offsetof(CSMI_SAS_RAID_CONFIG,DeviceId);
+-		if (csmisas_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST,
+-			VolumeBus, volumeID, 0x83,
+-			(u8*)&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
+-			vpd_page_sz) != 0) {
+-			pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_get_raid_config_exit;
+-		}
+-		pKarg->Configuration.bDriveCount = 1;
+-	}
+-
+-	if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	/* suppress drive information */
+-	if (pKarg->Configuration.bDriveCount ==
+-		CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	/* get hotspare info, used later in this function */
+-	if (pVolume0->VolumeSettings.HotSparePool) {
+-		/* Read and save IOC Page 5
+-		 */
+-		header.PageVersion = 0;
+-		header.PageLength = 0;
+-		header.PageNumber = 5;
+-		header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-		cfg.cfghdr.hdr = &header;
+-		cfg.physAddr = -1;
+-		cfg.pageAddr = 0;
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-		cfg.dir = 0;
+-		cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-		if ((mpt_config(ioc, &cfg) == 0) && (header.PageLength)) {
+-			ioc_page5_sz = header.PageLength * 4;
+-			pIocPage5 = pci_alloc_consistent(ioc->pcidev,
+-			    ioc_page5_sz,
+-			    &ioc_page5_dma);
+-			memset(pIocPage5,0,ioc_page5_sz);
+-			if (ioc_page5_dma) {
+-				cfg.physAddr = ioc_page5_dma;
+-				cfg.action =
+-				    MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-				mpt_config(ioc, &cfg);
+-			}
+-		}
+-	}
+-
+-	/*
+-	 * get RAID Physical Disk Page 0
+-	 */
+-	header.PageVersion = 0;
+-	header.PageLength = 0;
+-	header.PageNumber = 0;
+-	header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-	cfg.cfghdr.hdr = &header;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	if (header.PageLength == 0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-
+-	physdiskpage0sz = header.PageLength * 4;
+-	pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
+-	    &physdisk0_dma);
+-	if (!pPhysDisk0) {
+-		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_get_raid_config_exit;
+-	}
+-	cfg.physAddr = physdisk0_dma;
+-
+-	physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
+-	    offsetof(CSMI_SAS_RAID_CONFIG,Drives))
+-	    / sizeof(CSMI_SAS_RAID_DRIVES);
+-
+-	pKarg->Configuration.bDriveCount=0;
+-
+-	tmpTotalMaxLBA = totalMaxLBA;
+-	if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
+-		do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-		dcsmisasprintk(("IS Volume tmpTotalMaxLBA=%llX\n",
+-		(unsigned long long)tmpTotalMaxLBA));
+-	}
+-	else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
+-		do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks * 2);
+-		dcsmisasprintk(("IME Volume tmpTotalMaxLBA=%llX\n",
+-		(unsigned long long)tmpTotalMaxLBA));
+-	} else {
+-		dcsmisasprintk(("IM Volume tmpTotalMaxLBA=%llX\n",
+-		(unsigned long long)tmpTotalMaxLBA));
+-	}
+-
+-	for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
+-
+-		physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-		cfg.pageAddr = physDiskNum;
+-		if (mpt_config(ioc, &cfg) != 0){
+-			pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_get_raid_config_exit;
+-		}
+-
+-		/* Search the list for the matching SAS address. */
+-		sas_info = csmisas_get_device_component_by_fw(ioc, pPhysDisk0->PhysDiskBus,
+-		    pPhysDisk0->PhysDiskID);
+-
+-		if (!sas_info)
+-			continue;
+-
+-		sas_address = reverse_byte_order64(sas_info->sas_address);
+-		memcpy(pKarg->Configuration.Drives[i].bSASAddress,
+-		   &sas_address,sizeof(u64));
+-		if (!device_info)
+-			device_info = sas_info->device_info;
+-
+-		memcpy(pKarg->Configuration.Drives[i].bModel,
+-		    pPhysDisk0->InquiryData.VendorID,
+-		    offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
+-		memcpy(pKarg->Configuration.Drives[i].bFirmware,
+-			pPhysDisk0->InquiryData.ProductRevLevel,
+-			sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
+-		if (csmisas_is_sata(pPhysDisk0)) {
+-			memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
+-				&pPhysDisk0->ExtDiskIdentifier[4],
+-				4);
+-			memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
+-				&pPhysDisk0->DiskIdentifier,
+-				sizeof(pPhysDisk0->DiskIdentifier));
+-		} else {
+-			memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
+-				pPhysDisk0->DiskIdentifier,
+-				sizeof(pPhysDisk0->DiskIdentifier));
+-		}
+-
+-		pKarg->Configuration.Drives[i].bDriveUsage =
+-		    (pPhysDisk0->PhysDiskStatus.Flags &
+-		    MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
+-		    CSMI_SAS_DRIVE_CONFIG_NOT_USED :
+-		    CSMI_SAS_DRIVE_CONFIG_MEMBER;
+-
+-		pKarg->Configuration.Drives[i].bDriveStatus =
+-		    CSMI_SAS_DRIVE_STATUS_OK;
+-		if (pPhysDisk0->PhysDiskStatus.State ==
+-		    MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
+-			pKarg->Configuration.Drives[i].bDriveStatus =
+-			    CSMI_SAS_DRIVE_STATUS_OFFLINE;
+-		} else if(pPhysDisk0->PhysDiskStatus.State) {
+-			pKarg->Configuration.Drives[i].bDriveStatus =
+-			    CSMI_SAS_DRIVE_STATUS_FAILED;
+-			if(pKarg->Configuration.bStatus ==
+-			    CSMI_SAS_RAID_SET_STATUS_DEGRADED)
+-				pKarg->Configuration.bInformation = i;
+-		} else if((pVolume0->VolumeStatus.Flags &
+-		    MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
+-		    (pPhysDisk0->PhysDiskStatus.Flags &
+-		    MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
+-			pKarg->Configuration.Drives[i].bDriveStatus =
+-			    CSMI_SAS_DRIVE_STATUS_REBUILDING;
+-		else if(pPhysDisk0->ErrorData.SmartCount ||
+-		    (pPhysDisk0->PhysDiskStatus.Flags &
+-		    MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
+-			pKarg->Configuration.Drives[i].bDriveStatus =
+-			CSMI_SAS_DRIVE_STATUS_DEGRADED;
+-
+-		memset(pKarg->Configuration.Drives[i].bSASLun,
+-		    0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
+-		if (csmisas_is_sata(pPhysDisk0)) {
+-			pKarg->Configuration.Drives[i].bDriveType =
+-			CSMI_SAS_DRIVE_TYPE_SATA;
+-		} else { /* drive in a volume can only be SAS/SATA */
+-			pKarg->Configuration.Drives[i].bDriveType =
+-				CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
+-		}
+-
+-		pKarg->Configuration.Drives[i].usBlockSize = 512;
+-			pKarg->Configuration.Drives[i].uDriveIndex =
+-			    pPhysDisk0->PhysDiskNum;
+-		pKarg->Configuration.Drives[i].ulTotalUserBlocks.uLowPart =
+-		    (u32)tmpTotalMaxLBA;
+-		pKarg->Configuration.Drives[i].ulTotalUserBlocks.uHighPart =
+-		    (u32)(tmpTotalMaxLBA >> 32);
+-	        pKarg->Configuration.bDriveCount++;
+-	}
+-
+-	/* adding hot spare info at the end */
+-	if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5) &&
+-	    (pVolume0->VolumeType != MPI_RAID_VOL_TYPE_IS)) {
+-		for (idx = 0, i = pVolume0->NumPhysDisks ;
+-		    idx < pIocPage5->NumHotSpares ; idx++) {
+-			if (i >= physDiskNumMax)
+-				break;
+-			if ((pVolume0->VolumeSettings.HotSparePool &
+-			    pIocPage5->HotSpare[idx].HotSparePool) == 0)
+-				continue;
+-			if(pIocPage5->HotSpare[idx].Flags !=
+-			    MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
+-			    continue;
+-			physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
+-			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-			cfg.pageAddr = physDiskNum;
+-			if (mpt_config(ioc, &cfg) != 0)
+-				continue;
+-
+-			/* Search the list for the matching SAS address. */
+-			sas_info = csmisas_get_device_component_by_fw(ioc,
+-			    pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-
+-			if (!sas_info)
+-				continue;
+-
+-			sas_address = reverse_byte_order64(sas_info->sas_address);
+-			memcpy(pKarg->Configuration.Drives[i].bSASAddress,
+-			   &sas_address,sizeof(u64));
+-
+-			/* don't mix SSP hot spare
+-			 * in SATA volume
+-			 */
+-			if (!csmisas_is_sata(pPhysDisk0) &&
+-			    (device_info &
+-			    MPI_SAS_DEVICE_INFO_SATA_DEVICE))
+-				continue;
+-
+-			/* don't mix SATA hot spare
+-			 * in SSP volume
+-			 */
+-			if (csmisas_is_sata(pPhysDisk0) &&
+-			    (device_info &
+-			    MPI_SAS_DEVICE_INFO_SSP_TARGET))
+-				continue;
+-
+-			/* capacity check for IM volumes*/
+-			if ((pVolume0->VolumeType ==
+-			    MPI_RAID_VOL_TYPE_IM) &&
+-			    (totalMaxLBA +
+-			    (64*2*1024) /* metadata = 64MB*/ >
+-			    le32_to_cpu(pPhysDisk0->MaxLBA)))
+-				continue;
+-
+-			tmpTotalMaxLBA = totalMaxLBA;
+-			do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-			/* capacity check for IME volumes*/
+-			if ((pVolume0->VolumeType ==
+-				MPI_RAID_VOL_TYPE_IME) &&
+-			    ((tmpTotalMaxLBA * 2) +
+-			     (64*2*1024 ) /*metadata = 64MB*/ >
+-			    le32_to_cpu(pPhysDisk0->MaxLBA)))
+-				break;
+-
+-			/* capacity check for IME volumes*/
+-			if ((pVolume0->VolumeType ==
+-			    MPI_RAID_VOL_TYPE_IME) &&
+-			    (((totalMaxLBA +
+-			    pVolume0->NumPhysDisks) * 2) +
+-			    (64*2*1024 ) /*metadata = 64MB*/ >
+-			    le32_to_cpu(pPhysDisk0->MaxLBA)))
+-				continue;
+-
+-			memcpy(pKarg->Configuration.Drives[i].bModel,
+-			    pPhysDisk0->InquiryData.VendorID,
+-			    offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
+-			memcpy(pKarg->Configuration.Drives[i].bFirmware,
+-				pPhysDisk0->InquiryData.ProductRevLevel,
+-				sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
+-			if (csmisas_is_sata(pPhysDisk0)) {
+-				memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
+-					&pPhysDisk0->ExtDiskIdentifier[4],
+-					4);
+-				memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
+-					&pPhysDisk0->DiskIdentifier,
+-					sizeof(pPhysDisk0->DiskIdentifier));
+-			} else {
+-				memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
+-					pPhysDisk0->DiskIdentifier,
+-					sizeof(pPhysDisk0->DiskIdentifier));
+-			}
+-			pKarg->Configuration.Drives[i].bDriveStatus =
+-			    CSMI_SAS_DRIVE_STATUS_OK;
+-			if(pPhysDisk0->PhysDiskStatus.State)
+-				pKarg->Configuration.Drives[i].bDriveStatus =
+-				    CSMI_SAS_DRIVE_STATUS_FAILED;
+-			else if(pPhysDisk0->ErrorData.SmartCount)
+-				pKarg->Configuration.Drives[i].bDriveStatus =
+-				    CSMI_SAS_DRIVE_STATUS_DEGRADED;
+-			pKarg->Configuration.Drives[i].bDriveUsage =
+-			    CSMI_SAS_DRIVE_CONFIG_SPARE;
+-			pKarg->Configuration.Drives[i].usBlockSize = 512;
+-			pKarg->Configuration.Drives[i].uDriveIndex =
+-			    pPhysDisk0->PhysDiskNum;
+-			if (csmisas_is_sata(pPhysDisk0)) {
+-				pKarg->Configuration.Drives[i].bDriveType =
+-				CSMI_SAS_DRIVE_TYPE_SATA;
+-			} else { /* drive in a volume can only be SAS/SATA */
+-				pKarg->Configuration.Drives[i].bDriveType =
+-					CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
+-			}
+-
+-			i++;
+-			pKarg->Configuration.bDriveCount++;
+-		}
+-	}
+-
+-	// Only return data on the first 240 drives
+-	if( pKarg->Configuration.bDriveCount > 0xF0 )
+-		pKarg->Configuration.bDriveCount =
+-		    CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
+-
+-	pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- cim_get_raid_config_exit:
+-
+-	if (pVolume0 != NULL)
+-		pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
+-		    volume0_dma);
+-
+-	if(pPhysDisk0 != NULL)
+-		pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
+-		    physdisk0_dma);
+-
+-	if(pIocPage5 != NULL)
+-		pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
+-		    ioc_page5_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-
+-	/* find the buffer size to copy depending on how much is filled-in */
+-	switch (pKarg->Configuration.bDataType) {
+-	case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
+-		copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-		    offsetof(CSMI_SAS_RAID_CONFIG,Data) +
+-		    sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
+-		break;
+-	case CSMI_SAS_RAID_DATA_DRIVES:
+-		if (pKarg->Configuration.bDriveCount ==
+-		    CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED)
+-			copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-			    offsetof(CSMI_SAS_RAID_CONFIG,Drives);
+-	        else
+-			copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-			    offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
+-			    (pKarg->Configuration.bDriveCount *
+-			    sizeof(CSMI_SAS_RAID_DRIVES));
+-		break;
+-	case CSMI_SAS_RAID_DATA_DEVICE_ID:
+-		copy_buffer_sz = csmi_sas_raid_config_buffer_sz;
+-		break;
+-	}
+-
+-	if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		       "Unable to write out csmi_sas_get_raid_config @ %p\n",
+-			   __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)pKarg, memory_pages);
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Features command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_features(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
+-	int csmi_sas_raid_features_buffer_sz, iocnum;
+-	int				memory_pages;
+-	MPT_ADAPTER		*ioc = NULL;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
+-	memory_pages = get_order(csmi_sas_raid_features_buffer_sz);
+-	pKarg = (CSMI_SAS_RAID_FEATURES_BUFFER *)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!pKarg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to malloc RAID_FEATURES_BUFFER "
+-			"csmi_sas_raid_features_buffer_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			csmi_sas_raid_features_buffer_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-	memset(pKarg, 0, sizeof(*pKarg));
+-
+-	if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (pKarg->Information.uChangeCount != 0 &&
+-	    pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-		goto cim_get_raid_features_exit;
+-	}
+-
+-	pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD |
+-	    CSMI_SAS_RAID_FEATURE_SURFACE_SCAN |
+-	    CSMI_SAS_RAID_FEATURE_SPARES_SHARED;
+-	pKarg->Information.bDefaultTransformPriority =
+-	    CSMI_SAS_PRIORITY_UNKNOWN;
+-	pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-	pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-	pKarg->Information.bRebuildPriority =
+-	    pKarg->Information.bDefaultRebuildPriority;
+-	pKarg->Information.bDefaultSurfaceScanPriority =
+-	    CSMI_SAS_PRIORITY_UNKNOWN;
+-	pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-	pKarg->Information.uRaidSetTransformationRules = 0;
+-
+-	 /* IS */
+-	pKarg->Information.RaidType[0].bRaidType = CSMI_SAS_RAID_TYPE_0;
+-	pKarg->Information.RaidType[0].uSupportedStripeSizeMap = 0x80;
+-
+-	/* IM */
+-	pKarg->Information.RaidType[1].bRaidType = CSMI_SAS_RAID_TYPE_1;
+-	pKarg->Information.RaidType[1].uSupportedStripeSizeMap = 0;
+-
+-	/* IME */
+-	pKarg->Information.RaidType[2].bRaidType = CSMI_SAS_RAID_TYPE_1E;
+-	pKarg->Information.RaidType[2].uSupportedStripeSizeMap = 0x80;
+-
+-	pKarg->Information.RaidType[3].bRaidType = CSMI_SAS_RAID_TYPE_END;
+-	pKarg->Information.bCacheRatiosSupported[0] =
+-	    CSMI_SAS_RAID_CACHE_RATIO_END;
+-
+- cim_get_raid_features_exit:
+-
+-	/*
+-	 * Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, pKarg,
+-	    sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		"Unable to write out csmi_sas_get_raid_features @ %p\n",
+-		__FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)pKarg, memory_pages);
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set RAID Control command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_raid_control(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
+-	int csmi_sas_raid_control_buffer_sz, iocnum;
+-	int				memory_pages;
+-	MPT_ADAPTER	*ioc = NULL;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
+-	memory_pages = get_order(csmi_sas_raid_control_buffer_sz);
+-	pKarg = (CSMI_SAS_RAID_CONTROL_BUFFER *)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!pKarg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to malloc RAID_CONTROL_BUFFER "
+-			"csmi_sas_raid_control_buffer_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			csmi_sas_raid_control_buffer_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-	memset(pKarg, 0, sizeof(*pKarg));
+-
+-	if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (pKarg->Information.uChangeCount != 0 &&
+-		pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-		goto cim_set_raid_control_exit;
+-	}
+-
+-	if (pKarg->Information.bTransformPriority !=
+-	    CSMI_SAS_PRIORITY_UNCHANGED) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID;
+-		goto cim_set_raid_control_exit;
+-	}
+-
+-	if (pKarg->Information.bRebuildPriority !=
+-	    CSMI_SAS_PRIORITY_AUTO &&
+-		pKarg->Information.bRebuildPriority !=
+-		CSMI_SAS_PRIORITY_UNCHANGED) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
+-		goto cim_set_raid_control_exit;
+-	}
+-
+-	if (pKarg->Information.bCacheRatioFlag ==
+-	    CSMI_SAS_RAID_CACHE_RATIO_DISABLE) {
+-		pKarg->IoctlHeader.ReturnCode =
+-		    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-		    CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
+-		goto cim_set_raid_control_exit;
+-	}
+-
+-	if( !strcmp(pKarg->Information.bClearConfiguration,
+-		CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE) ) {
+-		pKarg->IoctlHeader.ReturnCode =
+-			CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		pKarg->Information.uFailureCode =
+-			CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID;
+-		goto cim_set_raid_control_exit;
+-	}
+-
+-	pKarg->Information.bFailureDescription[0] = '\0';
+-
+- cim_set_raid_control_exit:
+-
+-	/*
+-	 * Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, pKarg,
+-		sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		"Unable to write out csmi_sas_set_raid_control @ %p\n",
+-		__FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)pKarg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)pKarg, memory_pages);
+-	return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get Raid Element.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_element(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_ELEMENT_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_RAID_ELEMENT_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmisas_get_raid_element struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-/* TODO - implement IOCTL here */
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-	dcsmisasprintk((": not implemented\n"));
+-
+-// csmisas_get_raid_element_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmisas_get_raid_element @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set Raid Operation
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_raid_operation(unsigned long arg)
+-{
+-	CSMI_SAS_RAID_SET_OPERATION_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_RAID_SET_OPERATION_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_set_raid_operation struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-/* TODO - implement IOCTL here */
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-	dcsmisasprintk((": not implemented\n"));
+-
+-// cim_set_raid_operation:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_set_raid_operation @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-
+-}
+-
+-
+-/**
+- * Prototype Routine for the CSMI SAS Task Managment Config command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_task_managment(unsigned long arg)
+-{
+-	CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_SSP_TASK_IU_BUFFER	 karg;
+-	pSCSITaskMgmt_t			pScsiTm;
+-	pSCSITaskMgmtReply_t		pScsiTmReply;
+-	MPT_ADAPTER			*ioc = NULL;
+-	MPT_SCSI_HOST			*hd;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t			*mpi_hdr;
+-	int				iocnum;
+-	u8				taskType;
+-	u8				channel;
+-	u8				id;
+-	u8				queueTag;
+-	u32				msgContext = 0;
+-	int				i;
+-	u8 				found_qtag;
+-	struct sas_device_info		*sas_info;
+-	u16				ioc_status;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_task_managment struct @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-
+-	sas_info = csmisas_get_device_component_by_os(ioc,
+-	    karg.Parameters.bPathId, karg.Parameters.bTargetId);
+-	if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-		goto cim_get_task_managment_exit;
+-
+-	channel = sas_info->fw.channel;
+-	id = sas_info->fw.id;
+-	queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
+-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+-
+-	/* try to catch an error
+-	 */
+-	if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
+-	    (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE))
+-		goto cim_get_task_managment_exit;
+-
+-	if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
+-		switch (karg.Parameters.bTaskManagementFunction) {
+-
+-		case CSMI_SAS_SSP_ABORT_TASK:
+-			taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+-			break;
+-		case CSMI_SAS_SSP_ABORT_TASK_SET:
+-			taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
+-			break;
+-		case CSMI_SAS_SSP_CLEAR_TASK_SET:
+-			taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
+-			break;
+-		case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
+-			taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
+-			break;
+-		case CSMI_SAS_SSP_CLEAR_ACA:
+-		case CSMI_SAS_SSP_QUERY_TASK:
+-		default:
+-			goto cim_get_task_managment_exit;
+-		}
+-	} else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)
+-		taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+-	else
+-		goto cim_get_task_managment_exit;
+-
+-	switch (karg.Parameters.uInformation) {
+-		case CSMI_SAS_SSP_TEST:
+-			dcsmisasprintk(("TM request for test purposes\n"));
+-			break;
+-		case CSMI_SAS_SSP_EXCEEDED:
+-			dcsmisasprintk(("TM request due to timeout\n"));
+-			break;
+-		case CSMI_SAS_SSP_DEMAND:
+-			dcsmisasprintk(("TM request demanded by app\n"));
+-			break;
+-		case CSMI_SAS_SSP_TRIGGER:
+-			dcsmisasprintk(("TM request sent to trigger event\n"));
+-			break;
+-	}
+-
+-	switch (taskType) {
+-
+-	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+-	/*
+-	 * look up qtag in the ScsiLookup[] table
+-	 */
+-		for (i = 0, found_qtag = 0; i < hd->ioc->req_depth; i++) {
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-			if ((hd->ScsiLookup[i]) &&
+-			    (hd->ScsiLookup[i]->tag == queueTag)) {
+-#else
+-			if ((ioc->ScsiLookup[i]) &&
+-			    (ioc->ScsiLookup[i]->tag == queueTag)) {
+-#endif
+-				mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
+-				msgContext =
+-				    mf->u.frame.hwhdr.msgctxu.MsgContext;
+-				found_qtag=1;
+-				break;
+-			}
+-		}
+-
+-		if(!found_qtag)
+-			goto cim_get_task_managment_exit;
+-
+-	case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
+-	case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
+-	case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
+-	/* for now, this should work
+-	 */
+-	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+-
+-		/* Single threading ....
+-		 */
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-		if (mptctl_set_tm_flags(hd) != 0) {
+-			karg.IoctlHeader.ReturnCode =
+-			    CSMI_SAS_STATUS_FAILED;
+-			goto cim_get_task_managment_exit;
+-		}
+-#endif
+-
+-		/* Send request
+-		 */
+-		if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-			dcsmisasprintk((": no msg frames!\n"));
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-			mptctl_free_tm_flags(ioc);
+-#endif
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_get_task_managment_exit;
+-		}
+-
+-		mpi_hdr = (MPIHeader_t *) mf;
+-		pScsiTm = (pSCSITaskMgmt_t ) mf;
+-
+-		memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
+-		pScsiTm->TaskType = taskType;
+-		pScsiTm->Bus = channel;
+-		pScsiTm->TargetID = id;
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
+-		int_to_scsilun(karg.Parameters.bLun,
+-		    (struct scsi_lun *)pScsiTm->LUN);
+-#else
+-		pScsiTm->LUN[1] = karg.Parameters.bLun;
+-#endif
+-		pScsiTm->MsgContext = mpi_hdr->MsgContext;
+-		pScsiTm->TaskMsgContext = msgContext;
+-		pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+-
+-		if (csmisas_send_handshake_wait(ioc, mf,
+-		    karg.IoctlHeader.Timeout) != 0)  {
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_get_task_managment_exit;
+-		}
+-
+-		if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-			pScsiTmReply =
+-			    (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame;
+-
+-			ioc_status = le16_to_cpu(pScsiTmReply->IOCStatus)
+-			    & MPI_IOCSTATUS_MASK;
+-
+-			memset(&karg.Status,0,
+-			    sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
+-
+-			if(ioc_status == MPI_IOCSTATUS_SUCCESS) {
+-				karg.IoctlHeader.ReturnCode =
+-				    CSMI_SAS_STATUS_SUCCESS;
+-				karg.Status.bSSPStatus =
+-				    CSMI_SAS_SSP_STATUS_COMPLETED;
+-			}else if(ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
+-				karg.IoctlHeader.ReturnCode =
+-				    CSMI_SAS_STATUS_SUCCESS;
+-				karg.Status.bSSPStatus =
+-				    CSMI_SAS_SSP_STATUS_RETRY;
+-			}else {
+-				karg.IoctlHeader.ReturnCode =
+-				    CSMI_SAS_STATUS_FAILED;
+-				karg.Status.bSSPStatus =
+-				    CSMI_SAS_SSP_STATUS_FATAL_ERROR;
+-			}
+-		} else
+-			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-
+-		break;
+-
+-	default:
+-		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		break;
+-	}
+-
+-
+- cim_get_task_managment_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-				sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to write out csmi_sas_task_managment @ %p\n",
+-				__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- *	map_sas_status_to_csmi - Conversion  for Connection Status
+- *	@mpi_sas_status: Sas status returned by the firmware
+- *
+- *	Returns converted connection status
+- *
+- **/
+-static u8
+-map_sas_status_to_csmi(u8 mpi_sas_status)
+-{
+-	u8  csmi_connect_status;
+-
+-	switch (mpi_sas_status) {
+-
+-	case MPI_SASSTATUS_SUCCESS:
+-		csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
+-		break;
+-
+-	case MPI_SASSTATUS_UTC_BAD_DEST:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
+-		break;
+-
+-	case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
+-		break;
+-
+-	case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
+-		csmi_connect_status =
+-		    CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
+-		break;
+-
+-	case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
+-		break;
+-
+-	case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
+-		break;
+-
+-	case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
+-		break;
+-
+-	case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
+-		break;
+-
+-	case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
+-		csmi_connect_status =  CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
+-		break;
+-
+-	case MPI_SASSTATUS_UNKNOWN_ERROR:
+-	case MPI_SASSTATUS_INVALID_FRAME:
+-	case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
+-	case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
+-	case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
+-	case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
+-	case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
+-	case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
+-	case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
+-	case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
+-	case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
+-	case MPI_SASSTATUS_DATA_OFFSET_ERROR:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
+-		break;
+-
+-	default:
+-		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
+-		break;
+-	}
+-
+-	return csmi_connect_status;
+-}
+-
+-/**
+- *                      csmisas_phy_reset
+- *	Issues a phy link reset or phy hard reset
+- *
+- *	@ioc - Pointer to MPT_ADAPTER structure
+- *	@PhyNum - phy number
+- *	@opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
+- *
+- *	Returns: 0 for success, non-zero error
+- **/
+-static int
+-csmisas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
+-{
+-	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
+-	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t			*mpi_hdr;
+-	u16 				ioc_status;
+-
+-	if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
+-	    (opcode != MPI_SAS_OP_PHY_HARD_RESET))
+-	    return -1;
+-
+-	/* Get a MF for this command.
+-	 */
+-	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-		dcsmisasprintk((": no msg frames!\n"));
+-		return -1;
+-        }
+-
+-	mpi_hdr = (MPIHeader_t *) mf;
+-	sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+-	memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+-	sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+-	sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+-	sasIoUnitCntrReq->Operation = opcode;
+-	sasIoUnitCntrReq->PhyNum = PhyNum;
+-
+-	if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
+-		return -1;
+-
+-	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0)
+-		return -1;
+-
+-	/* process the completed Reply Message Frame */
+-	sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
+-	ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
+-	    & MPI_IOCSTATUS_MASK;
+-	if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
+-		printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-		    __FUNCTION__,
+-		    sasIoUnitCntrReply->IOCStatus,
+-		    sasIoUnitCntrReply->IOCLogInfo);
+-		return -1;
+-	}
+-	return 0;
+-}
+-
+-/** Prototype Routine for the CSMI SAS Phy Control command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_phy_control(unsigned long arg)
+-{
+-	CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
+-	IOCTL_HEADER			ioctl_header;
+-	PCSMI_SAS_PHY_CONTROL_BUFFER	karg;
+-	SasIOUnitPage0_t		*sasIoUnitPg0=NULL;
+-	dma_addr_t			sasIoUnitPg0_dma;
+-	int				sasIoUnitPg0_data_sz=0;
+-	SasIOUnitPage1_t		*sasIoUnitPg1=NULL;
+-	dma_addr_t			sasIoUnitPg1_dma;
+-	int				sasIoUnitPg1_data_sz=0;
+-	ConfigExtendedPageHeader_t  	hdr;
+-	CONFIGPARMS			cfg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum;
+-	int 				csmi_sas_phy_control_buffer_sz;
+-	int				memory_pages;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in IOCTL_HEADER"
+-		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
+-	memory_pages = get_order(csmi_sas_phy_control_buffer_sz);
+-	karg = (PCSMI_SAS_PHY_CONTROL_BUFFER)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!karg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to malloc SAS_PHY_CONTROL_BUFFER "
+-			"csmi_sas_phy_control_buffer_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			csmi_sas_phy_control_buffer_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-	memset(karg, 0, sizeof(*karg));
+-
+-	if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_phy_control_buffer "
+-		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (karg->bPhyIdentifier >= ioc->num_ports) {
+-		karg->IoctlHeader.ReturnCode =
+-		   CSMI_SAS_STATUS_INVALID_PARAMETER;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	/*
+-	 *  Retreive SAS IOUNIT PAGE 0
+-	 */
+-
+-	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		dcsmisasprintk((
+-		    ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
+-	sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-	    sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
+-
+-	if (!sasIoUnitPg0) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
+-	cfg.physAddr = sasIoUnitPg0_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		dcsmisasprintk((
+-		    ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	/*
+-	 *  Retreive SAS IOUNIT PAGE 1
+-	 */
+-
+-	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 1;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		dcsmisasprintk((
+-		    ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
+-	sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
+-	    sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
+-
+-	if (!sasIoUnitPg1) {
+-		dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
+-	cfg.physAddr = sasIoUnitPg1_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		dcsmisasprintk((
+-		    ": FAILED:  READ MPI_SASIOUNITPAGE1: CURRENT\n"));
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-		goto cim_sas_phy_control_exit;
+-	}
+-
+-	switch (karg->uFunction) {
+-
+-	case CSMI_SAS_PC_LINK_RESET:
+-	case CSMI_SAS_PC_HARD_RESET:
+-	{
+-		u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
+-		    MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
+-
+-		if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
+-		    (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
+-		    (karg->bNumberOfControls > 0)){
+-			if(karg->Control[0].bRate ==
+-			   CSMI_SAS_LINK_RATE_1_5_GBPS) {
+-				sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
+-				MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
+-				MPI_SAS_IOUNIT1_MIN_RATE_1_5;
+-			}
+-			else if(karg->Control[0].bRate ==
+-			   CSMI_SAS_LINK_RATE_3_0_GBPS) {
+-				sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
+-				MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
+-				MPI_SAS_IOUNIT1_MIN_RATE_3_0;
+-			}
+-			sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
+-			    ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
+-			cfg.dir = 1;
+-			cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+-			if (mpt_config(ioc, &cfg) != 0) {
+-				dcsmisasprintk((
+-			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
+-				karg->IoctlHeader.ReturnCode =
+-				   CSMI_SAS_STATUS_FAILED;
+-				goto cim_sas_phy_control_exit;
+-			}
+-			cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-			if (mpt_config(ioc, &cfg) != 0) {
+-				dcsmisasprintk((
+-			 ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
+-				karg->IoctlHeader.ReturnCode =
+-				   CSMI_SAS_STATUS_FAILED;
+-				goto cim_sas_phy_control_exit;
+-			}
+-		}
+-		if (csmisas_phy_reset(ioc,
+-		    karg->bPhyIdentifier, opcode) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: csmisas_phy_reset\n"));
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_sas_phy_control_exit;
+-		}
+-		break;
+-
+-	}
+-	case CSMI_SAS_PC_PHY_DISABLE:
+-		if(karg->usLengthOfControl || karg->bNumberOfControls) {
+-			karg->IoctlHeader.ReturnCode =
+-			    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-			break;
+-		}
+-		sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
+-		    MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
+-		cfg.dir = 1;
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+-		if (mpt_config(ioc, &cfg) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_sas_phy_control_exit;
+-		}
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-		if (mpt_config(ioc, &cfg) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_sas_phy_control_exit;
+-		}
+-		if (csmisas_phy_reset(ioc,
+-		    karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
+-			dcsmisasprintk((
+-			    ": FAILED: csmisas_phy_reset\n"));
+-			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-			goto cim_sas_phy_control_exit;
+-		}
+-		break;
+-
+-	case CSMI_SAS_PC_GET_PHY_SETTINGS:
+-		if(karg->usLengthOfControl || karg->bNumberOfControls) {
+-			karg->IoctlHeader.ReturnCode =
+-			    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-			break;
+-		}
+-		if(csmi_sas_phy_control_buffer_sz <
+-		    offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
+-		    (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
+-			karg->IoctlHeader.ReturnCode =
+-			    CSMI_SAS_STATUS_INVALID_PARAMETER;
+-			break;
+-		}
+-		karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
+-		karg->bNumberOfControls = 4;
+-		karg->Control[0].bType = CSMI_SAS_SAS;
+-		karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
+-		karg->Control[1].bType = CSMI_SAS_SAS;
+-		karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
+-		karg->Control[2].bType = CSMI_SAS_SATA;
+-		karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
+-		karg->Control[3].bType = CSMI_SAS_SATA;
+-		karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-		break;
+-	default:
+-		break;
+-	}
+-
+- cim_sas_phy_control_exit:
+-
+-	if (sasIoUnitPg0)
+-		pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
+-		    (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
+-
+-	if (sasIoUnitPg1)
+-		pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
+-		    (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)karg, memory_pages);
+-	return 0;
+-}
+-
+-/**
+- *	csmisas_get_manuf_pg_7 - Fetch Manufacturing config Page7.
+- * @ioc: Pointer to MPT_ADAPTER structure
+- * @mfgpage7_buffer: pointer to ManufacturingPage7_t that returns config
+- *                    page data
+- * @mfg_size - max size of buffer
+- *
+- *	Return: 0 for success
+- *	-ENOMEM if no memory available
+- *		-EPERM if not allowed due to ISR context
+- *		-EAGAIN if no msg frames currently available
+- *		-EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_manuf_pg_7(MPT_ADAPTER *ioc, ManufacturingPage7_t *mfgpage7_buffer, int mfg_size)
+-{
+-	ConfigPageHeader_t hdr;
+-	CONFIGPARMS	cfg;
+-	ManufacturingPage7_t *mfgPage7 = NULL;
+-	dma_addr_t	mfgPage7_dma;
+-	int		data_sz = 0;
+-	int		rc;
+-
+-	/* Get Manufacturing Page 7 header */
+-	hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
+-	hdr.PageLength = 0;
+-	hdr.PageNumber = 7;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.pageAddr = 0;
+-	cfg.timeout = 0;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto csmisas_get_manuf_pg_7_exit;
+-
+-	if (hdr.PageLength == 0) {
+-		rc = -EFAULT;
+-		goto csmisas_get_manuf_pg_7_exit;
+-	}
+-
+-	data_sz = hdr.PageLength * 4;
+-	mfgPage7 = pci_alloc_consistent(ioc->pcidev, data_sz, &mfgPage7_dma);
+-	if (!mfgPage7) {
+-		rc = -ENOMEM;
+-		goto csmisas_get_manuf_pg_7_exit;
+-	}
+-
+-	memset((u8 *)mfgPage7, 0, data_sz);
+-	cfg.physAddr = mfgPage7_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto csmisas_get_manuf_pg_7_exit;
+-
+-	/* copy buffer back to user */
+-	memcpy(mfgpage7_buffer, mfgPage7, min(data_sz, mfg_size));
+-
+- csmisas_get_manuf_pg_7_exit:
+-
+-	if (mfgPage7)
+-		pci_free_consistent(ioc->pcidev, data_sz, (u8 *)mfgPage7,
+-		    mfgPage7_dma);
+-
+-	return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get Connector info command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_connector_info(unsigned long arg)
+-{
+-	CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
+-	CSMI_SAS_CONNECTOR_INFO_BUFFER	 karg;
+-	MPT_ADAPTER			*ioc = NULL;
+-	ManufacturingPage7_t    	*mfgPg7 = NULL;
+-	int				mfgPg7_sz;
+-	int				iocnum;
+-	int				i;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&karg, uarg,
+-		sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		   "Unable to read in csmi_sas_connector_info_buffer"
+-		   " struct @ %p\n",
+-		   __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		return -ENODEV;
+-	}
+-
+-	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-	/* `32` is the sizeof MPI_MANPAGE7_CONNECTOR_INFO */
+-	for (i = 0; i < 32; i++) {
+-		karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
+-		strcpy(karg.Reference[i].bConnector,"");
+-		karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
+-	}
+-
+-	mfgPg7_sz = offsetof(CONFIG_PAGE_MANUFACTURING_7,ConnectorInfo) +
+-	    (ioc->num_ports * sizeof(MPI_MANPAGE7_CONNECTOR_INFO));
+-	mfgPg7 = kmalloc(mfgPg7_sz, GFP_KERNEL);
+-	if (!mfgPg7){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to malloc @ %p\n",
+-		    __FILE__, __LINE__, __FUNCTION__, mfgPg7);
+-		return -EFAULT;
+-	}
+-	memset(mfgPg7, 0, mfgPg7_sz);
+-
+-	if (!csmisas_get_manuf_pg_7(ioc, mfgPg7, mfgPg7_sz)) {
+-		for (i = 0; i < ioc->num_ports; i++) {
+-			karg.Reference[i].uPinout =
+-			    le32_to_cpu(mfgPg7->ConnectorInfo[i].Pinout);
+-			/*endian conversion , this is u8 * 16 ?? */
+-			strncpy(karg.Reference[i].bConnector,
+-			    mfgPg7->ConnectorInfo[i].Connector, 16);
+-			karg.Reference[i].bLocation =
+-			    mfgPg7->ConnectorInfo[i].Location;
+-		}
+-	}
+-
+-	kfree(mfgPg7);
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg,
+-		sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		"Unable to write out csmi_sas_connector_info_buffer @"
+-	       "%p\n",
+-		__FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return 0;
+-}
+-
+-/**
+- *                 csmisas_fill_location_data
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- **/
+-static int
+-csmisas_fill_location_data(MPT_ADAPTER *ioc, u8 bus, u8 id, u8 opcode,
+-	CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
+-{
+-
+-	ConfigExtendedPageHeader_t 	hdr;
+-	CONFIGPARMS			cfg;
+-	int				rc;
+-	SasDevicePage0_t		*sasDevicePg0=NULL;
+-	SasEnclosurePage0_t		*sasEnclosurePg0=NULL;
+-	dma_addr_t			sasDevicePg0_dma,sasEnclosurePg0_dma;
+-	int				sasDevicePg0_data_sz=0;
+-	int				sasEnclosurePg0_data_sz=0;
+-	u64				sas_address;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-	memset (location_ident, 0, sizeof(*location_ident));
+-
+-	/* SAS Device Page 0 */
+-	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		rc=-1;
+-		goto fill_location_data_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		rc=-1;
+-		goto fill_location_data_exit;
+-	}
+-
+-	sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
+-	sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
+-	    ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
+-	if (!sasDevicePg0) {
+-		rc=-1;
+-		goto fill_location_data_exit;
+-	}
+-
+-	memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
+-	cfg.physAddr = sasDevicePg0_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	cfg.pageAddr = (bus << 8) + id
+-	    + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+-			MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		rc=-1;
+-		goto fill_location_data_exit;
+-	}
+-
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
+-	memcpy(&sas_address, &sasDevicePg0->SASAddress, sizeof(u64));
+-	sas_address = reverse_byte_order64(sas_address);
+-	memcpy(location_ident->bSASAddress, &sas_address, sizeof(u64));
+-
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
+-	memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
+-
+-	/* SAS Enclosure Page 0 */
+-	hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		rc=0;
+-		goto fill_location_data_exit;
+-	}
+-
+-	if (hdr.ExtPageLength == 0) {
+-		rc=0;
+-		goto fill_location_data_exit;
+-	}
+-
+-	sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
+-	sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
+-	    ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
+-	if (!sasEnclosurePg0) {
+-		rc=0;
+-		goto fill_location_data_exit;
+-	}
+-	cfg.physAddr = sasEnclosurePg0_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	cfg.pageAddr = sasDevicePg0->EnclosureHandle
+-	    + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-		rc=0;
+-		goto fill_location_data_exit;
+-	}
+-
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
+-	memcpy(&sas_address, &sasEnclosurePg0->EnclosureLogicalID, sizeof(u64));
+-	sas_address = reverse_byte_order64(sas_address);
+-	if (sas_address)
+-		memcpy(location_ident->bEnclosureIdentifier, &sas_address, sizeof(u64));
+-	else
+-		strcpy(location_ident->bEnclosureIdentifier,"Internal");
+-
+-// bBayPrefix - not supported
+-
+-// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
+-//	whether SEP BUS/TargetID is valid.  Ifs its a SES device, then
+-//	issue internal inquiry to (bus/id) to gather the Enclosure name.
+-//	If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
+-//	If its direct attached, there is no enclosure name
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
+-	strcpy(location_ident->bEnclosureName,"Not Supported");
+-
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
+-	location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
+-
+-	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
+-	location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
+-
+-
+-// TODO - illuminating LEDs,
+-// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
+-// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
+-// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
+-
+-/* check sasEnclosurePg0->Flags -
+- * to validate whether we need to send the SEPRequest
+- * bit:5 should be set
+- * bit:3-0 any bit should be set.  If zero, then SEPRequest will fail
+-*/
+-
+-/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
+- * Look in mpi_init.h
+- * SEPRequest_t = structure
+- *
+- * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
+- *
+- * SEPRequest_t->Flags should be set to
+- * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
+- *
+- * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
+- * will illuminate the LEDs
+- */
+-
+-fill_location_data_exit:
+-
+-	if (sasDevicePg0 != NULL)
+-		pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
+-		    sasDevicePg0, sasDevicePg0_dma);
+-
+-	if (sasEnclosurePg0 != NULL)
+-		pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
+-		    sasEnclosurePg0, sasEnclosurePg0_dma);
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	return rc;
+-}
+-
+-static int
+-csmisas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 VolumeBus,
+-	u8 volumeID)
+-{
+-	pRaidVolumePage0_t		pVolume0 = NULL;
+-	pRaidPhysDiskPage0_t		pPhysDisk0 = NULL;
+-	CONFIGPARMS			cfg;
+-	ConfigPageHeader_t		header;
+-	u8				physDiskNumMax;
+-	int				volumepage0sz = 0, physdiskpage0sz = 0;
+-	dma_addr_t			volume0_dma, physdisk0_dma;
+-	int 				csmi_sas_get_location_sz;
+-	int				rc = 0, i, idx;
+-	int 				num_hotpares;
+-	u64				totalMaxLBA, tmpTotalMaxLBA;
+-	IOCPage5_t 			*iocPage5 = NULL;
+-	u32				device_info = 0;
+-	struct sas_device_info		*sas_info;
+-
+-	int 				sz;
+-
+-	csmi_sas_get_location_sz = karg->IoctlHeader.Length;
+-	physDiskNumMax = (csmi_sas_get_location_sz -
+-	    offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
+-	    / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
+-	karg->bNumberOfLocationIdentifiers=0;
+-
+-	/*
+-	 * get RAID Volume Page 0
+-	 */
+-
+-	header.PageVersion = 0;
+-	header.PageLength = 0;
+-	header.PageNumber = 0;
+-	header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-	cfg.cfghdr.hdr = &header;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = (VolumeBus << 8) + volumeID;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	if (header.PageLength == 0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	volumepage0sz = header.PageLength * 4;
+-	pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
+-	    &volume0_dma);
+-	if (!pVolume0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	cfg.physAddr = volume0_dma;
+-	if (mpt_config(ioc, &cfg) != 0){
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
+-	    ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
+-
+-	/*
+-	 * get RAID Physical Disk Page 0
+-	 */
+-	header.PageVersion = 0;
+-	header.PageLength = 0;
+-	header.PageNumber = 0;
+-	header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-	cfg.cfghdr.hdr = &header;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	if (header.PageLength == 0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-
+-	physdiskpage0sz = header.PageLength * 4;
+-	pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
+-	    &physdisk0_dma);
+-	if (!pPhysDisk0) {
+-		rc = -1;
+-		goto sas_fill_location_data_raid_exit;
+-	}
+-	cfg.physAddr = physdisk0_dma;
+-
+-	for (i=0; i < min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
+-
+-		/* obtain a refresh of pPhysDisk0 */
+-		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-		cfg.pageAddr = pVolume0->PhysDisk[i].PhysDiskNum;
+-		if (mpt_config(ioc, &cfg) != 0){
+-			rc = -1;
+-			goto sas_fill_location_data_raid_exit;
+-		}
+-
+-		if((csmisas_fill_location_data(ioc, pPhysDisk0->PhysDiskBus,
+-		    pPhysDisk0->PhysDiskID, karg->bIdentify,
+-		    &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
+-			karg->bNumberOfLocationIdentifiers++;
+-
+-		if (device_info)
+-			continue;
+-		sas_info = csmisas_get_device_component_by_fw(ioc,
+-		    pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-		if (!sas_info || sas_info->is_cached)
+-			continue;
+-		device_info = sas_info->device_info;
+-	}
+-
+-	if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS)
+-		goto sas_fill_location_data_raid_exit;
+-
+-	/*
+-	 * hot spare support
+-	 *
+-	 */
+-
+-	num_hotpares = csmisas_get_number_hotspares(ioc);
+-
+-	if (num_hotpares) {
+-
+-		sz = offsetof(IOCPage5_t, HotSpare) +
+-		    num_hotpares * sizeof(IOC_5_HOT_SPARE);
+-		iocPage5 = kmalloc(sz, GFP_KERNEL);
+-
+-		if (!iocPage5)
+-			goto sas_fill_location_data_raid_exit;
+-		memset(iocPage5, 0, sizeof(*iocPage5));
+-
+-		if (csmisas_get_ioc_pg5(ioc, iocPage5, sz) != 0)
+-			goto sas_fill_location_data_raid_exit;
+-
+-		for(i = 0, idx = pVolume0->NumPhysDisks ; i < num_hotpares;
+-		    i++, idx++) {
+-
+-			if (idx >= physDiskNumMax)
+-				break;
+-
+-			/* obtain a refresh of pPhysDisk0 */
+-			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-			cfg.pageAddr = iocPage5->HotSpare[i].PhysDiskNum;
+-			if (mpt_config(ioc, &cfg) != 0)
+-				goto sas_fill_location_data_raid_exit;
+-
+-			/* Search the list for the matching SAS address. */
+-			sas_info = csmisas_get_device_component_by_fw(ioc,
+-			    pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-
+-			if (!sas_info || sas_info->is_cached)
+-				continue;
+-
+-			/* don't mix SSP hot spare
+-			 * in SATA volume
+-			 */
+-			if (!csmisas_is_sata(pPhysDisk0) &&
+-			    (device_info &
+-			    MPI_SAS_DEVICE_INFO_SATA_DEVICE))
+-				continue;
+-
+-			/* don't mix SATA hot spare
+-			 * in SSP volume
+-			 */
+-			if (csmisas_is_sata(pPhysDisk0) &&
+-			    (device_info &
+-			    MPI_SAS_DEVICE_INFO_SSP_TARGET))
+-				continue;
+-
+-			/* capacity check for IM volumes*/
+-			if ((pVolume0->VolumeType ==
+-			    MPI_RAID_VOL_TYPE_IM) &&
+-			    (totalMaxLBA +
+-			    (64*2*1024) /* metadata = 64MB*/ >
+-			    le32_to_cpu(pPhysDisk0->MaxLBA)))
+-				continue;
+-
+-			tmpTotalMaxLBA = totalMaxLBA;
+-			do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-			/* capacity check for IME volumes*/
+-			if ((pVolume0->VolumeType ==
+-				MPI_RAID_VOL_TYPE_IME) &&
+-			    ((tmpTotalMaxLBA * 2) +
+-			     (64*2*1024 ) /*metadata = 64MB*/ >
+-			    le32_to_cpu(pPhysDisk0->MaxLBA)))
+-				continue;
+-
+-			if((csmisas_fill_location_data(ioc,
+-			    pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID,
+-			    karg->bIdentify,
+-			    &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
+-				karg->bNumberOfLocationIdentifiers++;
+-		}
+-	}
+-
+-
+- sas_fill_location_data_raid_exit:
+-
+-	kfree(iocPage5);
+-
+-	if (pVolume0)
+-		pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
+-		    volume0_dma);
+-
+-	if(pPhysDisk0)
+-		pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
+-		    physdisk0_dma);
+-
+-	return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get location command.
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- *		-ENODEV if no such device/adapter
+- */
+-static int
+-csmisas_get_location(unsigned long arg)
+-{
+-	CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
+-	PCSMI_SAS_GET_LOCATION_BUFFER	karg;
+-	IOCTL_HEADER			ioctl_header;
+-	MPT_ADAPTER			*ioc = NULL;
+-	int				iocnum,i;
+-	int				csmi_sas_get_location_sz;
+-	int				memory_pages;
+-	struct sas_device_info		*sas_info;
+-
+-	dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-	if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in IOCTL_HEADER"
+-		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-		return -EFAULT;
+-	}
+-
+-	csmi_sas_get_location_sz = ioctl_header.Length;
+-	memory_pages = get_order(csmi_sas_get_location_sz);
+-	karg = (PCSMI_SAS_GET_LOCATION_BUFFER)__get_free_pages(
+-		GFP_KERNEL, memory_pages);
+-	if (!karg){
+-		printk(KERN_ERR "%s@%d::%s() - "
+-			"Unable to malloc GET_LOCATION_BUFFER "
+-			"csmi_sas_get_location_sz=%d memory_pages=%d\n",
+-			__FILE__, __LINE__, __FUNCTION__,
+-			csmi_sas_get_location_sz, memory_pages);
+-		return -ENOMEM;
+-	}
+-	memset(karg, 0, sizeof(*karg));
+-
+-	if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to read in csmi_sas_phy_control_buffer "
+-		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
+-	    &ioc)) < 0) || (ioc == NULL)) {
+-		dcsmisasprintk((KERN_ERR
+-		"%s::%s() @%d - ioc%d not found!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	if (!csmisas_is_this_sas_cntr(ioc)) {
+-		dcsmisasprintk((KERN_ERR
+-		    "%s::%s() @%d - ioc%d not SAS controller!\n",
+-		    __FILE__, __FUNCTION__, __LINE__, iocnum));
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -ENODEV;
+-	}
+-
+-	karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-	if(karg->bLengthOfLocationIdentifier !=
+-	    sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
+-		goto cim_sas_get_location_exit;
+-
+-	sas_info = csmisas_get_device_component_by_os(ioc, karg->bPathId,
+-	    karg->bTargetId);
+-	if (!sas_info)
+-		goto cim_sas_get_location_exit;
+-
+-	/* RAID SUPPORT */
+-	if (ioc->raid_data.pIocPg2 && sas_info->is_logical_volume) {
+-		for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
+-			if (sas_info->fw.id ==
+-			    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID &&
+-			    sas_info->fw.channel ==
+-			    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) {
+-				if(csmisas_fill_location_data_raid(ioc, karg,
+-				    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus,
+-				    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) == 0)
+-					karg->IoctlHeader.ReturnCode =
+-					    CSMI_SAS_STATUS_SUCCESS;
+-				else
+-					karg->IoctlHeader.ReturnCode =
+-					    CSMI_SAS_STATUS_FAILED;
+-				goto cim_sas_get_location_exit;
+-			}
+-		}
+-	}
+-
+-	/* NON-RAID SUPPORT */
+-	if (sas_info->is_cached || sas_info->is_logical_volume)
+-		goto cim_sas_get_location_exit;
+-
+-	/* make sure there's enough room to populate the Location[] struct */
+-	if ((csmi_sas_get_location_sz -
+-	    offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
+-	    sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
+-		goto cim_sas_get_location_exit;
+-
+-	karg->bNumberOfLocationIdentifiers=1;
+-	karg->Location[0].bLocationFlags=0;
+-	if((csmisas_fill_location_data(ioc, sas_info->fw.channel,
+-	    sas_info->fw.id, karg->bIdentify, &karg->Location[0])) == 0)
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-	else
+-		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-
+- cim_sas_get_location_exit:
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) {
+-		printk(KERN_ERR "%s@%d::%s() - "
+-		    "Unable to write out csmi_sas_get_location_buffer "
+-		    "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
+-		free_pages((unsigned long)karg, memory_pages);
+-		return -EFAULT;
+-	}
+-
+-	dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-	free_pages((unsigned long)karg, memory_pages);
+-	return 0;
+-}
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,1854 +0,0 @@
+-/**************************************************************************
+-
+-Module Name:
+-
+-   CSMISAS.H
+-
+-
+-Abstract:
+-
+-   This file contains constants and data structure definitions used by drivers
+-   that support the Common Storage Management Interface specification for
+-   SAS or SATA in either the Windows or Linux.
+-
+-   This should be considered as a reference implementation only.  Changes may
+-   be necessary to accommodate a specific build environment or target OS.
+-
+-Revision History:
+-
+-   001  SEF   8/12/03  Initial release.
+-   002  SEF   8/20/03  Cleanup to match documentation.
+-   003  SEF   9/12/03  Additional cleanup, created combined header
+-   004  SEF   9/23/03  Changed base types to match linux defaults
+-                       Added RAID signature
+-                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
+-                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
+-                       Fixed other typos identified in first compilation test
+-   005  SEF  10/03/03  Additions to match first version of CSMI document
+-   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
+-                       Added defines for bConnectionRate
+-   007  SEF  10/15/03  Added Firmware Download Control Code and support
+-                       Added CSMI revision support
+-   008  SEF  10/30/03  No functional change, just updated version to track
+-                       spec changes
+-   009  SEF  12/09/03  No functional change, just updated version to track
+-                       spec changes
+-   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
+-                       bFirmware member that is defined in the spec, but
+-                       was missing in this file,
+-                       added CC_CSMI_SAS_TASK_MANAGEMENT
+-   011  SEF   4/02/04  No functional change, added comment line before
+-                       CC_CSMI_SAS_TASK_MANAGEMENT
+-   012  SEF   4/16/04  Added IOControllerNumber to linux header,
+-                       Modified linux control codes to have upper word of
+-                       0xCC77.... to indicate CSMI version 77
+-                       Added bSignalClass to CC_CSMI_SET_PHY_INFO
+-                       Added CC_CSMI_SAS_PHY_CONTROL support
+-   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
+-   014  SEF   5/24/04  No functional change, just updated version to track spec
+-                       changes
+-   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,
+-                       changed width of bLocation defines to reflect size
+-   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
+-                       to be proper size
+-   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,
+-                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
+-                       CSMI_SAS_CON_NOT_CONNECTED
+-   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN,
+-                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
+-                       conflict with activate definition
+-   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION
+-                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS
+-                       structure
+-   020  SEF   5/25/05  added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to
+-                       CSMI_SAS_GET_LOCATION
+-   021  SEF  11/03/05  added new RAID creation functionality
+-   022  SEF   2/01/06  corrected typo bNegotitiatedLInkRate
+-                       Added two more RAID_TYPES, 7 and 8
+-   023  SEF   4/04/06  added CSMI_RAID_TYPE_1E
+-                       changed structures that contained surface scan
+-                       to priority approach rather than time, causes
+-                       0.89 to incompatible with 0.87, so a version
+-                       check is necessary when interpreting the
+-                       raid structures
+-                       Added netware section
+-   024 DRG    5/22/06  Added uFailureCode to CSMI_SAS_RAID_CONFIG and
+-                       CSMI_SAS_RAID_FEATURES
+-                       Changed __u64 fields to high and low __u32 fields in
+-                       order to avoid backward compatibility issues with
+-                       packing and alignment.
+-                       Fixed alignment problem in CSMI_SAS_RAID_DRIVES.
+-                       Added CSMI_SAS_CNTLR_SMART_ARRAY to uControllerFlags
+-                       Reassigned the value of CSMI_SAS_CNTLR_RAID_CFG_SUPPORT
+-                       to avoid a conflict.
+-
+-**************************************************************************/
+-
+-#ifndef _CSMI_SAS_H_
+-#define _CSMI_SAS_H_
+-
+-// CSMI Specification Revision, the intent is that all versions of the
+-// specification will be backward compatible after the 1.00 release.
+-// Major revision number, corresponds to xxxx. of CSMI specification
+-// Minor revision number, corresponds to .xxxx of CSMI specification
+-#define CSMI_MAJOR_REVISION   0
+-#define CSMI_MINOR_REVISION   90
+-
+-/*************************************************************************/
+-/* PATCHES FOR TYPOS                                                     */
+-/*************************************************************************/
+-
+-#define bNegotitiatedLInkRate bNegotiatedLinkRate
+-
+-/*************************************************************************/
+-/* TARGET OS LINUX SPECIFIC CODE                                         */
+-/*************************************************************************/
+-
+-// EDM #ifdef _linux
+-#ifdef __KERNEL__
+-
+-// Linux base types
+-
+-#include <linux/types.h>
+-
+-#define __i8    char
+-
+-// pack definition
+-
+-// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)
+-// EDM #define CSMI_SAS_END_PACK         pack()
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes prior to 0.77
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678
+-// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781
+-// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812
+-// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123
+-// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345
+-// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456
+-// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567
+-// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567
+-// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567
+-// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567
+-// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
+-// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567
+-// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
+-// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678
+-
+-// Control Codes for 0.77 and later
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  0xCC77000C
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   0xCC77000D
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   0xCC77000E
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014
+-#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016
+-#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017
+-#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018
+-#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
+-#define CC_CSMI_SAS_GET_LOCATION       0xCC770025
+-
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// IOCTL_HEADER
+-typedef struct _IOCTL_HEADER {
+-    __u32 IOControllerNumber;
+-    __u32 Length;
+-    __u32 ReturnCode;
+-    __u32 Timeout;
+-    __u16 Direction;
+-} IOCTL_HEADER,
+-  *PIOCTL_HEADER;
+-
+-// EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS WINDOWS SPECIFIC CODE                                       */
+-/*************************************************************************/
+-
+-#ifdef _WIN32
+-
+-// windows IOCTL definitions
+-
+-#ifndef _NTDDSCSIH_
+-#include <ntddscsi.h>
+-#endif
+-
+-// pack definition
+-
+-#if defined _MSC_VER
+-   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)
+-   #define CSMI_SAS_END_PACK         pack(pop)
+-#elif defined __BORLANDC__
+-   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x
+-   #define CSMI_SAS_END_PACK         option -a.
+-#else
+-   #error "CSMISAS.H - Must externally define a pack compiler designator."
+-#endif
+-
+-// base types
+-
+-#define __u8    unsigned char
+-#define __u16   unsigned short
+-#define __u32   unsigned long
+-#define __u64   unsigned __int64
+-
+-#define __i8    char
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    1
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   3
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      10
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    11
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  12
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   13
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   14
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 15
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       20
+-#define CC_CSMI_SAS_SET_PHY_INFO       21
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    22
+-#define CC_CSMI_SAS_SMP_PASSTHRU       23
+-#define CC_CSMI_SAS_SSP_PASSTHRU       24
+-#define CC_CSMI_SAS_STP_PASSTHRU       25
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    29
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
+-#define CC_CSMI_SAS_GET_LOCATION       31
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        60
+-
+-#define IOCTL_HEADER SRB_IO_CONTROL
+-#define PIOCTL_HEADER PSRB_IO_CONTROL
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS NETWARE SPECIFIC CODE                                       */
+-/*************************************************************************/
+-
+-#ifdef _NETWARE
+-
+-// NetWare IOCTL definitions
+-
+-#define CSMI_SAS_BEGIN_PACK(x)    pack(x)
+-#define CSMI_SAS_END_PACK         pack()
+-
+-#ifndef LONG
+-typedef unsigned long LONG;
+-#endif
+-
+-#ifndef WORD
+-typedef unsigned short WORD;
+-#endif
+-
+-#ifndef BYTE
+-typedef unsigned char BYTE;
+-#endif
+-
+-/* Need to have these definitions for Netware */
+-#define __u8    unsigned char
+-#define __u16   unsigned short
+-#define __u32   unsigned long
+-#define __u64   unsigned __int64
+-
+-#define __i8    char
+-
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// IOCTL_HEADER
+-typedef struct _IOCTL_HEADER {
+-    __u32 Length;
+-    __u32 ReturnCode;
+-} IOCTL_HEADER,
+-  *PIOCTL_HEADER;
+-
+-// EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    0x01FF0001
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x01FF0002
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   0x01FF0003
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x01FF0004
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      0x01FF000A
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    0x01FF000B
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  0x01FF000C
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   0x01FF000D
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   0x01FF000E
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       0x01FF0014
+-#define CC_CSMI_SAS_SET_PHY_INFO       0x01FF0015
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    0x01FF0016
+-#define CC_CSMI_SAS_SMP_PASSTHRU       0x01FF0017
+-#define CC_CSMI_SAS_SSP_PASSTHRU       0x01FF0018
+-#define CC_CSMI_SAS_STP_PASSTHRU       0x01FF0019
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0x01FF001B
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    0x01FF001D
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
+-#define CC_CSMI_SAS_GET_LOCATION       0x01FF001F
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        60
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS NOT DEFINED ERROR                                           */
+-/*************************************************************************/
+-
+-// EDM
+-//#if (!_WIN32 && !_linux && !_NETWARE)
+-//   #error "Unknown target OS."
+-//#endif
+-
+-/*************************************************************************/
+-/* OS INDEPENDENT CODE                                                   */
+-/*************************************************************************/
+-
+-/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
+-
+-// Return codes for all IOCTL's regardless of class
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_STATUS_SUCCESS              0
+-#define CSMI_SAS_STATUS_FAILED               1
+-#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2
+-#define CSMI_SAS_STATUS_INVALID_PARAMETER    3
+-#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_ALL_SIGNATURE    "CSMIALL"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_ALL_TIMEOUT      60
+-
+-//  Direction values for data flow on this IOCTL
+-// (IoctlHeader.Direction, Linux only)
+-#define CSMI_SAS_DATA_READ    0
+-#define CSMI_SAS_DATA_WRITE   1
+-
+-// I/O Bus Types
+-// ISA and EISA bus types are not supported
+-// (bIoBusType)
+-
+-#define CSMI_SAS_BUS_TYPE_PCI       3
+-#define CSMI_SAS_BUS_TYPE_PCMCIA    4
+-
+-// Controller Status
+-// (uStatus)
+-
+-#define CSMI_SAS_CNTLR_STATUS_GOOD     1
+-#define CSMI_SAS_CNTLR_STATUS_FAILED   2
+-#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3
+-#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
+-
+-// Offline Status Reason
+-// (uOfflineReason)
+-
+-#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0
+-#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1
+-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
+-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3
+-
+-// Controller Class
+-// (bControllerClass)
+-
+-#define CSMI_SAS_CNTLR_CLASS_HBA    5
+-
+-// Controller Flag bits
+-// (uControllerFlags)
+-
+-#define CSMI_SAS_CNTLR_SAS_HBA          0x00000001
+-#define CSMI_SAS_CNTLR_SAS_RAID         0x00000002
+-#define CSMI_SAS_CNTLR_SATA_HBA         0x00000004
+-#define CSMI_SAS_CNTLR_SATA_RAID        0x00000008
+-#define CSMI_SAS_CNTLR_SMART_ARRAY      0x00000010
+-
+-// for firmware download
+-#define CSMI_SAS_CNTLR_FWD_SUPPORT      0x00010000
+-#define CSMI_SAS_CNTLR_FWD_ONLINE       0x00020000
+-#define CSMI_SAS_CNTLR_FWD_SRESET       0x00040000
+-#define CSMI_SAS_CNTLR_FWD_HRESET       0x00080000
+-#define CSMI_SAS_CNTLR_FWD_RROM         0x00100000
+-
+-// for RAID configuration supported
+-#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x01000000
+-
+-// Download Flag bits
+-// (uDownloadFlags)
+-#define CSMI_SAS_FWD_VALIDATE       0x00000001
+-#define CSMI_SAS_FWD_SOFT_RESET     0x00000002
+-#define CSMI_SAS_FWD_HARD_RESET     0x00000004
+-
+-// Firmware Download Status
+-// (usStatus)
+-#define CSMI_SAS_FWD_SUCCESS        0
+-#define CSMI_SAS_FWD_FAILED         1
+-#define CSMI_SAS_FWD_USING_RROM     2
+-#define CSMI_SAS_FWD_REJECT         3
+-#define CSMI_SAS_FWD_DOWNREV        4
+-
+-// Firmware Download Severity
+-// (usSeverity>
+-#define CSMI_SAS_FWD_INFORMATION    0
+-#define CSMI_SAS_FWD_WARNING        1
+-#define CSMI_SAS_FWD_ERROR          2
+-#define CSMI_SAS_FWD_FATAL          3
+-
+-/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */
+-
+-// Return codes for the RAID IOCTL's regardless of class
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000
+-#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL   1001
+-#define CSMI_SAS_RAID_SET_DATA_CHANGED       1002
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_RAID_SIGNATURE    "CSMIARY"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_RAID_TIMEOUT      60
+-
+-// RAID Types
+-// (bRaidType)
+-#define CSMI_SAS_RAID_TYPE_NONE     0
+-#define CSMI_SAS_RAID_TYPE_0        1
+-#define CSMI_SAS_RAID_TYPE_1        2
+-#define CSMI_SAS_RAID_TYPE_10       3
+-#define CSMI_SAS_RAID_TYPE_5        4
+-#define CSMI_SAS_RAID_TYPE_15       5
+-#define CSMI_SAS_RAID_TYPE_6        6
+-#define CSMI_SAS_RAID_TYPE_50       7
+-#define CSMI_SAS_RAID_TYPE_VOLUME   8
+-#define CSMI_SAS_RAID_TYPE_1E       9
+-#define CSMI_SAS_RAID_TYPE_OTHER    255
+-// the last value 255 was already defined for other
+-// so end is defined as 254
+-#define CSMI_SAS_RAID_TYPE_END      254
+-
+-// RAID Status
+-// (bStatus)
+-#define CSMI_SAS_RAID_SET_STATUS_OK             0
+-#define CSMI_SAS_RAID_SET_STATUS_DEGRADED       1
+-#define CSMI_SAS_RAID_SET_STATUS_REBUILDING     2
+-#define CSMI_SAS_RAID_SET_STATUS_FAILED         3
+-#define CSMI_SAS_RAID_SET_STATUS_OFFLINE        4
+-#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING   5
+-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD         6
+-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION  7
+-
+-// RAID Drive Count
+-// (bDriveCount, 0xF1 to 0xFF are reserved)
+-#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG   0xF1
+-#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
+-
+-// RAID Data Type
+-// (bDataType)
+-#define CSMI_SAS_RAID_DATA_DRIVES           0
+-#define CSMI_SAS_RAID_DATA_DEVICE_ID        1
+-#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA  2
+-
+-// RAID Drive Status
+-// (bDriveStatus)
+-#define CSMI_SAS_DRIVE_STATUS_OK          0
+-#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1
+-#define CSMI_SAS_DRIVE_STATUS_FAILED      2
+-#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3
+-#define CSMI_SAS_DRIVE_STATUS_OFFLINE     4
+-#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
+-
+-// RAID Drive Usage
+-// (bDriveUsage)
+-#define CSMI_SAS_DRIVE_CONFIG_NOT_USED      0
+-#define CSMI_SAS_DRIVE_CONFIG_MEMBER        1
+-#define CSMI_SAS_DRIVE_CONFIG_SPARE         2
+-#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE  3
+-
+-// RAID Drive Type
+-// (bDriveType)
+-#define CSMI_SAS_DRIVE_TYPE_UNKNOWN         0
+-#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
+-#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS   2
+-#define CSMI_SAS_DRIVE_TYPE_SATA            3
+-#define CSMI_SAS_DRIVE_TYPE_SATA_PS         4
+-#define CSMI_SAS_DRIVE_TYPE_OTHER           255
+-
+-// RAID Write Protect
+-// (bWriteProtect)
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN     0
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED   0
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED     1
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED    2
+-
+-// RAID Cache Setting
+-// (bCacheSetting)
+-#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN             0
+-#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED           0
+-#define CSMI_SAS_RAID_SET_CACHE_ENABLED             1
+-#define CSMI_SAS_RAID_SET_CACHE_DISABLED            2
+-#define CSMI_SAS_RAID_SET_CACHE_CORRUPT             3
+-
+-// RAID Features
+-// (uFeatures)
+-#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION    0x00000001
+-#define CSMI_SAS_RAID_FEATURE_REBUILD           0x00000002
+-#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR      0x00000004
+-#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR      0x00000008
+-#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER      0x00000010
+-#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN      0x00000020
+-#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED     0x00000040
+-
+-// RAID Priority
+-// (bDefaultTransformPriority, etc.)
+-#define CSMI_SAS_PRIORITY_UNKNOWN   0
+-#define CSMI_SAS_PRIORITY_UNCHANGED 0
+-#define CSMI_SAS_PRIORITY_AUTO      1
+-#define CSMI_SAS_PRIORITY_OFF       2
+-#define CSMI_SAS_PRIORITY_LOW       3
+-#define CSMI_SAS_PRIORITY_MEDIUM    4
+-#define CSMI_SAS_PRIORITY_HIGH      5
+-
+-// RAID Transformation Rules
+-// (uRaidSetTransformationRules)
+-#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY     0x00000001
+-#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS   0x00000002
+-
+-// RAID Cache Ratios Supported
+-// (bCacheRatiosSupported)
+-// from 0 to 100 defines the write to read ratio, 0 is 100% write
+-#define CSMI_SAS_RAID_CACHE_RATIO_RANGE     101
+-#define CSMI_SAS_RAID_CACHE_RATIO_FIXED     102
+-#define CSMI_SAS_RAID_CACHE_RATIO_AUTO      103
+-#define CSMI_SAS_RAID_CACHE_RATIO_END       255
+-
+-// RAID Cache Ratio Flag
+-// (bCacheRatioFlag)
+-#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE   0
+-#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE    1
+-
+-// RAID Clear Configuration Signature
+-// (bClearConfiguration)
+-#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
+-
+-// RAID Failure Codes
+-// (uFailureCode)
+-#define CSMI_SAS_FAIL_CODE_OK                           0
+-#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID            1000
+-#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID   1001
+-#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID     1002
+-#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID          1003
+-#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID         1004
+-#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID  1005
+-#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID        1006
+-#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID     1007
+-#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID               1008
+-#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID          1009
+-#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID          1010
+-#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID         1011
+-#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID            1012
+-#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID          1013
+-#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID       1014
+-#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID         1015
+-#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID     1016
+-
+-#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT      2000
+-#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN                2001
+-
+-#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION           3000
+-
+-// RAID Enumeration Types
+-// (uEnumerationType)
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE                0
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE               1
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET       2
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE         3
+-
+-// RAID Extent Types
+-// (bExtentType)
+-#define CSMI_SAS_RAID_EXTENT_RESERVED       0
+-#define CSMI_SAS_RAID_EXTENT_METADATA       1
+-#define CSMI_SAS_RAID_EXTENT_ALLOCATED      2
+-#define CSMI_SAS_RAID_EXTENT_UNALLOCATED    3
+-
+-// RAID Operation Types
+-// (uOperationType)
+-#define CSMI_SAS_RAID_SET_CREATE            0
+-#define CSMI_SAS_RAID_SET_LABEL             1
+-#define CSMI_SAS_RAID_SET_TRANSFORM         2
+-#define CSMI_SAS_RAID_SET_DELETE            3
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT     4
+-#define CSMI_SAS_RAID_SET_CACHE             5
+-#define CSMI_SAS_RAID_SET_ONLINE_STATE      6
+-#define CSMI_SAS_RAID_SET_SPARE             7
+-
+-// RAID Transform Types
+-// (bTransformType)
+-#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR    0
+-#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0    1
+-#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER    2
+-#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET        3
+-
+-// RAID Online State
+-// (bOnlineState)
+-#define CSMI_SAS_RAID_SET_STATE_UNKNOWN     0
+-#define CSMI_SAS_RAID_SET_STATE_ONLINE      1
+-#define CSMI_SAS_RAID_SET_STATE_OFFLINE     2
+-
+-/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
+-
+-// Return codes for SAS IOCTL's
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS
+-#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000
+-#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001
+-
+-#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002
+-#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003
+-#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004
+-#define CSMI_SAS_SELECT_PHY_OR_PORT          2005
+-#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006
+-#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007
+-#define CSMI_SAS_CONNECTION_FAILED           2008
+-
+-#define CSMI_SAS_NO_SATA_DEVICE              2009
+-#define CSMI_SAS_NO_SATA_SIGNATURE           2010
+-#define CSMI_SAS_SCSI_EMULATION              2011
+-#define CSMI_SAS_NOT_AN_END_DEVICE           2012
+-#define CSMI_SAS_NO_SCSI_ADDRESS             2013
+-#define CSMI_SAS_NO_DEVICE_ADDRESS           2014
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_SAS_SIGNATURE    "CSMISAS"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_SAS_TIMEOUT      60
+-
+-// Device types
+-// (bDeviceType)
+-
+-#define CSMI_SAS_PHY_UNUSED               0x00
+-#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00
+-#define CSMI_SAS_END_DEVICE               0x10
+-#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20
+-#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30
+-
+-// Protocol options
+-// (bInitiatorPortProtocol, bTargetPortProtocol)
+-
+-#define CSMI_SAS_PROTOCOL_SATA   0x01
+-#define CSMI_SAS_PROTOCOL_SMP    0x02
+-#define CSMI_SAS_PROTOCOL_STP    0x04
+-#define CSMI_SAS_PROTOCOL_SSP    0x08
+-
+-// Negotiated and hardware link rates
+-// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
+-
+-#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00
+-#define CSMI_SAS_PHY_DISABLED       0x01
+-#define CSMI_SAS_LINK_RATE_FAILED   0x02
+-#define CSMI_SAS_SATA_SPINUP_HOLD   0x03
+-#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
+-#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
+-#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
+-#define CSMI_SAS_LINK_VIRTUAL       0x10
+-
+-// Discover state
+-// (bAutoDiscover)
+-
+-#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00
+-#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01
+-#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02
+-#define CSMI_SAS_DISCOVER_COMPLETE        0x03
+-#define CSMI_SAS_DISCOVER_ERROR           0x04
+-
+-// Phy features
+-
+-#define CSMI_SAS_PHY_VIRTUAL_SMP          0x01
+-
+-// Programmed link rates
+-// (bMinimumLinkRate, bMaximumLinkRate)
+-// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
+-
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09
+-
+-// Link rate
+-// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
+-
+-#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00
+-#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01
+-
+-// Signal class
+-// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
+-
+-#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00
+-#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01
+-#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02
+-#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03
+-
+-// Link error reset
+-// (bResetCounts)
+-
+-#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00
+-#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01
+-
+-// Phy identifier
+-// (bPhyIdentifier)
+-
+-#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF
+-
+-// Port identifier
+-// (bPortIdentifier)
+-
+-#define CSMI_SAS_IGNORE_PORT           0xFF
+-
+-// Programmed link rates
+-// (bConnectionRate)
+-
+-#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00
+-#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08
+-#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09
+-
+-// Connection status
+-// (bConnectionStatus)
+-
+-#define CSMI_SAS_OPEN_ACCEPT                          0
+-#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1
+-#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2
+-#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3
+-#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4
+-#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9
+-#define CSMI_SAS_OPEN_REJECT_RETRY                    10
+-#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11
+-#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12
+-
+-// SSP Status
+-// (bSSPStatus)
+-
+-#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00
+-#define CSMI_SAS_SSP_STATUS_WAITING     0x01
+-#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02
+-#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
+-#define CSMI_SAS_SSP_STATUS_RETRY       0x04
+-#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05
+-
+-// SSP Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_SSP_READ           0x00000001
+-#define CSMI_SAS_SSP_WRITE          0x00000002
+-#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004
+-
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040
+-
+-// SSP Data present
+-// (bDataPresent)
+-
+-#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00
+-#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01
+-#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02
+-
+-// STP Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_STP_READ           0x00000001
+-#define CSMI_SAS_STP_WRITE          0x00000002
+-#define CSMI_SAS_STP_UNSPECIFIED    0x00000004
+-#define CSMI_SAS_STP_PIO            0x00000010
+-#define CSMI_SAS_STP_DMA            0x00000020
+-#define CSMI_SAS_STP_PACKET         0x00000040
+-#define CSMI_SAS_STP_DMA_QUEUED     0x00000080
+-#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100
+-#define CSMI_SAS_STP_RESET_DEVICE   0x00000200
+-
+-// Task Management Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_TASK_IU               0x00000001
+-#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002
+-#define CSMI_SAS_SUPPRESS_RESULT       0x00000004
+-
+-// Task Management Functions
+-// (bTaskManagement)
+-
+-#define CSMI_SAS_SSP_ABORT_TASK           0x01
+-#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02
+-#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04
+-#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08
+-#define CSMI_SAS_SSP_CLEAR_ACA            0x40
+-#define CSMI_SAS_SSP_QUERY_TASK           0x80
+-
+-// Task Management Information
+-// (uInformation)
+-
+-#define CSMI_SAS_SSP_TEST           1
+-#define CSMI_SAS_SSP_EXCEEDED       2
+-#define CSMI_SAS_SSP_DEMAND         3
+-#define CSMI_SAS_SSP_TRIGGER        4
+-
+-// Connector Pinout Information
+-// (uPinout)
+-
+-#define CSMI_SAS_CON_UNKNOWN              0x00000001
+-#define CSMI_SAS_CON_SFF_8482             0x00000002
+-#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100
+-#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200
+-#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400
+-#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800
+-#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000
+-#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000
+-#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000
+-#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000
+-
+-// Connector Location Information
+-// (bLocation)
+-
+-// same as uPinout above...
+-// #define CSMI_SAS_CON_UNKNOWN              0x01
+-#define CSMI_SAS_CON_INTERNAL             0x02
+-#define CSMI_SAS_CON_EXTERNAL             0x04
+-#define CSMI_SAS_CON_SWITCHABLE           0x08
+-#define CSMI_SAS_CON_AUTO                 0x10
+-#define CSMI_SAS_CON_NOT_PRESENT          0x20
+-#define CSMI_SAS_CON_NOT_CONNECTED        0x80
+-
+-// Device location identification
+-// (bIdentify)
+-
+-#define CSMI_SAS_LOCATE_UNKNOWN           0x00
+-#define CSMI_SAS_LOCATE_FORCE_OFF         0x01
+-#define CSMI_SAS_LOCATE_FORCE_ON          0x02
+-
+-// Location Valid flags
+-// (uLocationFlags)
+-
+-#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001
+-#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002
+-#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004
+-#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008
+-#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010
+-#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020
+-#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040
+-
+-/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
+-
+-// Return codes for SAS Phy Control IOCTL's
+-// (IoctlHeader.ReturnCode)
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_PHY_SIGNATURE    "CSMIPHY"
+-
+-// Phy Control Functions
+-// (bFunction)
+-
+-// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL
+-// function defined in the SAS spec
+-#define CSMI_SAS_PC_NOP                   0x00000000
+-#define CSMI_SAS_PC_LINK_RESET            0x00000001
+-#define CSMI_SAS_PC_HARD_RESET            0x00000002
+-#define CSMI_SAS_PC_PHY_DISABLE           0x00000003
+-// 0x04 to 0xFF reserved...
+-#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100
+-
+-// Link Flags
+-#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
+-#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002
+-#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004
+-
+-// Device Types for Phy Settings
+-// (bType)
+-#define CSMI_SAS_UNDEFINED 0x00
+-#define CSMI_SAS_SATA      0x01
+-#define CSMI_SAS_SAS       0x02
+-
+-// Transmitter Flags
+-// (uTransmitterFlags)
+-#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001
+-
+-// Receiver Flags
+-// (uReceiverFlags)
+-#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001
+-
+-// Pattern Flags
+-// (uPatternFlags)
+-// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
+-#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002
+-#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004
+-#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008
+-
+-#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010
+-#define CSMI_SAS_PHY_USER_PATTERN            0x00000020
+-
+-// Fixed Patterns
+-// (bFixedPattern)
+-#define CSMI_SAS_PHY_CJPAT                   0x00000001
+-#define CSMI_SAS_PHY_ALIGN                   0x00000002
+-
+-// Type Flags
+-// (bTypeFlags)
+-#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01
+-#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02
+-#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04
+-
+-// Miscellaneous
+-#define SLOT_NUMBER_UNKNOWN   0xFFFF
+-
+-/*************************************************************************/
+-/* DATA STRUCTURES                                                       */
+-/*************************************************************************/
+-
+-/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// CC_CSMI_SAS_DRIVER_INFO
+-
+-typedef struct _CSMI_SAS_DRIVER_INFO {
+-   __u8  szName[81];
+-   __u8  szDescription[81];
+-   __u16 usMajorRevision;
+-   __u16 usMinorRevision;
+-   __u16 usBuildRevision;
+-   __u16 usReleaseRevision;
+-   __u16 usCSMIMajorRevision;
+-   __u16 usCSMIMinorRevision;
+-} CSMI_SAS_DRIVER_INFO,
+-  *PCSMI_SAS_DRIVER_INFO;
+-
+-typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_DRIVER_INFO Information;
+-} CSMI_SAS_DRIVER_INFO_BUFFER,
+-  *PCSMI_SAS_DRIVER_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_CNTLR_CONFIGURATION
+-
+-typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
+-   __u8  bBusNumber;
+-   __u8  bDeviceNumber;
+-   __u8  bFunctionNumber;
+-   __u8  bReserved;
+-} CSMI_SAS_PCI_BUS_ADDRESS,
+-  *PCSMI_SAS_PCI_BUS_ADDRESS;
+-
+-typedef union _CSMI_SAS_IO_BUS_ADDRESS {
+-   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
+-   __u8  bReserved[32];
+-} CSMI_SAS_IO_BUS_ADDRESS,
+-  *PCSMI_SAS_IO_BUS_ADDRESS;
+-
+-typedef struct _CSMI_SAS_CNTLR_CONFIG {
+-   __u32 uBaseIoAddress;
+-   struct {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } BaseMemoryAddress;
+-   __u32 uBoardID;
+-   __u16 usSlotNumber;
+-   __u8  bControllerClass;
+-   __u8  bIoBusType;
+-   CSMI_SAS_IO_BUS_ADDRESS BusAddress;
+-   __u8  szSerialNumber[81];
+-   __u16 usMajorRevision;
+-   __u16 usMinorRevision;
+-   __u16 usBuildRevision;
+-   __u16 usReleaseRevision;
+-   __u16 usBIOSMajorRevision;
+-   __u16 usBIOSMinorRevision;
+-   __u16 usBIOSBuildRevision;
+-   __u16 usBIOSReleaseRevision;
+-   __u32 uControllerFlags;
+-   __u16 usRromMajorRevision;
+-   __u16 usRromMinorRevision;
+-   __u16 usRromBuildRevision;
+-   __u16 usRromReleaseRevision;
+-   __u16 usRromBIOSMajorRevision;
+-   __u16 usRromBIOSMinorRevision;
+-   __u16 usRromBIOSBuildRevision;
+-   __u16 usRromBIOSReleaseRevision;
+-   __u8  bReserved[7];
+-} CSMI_SAS_CNTLR_CONFIG,
+-  *PCSMI_SAS_CNTLR_CONFIG;
+-
+-typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CNTLR_CONFIG Configuration;
+-} CSMI_SAS_CNTLR_CONFIG_BUFFER,
+-  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
+-
+-// CC_CSMI_SAS_CNTLR_STATUS
+-
+-typedef struct _CSMI_SAS_CNTLR_STATUS {
+-   __u32 uStatus;
+-   __u32 uOfflineReason;
+-   __u8  bReserved[28];
+-} CSMI_SAS_CNTLR_STATUS,
+-  *PCSMI_SAS_CNTLR_STATUS;
+-
+-typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CNTLR_STATUS Status;
+-} CSMI_SAS_CNTLR_STATUS_BUFFER,
+-  *PCSMI_SAS_CNTLR_STATUS_BUFFER;
+-
+-// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
+-
+-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
+-   __u32 uBufferLength;
+-   __u32 uDownloadFlags;
+-   __u8  bReserved[32];
+-   __u16 usStatus;
+-   __u16 usSeverity;
+-} CSMI_SAS_FIRMWARE_DOWNLOAD,
+-  *PCSMI_SAS_FIRMWARE_DOWNLOAD;
+-
+-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_FIRMWARE_DOWNLOAD Information;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
+-  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
+-
+-// CC_CSMI_SAS_RAID_INFO
+-
+-typedef struct _CSMI_SAS_RAID_INFO {
+-   __u32 uNumRaidSets;
+-   __u32 uMaxDrivesPerSet;
+-   __u32 uMaxRaidSets;
+-   __u8  bMaxRaidTypes;
+-   __u8  bReservedByteFields[7];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulMinRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulMaxRaidSetBlocks;
+-   __u32 uMaxPhysicalDrives;
+-   __u32 uMaxExtents;
+-   __u32 uMaxModules;
+-   __u32 uMaxTransformationMemory;
+-   __u32 uChangeCount;
+-   __u8  bReserved[44];
+-} CSMI_SAS_RAID_INFO,
+-  *PCSMI_SAS_RAID_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_INFO Information;
+-} CSMI_SAS_RAID_INFO_BUFFER,
+-  *PCSMI_SAS_RAID_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_CONFIG
+-
+-typedef struct _CSMI_SAS_RAID_DRIVES {
+-   __u8  bModel[40];
+-   __u8  bFirmware[8];
+-   __u8  bSerialNumber[40];
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bDriveStatus;
+-   __u8  bDriveUsage;
+-   __u16 usBlockSize;
+-   __u8  bDriveType;
+-   __u8  bReserved[15];
+-   __u32 uDriveIndex;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulTotalUserBlocks;
+-} CSMI_SAS_RAID_DRIVES,
+-  *PCSMI_SAS_RAID_DRIVES;
+-
+-typedef struct _CSMI_SAS_RAID_DEVICE_ID {
+-   __u8  bDeviceIdentificationVPDPage[1];
+-} CSMI_SAS_RAID_DEVICE_ID,
+-  *PCSMI_SAS_RAID_DEVICE_ID;
+-
+-typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
+-   __u8  bLabel[16];
+-   __u8  bRaidSetLun[8];
+-   __u8  bWriteProtection;
+-   __u8  bCacheSetting;
+-   __u8  bCacheRatio;
+-   __u16 usBlockSize;
+-   __u8  bReservedBytes[11];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   __u32 uStripeSizeInBlocks;
+-   __u32 uSectorsPerTrack;
+-   __u8  bApplicationScratchPad[16];
+-   __u32 uNumberOfHeads;
+-   __u32 uNumberOfTracks;
+-   __u8  bReserved[24];
+-} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
+-  *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
+-
+-typedef struct _CSMI_SAS_RAID_CONFIG {
+-   __u32 uRaidSetIndex;
+-   __u32 uCapacity;
+-   __u32 uStripeSize;
+-   __u8  bRaidType;
+-   __u8  bStatus;
+-   __u8  bInformation;
+-   __u8  bDriveCount;
+-   __u8  bDataType;
+-   __u8  bReserved[11];
+-   __u32 uFailureCode;
+-   __u32 uChangeCount;
+-   union {
+-      CSMI_SAS_RAID_DRIVES Drives[1];
+-      CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
+-      CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
+-   };
+-} CSMI_SAS_RAID_CONFIG,
+-   *PCSMI_SAS_RAID_CONFIG;
+-
+-typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_CONFIG Configuration;
+-} CSMI_SAS_RAID_CONFIG_BUFFER,
+-  *PCSMI_SAS_RAID_CONFIG_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_FEATURES
+-
+-typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
+-  __u8  bRaidType;
+-  __u8  bReservedBytes[7];
+-  __u32 uSupportedStripeSizeMap;
+-  __u8  bReserved[24];
+-} CSMI_SAS_RAID_TYPE_DESCRIPTION,
+-  *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
+-
+-typedef struct _CSMI_SAS_RAID_FEATURES {
+-   __u32 uFeatures;
+-   __u8  bReservedFeatures[32];
+-   __u8  bDefaultTransformPriority;
+-   __u8  bTransformPriority;
+-   __u8  bDefaultRebuildPriority;
+-   __u8  bRebuildPriority;
+-   __u8  bDefaultSurfaceScanPriority;
+-   __u8  bSurfaceScanPriority;
+-   __u16 usReserved;
+-   __u32 uRaidSetTransformationRules;
+-   __u32 uReserved[11];
+-   CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
+-   __u8  bCacheRatiosSupported[104];
+-   __u32 uChangeCount;
+-   __u32 uFailureCode;
+-   __u8  bReserved[120];
+-} CSMI_SAS_RAID_FEATURES,
+-  *PCSMI_SAS_RAID_FEATURES;
+-
+-typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_FEATURES Information;
+-} CSMI_SAS_RAID_FEATURES_BUFFER,
+-  *PCSMI_SAS_RAID_FEATURES_BUFFER;
+-
+-// CC_CSMI_SAS_SET_RAID_CONTROL
+-
+-typedef struct _CSMI_SAS_RAID_CONTROL {
+-   __u8  bTransformPriority;
+-   __u8  bRebuildPriority;
+-   __u8  bCacheRatioFlag;
+-   __u8  bCacheRatio;
+-   __u8  bSurfaceScanPriority;
+-   __u8  bReservedBytes[15];
+-   __u8  bClearConfiguration[8];
+-   __u32 uChangeCount;
+-   __u8  bReserved[88];
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-} CSMI_SAS_RAID_CONTROL,
+-  *PCSMI_SAS_RAID_CONTROL;
+-
+-typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_CONTROL Information;
+-} CSMI_SAS_RAID_CONTROL_BUFFER,
+-  *PCSMI_SAS_RAID_CONTROL_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_ELEMENT
+-
+-typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
+-   __u32 uDriveIndex;
+-   __u8  bExtentType;
+-   __u8  bReservedBytes[7];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulExtentOffset;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulExtentBlocks;
+-   __u32 uRaidSetIndex;
+-   __u8  bReserved[96];
+-} CSMI_SAS_DRIVE_EXTENT_INFO,
+-  *PCSMI_SAS_DRIVE_EXTENT_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_MODULE_INFO {
+-   __u8  bReserved[128];
+-} CSMI_SAS_RAID_MODULE_INFO,
+-  *PCSMI_SAS_RAID_MODULE_INFO;
+-
+-typedef struct _CSMI_SAS_DRIVE_LOCATION {
+-   __u8  bConnector[16];
+-   __u8  bBoxName[16];
+-   __u32 uBay;
+-   __u8  bReservedBytes[4];
+-   __u8  bAttachedSASAddress[8];
+-   __u8  bAttachedPhyIdentifier;
+-   __u8  bReserved[79];
+-} CSMI_SAS_DRIVE_LOCATION,
+-  *PCSMI_SAS_DRIVE_LOCATION;
+-
+-typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
+-   __u8  bNegotiatedLinkRate[2];
+-   __u8  bReserved[126];
+-} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA,
+-  *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
+-
+-typedef struct _CSMI_SAS_DRIVE_INFO {
+-   CSMI_SAS_RAID_DRIVES Device;
+-   CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
+-   CSMI_SAS_DRIVE_LOCATION Location;
+-   __u8  bReserved[16];
+-} CSMI_SAS_DRIVE_INFO,
+-  *PCSMI_SAS_DRIVE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_ELEMENT {
+-   __u32 uEnumerationType;
+-   __u32 uElementIndex;
+-   __u32 uNumElements;
+-   __u32 uChangeCount;
+-   __u32 uSubElementIndex;
+-   __u8  bReserved[32];
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-   union {
+-       CSMI_SAS_DRIVE_INFO Drive;
+-       CSMI_SAS_RAID_MODULE_INFO Module;
+-       CSMI_SAS_DRIVE_EXTENT_INFO Extent;
+-   } Element;
+-} CSMI_SAS_RAID_ELEMENT,
+-  *PCSMI_SAS_RAID_ELEMENT;
+-
+-typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_ELEMENT Information;
+-} CSMI_SAS_RAID_ELEMENT_BUFFER,
+-  *PCSMI_SAS_RAID_ELEMENT_BUFFER;
+-
+-// CC_CSMI_SAS_SET_RAID_OPERATION
+-
+-typedef struct _CSMI_SAS_RAID_SET_LIST {
+-   __u32 uRaidSetIndex;
+-   __u8  bExistingLun[8];
+-   __u8  bNewLun[8];
+-   __u8  bReserved[12];
+-} CSMI_SAS_RAID_SET_LIST,
+-  *PCSMI_SAS_RAID_SET_LIST;
+-
+-typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
+-   __u32 uDriveIndex;
+-   __u8  bDriveUsage;
+-   __u8  bReserved[27];
+-} CSMI_SAS_RAID_SET_DRIVE_LIST,
+-  *PCSMI_SAS_RAID_SET_DRIVE_LIST;
+-
+-typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u32 uDriveCount;
+-   __u8  bApplicationScratchPad[16];
+-   __u8  bReserved[104];
+-} CSMI_SAS_RAID_SET_SPARE_INFO,
+-  *PCSMI_SAS_RAID_SET_SPARE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bOnlineState;
+-   __u8  bReserved[123];
+-} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO,
+-  *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bCacheSetting;
+-   __u8  bCacheRatioFlag;
+-   __u8  bCacheRatio;
+-   __u8  bReserved[121];
+-} CSMI_SAS_RAID_SET_CACHE_INFO,
+-  *PCSMI_SAS_RAID_SET_CACHE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bWriteProtectSetting;
+-   __u8  bReserved[123];
+-} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO,
+-  *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bReserved[124];
+-} CSMI_SAS_RAID_SET_DELETE_INFO,
+-  *PCSMI_SAS_RAID_SET_DELETE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
+-   __u8  bRaidType;
+-   __u8  bReservedBytes[7];
+-   __u32 uStripeSize;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   __u32 uDriveCount;
+-   __u8  bReserved[96];
+-} CSMI_SAS_RAID_SET_MODIFY_INFO,
+-  *PCSMI_SAS_RAID_SET_MODIFY_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
+-   __u8  bTransformType;
+-   __u8  bReservedBytes[3];
+-   __u32 uRaidSetIndex;
+-   __u8  bRaidType;
+-   __u8  bReservedBytes2[11];
+-   __u32 uAdditionalRaidSetIndex;
+-   __u32 uRaidSetCount;
+-   __u8  bApplicationScratchPad[16];
+-   CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
+-   __u8  bReserved[80];
+-} CSMI_SAS_RAID_SET_TRANSFORM_INFO,
+-  *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bLabel[16];
+-   __u8  bReserved[108];
+-} CSMI_SAS_RAID_SET_LABEL_INFO,
+-  *PCSMI_SAS_RAID_SET_LABEL_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
+-   __u8  bRaidType;
+-   __u8  bReservedBytes[7];
+-   __u32 uStripeSize;
+-   __u32 uTrackSectorCount;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   __u32 uDriveCount;
+-   __u8  bLabel[16];
+-   __u32 uRaidSetIndex;
+-   __u8  bApplicationScratchPad[16];
+-   __u32 uNumberOfHeads;
+-   __u32 uNumberOfTracks;
+-   __u8  bReserved[48];
+-} CSMI_SAS_RAID_SET_CREATE_INFO,
+-  *PCSMI_SAS_RAID_SET_CREATE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_OPERATION {
+-   __u32 uOperationType;
+-   __u32 uChangeCount;
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-   __u8  bReserved[28];
+-   union {
+-       CSMI_SAS_RAID_SET_CREATE_INFO Create;
+-       CSMI_SAS_RAID_SET_LABEL_INFO Label;
+-       CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
+-       CSMI_SAS_RAID_SET_DELETE_INFO Delete;
+-       CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
+-       CSMI_SAS_RAID_SET_CACHE_INFO Cache;
+-       CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
+-       CSMI_SAS_RAID_SET_SPARE_INFO Spare;
+-   } Operation;
+-   union {
+-       CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
+-       CSMI_SAS_RAID_SET_LIST RaidSetList[1];
+-   } Parameters;
+-} CSMI_SAS_RAID_SET_OPERATION,
+-  *PCSMI_SAS_RAID_SET_OPERATION;
+-
+-typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_SET_OPERATION Information;
+-} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
+-  *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
+-
+-/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
+-
+-// CC_CSMI_SAS_GET_PHY_INFO
+-
+-typedef struct _CSMI_SAS_IDENTIFY {
+-   __u8  bDeviceType;
+-   __u8  bRestricted;
+-   __u8  bInitiatorPortProtocol;
+-   __u8  bTargetPortProtocol;
+-   __u8  bRestricted2[8];
+-   __u8  bSASAddress[8];
+-   __u8  bPhyIdentifier;
+-   __u8  bSignalClass;
+-   __u8  bReserved[6];
+-} CSMI_SAS_IDENTIFY,
+-  *PCSMI_SAS_IDENTIFY;
+-
+-typedef struct _CSMI_SAS_PHY_ENTITY {
+-   CSMI_SAS_IDENTIFY Identify;
+-   __u8  bPortIdentifier;
+-   __u8  bNegotiatedLinkRate;
+-   __u8  bMinimumLinkRate;
+-   __u8  bMaximumLinkRate;
+-   __u8  bPhyChangeCount;
+-   __u8  bAutoDiscover;
+-   __u8  bPhyFeatures;
+-   __u8  bReserved;
+-   CSMI_SAS_IDENTIFY Attached;
+-} CSMI_SAS_PHY_ENTITY,
+-  *PCSMI_SAS_PHY_ENTITY;
+-
+-typedef struct _CSMI_SAS_PHY_INFO {
+-   __u8  bNumberOfPhys;
+-   __u8  bReserved[3];
+-   CSMI_SAS_PHY_ENTITY Phy[32];
+-} CSMI_SAS_PHY_INFO,
+-  *PCSMI_SAS_PHY_INFO;
+-
+-typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_PHY_INFO Information;
+-} CSMI_SAS_PHY_INFO_BUFFER,
+-  *PCSMI_SAS_PHY_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_SET_PHY_INFO
+-
+-typedef struct _CSMI_SAS_SET_PHY_INFO {
+-   __u8  bPhyIdentifier;
+-   __u8  bNegotiatedLinkRate;
+-   __u8  bProgrammedMinimumLinkRate;
+-   __u8  bProgrammedMaximumLinkRate;
+-   __u8  bSignalClass;
+-   __u8  bReserved[3];
+-} CSMI_SAS_SET_PHY_INFO,
+-  *PCSMI_SAS_SET_PHY_INFO;
+-
+-typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SET_PHY_INFO Information;
+-} CSMI_SAS_SET_PHY_INFO_BUFFER,
+-  *PCSMI_SAS_SET_PHY_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_LINK_ERRORS
+-
+-typedef struct _CSMI_SAS_LINK_ERRORS {
+-   __u8  bPhyIdentifier;
+-   __u8  bResetCounts;
+-   __u8  bReserved[2];
+-   __u32 uInvalidDwordCount;
+-   __u32 uRunningDisparityErrorCount;
+-   __u32 uLossOfDwordSyncCount;
+-   __u32 uPhyResetProblemCount;
+-} CSMI_SAS_LINK_ERRORS,
+-  *PCSMI_SAS_LINK_ERRORS;
+-
+-typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_LINK_ERRORS Information;
+-} CSMI_SAS_LINK_ERRORS_BUFFER,
+-  *PCSMI_SAS_LINK_ERRORS_BUFFER;
+-
+-// CC_CSMI_SAS_SMP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_SMP_REQUEST {
+-   __u8  bFrameType;
+-   __u8  bFunction;
+-   __u8  bReserved[2];
+-   __u8  bAdditionalRequestBytes[1016];
+-} CSMI_SAS_SMP_REQUEST,
+-  *PCSMI_SAS_SMP_REQUEST;
+-
+-typedef struct _CSMI_SAS_SMP_RESPONSE {
+-   __u8  bFrameType;
+-   __u8  bFunction;
+-   __u8  bFunctionResult;
+-   __u8  bReserved;
+-   __u8  bAdditionalResponseBytes[1016];
+-} CSMI_SAS_SMP_RESPONSE,
+-  *PCSMI_SAS_SMP_RESPONSE;
+-
+-typedef struct _CSMI_SAS_SMP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u32 uRequestLength;
+-   CSMI_SAS_SMP_REQUEST Request;
+-   __u8  bConnectionStatus;
+-   __u8  bReserved2[3];
+-   __u32 uResponseBytes;
+-   CSMI_SAS_SMP_RESPONSE Response;
+-} CSMI_SAS_SMP_PASSTHRU,
+-  *PCSMI_SAS_SMP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SMP_PASSTHRU Parameters;
+-} CSMI_SAS_SMP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_SSP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u8  bLun[8];
+-   __u8  bCDBLength;
+-   __u8  bAdditionalCDBLength;
+-   __u8  bReserved2[2];
+-   __u8  bCDB[16];
+-   __u32 uFlags;
+-   __u8  bAdditionalCDB[24];
+-   __u32 uDataLength;
+-} CSMI_SAS_SSP_PASSTHRU,
+-  *PCSMI_SAS_SSP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
+-   __u8  bConnectionStatus;
+-   __u8  bSSPStatus;
+-   __u8  bReserved[2];
+-   __u8  bDataPresent;
+-   __u8  bStatus;
+-   __u8  bResponseLength[2];
+-   __u8  bResponse[256];
+-   __u32 uDataBytes;
+-} CSMI_SAS_SSP_PASSTHRU_STATUS,
+-  *PCSMI_SAS_SSP_PASSTHRU_STATUS;
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SSP_PASSTHRU Parameters;
+-   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_SSP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_STP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u8  bReserved2[4];
+-   __u8  bCommandFIS[20];
+-   __u32 uFlags;
+-   __u32 uDataLength;
+-} CSMI_SAS_STP_PASSTHRU,
+-  *PCSMI_SAS_STP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
+-   __u8  bConnectionStatus;
+-   __u8  bReserved[3];
+-   __u8  bStatusFIS[20];
+-   __u32 uSCR[16];
+-   __u32 uDataBytes;
+-} CSMI_SAS_STP_PASSTHRU_STATUS,
+-  *PCSMI_SAS_STP_PASSTHRU_STATUS;
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_STP_PASSTHRU Parameters;
+-   CSMI_SAS_STP_PASSTHRU_STATUS Status;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_STP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_STP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_GET_SATA_SIGNATURE
+-
+-typedef struct _CSMI_SAS_SATA_SIGNATURE {
+-   __u8  bPhyIdentifier;
+-   __u8  bReserved[3];
+-   __u8  bSignatureFIS[20];
+-} CSMI_SAS_SATA_SIGNATURE,
+-  *PCSMI_SAS_SATA_SIGNATURE;
+-
+-typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SATA_SIGNATURE Signature;
+-} CSMI_SAS_SATA_SIGNATURE_BUFFER,
+-  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
+-
+-// CC_CSMI_SAS_GET_SCSI_ADDRESS
+-
+-typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
+-   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
+-
+-// CC_CSMI_SAS_GET_DEVICE_ADDRESS
+-
+-typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
+-  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
+-
+-// CC_CSMI_SAS_TASK_MANAGEMENT
+-
+-typedef struct _CSMI_SAS_SSP_TASK_IU {
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u32 uFlags;
+-   __u32 uQueueTag;
+-   __u32 uReserved;
+-   __u8  bTaskManagementFunction;
+-   __u8  bReserved[7];
+-   __u32 uInformation;
+-} CSMI_SAS_SSP_TASK_IU,
+-  *PCSMI_SAS_SSP_TASK_IU;
+-
+-typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SSP_TASK_IU Parameters;
+-   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
+-} CSMI_SAS_SSP_TASK_IU_BUFFER,
+-  *PCSMI_SAS_SSP_TASK_IU_BUFFER;
+-
+-// CC_CSMI_SAS_GET_CONNECTOR_INFO
+-
+-typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
+-   __u32 uPinout;
+-   __u8  bConnector[16];
+-   __u8  bLocation;
+-   __u8  bReserved[15];
+-} CSMI_SAS_CONNECTOR_INFO,
+-  *PCSMI_SAS_CONNECTOR_INFO;
+-
+-typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CONNECTOR_INFO Reference[32];
+-} CSMI_SAS_CONNECTOR_INFO_BUFFER,
+-  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_LOCATION
+-
+-typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
+-   __u32 bLocationFlags;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bEnclosureIdentifier[8];
+-   __u8  bEnclosureName[32];
+-   __u8  bBayPrefix[32];
+-   __u8  bBayIdentifier;
+-   __u8  bLocationState;
+-   __u8  bReserved[2];
+-} CSMI_SAS_LOCATION_IDENTIFIER,
+-  *PCSMI_SAS_LOCATION_IDENTIFIER;
+-
+-typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u8  bIdentify;
+-   __u8  bNumberOfLocationIdentifiers;
+-   __u8  bLengthOfLocationIdentifier;
+-   CSMI_SAS_LOCATION_IDENTIFIER Location[1];
+-} CSMI_SAS_GET_LOCATION_BUFFER,
+-  *PCSMI_SAS_GET_LOCATION_BUFFER;
+-
+-// CC_CSMI_SAS_PHY_CONTROL
+-
+-typedef struct _CSMI_SAS_CHARACTER {
+-   __u8  bTypeFlags;
+-   __u8  bValue;
+-} CSMI_SAS_CHARACTER,
+-  *PCSMI_SAS_CHARACTER;
+-
+-typedef struct _CSMI_SAS_PHY_CONTROL {
+-   __u8  bType;
+-   __u8  bRate;
+-   __u8  bReserved[6];
+-   __u32 uVendorUnique[8];
+-   __u32 uTransmitterFlags;
+-   __i8  bTransmitAmplitude;
+-   __i8  bTransmitterPreemphasis;
+-   __i8  bTransmitterSlewRate;
+-   __i8  bTransmitterReserved[13];
+-   __u8  bTransmitterVendorUnique[64];
+-   __u32 uReceiverFlags;
+-   __i8  bReceiverThreshold;
+-   __i8  bReceiverEqualizationGain;
+-   __i8  bReceiverReserved[14];
+-   __u8  bReceiverVendorUnique[64];
+-   __u32 uPatternFlags;
+-   __u8  bFixedPattern;
+-   __u8  bUserPatternLength;
+-   __u8  bPatternReserved[6];
+-   CSMI_SAS_CHARACTER UserPatternBuffer[16];
+-} CSMI_SAS_PHY_CONTROL,
+-  *PCSMI_SAS_PHY_CONTROL;
+-
+-typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u32 uFunction;
+-   __u8  bPhyIdentifier;
+-   __u16 usLengthOfControl;
+-   __u8  bNumberOfControls;
+-   __u8  bReserved[4];
+-   __u32 uLinkFlags;
+-   __u8  bSpinupRate;
+-   __u8  bLinkReserved[7];
+-   __u32 uVendorUnique[8];
+-   CSMI_SAS_PHY_CONTROL Control[1];
+-} CSMI_SAS_PHY_CONTROL_BUFFER,
+-  *PCSMI_SAS_PHY_CONTROL_BUFFER;
+-
+-//EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-#endif // _CSMI_SAS_H_
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c	2007-11-02 09:10:23.000000000 +0100
+@@ -0,0 +1,5095 @@
++#define mptctl_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
++
++#ifndef TRUE
++#define TRUE     (1)
++#endif
++#ifndef FALSE
++#define FALSE    (0)
++#endif
++
++#ifdef QUIESE_IO
++static int mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID,
++    u8 *VolumeBus);
++#endif
++static int mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
++    u8 VolumeId, pMpiRaidActionReply_t reply);
++static u8  map_sas_status_to_csmi(u8 mpi_sas_status);
++
++static u64 reverse_byte_order64(u64 * data64)
++{
++	int i;
++	u64 rc;
++	u8  * inWord = (u8 *)data64, * outWord = (u8 *)&rc;
++
++	for (i=0;i<8;i++) outWord[i] = inWord[7-i];
++
++	return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Routine for the CSMI Sas Get Driver Info command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_driver_info(unsigned long arg)
++{
++
++	CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_DRIVER_INFO_BUFFER	karg;
++	MPT_ADAPTER	*ioc = NULL;
++	int		iocnum;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++	      "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++	memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
++	    sizeof(MPT_MISCDEV_BASENAME));
++	memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
++	    sizeof(MPT_CSMI_DESCRIPTION));
++
++	karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
++	karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
++	karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
++	karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
++
++	karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
++	karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++		sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++		   "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_cntlr_config(unsigned long arg)
++{
++
++	CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_CNTLR_CONFIG_BUFFER	karg;
++	MPT_ADAPTER	*ioc = NULL;
++	int		iocnum;
++	int		ii;
++	unsigned int 	reg;
++	u32      	l;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++	     "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++	      "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Clear the struct before filling in data. */
++	memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++
++	/* Get Base IO and Mem Mapped Addresses. */
++	for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
++		reg = PCI_BASE_ADDRESS_0 + (ii << 2);
++		pci_read_config_dword(ioc->pcidev, reg, &l);
++
++		if ((l & PCI_BASE_ADDRESS_SPACE) ==
++		    PCI_BASE_ADDRESS_SPACE_MEMORY) {
++			karg.Configuration.BaseMemoryAddress.uLowPart =
++			    l & PCI_BASE_ADDRESS_MEM_MASK;
++		}
++		else {
++			karg.Configuration.uBaseIoAddress =
++			    l & PCI_BASE_ADDRESS_IO_MASK;
++		}
++
++		if ((l & (PCI_BASE_ADDRESS_SPACE |
++		    PCI_BASE_ADDRESS_MEM_TYPE_MASK))
++		    == (PCI_BASE_ADDRESS_SPACE_MEMORY |
++		    PCI_BASE_ADDRESS_MEM_TYPE_64)) {
++			pci_read_config_dword(ioc->pcidev, reg+4, &l);
++			karg.Configuration.BaseMemoryAddress.uHighPart = l;
++		}
++		if ((l & PCI_BASE_ADDRESS_SPACE) ==
++		    PCI_BASE_ADDRESS_SPACE_MEMORY) {
++			break;
++		}
++	}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
++	karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
++	    (ioc->pcidev->subsystem_vendor);
++#endif
++
++	karg.Configuration.usSlotNumber =
++	    (ioc->pci_slot_number = 0xff) ?
++	    SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
++	karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
++	karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
++	karg.Configuration.BusAddress.PciAddress.bBusNumber =
++	    ioc->pcidev->bus->number;
++	karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
++	    PCI_SLOT(ioc->pcidev->devfn);
++	karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
++	    PCI_FUNC(ioc->pcidev->devfn);
++	karg.Configuration.BusAddress.PciAddress.bReserved = 0;
++	memcpy( &karg.Configuration.szSerialNumber,ioc->BoardTracerNumber, 16 );
++	karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
++	karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
++	karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
++	karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
++	karg.Configuration.usBIOSMajorRevision =
++	    (ioc->biosVersion & 0xFF000000) >> 24;
++	karg.Configuration.usBIOSMinorRevision =
++	    (ioc->biosVersion & 0x00FF0000) >> 16;
++	karg.Configuration.usBIOSBuildRevision =
++	    (ioc->biosVersion & 0x0000FF00) >> 8;
++	karg.Configuration.usBIOSReleaseRevision =
++	    (ioc->biosVersion & 0x000000FF);
++	karg.Configuration.uControllerFlags =
++	    CSMI_SAS_CNTLR_SAS_HBA | CSMI_SAS_CNTLR_SAS_RAID | 
++	    CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE | 
++	    CSMI_SAS_CNTLR_FWD_SRESET ;
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* All Rrom entries will be zero. Skip them. */
++	/* bReserved will also be zeros. */
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++		sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++		"Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Controller Status command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_cntlr_status(unsigned long arg)
++{
++
++	CSMI_SAS_CNTLR_STATUS_BUFFER  __user *uarg = (void __user *) arg;
++	MPT_ADAPTER		*ioc = NULL;
++	CSMI_SAS_CNTLR_STATUS_BUFFER	karg;
++	int			iocnum;
++	int			rc;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++	     "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++
++	rc = mpt_GetIocState(ioc, 1);
++	switch (rc) {
++	case MPI_IOC_STATE_OPERATIONAL:
++		karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_GOOD;
++		karg.Status.uOfflineReason = 0;
++		break;
++
++	case MPI_IOC_STATE_FAULT:
++		karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
++		karg.Status.uOfflineReason = 0;
++		break;
++
++	case MPI_IOC_STATE_RESET:
++	case MPI_IOC_STATE_READY:
++	default:
++		karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_OFFLINE;
++		karg.Status.uOfflineReason =
++		    CSMI_SAS_OFFLINE_REASON_INITIALIZING;
++		break;
++	}
++
++	memset(&karg.Status.bReserved, 0, 28);
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++		sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++		    "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Phy Info command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_phy_info(unsigned long arg)
++{
++	CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_PHY_INFO_BUFFER  karg;
++	MPT_ADAPTER		*ioc = NULL;
++	ConfigExtendedPageHeader_t  hdr;
++	CONFIGPARMS		cfg;
++	SasIOUnitPage0_t	*sasIoUnitPg0;
++	dma_addr_t		sasIoUnitPg0_dma;
++	int			sasIoUnitPg0_data_sz;
++	SasPhyPage0_t		*sasPhyPg0;
++	dma_addr_t		sasPhyPg0_dma;
++	int			sasPhyPg0_data_sz;
++	u16			protocol;
++	int			iocnum;
++	int			rc;
++	int			ii;
++	u64			SASAddress64;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++	sasIoUnitPg0=NULL;
++	sasPhyPg0=NULL;
++	sasIoUnitPg0_data_sz=0;
++	sasPhyPg0_data_sz=0;
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++		"Unable to read in csmi_sas_get_phy_info_buffer struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++	memset( &karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO));
++
++	/* Issue a config request to get the number of phys
++	 */
++	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((
++		    ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto sas_get_phy_info_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto sas_get_phy_info_exit;
++	}
++
++	sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++	rc = -ENOMEM;
++
++	sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++
++	if (!sasIoUnitPg0) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto sas_get_phy_info_exit;
++	}
++
++	memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++	cfg.physAddr = sasIoUnitPg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((
++		    ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto sas_get_phy_info_exit;
++	}
++
++
++	/* Number of Phys. */
++	karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
++
++	/* Fill in information for each phy. */
++	for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) {
++
++/* EDM : dump IO Unit Page 0 data*/
++		dsasprintk(("---- IO UNIT PAGE 0 ------------\n"));
++		dsasprintk(("Handle=0x%X\n",
++		    le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
++		dsasprintk(("Controller Handle=0x%X\n",
++		    le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
++		dsasprintk(("Port=0x%X\n",
++		    sasIoUnitPg0->PhyData[ii].Port));
++		dsasprintk(("Port Flags=0x%X\n",
++		    sasIoUnitPg0->PhyData[ii].PortFlags));
++		dsasprintk(("PHY Flags=0x%X\n",
++		    sasIoUnitPg0->PhyData[ii].PhyFlags));
++		dsasprintk(("Negotiated Link Rate=0x%X\n",
++		    sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
++		dsasprintk(("Controller PHY Device Info=0x%X\n",
++		    le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
++		dsasprintk(("DiscoveryStatus=0x%X\n",
++		    le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
++		dsasprintk(("\n"));
++/* EDM : debug data */
++
++		/* PHY stuff. */
++		karg.Information.Phy[ii].bPortIdentifier =
++		    sasIoUnitPg0->PhyData[ii].Port;
++
++		/* Get the negotiated link rate for the phy. */
++		switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
++
++		case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
++			karg.Information.Phy[ii].bNegotiatedLinkRate =
++			    CSMI_SAS_PHY_DISABLED;
++			break;
++
++		case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
++			karg.Information.Phy[ii].bNegotiatedLinkRate =
++			    CSMI_SAS_LINK_RATE_FAILED;
++			break;
++
++		case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
++			break;
++
++		case MPI_SAS_IOUNIT0_RATE_1_5:
++			karg.Information.Phy[ii].bNegotiatedLinkRate =
++			    CSMI_SAS_LINK_RATE_1_5_GBPS;
++			break;
++
++		case MPI_SAS_IOUNIT0_RATE_3_0:
++			karg.Information.Phy[ii].bNegotiatedLinkRate =
++			    CSMI_SAS_LINK_RATE_3_0_GBPS;
++			break;
++
++		case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
++		default:
++			karg.Information.Phy[ii].bNegotiatedLinkRate =
++			    CSMI_SAS_LINK_RATE_UNKNOWN;
++			break;
++		}
++
++		if (sasIoUnitPg0->PhyData[ii].PortFlags &
++		    MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
++			karg.Information.Phy[ii].bAutoDiscover =
++			    CSMI_SAS_DISCOVER_IN_PROGRESS;
++		} else {
++			karg.Information.Phy[ii].bAutoDiscover =
++			    CSMI_SAS_DISCOVER_COMPLETE;
++		}
++
++		/* Issue a config request to get
++		 * phy information.
++		 */
++		hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++		hdr.ExtPageLength = 0;
++		hdr.PageNumber = 0;
++		hdr.Reserved1 = 0;
++		hdr.Reserved2 = 0;
++		hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++		hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++		cfg.cfghdr.ehdr = &hdr;
++		cfg.physAddr = -1;
++		cfg.pageAddr = ii;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++		cfg.dir = 0;	/* read */
++		cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++			dctlprintk((
++			    ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
++			dctlprintk((": rc=%x\n",rc));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto sas_get_phy_info_exit;
++		}
++
++		if (hdr.ExtPageLength == 0) {
++			dctlprintk((": pci_alloc_consistent: FAILED\n"));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto sas_get_phy_info_exit;
++		}
++
++		sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++		rc = -ENOMEM;
++
++		sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
++		    ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
++
++		if (! sasPhyPg0) {
++			dctlprintk((": pci_alloc_consistent: FAILED\n"));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto sas_get_phy_info_exit;
++		}
++
++		memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++		cfg.physAddr = sasPhyPg0_dma;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++			dctlprintk((
++			    ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
++			dctlprintk((": rc=%x\n",rc));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++			    (u8 *) sasPhyPg0, sasPhyPg0_dma);
++			goto sas_get_phy_info_exit;
++		}
++
++		le64_to_cpus((u64 *)&sasPhyPg0->SASAddress);
++		memcpy(&SASAddress64, &sasPhyPg0->SASAddress, sizeof(u64));
++
++/* EDM : dump PHY Page 0 data*/
++		dsasprintk(("---- SAS PHY PAGE 0 ------------\n"));
++		dsasprintk(("Handle=0x%X\n",
++		    le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
++		dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++		dsasprintk(("Attached PHY Identifier=0x%X\n",
++		    sasPhyPg0->AttachedPhyIdentifier));
++		dsasprintk(("Attached Device Info=0x%X\n",
++		    le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
++		dsasprintk(("Programmed Link Rate=0x%X\n",
++		    sasPhyPg0->ProgrammedLinkRate));
++		dsasprintk(("Hardware Link Rate=0x%X\n",
++		    ioc->sasPhyInfo[ii].hwLinkRate));
++		dsasprintk(("Change Count=0x%X\n",
++		    sasPhyPg0->ChangeCount));
++		dsasprintk(("PHY Info=0x%X\n",
++		    le32_to_cpu(sasPhyPg0->PhyInfo)));
++		dsasprintk(("\n"));
++/* EDM : debug data */
++
++		/* save the data */
++
++		/* Set Max hardware link rate.
++		 * This value is hard coded
++		 * because the HW link rate
++		 * is currently being
++		 * overwritten in FW.
++		 */
++
++		/* Set Max hardware link rate. */
++		switch (sasPhyPg0->HwLinkRate &
++		    MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
++
++		case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
++			karg.Information.Phy[ii].bMaximumLinkRate =
++			    CSMI_SAS_LINK_RATE_1_5_GBPS;
++			break;
++
++		case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
++			karg.Information.Phy[ii].bMaximumLinkRate =
++			    CSMI_SAS_LINK_RATE_3_0_GBPS;
++			break;
++		default:
++			break;
++		}
++
++		/* Set Max programmed link rate. */
++		switch (sasPhyPg0->ProgrammedLinkRate &
++		    MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
++
++		case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
++			karg.Information.Phy[ii].bMaximumLinkRate |=
++			    (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
++			break;
++
++		case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
++			karg.Information.Phy[ii].bMaximumLinkRate |=
++			    (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
++			break;
++		default:
++			break;
++		}
++
++		/* Set Min hardware link rate. */
++		switch (sasPhyPg0->HwLinkRate &
++		    MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
++
++		case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
++			karg.Information.Phy[ii].bMinimumLinkRate =
++			    CSMI_SAS_LINK_RATE_1_5_GBPS;
++			break;
++
++		case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
++			karg.Information.Phy[ii].bMinimumLinkRate =
++			    CSMI_SAS_LINK_RATE_3_0_GBPS;
++			break;
++		default:
++			break;
++		}
++
++		/* Set Min programmed link rate. */
++		switch (sasPhyPg0->ProgrammedLinkRate &
++		    MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
++
++		case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
++			karg.Information.Phy[ii].bMinimumLinkRate |=
++			    (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
++			break;
++
++		case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
++			karg.Information.Phy[ii].bMinimumLinkRate |=
++			    (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
++			break;
++		default:
++			break;
++		}
++
++		/* Fill in Attached Device
++		 * Initiator Port Protocol.
++		 * Bits 6:3
++		 * More than one bit can be set.
++		 */
++		protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
++		karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
++		if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
++		      karg.Information.Phy[ii].Attached.bInitiatorPortProtocol =
++			    CSMI_SAS_PROTOCOL_SSP;
++		if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
++		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_STP;
++		if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
++		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SMP;
++		if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
++		     karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SATA;
++
++
++		/* Fill in Phy Target Port
++		 * Protocol. Bits 10:7
++		 * More than one bit can be set.
++		 */
++		protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
++		karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0;
++		if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
++			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SSP;
++		if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
++			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_STP;
++		if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
++			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SMP;
++		if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++			karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SATA;
++
++
++		/* Fill in Attached device type */
++		switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
++		    MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
++
++		case MPI_SAS_DEVICE_INFO_NO_DEVICE:
++			karg.Information.Phy[ii].Attached.bDeviceType =
++			    CSMI_SAS_NO_DEVICE_ATTACHED;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_END_DEVICE:
++			karg.Information.Phy[ii].Attached.bDeviceType =
++			    CSMI_SAS_END_DEVICE;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
++			karg.Information.Phy[ii].Attached.bDeviceType =
++			    CSMI_SAS_EDGE_EXPANDER_DEVICE;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
++			karg.Information.Phy[ii].Attached.bDeviceType =
++			    CSMI_SAS_FANOUT_EXPANDER_DEVICE;
++			break;
++		}
++
++		/* Identify Info. */
++		switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
++		    MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
++
++		case MPI_SAS_DEVICE_INFO_NO_DEVICE:
++			karg.Information.Phy[ii].Identify.bDeviceType =
++			    CSMI_SAS_NO_DEVICE_ATTACHED;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_END_DEVICE:
++			karg.Information.Phy[ii].Identify.bDeviceType =
++			    CSMI_SAS_END_DEVICE;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
++			karg.Information.Phy[ii].Identify.bDeviceType =
++			    CSMI_SAS_EDGE_EXPANDER_DEVICE;
++			break;
++
++		case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
++			karg.Information.Phy[ii].Identify.bDeviceType =
++			    CSMI_SAS_FANOUT_EXPANDER_DEVICE;
++			break;
++		}
++
++		/* Fill in Phy Initiator Port Protocol. Bits 6:3
++		 * More than one bit can be set, fall through cases.
++		 */
++		protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)
++		    & 0x78;
++		karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
++		if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
++		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SSP;
++		if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
++		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_STP;
++		if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
++		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SMP;
++		if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
++		     karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SATA;
++
++		/* Fill in Phy Target Port Protocol. Bits 10:7
++		 * More than one bit can be set, fall through cases.
++		 */
++		protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)
++		    & 0x780;
++		karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0;
++		if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
++			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SSP;
++		if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
++			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_STP;
++		if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
++			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SMP;
++		if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
++			karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++			    CSMI_SAS_PROTOCOL_SATA;
++
++
++		/* Setup Identify SAS Address and Phy Identifier
++		 *
++		 * Get phy Sas address from device list.
++		 * Search the list for the matching
++		 * devHandle.
++		 */
++
++		/* Setup SAS Address for the Phy */
++		SASAddress64 = reverse_byte_order64((u64 *)&ioc->sasPhyInfo[ii].SASAddress);
++		memcpy(karg.Information.Phy[ii].Identify.bSASAddress,&SASAddress64,
++		    sizeof(u64));
++
++		karg.Information.Phy[ii].Identify.bPhyIdentifier = ii;
++
++		/* Setup SAS Address for the attached device */
++		SASAddress64 = reverse_byte_order64((u64 *)&sasPhyPg0->SASAddress);
++		memcpy(karg.Information.Phy[ii].Attached.bSASAddress,&SASAddress64,
++		    sizeof(u64));
++
++		karg.Information.Phy[ii].Attached.bPhyIdentifier =
++		    sasPhyPg0->AttachedPhyIdentifier;
++
++		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
++	}
++
++sas_get_phy_info_exit:
++
++	if (sasIoUnitPg0)
++		pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++		    (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s - "
++		    "Unable to write out csmi_sas_get_phy_info_buffer @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Set PHY Info command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_set_phy_info(unsigned long arg)
++{
++	CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_SET_PHY_INFO_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++/* TODO - implement IOCTL here */
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++	dctlprintk((": not implemented\n"));
++
++// cim_set_phy_info_exit:
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++				sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_set_phy_info @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_scsi_address(unsigned long arg)
++{
++	CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_GET_SCSI_ADDRESS_BUFFER	 karg;
++	MPT_ADAPTER		*ioc = NULL;
++	int			iocnum;
++	sas_device_info_t	*sasDevice;
++	u64			SASAddress64;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg,
++	    sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++	      "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++
++	/* Copy the SAS address in reverse byte order. */
++	SASAddress64 = reverse_byte_order64((u64 *)&karg.bSASAddress);
++
++	/* Search the list for the matching SAS address. */
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
++	list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++		/* Found the matching device. */
++		if ((memcmp(&sasDevice->SASAddress,
++		    &SASAddress64, sizeof(u64)) != 0))
++			continue;
++
++		karg.bPathId = sasDevice->Bus;
++		karg.bTargetId = sasDevice->TargetId;
++		karg.bLun = karg.bSASLun[0];
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++		if (((sasDevice->DeviceInfo & 0x00000003) ==
++			MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) ||
++			((sasDevice->DeviceInfo & 0x00000003) ==
++			 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER))
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_NOT_AN_END_DEVICE;
++		break;
++	}
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to write out csmi_sas_get_scsi_address @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_sata_signature(unsigned long arg)
++{
++	CSMI_SAS_SATA_SIGNATURE_BUFFER  __user *uarg = (void __user *) arg;
++	CSMI_SAS_SATA_SIGNATURE_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++	int				rc, jj;
++	ConfigExtendedPageHeader_t	hdr;
++	CONFIGPARMS			cfg;
++	SasPhyPage0_t			*sasPhyPg0;
++	dma_addr_t			sasPhyPg0_dma;
++	int				sasPhyPg0_data_sz;
++	SasDevicePage1_t		*sasDevicePg1;
++	dma_addr_t			sasDevicePg1_dma;
++	int				sasDevicePg1_data_sz;
++	u8				phyId;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++	sasPhyPg0=NULL;
++	sasPhyPg0_data_sz=0;
++	sasDevicePg1=NULL;
++	sasDevicePg1_data_sz=0;
++
++	if (copy_from_user(&karg, uarg,
++	     sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_sata_signature struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++	    "%s::%s() @%d - ioc%d not found!\n",
++		     __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	phyId = karg.Signature.bPhyIdentifier;
++	if (phyId >= ioc->numPhys) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
++		dctlprintk((": phyId >= ioc->numPhys\n"));
++		goto cim_sata_signature_exit;
++	}
++
++	/* Default to success.*/
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Issue a config request to get the devHandle of the attached device
++	 */
++
++	/* Issue a config request to get phy information. */
++	hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = phyId;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++
++	sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++	rc = -ENOMEM;
++
++	sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasPhyPg0_data_sz, &sasPhyPg0_dma);
++
++	if (! sasPhyPg0) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++	cfg.physAddr = sasPhyPg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	/* Make sure a SATA device is attached. */
++	if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
++	    MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
++		dctlprintk((": NOT A SATA DEVICE\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
++		goto cim_sata_signature_exit;
++	}
++
++	/* Get device page 1 for FIS  signature. */
++	hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 1 /* page number 1 */;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++
++	cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
++	    MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
++	    le16_to_cpu(sasPhyPg0->AttachedDevHandle));
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
++	rc = -ENOMEM;
++
++	sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
++	    (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
++
++	if (! sasDevicePg1) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++	memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
++	cfg.physAddr = sasDevicePg1_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sata_signature_exit;
++	}
++
++/* EDM : dump Device Page 1 data*/
++	dsasprintk(("---- SAS DEVICE PAGE 1 ---------\n"));
++	dsasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle));
++	dsasprintk(("SAS Address="));
++	for(jj=0;jj<8;jj++)
++		dsasprintk(("%02x ",
++		((u8 *)&sasDevicePg1->SASAddress)[jj]));
++	dsasprintk(("\n"));
++	dsasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID));
++	dsasprintk(("Bus=0x%x\n",sasDevicePg1->Bus));
++	dsasprintk(("Initial Reg Device FIS="));
++	for(jj=0;jj<20;jj++)
++		dsasprintk(("%02x ",
++		((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
++	dsasprintk(("\n\n"));
++/* EDM : debug data */
++
++	memcpy(karg.Signature.bSignatureFIS,
++		sasDevicePg1->InitialRegDeviceFIS,20);
++
++cim_sata_signature_exit:
++
++	if (sasPhyPg0)
++		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++	if (sasDevicePg1)
++		pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
++		    (u8 *) sasDevicePg1, sasDevicePg1_dma);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to write out csmi_sas_sata_signature @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_device_address(unsigned long arg)
++{
++	CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER	 karg;
++	MPT_ADAPTER		*ioc = NULL;
++	int			iocnum;
++	sas_device_info_t	*sasDevice;
++	u64			SASAddress64;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg,
++	    sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++	   "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++	    "%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Fill in the data and return the structure to the calling
++	 * program
++	 */
++
++	/* Search the list for the matching SAS address. */
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
++	list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++		/* Find the matching device. */
++		if ((karg.bPathId == sasDevice->Bus) &&
++			(karg.bTargetId == sasDevice->TargetId)) {
++
++			SASAddress64 = reverse_byte_order64(&sasDevice->SASAddress);
++			memcpy(&karg.bSASAddress,&SASAddress64,sizeof(u64));
++			karg.bSASLun[0] = karg.bLun;
++			memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++			break;
++		} else
++			/* Keep looking. */
++			continue;
++	}
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		"Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Link Errors command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_link_errors(unsigned long arg)
++{
++	CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_LINK_ERRORS_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t			*mpi_hdr;
++	int				iocnum;
++	int				rc,ii;
++	ConfigExtendedPageHeader_t	hdr;
++	CONFIGPARMS			cfg;
++	SasPhyPage1_t			*sasPhyPage1;
++	dma_addr_t			sasPhyPage1_dma;
++	int				sasPhyPage1_data_sz;
++	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
++	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
++	u8				phyId;
++	int				wait_timeout;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++	sasPhyPage1=NULL;
++	sasPhyPage1_data_sz=0;
++
++	if (copy_from_user(&karg, uarg,
++	     sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in mptctl_csmi_sas_get_link_errors struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++	    "%s::%s() @%d - ioc%d not found!\n",
++		     __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	phyId = karg.Information.bPhyIdentifier;
++	if (phyId >= ioc->numPhys) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
++		dctlprintk((": phyId >= ioc->numPhys\n"));
++		goto cim_get_link_errors_exit;
++	}
++
++	/* Default to success.*/
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Issue a config request to get the devHandle of the attached device
++	 */
++
++	/* Issue a config request to get phy information. */
++	hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 1 /* page number 1*/;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = phyId;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_link_errors_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_link_errors_exit;
++	}
++
++
++	sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
++	rc = -ENOMEM;
++
++	sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasPhyPage1_data_sz, &sasPhyPage1_dma);
++
++	if (! sasPhyPage1) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_link_errors_exit;
++	}
++
++	memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
++	cfg.physAddr = sasPhyPage1_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		/* Don't check if this failed.  Already in a
++		 * failure case.
++		 */
++		dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
++		dctlprintk((": rc=%x\n",rc));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_link_errors_exit;
++	}
++
++/* EDM : dump PHY Page 1 data*/
++	dsasprintk(("---- SAS PHY PAGE 1 ------------\n"));
++	dsasprintk(("Invalid Dword Count=0x%x\n",
++	    sasPhyPage1->InvalidDwordCount));
++	dsasprintk(("Running Disparity Error Count=0x%x\n",
++	    sasPhyPage1->RunningDisparityErrorCount));
++	dsasprintk(("Loss Dword Synch Count=0x%x\n",
++	    sasPhyPage1->LossDwordSynchCount));
++	dsasprintk(("PHY Reset Problem Count=0x%x\n",
++	    sasPhyPage1->PhyResetProblemCount));
++	dsasprintk(("\n\n"));
++/* EDM : debug data */
++
++	karg.Information.uInvalidDwordCount =
++		le32_to_cpu(sasPhyPage1->InvalidDwordCount);
++	karg.Information.uRunningDisparityErrorCount =
++		le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
++	karg.Information.uLossOfDwordSyncCount =
++		le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
++	karg.Information.uPhyResetProblemCount =
++		le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
++
++	if (karg.Information.bResetCounts ==
++	    CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
++		goto cim_get_link_errors_exit;
++	}
++
++	/* Clear Error log
++	 *
++	 * Issue IOUNIT Control Reqeust Message
++	 */
++
++	/* Get a MF for this command.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_link_errors_exit;
++        }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
++	memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
++	sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
++	sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
++	sasIoUnitCntrReq->PhyNum = phyId;
++	sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
++
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*wait_timeout);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		goto cim_get_link_errors_exit;
++	}
++
++	/* process the completed Reply Message Frame */
++	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++
++		sasIoUnitCntrReply =
++		    (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
++
++		if ( le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
++			dctlprintk((": SAS IO Unit Control: "));
++			dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
++			    sasIoUnitCntrReply->IOCStatus,
++			    sasIoUnitCntrReply->IOCLogInfo));
++		}
++	}
++
++cim_get_link_errors_exit:
++
++	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID);
++
++	if (sasPhyPage1)
++		pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
++		    (u8 *) sasPhyPage1, sasPhyPage1_dma);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to write out mptctl_csmi_sas_get_link_errors @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS SMP Passthru command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_smp_passthru(unsigned long arg)
++{
++	CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++	MPT_ADAPTER			*ioc;
++	CSMI_SAS_SMP_PASSTHRU_BUFFER	 karg;
++	pSmpPassthroughRequest_t	smpReq;
++	pSmpPassthroughReply_t		smpReply;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t			*mpi_hdr;
++	char				*psge;
++	int				iocnum, flagsLength,ii;
++	u8				index;
++	void *				request_data;
++	dma_addr_t			request_data_dma;
++	u32				request_data_sz;
++	void *				response_data;
++	dma_addr_t			response_data_dma;
++	u32				response_data_sz;
++	u16				ioc_stat;
++	int				wait_timeout;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	request_data = NULL;
++	response_data = NULL;
++	response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
++	request_data_sz  = karg.Parameters.uRequestLength;
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Make sure the adapter is not being reset. */
++	if (!ioc->ioctl) {
++		printk(KERN_ERR "%s@%d::%s - "
++		    "No memory available during driver init.\n",
++		    __FILE__, __LINE__,__FUNCTION__);
++		return -ENOMEM;
++	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
++		printk(KERN_ERR "%s@%d::%s - "
++		    "Busy with IOC Reset \n",
++		    __FILE__, __LINE__,__FUNCTION__);
++		return -EBUSY;
++	}
++
++	/* Default to success.*/
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Do some error checking on the request. */
++	if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++		goto cim_smp_passthru_exit;
++	}
++
++	if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_smp_passthru_exit;
++	}
++
++	/* Get a free request frame and save the message context.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_smp_passthru_exit;
++        }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	smpReq = (pSmpPassthroughRequest_t ) mf;
++
++	memset(smpReq,0,ioc->req_sz);
++
++	/* Fill in smp request. */
++	smpReq->PhysicalPort = karg.Parameters.bPortIdentifier;
++	smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
++	smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
++	smpReq->ConnectionRate = karg.Parameters.bConnectionRate;
++	smpReq->MsgContext = mpi_hdr->MsgContext;
++	for ( index = 0; index < 8; index++ ) {
++		((u8*)&smpReq->SASAddress)[7 - index] =
++		    karg.Parameters.bDestinationSASAddress[index];
++	}
++	smpReq->Reserved2 = 0;
++	smpReq->Reserved3 = 0;
++
++	/*
++	 * Prepare the necessary pointers to run
++	 * through the SGL generation
++	 */
++
++	psge = (char *)&smpReq->SGL;
++
++	/* setup the *Request* payload SGE */
++	flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++		MPI_SGE_FLAGS_SYSTEM_ADDRESS |
++		MPI_SGE_FLAGS_32_BIT_ADDRESSING |
++		MPI_SGE_FLAGS_HOST_TO_IOC |
++		MPI_SGE_FLAGS_END_OF_BUFFER;
++
++	if (sizeof(dma_addr_t) == sizeof(u64)) {
++		flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
++	}
++	flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
++	flagsLength |= request_data_sz;
++
++	request_data = pci_alloc_consistent(
++	    ioc->pcidev, request_data_sz, &request_data_dma);
++
++	if (!request_data) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		goto cim_smp_passthru_exit;
++	}
++
++	mpt_add_sge(psge, flagsLength, request_data_dma);
++	psge += (sizeof(u32) + sizeof(dma_addr_t));
++
++	memcpy(request_data,&karg.Parameters.Request,request_data_sz);
++
++	/* setup the *Response* payload SGE */
++	response_data = pci_alloc_consistent(
++	    ioc->pcidev, response_data_sz, &response_data_dma);
++
++	if (!response_data) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		goto cim_smp_passthru_exit;
++	}
++
++	flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++		MPI_SGE_FLAGS_SYSTEM_ADDRESS |
++		MPI_SGE_FLAGS_32_BIT_ADDRESSING |
++		MPI_SGE_FLAGS_IOC_TO_HOST |
++		MPI_SGE_FLAGS_END_OF_BUFFER;
++
++	if (sizeof(dma_addr_t) == sizeof(u64)) {
++		flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
++	}
++
++	flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
++	flagsLength |= response_data_sz;
++
++	mpt_add_sge(psge, flagsLength, response_data_dma);
++
++	/* The request is complete. Set the timer parameters
++	 * and issue the request.
++	 */
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*wait_timeout);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		goto cim_smp_passthru_exit;
++	}
++
++	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
++		dctlprintk((": SMP Passthru: oh no, there is no reply!!"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_smp_passthru_exit;
++	}
++
++	/* process the completed Reply Message Frame */
++	smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame;
++	ioc_stat = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++
++	if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) &&
++	    (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		dctlprintk((": SMP Passthru: "));
++		dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
++		    smpReply->IOCStatus,
++		    smpReply->IOCLogInfo,
++		    smpReply->SASStatus));
++		goto cim_smp_passthru_exit;
++	}
++
++	karg.Parameters.bConnectionStatus =
++	    map_sas_status_to_csmi(smpReply->SASStatus);
++
++
++	if (le16_to_cpu(smpReply->ResponseDataLength)) {
++		karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
++		memcpy(&karg.Parameters.Response,
++		    response_data, le16_to_cpu(smpReply->ResponseDataLength));
++	}
++
++cim_smp_passthru_exit:
++
++	ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID);
++
++	if (request_data)
++		pci_free_consistent(ioc->pcidev, request_data_sz,
++		    (u8 *)request_data, request_data_dma);
++
++	if (response_data)
++		pci_free_consistent(ioc->pcidev, response_data_sz,
++		    (u8 *)response_data, response_data_dma);
++
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++				sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_smp_passthru @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS SSP Passthru command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg)
++{
++	CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_SSP_PASSTHRU_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	pSCSIIORequest_t		pScsiRequest;
++	pSCSIIOReply_t			pScsiReply;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t 			*mpi_hdr;
++	int				iocnum,ii;
++	u32				data_sz;
++	u64				SASAddress64;
++	sas_device_info_t		*sasDevice;
++	u16				req_idx;
++	char				*psge;
++	int				flagsLength;
++	void *				request_data;
++	dma_addr_t			request_data_dma;
++	u32				request_data_sz;
++	u8				found;
++	u16				ioc_stat;
++	u8 				volume_id;
++	u8				volume_bus;
++	u8				quiese_io_flag=0;
++	u8				bus;
++	u8				target;
++	int				wait_timeout;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	request_data=NULL;
++	request_data_sz = karg.Parameters.uDataLength;
++	bus=0;
++	target=0;
++	volume_id=0;
++	volume_bus=0;
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s()"
++		    " @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Default to success.
++	 */
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Neither a phy nor a port has been selected.
++	 */
++	if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
++		(karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++		dctlprintk((KERN_ERR
++		    "%s::%s()"
++		    " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_ssp_passthru_exit;
++	}
++
++	/* A phy has been selected. Verify that it's valid.
++	 */
++	if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++
++		/* Is the phy in range? */
++		if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) {
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_PHY_DOES_NOT_EXIST;
++			goto cim_ssp_passthru_exit;
++		}
++	}
++
++	/* some checks of the incoming frame
++	 */
++	if (request_data_sz > 0xFFFF) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		dctlprintk((KERN_ERR
++		    "%s::%s()"
++		    " @%d - uDataLength > 0xFFFF!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_ssp_passthru_exit;
++	}
++
++	data_sz = sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER) -
++	    sizeof(IOCTL_HEADER) - sizeof(u8*) +
++	    request_data_sz;
++
++	if ( data_sz > karg.IoctlHeader.Length ) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		dctlprintk((KERN_ERR
++		    "%s::%s()"
++		    " @%d - expected datalen incorrect!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_ssp_passthru_exit;
++	}
++
++	/* we will use SAS address to resolve the scsi adddressing
++	 */
++	memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress,
++	    sizeof(u64));
++	SASAddress64 = reverse_byte_order64(&SASAddress64);
++
++	/* Search the list for the matching SAS address.
++	 */
++	found = FALSE;
++	list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++		/* Find the matching device.
++		 */
++		if (sasDevice->SASAddress != SASAddress64)
++			continue;
++
++		found = TRUE;
++		bus = sasDevice->Bus;
++		target = sasDevice->TargetId;
++		break;
++	}
++
++	/* Invalid SAS address
++	 */
++	if (found == FALSE) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		dctlprintk((KERN_ERR
++		    "%s::%s()"
++		    " @%d - couldn't find associated SASAddress!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_ssp_passthru_exit;
++	}
++
++	if(karg.Parameters.bAdditionalCDBLength) {
++	/* TODO - SCSI IO (32) Request Message support
++	 */
++		dctlprintk((": greater than 16-byte cdb is not supported!\n"));
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_ssp_passthru_exit;
++	}
++
++	/* see if this is for raid phy disk */
++	if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) {
++		for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks &&
++		    quiese_io_flag==0); ii++) {
++			if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) {
++				target = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum;
++				quiese_io_flag=1;
++			}
++		}
++	}
++#ifdef QUIESE_IO
++	/* if RAID Volume, then quiesce io to phys disk*/
++	if (quiese_io_flag==1) {
++		if (mptctl_raid_get_volume_id(ioc, target,
++		    &volume_id, &volume_bus) != 0) {
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_ssp_passthru_exit;
++		}
++		mptctl_do_raid(ioc,
++		    MPI_RAID_ACTION_QUIESCE_PHYS_IO,
++		    target, volume_bus, volume_id, NULL);
++	}
++#endif
++	/* Get a free request frame and save the message context.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_ssp_passthru_exit;
++        }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	pScsiRequest = (pSCSIIORequest_t) mf;
++	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++	memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
++
++	/* Fill in SCSI IO (16) request.
++	 */
++
++	pScsiRequest->Function = (quiese_io_flag==1) ?
++	    MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
++	pScsiRequest->TargetID = target;
++	pScsiRequest->Bus = bus;
++	memcpy(pScsiRequest->LUN,karg.Parameters.bLun,8);
++	pScsiRequest->CDBLength = karg.Parameters.bCDBLength;
++	pScsiRequest->DataLength = cpu_to_le16(request_data_sz);
++	pScsiRequest->MsgContext = mpi_hdr->MsgContext;
++	memcpy(pScsiRequest->CDB,karg.Parameters.bCDB,
++	    pScsiRequest->CDBLength);
++
++	/* direction
++	 */
++	if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) {
++		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++	} else if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
++	} else if ((karg.Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
++	    (!karg.Parameters.uDataLength)) {
++		/* no data transfer
++		 */
++		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
++	} else {
++		/* no direction specified
++		 */
++		pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++		pScsiRequest->MsgFlags =
++		    MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
++	}
++
++	/* task attributes
++	 */
++	if((karg.Parameters.uFlags && 0xFF) == 0) {
++		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
++	} else if (karg.Parameters.uFlags &
++	    CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
++		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
++	} else if (karg.Parameters.uFlags &
++	    CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
++		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
++	} else if (karg.Parameters.uFlags &
++	    CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
++		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
++	} else {
++		pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
++	}
++
++	/* setup sense
++	 */
++	pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
++	pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
++	    (req_idx * MPT_SENSE_BUFFER_ALLOC));
++
++	/* setup databuffer sg, assuming we fit everything one contiguous buffer
++	 */
++	psge = (char *)&pScsiRequest->SGL;
++
++	if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
++	} else if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) {
++		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++	}else {
++		flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++				MPI_SGE_FLAGS_DIRECTION |
++				mpt_addr_size() )
++				<< MPI_SGE_FLAGS_SHIFT;
++	}
++	flagsLength |= request_data_sz;
++
++	if ( request_data_sz > 0) {
++		request_data = pci_alloc_consistent(
++		    ioc->pcidev, request_data_sz, &request_data_dma);
++
++		if (request_data == NULL) {
++			dctlprintk((": pci_alloc_consistent: FAILED request_data_sz=%d\n", request_data_sz));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			mpt_free_msg_frame(ioc, mf);
++			goto cim_ssp_passthru_exit;
++		}
++
++		mpt_add_sge(psge, flagsLength, request_data_dma);
++
++		if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++
++			if (copy_from_user(request_data,
++			    karg.bDataBuffer,
++			    request_data_sz)) {
++				printk(KERN_ERR
++				"%s@%d::%s - Unable "
++				    "to read user data "
++				    "struct @ %p\n",
++				    __FILE__, __LINE__,__FUNCTION__,
++				    (void*)karg.bDataBuffer);
++				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++				mpt_free_msg_frame(ioc, mf);
++				goto cim_ssp_passthru_exit;
++			}
++		}
++	} else {
++		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
++	}
++
++	/* The request is complete. Set the timer parameters
++	 * and issue the request.
++	 */
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*wait_timeout);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		goto cim_ssp_passthru_exit;
++	}
++
++	memset(&karg.Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
++	karg.Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
++	karg.Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
++	karg.Status.bStatus = GOOD;
++	karg.Status.bResponseLength[0] = 0;
++	karg.Status.bResponseLength[1] = 0;
++	karg.Status.uDataBytes = request_data_sz;
++
++	/* process the completed Reply Message Frame */
++	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++
++		pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame;
++		karg.Status.bStatus = pScsiReply->SCSIStatus;
++		karg.Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
++		    request_data_sz);
++		ioc_stat = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++
++		if (pScsiReply->SCSIState ==
++		    MPI_SCSI_STATE_AUTOSENSE_VALID) {
++			karg.Status.bConnectionStatus =
++			    CSMI_SAS_SSP_SENSE_DATA_PRESENT;
++			karg.Status.bResponseLength[0] =
++				(u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
++			memcpy(karg.Status.bResponse,
++			    ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount));
++		} else if(pScsiReply->SCSIState ==
++		    MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
++			karg.Status.bDataPresent =
++			    CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
++			karg.Status.bResponseLength[0] =
++				sizeof(pScsiReply->ResponseInfo);
++			for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
++				karg.Status.bResponse[ii] =
++				((u8*)&pScsiReply->ResponseInfo)[
++				    (sizeof(pScsiReply->ResponseInfo)-1)-ii];
++			}
++		} else if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) &&
++		    (ioc_stat !=  MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
++		    (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			dctlprintk((": SCSI IO : "));
++			dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
++			    pScsiReply->IOCStatus,
++			    pScsiReply->IOCLogInfo));
++		}
++	}
++
++	if ((karg.Status.uDataBytes) && (request_data) &&
++	    (karg.Parameters.uFlags & CSMI_SAS_SSP_READ)) {
++		if (copy_to_user((char *)uarg->bDataBuffer,
++		    request_data, karg.Status.uDataBytes)) {
++			printk(KERN_ERR "%s@%d::%s - "
++			    "Unable to write data to user %p\n",
++			    __FILE__, __LINE__,__FUNCTION__,
++			    (void*)karg.bDataBuffer);
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		}
++	}
++
++cim_ssp_passthru_exit:
++
++	ioc->ioctl->status &= ~(  MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID);
++
++	if (request_data)
++		pci_free_consistent(ioc->pcidev, request_data_sz,
++		    (u8 *)request_data, request_data_dma);
++
++#ifdef QUIESE_IO
++	if (quiese_io_flag) {
++		mptctl_do_raid(ioc,
++		    MPI_RAID_ACTION_ENABLE_PHYS_IO,
++		    target, volume_bus, volume_id, NULL);
++	}
++#endif
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_ssp_passthru @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS STP Passthru command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_stp_passthru(unsigned long arg)
++{
++	CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_STP_PASSTHRU_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	pSataPassthroughRequest_t  	pSataRequest;
++	pSataPassthroughReply_t		pSataReply;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t 			*mpi_hdr;
++	int				iocnum,ii;
++	u32				data_sz;
++	u64				SASAddress64;
++	sas_device_info_t		*sasDevice=NULL;
++	u16				req_idx;
++	char				*psge;
++	int				flagsLength;
++	void *				request_data;
++	dma_addr_t			request_data_dma;
++	u32				request_data_sz;
++	u8				found;
++	u8				bus;
++	u8				target;
++	u8 				volume_id;
++	u8				volume_bus;
++#ifdef QUIESE_IO
++	u8				quiese_io_flag=0;
++	u8				phys_disk_num=0;
++#endif
++	int				wait_timeout;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	request_data=NULL;
++	request_data_sz = karg.Parameters.uDataLength;
++	volume_id=0;
++	volume_bus=0;
++	bus=0;
++	target=0;
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Default to success.
++	 */
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	/* Neither a phy nor a port has been selected.
++	 */
++	if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
++		(karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
++		    __FILE__,__FUNCTION__, __LINE__));
++		goto cim_stp_passthru_exit;
++	}
++
++	/* A phy has been selected. Verify that it's valid.
++	 */
++	if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++
++		/* Is the phy in range? */
++		if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) {
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_PHY_DOES_NOT_EXIST;
++			goto cim_stp_passthru_exit;
++		}
++	}
++
++	/* some checks of the incoming frame
++	 */
++	if (request_data_sz > 0xFFFF) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - uDataLength > 0xFFFF!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_stp_passthru_exit;
++	}
++
++	data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
++	    sizeof(IOCTL_HEADER) - sizeof(u8*) +
++	    request_data_sz;
++
++	if ( data_sz > karg.IoctlHeader.Length ) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - expected datalen incorrect!\n",
++		    __FILE__, __FUNCTION__,__LINE__));
++		goto cim_stp_passthru_exit;
++	}
++
++	/* we will use SAS address to resolve the scsi adddressing
++	 */
++	memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress,
++	    sizeof(u64));
++	SASAddress64 = reverse_byte_order64(&SASAddress64);
++
++	/* Search the list for the matching SAS address.
++	 */
++	found = FALSE;
++	list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++		/* Find the matching device.
++		 */
++		if (sasDevice->SASAddress != SASAddress64)
++			continue;
++
++		found = TRUE;
++		bus = sasDevice->Bus;
++		target = sasDevice->TargetId;;
++		break;
++	}
++
++	/* Invalid SAS address
++	 */
++	if (found == FALSE) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - couldn't find associated SASAddress!\n",
++		    __FILE__, __FUNCTION__, __LINE__));
++		goto cim_stp_passthru_exit;
++	}
++
++	/* check that this is an STP or SATA target device
++	 */
++	if ( !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
++	     !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_stp_passthru_exit;
++	}
++
++#ifdef QUIESE_IO
++	/* see if this is for raid phy disk */
++	if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) {
++		for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks &&
++		    quiese_io_flag==0); ii++)
++			if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) {
++				phys_disk_num = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum;
++				quiese_io_flag=1;
++			}
++	}
++	/* if RAID Volume, then quiesce io to phys disk*/
++	if (quiese_io_flag==1) {
++		if (mptctl_raid_get_volume_id(ioc, phys_disk_num,
++		    &volume_id, &volume_bus) != 0) {
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_stp_passthru_exit;
++		}
++		mptctl_do_raid(ioc,
++		    MPI_RAID_ACTION_QUIESCE_PHYS_IO,
++		    phys_disk_num, volume_bus, volume_id, NULL);
++	}
++#endif
++	/* Get a free request frame and save the message context.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_stp_passthru_exit;
++        }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	pSataRequest = (pSataPassthroughRequest_t) mf;
++	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++	memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
++
++	pSataRequest->TargetID = target;
++	pSataRequest->Bus = bus;
++	pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
++	pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags);
++	pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate;
++	pSataRequest->MsgContext = mpi_hdr->MsgContext;
++	pSataRequest->DataLength = cpu_to_le32(request_data_sz);
++	pSataRequest->MsgFlags = 0;
++	memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20);
++
++	psge = (char *)&pSataRequest->SGL;
++	if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
++		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
++	} else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) {
++		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++	}else {
++		flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++				MPI_SGE_FLAGS_DIRECTION |
++				mpt_addr_size() )
++				<< MPI_SGE_FLAGS_SHIFT;
++	}
++
++	flagsLength |= request_data_sz;
++	if (request_data_sz > 0) {
++		request_data = pci_alloc_consistent(
++		    ioc->pcidev, request_data_sz, &request_data_dma);
++
++		if (request_data == NULL) {
++			dctlprintk((": pci_alloc_consistent: FAILED\n"));
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			mpt_free_msg_frame(ioc, mf);
++			goto cim_stp_passthru_exit;
++		}
++
++		mpt_add_sge(psge, flagsLength, request_data_dma);
++		if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
++			if (copy_from_user(request_data,
++			    karg.bDataBuffer,
++			    request_data_sz)) {
++				printk(KERN_ERR
++				    "%s::%s() @%d - Unable to read user data "
++				    "struct @ %p\n",
++				    __FILE__, __FUNCTION__, __LINE__,
++				    (void*)karg.bDataBuffer);
++				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++				mpt_free_msg_frame(ioc, mf);
++				goto cim_stp_passthru_exit;
++			}
++		}
++	} else {
++		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
++	}
++
++	/* The request is complete. Set the timer parameters
++	 * and issue the request.
++	 */
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*wait_timeout);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		goto cim_stp_passthru_exit;
++	}
++
++	memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
++
++	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
++		dctlprintk((": STP Passthru: oh no, there is no reply!!"));
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_stp_passthru_exit;
++	}
++
++	/* process the completed Reply Message Frame */
++	pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame;
++
++	if ((le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) &&
++	    (le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN )) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		dctlprintk((": STP Passthru: "));
++		dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
++		    le16_to_cpu(pSataReply->IOCStatus),
++		    le32_to_cpu(pSataReply->IOCLogInfo),
++		    pSataReply->SASStatus));
++	}
++
++	karg.Status.bConnectionStatus =
++	    map_sas_status_to_csmi(pSataReply->SASStatus);
++
++	memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20);
++
++	/*
++	 * for now, just zero out uSCR array,
++	 * then copy the one dword returned
++	 * in the reply frame into uSCR[0]
++	 */
++	memset( karg.Status.uSCR, 0, 64);
++	karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
++
++	if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
++	    (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) {
++		karg.Status.uDataBytes =
++		    min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
++		if (copy_to_user((char *)uarg->bDataBuffer,
++		    request_data, karg.Status.uDataBytes)) {
++			printk(KERN_ERR "%s::%s() @%d - "
++			    "Unable to write data to user %p\n",
++			    __FILE__, __FUNCTION__, __LINE__,
++			    (void*)karg.bDataBuffer);
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		}
++	}
++
++cim_stp_passthru_exit:
++
++	ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID );
++
++	if (request_data)
++		pci_free_consistent(ioc->pcidev, request_data_sz,
++		    (u8 *)request_data, request_data_dma);
++
++#ifdef QUIESE_IO
++	if (quiese_io_flag)
++		mptctl_do_raid(ioc,
++		    MPI_RAID_ACTION_ENABLE_PHYS_IO,
++		    phys_disk_num, volume_bus, volume_id, NULL);
++#endif
++
++	/* Copy th data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++	    offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_ssp_passthru @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Firmware Download command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_firmware_download(unsigned long arg)
++{
++	CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++	pMpiFwHeader_t			pFwHeader=NULL;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg,
++		sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_firmware_download struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* Default to success.*/
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++	karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
++	karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
++
++	/* some checks of the incoming frame */
++	if ((karg.Information.uBufferLength +
++	    sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
++	    karg.IoctlHeader.Length) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++		goto cim_firmware_download_exit;
++	}
++
++	if ( karg.Information.uDownloadFlags &
++	    (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++		goto cim_firmware_download_exit;
++	}
++
++	/* now we need to alloc memory so we can pull in the
++	 * fw image attached to end of incomming packet.
++	 */
++	pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
++	if(pFwHeader==NULL){
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++		goto cim_firmware_download_exit;
++	}
++
++	if (copy_from_user(pFwHeader, uarg->bDataBuffer,
++		karg.Information.uBufferLength)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in pFwHeader @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
++	    (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
++	    (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
++		// the signature check failed
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++		karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++		goto cim_firmware_download_exit;
++	}
++
++	if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
++	    uarg->bDataBuffer, karg.Information.uBufferLength)
++	    != 0) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++		karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
++		goto cim_firmware_download_exit;
++	}
++
++	if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
++	    (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
++		if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++			karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
++		}
++	}
++
++cim_firmware_download_exit:
++
++	if(pFwHeader)
++		kfree(pFwHeader);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++				sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_firmware_download @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Info command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_info(unsigned long arg)
++{
++	CSMI_SAS_RAID_INFO_BUFFER __user *uarg =  (void __user *) arg;
++	CSMI_SAS_RAID_INFO_BUFFER	 karg;
++	MPT_ADAPTER		*ioc = NULL;
++	int				iocnum;
++    u32             raidFlags;
++	u8				maxRaidTypes;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++	if( !mpt_findImVolumes(ioc)) {
++		if ( ioc->raid_data.pIocPg2 ) {
++			karg.Information.uNumRaidSets = ioc->raid_data.pIocPg2->NumActiveVolumes;
++            // uMaxDrivesPerSet hard coded until value is available through RAID config page
++			karg.Information.uMaxDrivesPerSet = 8;
++            karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
++            // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
++            raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
++            for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
++            {
++                raidFlags &= raidFlags - 1;
++            }
++            karg.Information.bMaxRaidTypes = maxRaidTypes;
++            // ulMinRaidSetBlocks hard coded to 1MB until available from config page
++            karg.Information.ulMinRaidSetBlocks = 2048;
++            karg.Information.ulMaxRaidSetBlocks = 
++                (ioc->raid_data.pIocPg2->CapabilitiesFlags & 
++                 MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING)
++                ? 0xffffffffffffffffULL : 0x00000000ffffffffULL;
++            karg.Information.uMaxPhysicalDrives = ioc->raid_data.pIocPg2->MaxPhysDisks;
++            karg.Information.uMaxExtents = 1;
++            karg.Information.uMaxModules = 0;
++            karg.Information.uMaxTransformationMemory = 0;
++            karg.Information.uChangeCount = ioc->csmi_change_count;
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++		}
++	}
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++				sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_get_raid_info @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*	mptscsih_do_raid - Format and Issue a RAID volume request message.
++ *	@ioc: Pointer to MPT_ADAPTER structure
++ *	@action: What do be done.
++ *	@PhysDiskNum: Logical target id.
++ *	@VolumeBus: Target locations bus.
++ *	@VolumeId: Volume id
++ *
++ *	Returns: < 0 on a fatal error
++ *		0 on success
++ *
++ *	Remark: Wait to return until reply processed by the ISR.
++ */
++static int
++mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
++{
++	MpiRaidActionRequest_t	*pReq;
++	MpiRaidActionReply_t	*pReply;
++	MPT_FRAME_HDR		*mf;
++	int ii;
++
++	/* Get and Populate a free Frame
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		return -EAGAIN;
++	}
++	pReq = (MpiRaidActionRequest_t *)mf;
++	pReq->Action = action;
++	pReq->Reserved1 = 0;
++	pReq->ChainOffset = 0;
++	pReq->Function = MPI_FUNCTION_RAID_ACTION;
++	pReq->VolumeID = VolumeId;
++	pReq->VolumeBus = VolumeBus;
++	pReq->PhysDiskNum = PhysDiskNum;
++	pReq->MsgFlags = 0;
++	pReq->Reserved2 = 0;
++	pReq->ActionDataWord = 0; /* Reserved for this action */
++	//pReq->ActionDataSGE = 0;
++
++	mpt_add_sge((char *)&pReq->ActionDataSGE,
++		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
++
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		return -ENODATA;
++	}
++
++	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) &&
++	    (reply != NULL)){
++		pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame);
++		memcpy(reply, pReply,
++			min(ioc->reply_sz,
++			4*pReply->MsgLength));
++	}
++
++	return 0;
++}
++
++#ifdef QUIESE_IO
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*	mptctl_raid_get_volume_id - figures out which Volume a PhysDisk belongs to.
++ *	@ioc: Pointer to MPT_ADAPTER structure
++ *	@PhysDiskNum: an unique number assigned by IOC to identify a specific IR phy disk
++ *
++ *	Returns: < 0 on a fatal error
++ *		0 on success
++ *
++ * 	Following parameters are valid when successful return
++ *	@VolumeID - target device identification number of the volume
++ *	@VolumeBus - the SCSI bus number of the volume
++ *
++ */
++static int
++mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID, u8 *VolumeBus)
++{
++	CONFIGPARMS		cfg;
++	ConfigPageHeader_t	header;
++	dma_addr_t		volume0_dma;
++	int			i,j;
++	int			rc=0;
++	int			volumepage0sz = 0;
++	pRaidVolumePage0_t	pVolume0 = NULL;
++
++	/*
++	 * get RAID Volume Page 0
++	 */
++	header.PageVersion = 0;
++	header.PageLength = 0;
++	header.PageNumber = 0;
++	header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++	cfg.cfghdr.hdr = &header;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++	if (mpt_config(ioc, &cfg) != 0) {
++		rc = -1;
++		goto mptctl_raid_get_volume_id_exit;
++	}
++
++	if (header.PageLength == 0) {
++		rc = -1;
++		goto mptctl_raid_get_volume_id_exit;
++	}
++
++	volumepage0sz = header.PageLength * 4;
++	pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++	    &volume0_dma);
++	if (!pVolume0) {
++		rc = -1;
++		goto mptctl_raid_get_volume_id_exit;
++	}
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++	cfg.physAddr = volume0_dma;
++
++	for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
++		*VolumeID = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID;
++		*VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
++		cfg.pageAddr = (*VolumeBus << 8) + *VolumeID;
++		if (mpt_config(ioc, &cfg) != 0){
++			rc = -1;
++			goto mptctl_raid_get_volume_id_exit;
++		}
++		for (j=0; j<pVolume0->NumPhysDisks; j++){
++			if (PhysDiskNum == pVolume0->PhysDisk[i].PhysDiskNum)
++				goto mptctl_raid_get_volume_id_exit;
++		}
++	}
++
++mptctl_raid_get_volume_id_exit:
++
++	if (pVolume0 != NULL)
++		pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++		    volume0_dma);
++
++	return rc;
++}
++#endif
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* mptctl_raid_inq
++ * @ioc = per host instance
++ * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or MPI_FUNCTION_SCSI_IO_REQUEST
++ * @target = target id
++ * @inq_vpd = inquiry data, returned
++ * @inq_vpd_sz = maximum size of inquiry data
++ *
++ * Return = 0(sucess), non-zero(failure)
++ */
++static int
++mptctl_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 target, u8 inq_vpd_page, u8 * inq_vpd, u32 inq_vpd_sz)
++{
++	MPT_FRAME_HDR		*mf = NULL;
++	MPIHeader_t 		*mpi_hdr;
++	pSCSIIORequest_t	pScsiRequest;
++	u16			        req_idx;
++	char			    *psge;
++	u8 			        inq_vpd_cdb[6];
++	u8 			        *request_data=NULL;
++	dma_addr_t		    request_data_dma;
++	u32			        request_data_sz;
++	int		    	    rc=0,ii;
++
++	request_data_sz = 0xFFFF; /* max data size */
++
++    /* fill-in cdb */
++    inq_vpd_cdb[0] = 0x12;
++    if (inq_vpd_page) {
++        inq_vpd_cdb[1] = 0x01; /* evpd bit */
++        inq_vpd_cdb[2] = inq_vpd_page;
++    }
++    inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
++    inq_vpd_cdb[4] = (u8)request_data_sz;
++
++	/* Get a free request frame and save the message context.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		goto mptctl_raid_inq_exit;
++    }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	pScsiRequest = (pSCSIIORequest_t) mf;
++	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++	memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
++	pScsiRequest->Function = opcode;
++	pScsiRequest->TargetID = target;
++	pScsiRequest->Bus = 0;
++	pScsiRequest->CDBLength = 6;
++	pScsiRequest->DataLength = cpu_to_le16(request_data_sz);
++	pScsiRequest->MsgContext = mpi_hdr->MsgContext;
++	memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
++	pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++	pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
++
++	/* setup sense
++	 */
++	pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
++	pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
++	    (req_idx * MPT_SENSE_BUFFER_ALLOC));
++
++	request_data = pci_alloc_consistent(
++	    ioc->pcidev, request_data_sz, &request_data_dma);
++
++	if (request_data == NULL) {
++		mpt_free_msg_frame(ioc, mf);
++		rc=-1;
++		goto mptctl_raid_inq_exit;
++	}
++
++	memset(request_data,0,request_data_sz);
++	psge = (char *)&pScsiRequest->SGL;
++	mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) , request_data_dma);
++
++	/* The request is complete. Set the timer parameters
++	 * and issue the request.
++	 */
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now we need to reset the board */
++		rc=-1;
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		goto mptctl_raid_inq_exit;
++	}
++
++    /* copy the request_data */
++    memcpy(inq_vpd,request_data,min(request_data_sz,inq_vpd_sz));
++
++mptctl_raid_inq_exit:
++
++	if (request_data)
++		pci_free_consistent(ioc->pcidev, request_data_sz,
++		    request_data, request_data_dma);
++
++    return rc;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Config command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_config(unsigned long arg)
++{
++	CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_RAID_CONFIG_BUFFER	 karg,*pKarg=NULL;
++	CONFIGPARMS		 	cfg;
++	ConfigPageHeader_t	 	header;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++	u8				volumeID, VolumeBus, physDiskNum, physDiskNumMax, found;
++	int			 	volumepage0sz = 0, physdiskpage0sz = 0, ioc_page5_sz = 0;
++	dma_addr_t			volume0_dma, physdisk0_dma, ioc_page5_dma;
++	pRaidVolumePage0_t		pVolume0 = NULL;
++	pRaidPhysDiskPage0_t		pPhysDisk0 = NULL;
++	pMpiRaidActionReply_t 		pRaidActionReply = NULL;
++	pIOCPage5_t			pIocPage5 = NULL;
++	int 				i, idx, csmi_sas_raid_config_buffer_sz;
++    int                 copy_buffer_sz=0;
++	sas_device_info_t		*sasDevice;
++	u32				device_info=0;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_config struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
++	pKarg = kmalloc(csmi_sas_raid_config_buffer_sz, GFP_KERNEL);
++	if(!pKarg){
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to malloc @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__,pKarg);
++		return -EFAULT;
++	}
++
++	if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_config struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(pKarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++	if (!ioc->raid_data.isRaid) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++    if (pKarg->Configuration.uChangeCount != 0 &&
++        pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++	    	CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Configuration.uFailureCode = 
++	    //	CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_config_exit;
++    }
++
++	/* check to see if the input uRaidSetIndex is greater than the number of RAID sets */
++	if(pKarg->Configuration.uRaidSetIndex >=
++	    ioc->raid_data.pIocPg2->NumActiveVolumes) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
++		goto cim_get_raid_config_exit;
++	}
++
++	/*
++	 * get RAID Volume Page 0
++	 */
++	volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
++	VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
++
++	header.PageVersion = 0;
++	header.PageLength = 0;
++	header.PageNumber = 0;
++	header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++	cfg.cfghdr.hdr = &header;
++	cfg.physAddr = -1;
++	cfg.pageAddr = (VolumeBus << 8) + volumeID;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++	if (mpt_config(ioc, &cfg) != 0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	if (header.PageLength == 0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	volumepage0sz = header.PageLength * 4;
++	pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++	    &volume0_dma);
++	if (!pVolume0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++	cfg.physAddr = volume0_dma;
++	if (mpt_config(ioc, &cfg) != 0){
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	pKarg->Configuration.uCapacity =
++		(le32_to_cpu(pVolume0->MaxLBA)+1)/2048;
++	pKarg->Configuration.uStripeSize =
++		le32_to_cpu(pVolume0->StripeSize)/2;
++
++	switch(pVolume0->VolumeType) {
++	case MPI_RAID_VOL_TYPE_IS:
++		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
++		break;
++	case MPI_RAID_VOL_TYPE_IME:
++		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
++		break;
++	case MPI_RAID_VOL_TYPE_IM:
++		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
++		break;
++	default:
++		pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
++		break;
++	}
++
++    switch (pVolume0->VolumeStatus.State) {
++	case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
++		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
++		break;
++    case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
++        /* Volume is degraded, check if Resyncing or Inactive */
++        if (pVolume0->VolumeStatus.State & 
++            MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
++        }
++        else if (pVolume0->VolumeStatus.State & 
++                 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
++        }
++        else {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
++        }
++		break;
++	case MPI_RAIDVOL0_STATUS_STATE_FAILED:
++		pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
++		break;
++	}
++
++    pKarg->Configuration.bInformation = 0;  /* default */
++	if(pVolume0->VolumeStatus.Flags &
++	    MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
++
++		uint64_t 	* ptrUint64;
++		uint64_t	totalBlocks64, blocksRemaining64;
++		uint32_t	totalBlocks32, blocksRemaining32;
++
++		/* get percentage complete */
++		pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
++		    offsetof(MSG_RAID_ACTION_REPLY,ActionData),
++		    GFP_KERNEL);
++
++		if(pRaidActionReply == NULL){
++			printk(KERN_ERR "%s@%d::%s() - "
++			    "Unable to malloc @ %p\n",
++			    __FILE__, __LINE__, __FUNCTION__,pKarg);
++			goto cim_get_raid_config_exit;
++		}
++
++		mptctl_do_raid(ioc,
++		    MPI_RAID_ACTION_INDICATOR_STRUCT,
++		    0, VolumeBus, volumeID, pRaidActionReply);
++
++		ptrUint64       = (uint64_t *)&pRaidActionReply->ActionData;
++		totalBlocks64     = *ptrUint64;
++		ptrUint64++;
++		blocksRemaining64 = *ptrUint64;
++		while(totalBlocks64 > 0xFFFFFFFFUL){
++			totalBlocks64 = totalBlocks64 >> 1;
++			blocksRemaining64 = blocksRemaining64 >> 1;
++		}
++		totalBlocks32 = (uint32_t)totalBlocks64;
++		blocksRemaining32 = (uint32_t)blocksRemaining64;
++
++		if(totalBlocks32)
++			pKarg->Configuration.bInformation =
++			    (totalBlocks32 - blocksRemaining32) /
++			    (totalBlocks32 / 100);
++
++		kfree(pRaidActionReply);
++	}
++
++    /* fill-in more information depending on data type */
++    if (pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
++        pKarg->Configuration.Data->bLabel[0] = '\0';
++        pKarg->Configuration.Data->bRaidSetLun[1] = 0;
++        pKarg->Configuration.Data->bWriteProtection = 
++            CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
++        pKarg->Configuration.Data->bCacheSetting = 
++            CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
++        pKarg->Configuration.Data->bCacheRatio = 0;
++        pKarg->Configuration.Data->usBlockSize = 512;
++        pKarg->Configuration.Data->ulRaidSetExtentOffset = 0;
++        pKarg->Configuration.Data->ulRaidSetBlocks = le32_to_cpu(pVolume0->MaxLBA);
++        if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
++            pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
++            pKarg->Configuration.Data->uStripeSizeInBlocks = 
++                le32_to_cpu(pVolume0->StripeSize);
++        }
++        else {
++            pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
++        }
++        pKarg->Configuration.Data->uSectorsPerTrack = 128;
++        for (i=0; i<16; i++) {
++            // unsupported
++            pKarg->Configuration.Data->bApplicationScratchPad[i] = 0xFF;
++        }
++    }
++    else if( pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_DEVICE_ID ) {
++        /* Send inquiry to get VPD Page 0x83 */
++        u8 * vpd_page=NULL;
++        u32 vpd_page_sz;
++        vpd_page_sz = pKarg->IoctlHeader.Length - sizeof(CSMI_SAS_RAID_CONFIG);
++		vpd_page = kmalloc(vpd_page_sz, GFP_KERNEL);
++        if (mptctl_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST, volumeID, 0x83, vpd_page, vpd_page_sz) != 0) {
++            pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			kfree(vpd_page);
++            goto cim_get_raid_config_exit;
++        }
++        memset(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
++               0,vpd_page_sz);
++        memcpy(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage, 
++               vpd_page,vpd_page_sz);
++		kfree(vpd_page);
++    }
++
++    if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) {
++        pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++        goto cim_get_raid_config_exit;
++    }
++
++    /* suppress drive information */
++    if (pKarg->Configuration.bDriveCount == 
++        CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
++            pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++            goto cim_get_raid_config_exit;
++    }
++
++	/* get hotspare info, used later in this function */
++	if (pVolume0->VolumeSettings.HotSparePool) {
++		/* Read and save IOC Page 5
++		 */
++		header.PageVersion = 0;
++		header.PageLength = 0;
++		header.PageNumber = 5;
++		header.PageType = MPI_CONFIG_PAGETYPE_IOC;
++		cfg.cfghdr.hdr = &header;
++		cfg.physAddr = -1;
++		cfg.pageAddr = 0;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++		cfg.dir = 0;
++		cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++		if ((mpt_config(ioc, &cfg)==0) && (header.PageLength)) {
++			ioc_page5_sz = header.PageLength * 4;
++			pIocPage5 = pci_alloc_consistent(ioc->pcidev,
++			    ioc_page5_sz,
++			    &ioc_page5_dma);
++			memset(pIocPage5,0,ioc_page5_sz);
++			if (ioc_page5_dma) {
++				cfg.physAddr = ioc_page5_dma;
++				cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++				mpt_config(ioc, &cfg);
++			}
++		}
++	}
++
++	/*
++	 * get RAID Physical Disk Page 0
++	 */
++	header.PageVersion = 0;
++	header.PageLength = 0;
++	header.PageNumber = 0;
++	header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
++	cfg.cfghdr.hdr = &header;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++	if (mpt_config(ioc, &cfg) != 0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	if (header.PageLength == 0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++
++	physdiskpage0sz = header.PageLength * 4;
++	pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
++	    &physdisk0_dma);
++	if (!pPhysDisk0) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_config_exit;
++	}
++	cfg.physAddr = physdisk0_dma;
++
++	physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
++	    offsetof(CSMI_SAS_RAID_CONFIG,Drives))
++	    / sizeof(CSMI_SAS_RAID_DRIVES);
++
++	pKarg->Configuration.bDriveCount=0;
++
++	for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
++
++		physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++		cfg.pageAddr = physDiskNum;
++		if (mpt_config(ioc, &cfg) != 0){
++			pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_get_raid_config_exit;
++		}
++		memset(&pKarg->Configuration.Drives[i],0,
++		    sizeof(CSMI_SAS_RAID_DRIVES));
++		memcpy(pKarg->Configuration.Drives[i].bModel,
++		    pPhysDisk0->InquiryData.VendorID,
++		    offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
++		memcpy(pKarg->Configuration.Drives[i].bFirmware,
++			pPhysDisk0->InquiryData.ProductRevLevel,
++			sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
++		if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') &&
++		    (pPhysDisk0->ExtDiskIdentifier[1] == 'T') &&
++		    (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) {
++			memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
++				&pPhysDisk0->ExtDiskIdentifier[4],
++				4);
++			memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
++				&pPhysDisk0->DiskIdentifier,
++				sizeof(pPhysDisk0->DiskIdentifier));
++		} else {
++			memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
++				pPhysDisk0->DiskIdentifier,
++				sizeof(pPhysDisk0->DiskIdentifier));
++		}
++
++		pKarg->Configuration.Drives[i].bDriveUsage =
++		    (pPhysDisk0->PhysDiskStatus.Flags &
++		    MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
++		    CSMI_SAS_DRIVE_CONFIG_NOT_USED :
++		    CSMI_SAS_DRIVE_CONFIG_MEMBER;
++
++		pKarg->Configuration.Drives[i].bDriveStatus =
++		    CSMI_SAS_DRIVE_STATUS_OK;
++        if (pPhysDisk0->PhysDiskStatus.State == 
++            MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
++            pKarg->Configuration.Drives[i].bDriveStatus = 
++                CSMI_SAS_DRIVE_STATUS_OFFLINE;
++        }
++        else if(pPhysDisk0->PhysDiskStatus.State) {
++			pKarg->Configuration.Drives[i].bDriveStatus =
++			    CSMI_SAS_DRIVE_STATUS_FAILED;
++			if(pKarg->Configuration.bStatus ==
++			    CSMI_SAS_RAID_SET_STATUS_DEGRADED)
++				pKarg->Configuration.bInformation = i;
++		}
++		else if((pVolume0->VolumeStatus.Flags &
++		    MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
++		    (pPhysDisk0->PhysDiskStatus.Flags &
++		    MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
++			pKarg->Configuration.Drives[i].bDriveStatus =
++			    CSMI_SAS_DRIVE_STATUS_REBUILDING;
++		else if(pPhysDisk0->ErrorData.SmartCount)
++			pKarg->Configuration.Drives[i].bDriveStatus =
++			CSMI_SAS_DRIVE_STATUS_DEGRADED;
++
++		/* Search the list for the matching SAS address. */
++		found = FALSE;
++		list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++			/* Found the matching device. */
++			if ((pPhysDisk0->PhysDiskIOC == sasDevice->Bus) &&
++				(pPhysDisk0->PhysDiskID ==
++				 sasDevice->TargetId)) {
++				u64 SASAddress64;
++				found = TRUE;
++
++				SASAddress64 =
++				    reverse_byte_order64(&sasDevice->SASAddress);
++				memcpy(pKarg->Configuration.Drives[i].bSASAddress,
++				   &SASAddress64,sizeof(u64));
++				memset(pKarg->Configuration.Drives[i].bSASLun,
++				    0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
++				device_info = sasDevice->DeviceInfo;
++                if (device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) {
++                    pKarg->Configuration.Drives[i].bDriveType = 
++                        CSMI_SAS_DRIVE_TYPE_SATA;
++                }
++                else { /* drive in a volume can only be SAS/SATA */
++                    pKarg->Configuration.Drives[i].bDriveType = 
++                        CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
++                }
++				break;
++			} else
++				continue; /* Keep looking. */
++		}
++        pKarg->Configuration.Drives[i].usBlockSize = 512;
++		pKarg->Configuration.Drives[i].uDriveIndex = pPhysDisk0->PhysDiskNum;
++        if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IM) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                le32_to_cpu(pVolume0->MaxLBA) + 1;
++        }
++        else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                (le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks);
++        }
++        else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                ((le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks)) * 2;
++        }
++        pKarg->Configuration.bDriveCount++;
++	}
++
++	/* adding hot spare info at the end */
++	if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5 != NULL)) {
++		for (idx = 0, i = pVolume0->NumPhysDisks ;
++		    idx < pIocPage5->NumHotSpares ; idx++) {
++			if (i >= physDiskNumMax)
++				break;
++			if ((pVolume0->VolumeSettings.HotSparePool &
++			    pIocPage5->HotSpare[idx].HotSparePool) == 0)
++				continue;
++			if(pIocPage5->HotSpare[idx].Flags !=
++			    MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
++			    continue;
++			physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
++			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++			cfg.pageAddr = physDiskNum;
++			if (mpt_config(ioc, &cfg) != 0)
++				continue;
++			/* Search the list for the matching SAS address. */
++			found = FALSE;
++			list_for_each_entry(sasDevice, &ioc->sasDeviceList,
++			    list) {
++				/* Found the matching device. */
++				if ((pPhysDisk0->PhysDiskIOC ==
++					sasDevice->Bus) &&
++					(pPhysDisk0->PhysDiskID ==
++					 sasDevice->TargetId)) {
++					u64 SASAddress64;
++
++					/* sanity checks */
++
++					/* don't mix SSP hot spare
++					 * in SATA volume
++					 */
++					if ((sasDevice->DeviceInfo &
++					    MPI_SAS_DEVICE_INFO_SSP_TARGET) &&
++					    (device_info &
++					    MPI_SAS_DEVICE_INFO_SATA_DEVICE))
++						break;
++
++					/* don't mix SATA hot spare
++					 * in SSP volume
++					 */
++					if ((sasDevice->DeviceInfo &
++					    MPI_SAS_DEVICE_INFO_SATA_DEVICE) &&
++					    (device_info &
++					    MPI_SAS_DEVICE_INFO_SSP_TARGET))
++						break;
++
++					/* capacity check for IM volumes*/
++					if ((pVolume0->VolumeType ==
++						MPI_RAID_VOL_TYPE_IM) &&
++					    (le32_to_cpu(pVolume0->MaxLBA) +
++					     (64*2*1024) /* metadata = 64MB*/ >
++					    le32_to_cpu(pPhysDisk0->MaxLBA)))
++						break;
++
++					/* capacity check for IME volumes*/
++					if ((pVolume0->VolumeType ==
++						MPI_RAID_VOL_TYPE_IME) &&
++					    (((le32_to_cpu(pVolume0->MaxLBA)/
++					      pVolume0->NumPhysDisks) * 2) +
++					     (64*2*1024 ) /*metadata = 64MB*/ >
++					    le32_to_cpu(pPhysDisk0->MaxLBA)))
++						break;
++
++					found = TRUE;
++
++					SASAddress64 =
++					    reverse_byte_order64(&sasDevice->SASAddress);
++					memcpy(pKarg->Configuration.Drives[i].bSASAddress,
++					   &SASAddress64,sizeof(u64));
++					memset(pKarg->Configuration.Drives[i].bSASLun, 0,
++					     sizeof(pKarg->Configuration.Drives[i].bSASLun));
++					break;
++				} else
++					continue; /* Keep looking. */
++			}
++			if (found==FALSE)
++				continue;
++			memset(&pKarg->Configuration.Drives[i],0,
++			    sizeof(CSMI_SAS_RAID_DRIVES));
++			memcpy(pKarg->Configuration.Drives[i].bModel,
++			    pPhysDisk0->InquiryData.VendorID,
++			    offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
++			memcpy(pKarg->Configuration.Drives[i].bFirmware,
++				pPhysDisk0->InquiryData.ProductRevLevel,
++				sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
++			if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') &&
++			    (pPhysDisk0->ExtDiskIdentifier[1] == 'T') &&
++			    (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) {
++				memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
++					&pPhysDisk0->ExtDiskIdentifier[4],
++					4);
++				memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
++					&pPhysDisk0->DiskIdentifier,
++					sizeof(pPhysDisk0->DiskIdentifier));
++			} else {
++				memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
++					pPhysDisk0->DiskIdentifier,
++					sizeof(pPhysDisk0->DiskIdentifier));
++			}
++			pKarg->Configuration.Drives[i].bDriveStatus =
++			    CSMI_SAS_DRIVE_STATUS_OK;
++			if(pPhysDisk0->PhysDiskStatus.State)
++				pKarg->Configuration.Drives[i].bDriveStatus =
++				    CSMI_SAS_DRIVE_STATUS_FAILED;
++			else if(pPhysDisk0->ErrorData.SmartCount)
++				pKarg->Configuration.Drives[i].bDriveStatus =
++				    CSMI_SAS_DRIVE_STATUS_DEGRADED;
++			pKarg->Configuration.Drives[i].bDriveUsage =
++			    CSMI_SAS_DRIVE_CONFIG_SPARE;
++			i++;
++			pKarg->Configuration.bDriveCount++;
++		}
++	}
++
++    // Only return data on the first 240 drives
++    if( pKarg->Configuration.bDriveCount > 0xF0 ) {
++        pKarg->Configuration.bDriveCount = 
++            CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
++    }
++
++	pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++cim_get_raid_config_exit:
++
++	if (pVolume0 != NULL)
++		pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++		    volume0_dma);
++
++	if(pPhysDisk0 != NULL)
++		pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
++		    physdisk0_dma);
++
++	if(pIocPage5 != NULL)
++		pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
++		    ioc_page5_dma);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++
++    /* find the buffer size to copy depending on how much is filled-in */
++    switch (pKarg->Configuration.bDataType) {
++    case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
++        copy_buffer_sz = sizeof(IOCTL_HEADER) +
++            offsetof(CSMI_SAS_RAID_CONFIG,Data) +
++            sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
++        break;
++    case CSMI_SAS_RAID_DATA_DRIVES:
++        if (pKarg->Configuration.bDriveCount == 
++            CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
++            copy_buffer_sz = sizeof(IOCTL_HEADER) +
++                offsetof(CSMI_SAS_RAID_CONFIG,Drives);
++        }
++        else {
++            copy_buffer_sz = sizeof(IOCTL_HEADER) +
++                offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
++                (pKarg->Configuration.bDriveCount * sizeof(CSMI_SAS_RAID_DRIVES));
++        }
++        break;
++    case CSMI_SAS_RAID_DATA_DEVICE_ID:
++        copy_buffer_sz = sizeof(IOCTL_HEADER) +
++            offsetof(CSMI_SAS_RAID_CONFIG,DeviceId) +
++            sizeof(CSMI_SAS_RAID_DEVICE_ID);
++        break;
++    }
++
++    if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		       "Unable to write out csmi_sas_get_raid_config @ %p\n",
++		   	   __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(pKarg);
++		return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Features command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_features(unsigned long arg)
++{
++	CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
++	int i, csmi_sas_raid_features_buffer_sz, iocnum;
++    MPT_ADAPTER			*ioc = NULL;
++
++    u8 raidTypes[4] = { CSMI_SAS_RAID_TYPE_0, CSMI_SAS_RAID_TYPE_10,
++                        CSMI_SAS_RAID_TYPE_1, CSMI_SAS_RAID_TYPE_1E };
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
++	pKarg = kmalloc(csmi_sas_raid_features_buffer_sz, GFP_KERNEL);
++	if(!pKarg){
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to malloc @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__,pKarg);
++		return -EFAULT;
++	}
++
++	if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(pKarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++    if (pKarg->Information.uChangeCount != 0 &&
++        pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++			CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Information.uFailureCode = 
++		//	CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_features_exit;
++    }
++
++    pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD;
++    pKarg->Information.bDefaultTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bRebuildPriority = pKarg->Information.bDefaultRebuildPriority;
++    pKarg->Information.bDefaultSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.uRaidSetTransformationRules = 0;
++    for (i=0; i<4; i++) {
++        pKarg->Information.RaidType[i].bRaidType = raidTypes[i];
++        // Only support 64K stripe size
++        pKarg->Information.RaidType[i].uSupportedStripeSizeMap = 0x80;
++    }
++    pKarg->Information.RaidType[i].bRaidType = CSMI_SAS_RAID_TYPE_END;
++    pKarg->Information.bCacheRatiosSupported[0] = CSMI_SAS_RAID_CACHE_RATIO_END;
++
++cim_get_raid_features_exit:
++
++    /*
++     * Copy the data from kernel memory to user memory
++     */
++    if (copy_to_user((char *)arg, pKarg,
++        sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
++        printk(KERN_ERR "%s@%d::%s() - "
++               "Unable to write out csmi_sas_get_raid_features @ %p\n",
++               __FILE__, __LINE__, __FUNCTION__, uarg);
++        kfree(pKarg);
++        return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++    return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Control command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_control(unsigned long arg)
++{
++	CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
++	int csmi_sas_raid_control_buffer_sz, iocnum;
++    MPT_ADAPTER			*ioc = NULL;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_control struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
++	pKarg = kmalloc(csmi_sas_raid_control_buffer_sz, GFP_KERNEL);
++	if(!pKarg){
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to malloc @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__,pKarg);
++		return -EFAULT;
++	}
++
++	if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(pKarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(pKarg);
++		return -ENODEV;
++	}
++
++	if (!ioc->raid_data.isRaid) {
++		pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_get_raid_control_exit;
++	}
++
++    if (pKarg->Information.uChangeCount != 0 &&
++        pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++			CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++			CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_control_exit;
++    }
++
++    if (pKarg->Information.bTransformPriority != CSMI_SAS_PRIORITY_UNCHANGED) {
++        pKarg->IoctlHeader.ReturnCode = 
++			CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Information.uFailureCode = 
++		//	CSMI_SAS_FAIL_CODE_EXPANSION_PRIORITY_INVALID;
++    }
++    if (pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_AUTO &&
++        pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_UNCHANGED) {
++        pKarg->IoctlHeader.ReturnCode = 
++			CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++			CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
++    }
++    if (pKarg->Information.bCacheRatioFlag == CSMI_SAS_RAID_CACHE_RATIO_ENABLE) {
++        pKarg->IoctlHeader.ReturnCode = 
++			CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++			CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
++    }
++    pKarg->Information.bFailureDescription[0] = '\0';
++
++cim_get_raid_control_exit:
++
++    /*
++     * Copy the data from kernel memory to user memory
++     */
++    if (copy_to_user((char *)arg, pKarg,
++        sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
++        printk(KERN_ERR "%s@%d::%s() - "
++               "Unable to write out csmi_sas_get_raid_control @ %p\n",
++               __FILE__, __LINE__, __FUNCTION__, uarg);
++        kfree(pKarg);
++        return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++    return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Task Managment Config command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_task_managment(unsigned long arg)
++{
++	CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_SSP_TASK_IU_BUFFER	 karg;
++	pSCSITaskMgmt_t			pScsiTm;
++	pSCSITaskMgmtReply_t		pScsiTmReply;
++	MPT_ADAPTER			*ioc = NULL;
++	MPT_SCSI_HOST			*hd;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t			*mpi_hdr;
++	int				iocnum;
++	u8				taskType;
++	u8				path;
++	u8				target;
++	u8				lun;
++	u8				queueTag;
++	u32				msgContext = 0;
++	int				retval;
++	int				i, ii;
++	u8 				found_qtag;
++	int				wait_timeout;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_task_managment struct @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	/* try to catch an error
++	 */
++	if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
++	    (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)) {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_get_task_managment_exit;
++	}
++
++	if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
++		switch (karg.Parameters.bTaskManagementFunction) {
++
++		case CSMI_SAS_SSP_ABORT_TASK:
++			taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
++			break;
++		case CSMI_SAS_SSP_ABORT_TASK_SET:
++			taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
++			break;
++		case CSMI_SAS_SSP_CLEAR_TASK_SET:
++			taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
++			break;
++		case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
++			taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
++			break;
++		case CSMI_SAS_SSP_CLEAR_ACA:
++		case CSMI_SAS_SSP_QUERY_TASK:
++		default:
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_INVALID_PARAMETER;
++			goto cim_get_task_managment_exit;
++		}
++	}else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE) {
++		/* set the code up to do a hard reset
++		 */
++		taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
++	}else {
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_get_task_managment_exit;
++	}
++
++	path = karg.Parameters.bPathId;
++	target = karg.Parameters.bTargetId;
++	lun = karg.Parameters.bLun;
++	queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
++
++	if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) {
++		karg.IoctlHeader.ReturnCode =
++		    CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_get_task_managment_exit;
++	}
++	else
++		hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++
++	switch ( karg.Parameters.uInformation ) {
++		case CSMI_SAS_SSP_TEST:
++			dsasprintk(("TM request for test purposes\n"));
++			break;
++		case CSMI_SAS_SSP_EXCEEDED:
++			dsasprintk(("TM request due to timeout\n"));
++			break;
++		case CSMI_SAS_SSP_DEMAND:
++			dsasprintk(("TM request demanded by app\n"));
++			break;
++		case CSMI_SAS_SSP_TRIGGER:
++			dsasprintk(("TM request sent to trigger event\n"));
++			break;
++	}
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++	switch (taskType) {
++
++	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
++	/*
++	 * look up qtag in the ScsiLookup[] table
++	 */
++		for (i=0,found_qtag=0;i<hd->ioc->req_depth;i++) {
++			if ((hd->ScsiLookup[i]) &&
++			    (hd->ScsiLookup[i]->tag == queueTag)) {
++				mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
++				msgContext =
++				    mf->u.frame.hwhdr.msgctxu.MsgContext;
++				found_qtag=1;
++				break;
++			}
++		}
++
++		if(!found_qtag) {
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_INVALID_PARAMETER;
++			goto cim_get_task_managment_exit;
++		}
++
++	case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
++	case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
++	case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
++	/* for now, this should work
++	 */
++	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
++
++		/* Single threading ....
++		 */
++		if (mptctl_set_tm_flags(hd) != 0) {
++			karg.IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_FAILED;
++			goto cim_get_task_managment_exit;
++		}
++
++		/* Send request
++		 */
++		if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++			dctlprintk((": no msg frames!\n"));
++			mptctl_free_tm_flags(ioc);
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_get_task_managment_exit;
++		}
++
++		mpi_hdr = (MPIHeader_t *) mf;
++		pScsiTm = (pSCSITaskMgmt_t ) mf;
++
++		memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
++		pScsiTm->TaskType = taskType;
++		pScsiTm->Bus = path;
++		pScsiTm->TargetID = target;
++		pScsiTm->LUN[1] = lun;
++		pScsiTm->MsgContext = mpi_hdr->MsgContext;
++		pScsiTm->TaskMsgContext = msgContext;
++		pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
++
++		ioc->ioctl->wait_done = 0;
++
++		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
++
++		if ((retval = mpt_send_handshake_request(mptctl_id, ioc->ioctl->ioc,
++		     sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
++			dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
++				" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
++				hd->ioc, mf));
++			goto cim_get_task_managment_exit;
++		}
++
++		/* Now wait for the command to complete */
++		wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++		ii = wait_event_timeout(mptctl_wait,
++		     ioc->ioctl->wait_done == 1,
++		     HZ*wait_timeout);
++
++		if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++		/* Now we need to reset the board */
++			mptctl_free_tm_flags(ioc);
++			mpt_free_msg_frame(hd->ioc, mf);
++			mptctl_timeout_expired(ioc->ioctl);
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_get_task_managment_exit;
++		}
++
++		if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++			pScsiTmReply =
++			    (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame;
++
++			memset(&karg.Status,0,
++			    sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
++
++			if(le16_to_cpu(pScsiTmReply->IOCStatus) == MPI_IOCSTATUS_SUCCESS) {
++				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++				karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_COMPLETED;
++			}else if(le16_to_cpu(pScsiTmReply->IOCStatus) ==
++			    MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
++				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++				karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_RETRY;
++			}else {
++				karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++				karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_FATAL_ERROR;
++			}
++		}else{
++			karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		}
++
++		break;
++
++	default:
++		karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++		break;
++	}
++
++
++cim_get_task_managment_exit:
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++				sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++			"Unable to write out csmi_sas_task_managment @ %p\n",
++				__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*
++ *	map_sas_status_to_csmi - Conversion  for Connection Status
++ *	@mpi_sas_status: Sas status returned by the firmware
++ *
++ *	Returns converted connection status
++ *
++ */
++static u8
++map_sas_status_to_csmi(u8 mpi_sas_status)
++{
++	u8  csmi_connect_status;
++
++	switch (mpi_sas_status) {
++
++	case MPI_SASSTATUS_SUCCESS:
++		csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
++		break;
++
++	case MPI_SASSTATUS_UTC_BAD_DEST:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
++		break;
++
++	case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
++		break;
++
++	case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
++		break;
++
++	case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
++		break;
++
++	case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
++		break;
++
++	case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
++		break;
++
++	case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
++		break;
++
++	case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
++		csmi_connect_status =  CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
++		break;
++
++	case MPI_SASSTATUS_UNKNOWN_ERROR:
++	case MPI_SASSTATUS_INVALID_FRAME:
++	case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
++	case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
++	case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
++	case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
++	case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
++	case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
++	case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
++	case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
++	case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
++	case MPI_SASSTATUS_DATA_OFFSET_ERROR:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
++		break;
++
++	default:
++		csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
++		break;
++	}
++
++	return csmi_connect_status;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*                      mptctl_csmi_sas_phy_reset
++ *	Issues a phy link reset or phy hard reset
++ *
++ *	@ioc - Pointer to MPT_ADAPTER structure
++ *	@PhyNum - phy number
++ *	@opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
++ *
++ *	Returns: 0 for success, non-zero error
++ */
++static int
++mptctl_csmi_sas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
++{
++	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
++	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t			*mpi_hdr;
++	int 				ii;
++
++	if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
++	    (opcode != MPI_SAS_OP_PHY_HARD_RESET))
++	    return -1;
++
++	/* Get a MF for this command.
++	 */
++	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++		dctlprintk((": no msg frames!\n"));
++		return -1;
++        }
++
++	mpi_hdr = (MPIHeader_t *) mf;
++	sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
++	memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
++	sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
++	sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
++	sasIoUnitCntrReq->Operation = opcode;
++	sasIoUnitCntrReq->PhyNum = PhyNum;
++
++	ioc->ioctl->wait_done = 0;
++	mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++	/* Now wait for the command to complete */
++	ii = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++	if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++		/* Now we need to reset the board */
++		mpt_free_msg_frame(ioc, mf);
++		mptctl_timeout_expired(ioc->ioctl);
++		return -1;
++	}
++
++	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0)
++		return -1;
++
++	/* process the completed Reply Message Frame */
++	sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
++	if (sasIoUnitCntrReply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
++		printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
++		    __FUNCTION__,
++		    sasIoUnitCntrReply->IOCStatus,
++		    sasIoUnitCntrReply->IOCLogInfo);
++		return -1;
++	}
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Phy Control command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_phy_control(unsigned long arg)
++{
++	CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
++	IOCTL_HEADER			ioctl_header;
++	PCSMI_SAS_PHY_CONTROL_BUFFER	karg;
++	SasIOUnitPage0_t		*sasIoUnitPg0=NULL;
++	dma_addr_t			sasIoUnitPg0_dma;
++	int				sasIoUnitPg0_data_sz=0;
++	SasIOUnitPage1_t		*sasIoUnitPg1=NULL;
++	dma_addr_t			sasIoUnitPg1_dma;
++	int				sasIoUnitPg1_data_sz=0;
++	ConfigExtendedPageHeader_t  	hdr;
++	CONFIGPARMS			cfg;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++	int 				csmi_sas_phy_control_buffer_sz;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in IOCTL_HEADER"
++		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
++	karg = kmalloc(csmi_sas_phy_control_buffer_sz,GFP_KERNEL);
++	if(karg==NULL){
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to malloc @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__,karg);
++		return -EFAULT;
++	}
++
++	if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_phy_control_buffer "
++		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(karg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(karg);
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(karg);
++		return -ENODEV;
++	}
++
++	if (karg->bPhyIdentifier >= ioc->numPhys) {
++		karg->IoctlHeader.ReturnCode =
++		   CSMI_SAS_STATUS_INVALID_PARAMETER;
++		goto cim_sas_phy_control_exit;
++	}
++
++	/*
++	 *  Retreive SAS IOUNIT PAGE 0
++	 */
++
++	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if (mpt_config(ioc, &cfg) != 0) {
++		dctlprintk((
++		    ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++	sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++
++	if (!sasIoUnitPg0) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++	cfg.physAddr = sasIoUnitPg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if (mpt_config(ioc, &cfg) != 0) {
++		dctlprintk((
++		    ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	/*
++	 *  Retreive SAS IOUNIT PAGE 1
++	 */
++
++	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 1;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if (mpt_config(ioc, &cfg) != 0) {
++		dctlprintk((
++		    ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		dctlprintk((": hdr.ExtPageLength == 0\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
++	sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
++
++	if (!sasIoUnitPg1) {
++		dctlprintk((": pci_alloc_consistent: FAILED\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
++	cfg.physAddr = sasIoUnitPg1_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if (mpt_config(ioc, &cfg) != 0) {
++		dctlprintk((
++		    ": FAILED:  READ MPI_SASIOUNITPAGE1: CURRENT\n"));
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++		goto cim_sas_phy_control_exit;
++	}
++
++	switch (karg->uFunction) {
++
++	case CSMI_SAS_PC_LINK_RESET:
++	case CSMI_SAS_PC_HARD_RESET:
++	{
++		u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
++		    MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
++
++		if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
++		    (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
++		    (karg->bNumberOfControls > 0)){
++			if(karg->Control[0].bRate ==
++			   CSMI_SAS_LINK_RATE_1_5_GBPS) {
++				sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
++				MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
++				MPI_SAS_IOUNIT1_MIN_RATE_1_5;
++			}
++			else if(karg->Control[0].bRate ==
++			   CSMI_SAS_LINK_RATE_3_0_GBPS) {
++				sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
++				MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
++				MPI_SAS_IOUNIT1_MIN_RATE_3_0;
++			}
++			sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
++			    ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
++			cfg.dir = 1;
++			cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
++			if (mpt_config(ioc, &cfg) != 0) {
++				dctlprintk((
++			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
++				karg->IoctlHeader.ReturnCode =
++				   CSMI_SAS_STATUS_FAILED;
++				goto cim_sas_phy_control_exit;
++			}
++			cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++			if (mpt_config(ioc, &cfg) != 0) {
++				dctlprintk((
++			 ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
++				karg->IoctlHeader.ReturnCode =
++				   CSMI_SAS_STATUS_FAILED;
++				goto cim_sas_phy_control_exit;
++			}
++		}
++		if (mptctl_csmi_sas_phy_reset(ioc,
++		    karg->bPhyIdentifier, opcode) != 0) {
++			dctlprintk((
++			    ": FAILED: mptctl_csmi_sas_phy_reset\n"));
++			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_sas_phy_control_exit;
++		}
++		break;
++
++	}
++	case CSMI_SAS_PC_PHY_DISABLE:
++		if(karg->usLengthOfControl || karg->bNumberOfControls) {
++			karg->IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_INVALID_PARAMETER;
++			break;
++		}
++		sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
++		    MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
++		cfg.dir = 1;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
++		if (mpt_config(ioc, &cfg) != 0) {
++			dctlprintk((
++			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
++			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_sas_phy_control_exit;
++		}
++		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++		if (mpt_config(ioc, &cfg) != 0) {
++			dctlprintk((
++			    ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
++			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_sas_phy_control_exit;
++		}
++		if (mptctl_csmi_sas_phy_reset(ioc,
++		    karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
++			dctlprintk((
++			    ": FAILED: mptctl_csmi_sas_phy_reset\n"));
++			karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++			goto cim_sas_phy_control_exit;
++		}
++		break;
++
++	case CSMI_SAS_PC_GET_PHY_SETTINGS:
++		if(karg->usLengthOfControl || karg->bNumberOfControls) {
++			karg->IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_INVALID_PARAMETER;
++			break;
++		}
++		if(csmi_sas_phy_control_buffer_sz <
++		    offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
++		    (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
++			karg->IoctlHeader.ReturnCode =
++			    CSMI_SAS_STATUS_INVALID_PARAMETER;
++			break;
++		}
++		karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
++		karg->bNumberOfControls = 4;
++		karg->Control[0].bType = CSMI_SAS_SAS;
++		karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
++		karg->Control[1].bType = CSMI_SAS_SAS;
++		karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
++		karg->Control[2].bType = CSMI_SAS_SATA;
++		karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
++		karg->Control[3].bType = CSMI_SAS_SATA;
++		karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++		break;
++	default:
++		break;
++	}
++
++cim_sas_phy_control_exit:
++
++	if (sasIoUnitPg0)
++		pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++		    (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++	if (sasIoUnitPg1)
++		pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
++		    (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(karg);
++		return -EFAULT;
++	}
++
++	kfree(karg);
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get Connector info command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_connector_info(unsigned long arg)
++{
++	CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
++	CSMI_SAS_CONNECTOR_INFO_BUFFER	 karg;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum;
++	int				i;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		   "Unable to read in csmi_sas_connector_info_buffer"
++		   " struct @ %p\n",
++		   __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		return -ENODEV;
++	}
++
++	karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++// TODO - to be implemented - This requires MPI changes to a Manufacturing page
++	for (i=0;i< ioc->numPhys;i++) {
++		karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
++		strcpy(karg.Reference[i].bConnector,"");
++		karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
++	}
++
++// cim_sas_get_connector_info_exit:
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, &karg,
++		sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		"Unable to write out csmi_sas_connector_info_buffer @"
++	       "%p\n",
++		__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*                 mptctl_csmi_sas_fill_location_data
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ */
++static int
++mptctl_csmi_sas_fill_location_data(MPT_ADAPTER *ioc, u8 target, u8 bus, u8 opcode, CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
++{
++
++	ConfigExtendedPageHeader_t 	hdr;
++	CONFIGPARMS			cfg;
++	int				rc;
++	SasDevicePage0_t		*sasDevicePg0=NULL;
++	SasEnclosurePage0_t		*sasEnclosurePg0=NULL;
++	dma_addr_t			sasDevicePg0_dma,sasEnclosurePg0_dma;
++	int				sasDevicePg0_data_sz=0;
++	int				sasEnclosurePg0_data_sz=0;
++	u64				SASAddress64;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	/* SAS Device Page 0 */
++	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		rc=-1;
++		goto fill_location_data_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		rc=-1;
++		goto fill_location_data_exit;
++	}
++
++	sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
++	sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
++	    ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
++	if (!sasDevicePg0) {
++		rc=-1;
++		goto fill_location_data_exit;
++	}
++
++	memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
++	cfg.physAddr = sasDevicePg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++	cfg.pageAddr = (bus << 8) + target
++	    + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
++	       	MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		rc=-1;
++		goto fill_location_data_exit;
++	}
++
++	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
++	SASAddress64 = reverse_byte_order64((u64 *)&sasDevicePg0->SASAddress);
++	memcpy(&location_ident->bSASAddress,&SASAddress64,sizeof(u64));
++
++	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
++	memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
++
++	/* SAS Enclosure Page 0 */
++	hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		rc=0;
++		goto fill_location_data_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		rc=0;
++		goto fill_location_data_exit;
++	}
++
++	sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
++	sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
++	    ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
++	if (!sasEnclosurePg0) {
++		rc=0;
++		goto fill_location_data_exit;
++	}
++	cfg.physAddr = sasEnclosurePg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++	cfg.pageAddr = le16_to_cpu(sasDevicePg0->EnclosureHandle)
++	    + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
++	    MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		rc=0;
++		goto fill_location_data_exit;
++	}
++
++	location_ident->bLocationFlags |=
++	    CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
++	SASAddress64 = reverse_byte_order64(
++	    (u64 *)&sasEnclosurePg0->EnclosureLogicalID);
++	if (SASAddress64)
++		memcpy(&location_ident->bEnclosureIdentifier,
++		    &SASAddress64,sizeof(u64));
++	else
++		strcpy(location_ident->bEnclosureIdentifier,"Internal");
++
++// bBayPrefix - not supported
++
++// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
++//	whether SEP BUS/TargetID is valid.  Ifs its a SES device, then
++//	issue internal inquiry to (bus/target) to gather the Enclosure name.
++//	If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
++//	If its direct attached, there is no enclosure name
++	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
++	strcpy(location_ident->bEnclosureName,"Not Supported");
++
++	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
++	location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
++
++	location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
++	location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
++
++
++// TODO - illuminating LEDs,
++// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
++// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
++// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
++
++/* check sasEnclosurePg0->Flags -
++ * to validate whether we need to send the SEPRequest
++ * bit:5 should be set
++ * bit:3-0 any bit should be set.  If zero, then SEPRequest will fail
++*/
++
++/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
++ * Look in mpi_init.h
++ * SEPRequest_t = structure
++ *
++ * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
++ *
++ * SEPRequest_t->Flags should be set to
++ * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
++ *
++ * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
++ * will illuminate the LEDs
++ */
++
++fill_location_data_exit:
++
++	if (sasDevicePg0 != NULL)
++		pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++		    sasDevicePg0, sasDevicePg0_dma);
++
++	if (sasEnclosurePg0 != NULL)
++		pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
++		    sasEnclosurePg0, sasEnclosurePg0_dma);
++	return rc;
++}
++
++
++static int
++mptctl_csmi_sas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 volumeID, u8 VolumeBus)
++{
++	pRaidVolumePage0_t		pVolume0 = NULL;
++	pRaidPhysDiskPage0_t		pPhysDisk0 = NULL;
++	CONFIGPARMS			cfg;
++	ConfigPageHeader_t		header;
++	u8				physDiskNumMax,physDiskNum;
++	int				volumepage0sz = 0, physdiskpage0sz = 0;
++	dma_addr_t			volume0_dma, physdisk0_dma;
++	int 				csmi_sas_get_location_sz;
++	int				rc = 0,i;
++
++	csmi_sas_get_location_sz = karg->IoctlHeader.Length;
++	physDiskNumMax = (csmi_sas_get_location_sz -
++	    offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
++	    / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
++	karg->bNumberOfLocationIdentifiers=0;
++
++	/*
++	 * get RAID Volume Page 0
++	 */
++
++	header.PageVersion = 0;
++	header.PageLength = 0;
++	header.PageNumber = 0;
++	header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++	cfg.cfghdr.hdr = &header;
++	cfg.physAddr = -1;
++	cfg.pageAddr = (VolumeBus << 8) + volumeID;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++	if (mpt_config(ioc, &cfg) != 0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++	if (header.PageLength == 0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++	volumepage0sz = header.PageLength * 4;
++	pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++	    &volume0_dma);
++	if (!pVolume0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++	cfg.physAddr = volume0_dma;
++	if (mpt_config(ioc, &cfg) != 0){
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++
++	/*
++	 * get RAID Physical Disk Page 0
++	 */
++	header.PageVersion = 0;
++	header.PageLength = 0;
++	header.PageNumber = 0;
++	header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
++	cfg.cfghdr.hdr = &header;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;
++	cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++	if (mpt_config(ioc, &cfg) != 0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++	if (header.PageLength == 0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++
++	physdiskpage0sz = header.PageLength * 4;
++	pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
++	    &physdisk0_dma);
++	if (!pPhysDisk0) {
++		rc = -1;
++		goto sas_fill_location_data_raid_exit;
++	}
++	cfg.physAddr = physdisk0_dma;
++
++	for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
++
++		physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++		cfg.pageAddr = physDiskNum;
++		if (mpt_config(ioc, &cfg) != 0){
++			rc = -1;
++			goto sas_fill_location_data_raid_exit;
++		}
++
++		if((mptctl_csmi_sas_fill_location_data(ioc,
++		   pPhysDisk0->PhysDiskID,
++		   karg->bPathId, karg->bIdentify,
++		   &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
++			karg->bNumberOfLocationIdentifiers++;
++	}
++
++
++sas_fill_location_data_raid_exit:
++
++	if (pVolume0 != NULL)
++		pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++		    volume0_dma);
++
++	if(pPhysDisk0 != NULL)
++		pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
++		    physdisk0_dma);
++
++	return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get location command.
++ *
++ * Outputs:	None.
++ * Return:	0 if successful
++ *		-EFAULT if data unavailable
++ *		-ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_location(unsigned long arg)
++{
++	CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
++	PCSMI_SAS_GET_LOCATION_BUFFER	karg;
++	IOCTL_HEADER			ioctl_header;
++	MPT_ADAPTER			*ioc = NULL;
++	int				iocnum,i;
++	int				csmi_sas_get_location_sz;
++
++	dctlprintk((": %s called.\n",__FUNCTION__));
++
++	if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in IOCTL_HEADER"
++		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	csmi_sas_get_location_sz = ioctl_header.Length;
++	karg = kmalloc(csmi_sas_get_location_sz,GFP_KERNEL);
++	if(karg==NULL){
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to malloc @ %p\n",
++		    __FILE__, __LINE__, __FUNCTION__,karg);
++		return -EFAULT;
++	}
++
++	if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to read in csmi_sas_phy_control_buffer "
++		    "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++		kfree(karg);
++		return -EFAULT;
++	}
++
++	if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
++	    &ioc)) < 0) || (ioc == NULL)) {
++		dctlprintk((KERN_ERR
++		"%s::%s() @%d - ioc%d not found!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(karg);
++		return -ENODEV;
++	}
++
++	if (!mptctl_is_this_sas_cntr(ioc)) {
++		dctlprintk((KERN_ERR
++		    "%s::%s() @%d - ioc%d not SAS controller!\n",
++		    __FILE__, __FUNCTION__, __LINE__, iocnum));
++		kfree(karg);
++		return -ENODEV;
++	}
++
++	karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++	if(karg->bLengthOfLocationIdentifier != sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
++		goto cim_sas_get_location_exit;
++
++
++	/* RAID SUPPORT */
++	if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg2) {
++		for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
++			if (karg->bTargetId ==
++			    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) {
++				if(mptctl_csmi_sas_fill_location_data_raid(ioc, karg,
++				    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID,
++				    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) == 0)
++					karg->IoctlHeader.ReturnCode =
++					    CSMI_SAS_STATUS_SUCCESS;
++				else
++					karg->IoctlHeader.ReturnCode =
++					    CSMI_SAS_STATUS_FAILED;
++				goto cim_sas_get_location_exit;
++			}
++		}
++	}
++
++	/* NON-RAID SUPPORT */
++
++	/* make sure there's enough room to populate the Location[] struct */
++	if ((csmi_sas_get_location_sz -
++	    offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
++	    sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
++		goto cim_sas_get_location_exit;
++
++	karg->bNumberOfLocationIdentifiers=1; 
++	karg->Location[0].bLocationFlags=0;
++	if((mptctl_csmi_sas_fill_location_data(ioc, karg->bTargetId,
++		   karg->bPathId, karg->bIdentify, &karg->Location[0])) == 0)
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++	else
++		karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++
++cim_sas_get_location_exit:
++
++	/* Copy the data from kernel memory to user memory
++	 */
++	if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) {
++		printk(KERN_ERR "%s@%d::%s() - "
++		    "Unable to write out csmi_sas_get_location_buffer "
++		    "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
++		return -EFAULT;
++	}
++
++	kfree(karg);
++	return 0;
++}
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h	2007-11-02 09:10:23.000000000 +0100
+@@ -0,0 +1,1796 @@
++/**************************************************************************
++
++Module Name:
++
++   CSMISAS.H
++
++
++Abstract:
++
++   This file contains constants and data structure definitions used by drivers
++   that support the Common Storage Management Interface specification for
++   SAS or SATA in either the Windows or Linux.
++
++   This should be considered as a reference implementation only.  Changes may 
++   be necessary to accommodate a specific build environment or target OS.
++
++Revision History:
++
++   001  SEF   8/12/03  Initial release.
++   002  SEF   8/20/03  Cleanup to match documentation.
++   003  SEF   9/12/03  Additional cleanup, created combined header
++   004  SEF   9/23/03  Changed base types to match linux defaults
++                       Added RAID signature
++                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
++                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
++                       Fixed other typos identified in first compilation test
++   005  SEF  10/03/03  Additions to match first version of CSMI document
++   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
++                       Added defines for bConnectionRate
++   007  SEF  10/15/03  Added Firmware Download Control Code and support
++                       Added CSMI revision support
++   008  SEF  10/30/03  No functional change, just updated version to track
++                       spec changes
++   009  SEF  12/09/03  No functional change, just updated version to track
++                       spec changes
++   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
++                       bFirmware member that is defined in the spec, but
++                       was missing in this file,
++                       added CC_CSMI_SAS_TASK_MANAGEMENT
++   011  SEF   4/02/04  No functional change, added comment line before
++                       CC_CSMI_SAS_TASK_MANAGEMENT
++   012  SEF   4/16/04  Added IOControllerNumber to linux header,
++                       Modified linux control codes to have upper word of
++                       0xCC77.... to indicate CSMI version 77
++                       Added bSignalClass to CC_CSMI_SET_PHY_INFO
++                       Added CC_CSMI_SAS_PHY_CONTROL support
++   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
++   014  SEF   5/24/04  No functional change, just updated version to track spec
++                       changes
++   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,
++                       changed width of bLocation defines to reflect size
++   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
++                       to be proper size
++   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,
++                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
++                       CSMI_SAS_CON_NOT_CONNECTED
++   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN, 
++                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
++                       conflict with activate definition
++   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION
++                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS 
++                       structure
++   020  SEF   5/25/05  added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to 
++                       CSMI_SAS_GET_LOCATION
++   021  SEF  11/03/05  added new RAID creation functionality 
++   022  SEF   2/01/06  corrected typo bNegotitiatedLInkRate
++                       Added two more RAID_TYPES, 7 and 8
++   023  SEF   4/04/06  added CSMI_RAID_TYPE_1E
++                       changed structures that contained surface scan
++                       to priority approach rather than time, causes
++                       0.89 to incompatible with 0.87, so a version 
++                       check is necessary when interpreting the 
++                       raid structures
++                       Added netware section
++
++**************************************************************************/
++
++#ifndef _CSMI_SAS_H_
++#define _CSMI_SAS_H_
++
++// CSMI Specification Revision, the intent is that all versions of the
++// specification will be backward compatible after the 1.00 release.
++// Major revision number, corresponds to xxxx. of CSMI specification
++// Minor revision number, corresponds to .xxxx of CSMI specification
++#define CSMI_MAJOR_REVISION   0
++#define CSMI_MINOR_REVISION   89
++
++/*************************************************************************/
++/* PATCHES FOR TYPOS                                                     */
++/*************************************************************************/
++
++#define bNegotitiatedLInkRate bNegotiatedLinkRate
++
++/*************************************************************************/
++/* TARGET OS LINUX SPECIFIC CODE                                         */
++/*************************************************************************/
++
++// EDM #ifdef _linux
++#ifdef __KERNEL__
++
++// Linux base types
++
++#include <linux/types.h>
++
++#define __i8    char
++
++// pack definition
++
++// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)
++// EDM #define CSMI_SAS_END_PACK         pack()
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes prior to 0.77
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678
++// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781
++// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812
++// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123
++// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345
++// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456
++// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567
++// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567
++// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567
++// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567
++// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
++// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567
++// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
++// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678
++
++// Control Codes for 0.77 and later
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A
++#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B
++#define CC_CSMI_SAS_GET_RAID_FEATURES  0xCC77000C
++#define CC_CSMI_SAS_SET_RAID_CONTROL   0xCC77000D
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   0xCC77000E
++#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014
++#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015
++#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016
++#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017
++#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018
++#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
++#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
++#define CC_CSMI_SAS_GET_LOCATION       0xCC770025
++
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C
++
++// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
++#pragma pack(8)
++
++// IOCTL_HEADER
++typedef struct _IOCTL_HEADER {
++   __u32 IOControllerNumber;
++    __u32 Length;
++    __u32 ReturnCode;
++    __u32 Timeout;
++    __u16 Direction;
++} IOCTL_HEADER, 
++  *PIOCTL_HEADER;
++
++// EDM #pragma CSMI_SAS_END_PACK
++#pragma pack()
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS WINDOWS SPECIFIC CODE                                       */
++/*************************************************************************/
++
++#ifdef _WIN32
++
++// windows IOCTL definitions
++
++#ifndef _NTDDSCSIH_
++#include <ntddscsi.h>
++#endif
++
++// pack definition
++
++#if defined _MSC_VER
++   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)
++   #define CSMI_SAS_END_PACK         pack(pop)
++#elif defined __BORLANDC__
++   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x
++   #define CSMI_SAS_END_PACK         option -a.
++#else
++   #error "CSMISAS.H - Must externally define a pack compiler designator."
++#endif
++
++// base types
++
++#define __u8    unsigned char
++#define __u16   unsigned short
++#define __u32   unsigned long
++#define __u64   unsigned __int64
++
++#define __i8    char
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    1
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   3
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      10
++#define CC_CSMI_SAS_GET_RAID_CONFIG    11
++#define CC_CSMI_SAS_GET_RAID_FEATURES  12
++#define CC_CSMI_SAS_SET_RAID_CONTROL   13
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   14
++#define CC_CSMI_SAS_SET_RAID_OPERATION 15
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       20
++#define CC_CSMI_SAS_SET_PHY_INFO       21
++#define CC_CSMI_SAS_GET_LINK_ERRORS    22
++#define CC_CSMI_SAS_SMP_PASSTHRU       23
++#define CC_CSMI_SAS_SSP_PASSTHRU       24
++#define CC_CSMI_SAS_STP_PASSTHRU       25
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
++#define CC_CSMI_SAS_TASK_MANAGEMENT    29
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
++#define CC_CSMI_SAS_GET_LOCATION       31
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        60
++
++#define IOCTL_HEADER SRB_IO_CONTROL
++#define PIOCTL_HEADER PSRB_IO_CONTROL
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS NETWARE SPECIFIC CODE                                       */
++/*************************************************************************/
++
++#ifdef _NETWARE
++
++// NetWare IOCTL definitions
++
++#define CSMI_SAS_BEGIN_PACK(x)    pack(x)
++#define CSMI_SAS_END_PACK         pack()
++
++#ifndef LONG
++typedef unsigned long LONG;
++#endif
++
++#ifndef WORD
++typedef unsigned short WORD;
++#endif
++
++#ifndef BYTE
++typedef unsigned char BYTE;
++#endif
++
++/* Need to have these definitions for Netware */
++#define __u8    unsigned char
++#define __u16   unsigned short
++#define __u32   unsigned long
++#define __u64   unsigned __int64
++
++#define __i8    char
++
++
++#pragma CSMI_SAS_BEGIN_PACK(8)
++
++// IOCTL_HEADER
++typedef struct _IOCTL_HEADER {
++    __u32 Length;
++    __u32 ReturnCode;
++} IOCTL_HEADER, 
++  *PIOCTL_HEADER;
++
++#pragma CSMI_SAS_END_PACK
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    0x01FF0001
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x01FF0002
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   0x01FF0003
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x01FF0004
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      0x01FF000A
++#define CC_CSMI_SAS_GET_RAID_CONFIG    0x01FF000B
++#define CC_CSMI_SAS_GET_RAID_FEATURES  0x01FF000C
++#define CC_CSMI_SAS_SET_RAID_CONTROL   0x01FF000D
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   0x01FF000E
++#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       0x01FF0014
++#define CC_CSMI_SAS_SET_PHY_INFO       0x01FF0015
++#define CC_CSMI_SAS_GET_LINK_ERRORS    0x01FF0016
++#define CC_CSMI_SAS_SMP_PASSTHRU       0x01FF0017
++#define CC_CSMI_SAS_SSP_PASSTHRU       0x01FF0018
++#define CC_CSMI_SAS_STP_PASSTHRU       0x01FF0019
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0x01FF001B
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
++#define CC_CSMI_SAS_TASK_MANAGEMENT    0x01FF001D
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
++#define CC_CSMI_SAS_GET_LOCATION       0x01FF001F
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        60
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS NOT DEFINED ERROR                                           */
++/*************************************************************************/
++
++// EDM #if (!_WIN32 && !_linux && !_NETWARE)
++//#if (!_WIN32 && !__KERNEL__ && !_NETWARE)
++//   #error "Unknown target OS."
++//#endif
++
++/*************************************************************************/
++/* OS INDEPENDENT CODE                                                   */
++/*************************************************************************/
++
++/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
++
++// Return codes for all IOCTL's regardless of class
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_STATUS_SUCCESS              0
++#define CSMI_SAS_STATUS_FAILED               1
++#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2
++#define CSMI_SAS_STATUS_INVALID_PARAMETER    3
++#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_ALL_SIGNATURE    "CSMIALL"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_ALL_TIMEOUT      60
++
++//  Direction values for data flow on this IOCTL
++// (IoctlHeader.Direction, Linux only)
++#define CSMI_SAS_DATA_READ    0
++#define CSMI_SAS_DATA_WRITE   1
++
++// I/O Bus Types
++// ISA and EISA bus types are not supported
++// (bIoBusType)
++
++#define CSMI_SAS_BUS_TYPE_PCI       3
++#define CSMI_SAS_BUS_TYPE_PCMCIA    4
++
++// Controller Status
++// (uStatus)
++
++#define CSMI_SAS_CNTLR_STATUS_GOOD     1
++#define CSMI_SAS_CNTLR_STATUS_FAILED   2
++#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3
++#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
++
++// Offline Status Reason
++// (uOfflineReason)
++
++#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0
++#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1
++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3
++
++// Controller Class
++// (bControllerClass)
++
++#define CSMI_SAS_CNTLR_CLASS_HBA    5
++
++// Controller Flag bits
++// (uControllerFlags)
++
++#define CSMI_SAS_CNTLR_SAS_HBA   0x00000001
++#define CSMI_SAS_CNTLR_SAS_RAID  0x00000002
++#define CSMI_SAS_CNTLR_SATA_HBA  0x00000004
++#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008
++
++// for firmware download
++#define CSMI_SAS_CNTLR_FWD_SUPPORT  0x00010000
++#define CSMI_SAS_CNTLR_FWD_ONLINE   0x00020000
++#define CSMI_SAS_CNTLR_FWD_SRESET   0x00040000
++#define CSMI_SAS_CNTLR_FWD_HRESET   0x00080000
++#define CSMI_SAS_CNTLR_FWD_RROM     0x00100000
++
++// for RAID configuration supported
++#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT  0x010000
++
++// Download Flag bits
++// (uDownloadFlags)
++#define CSMI_SAS_FWD_VALIDATE       0x00000001
++#define CSMI_SAS_FWD_SOFT_RESET     0x00000002
++#define CSMI_SAS_FWD_HARD_RESET     0x00000004
++
++// Firmware Download Status
++// (usStatus)
++#define CSMI_SAS_FWD_SUCCESS        0
++#define CSMI_SAS_FWD_FAILED         1
++#define CSMI_SAS_FWD_USING_RROM     2
++#define CSMI_SAS_FWD_REJECT         3
++#define CSMI_SAS_FWD_DOWNREV        4
++
++// Firmware Download Severity
++// (usSeverity>
++#define CSMI_SAS_FWD_INFORMATION    0
++#define CSMI_SAS_FWD_WARNING        1
++#define CSMI_SAS_FWD_ERROR          2
++#define CSMI_SAS_FWD_FATAL          3
++
++/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */
++
++// Return codes for the RAID IOCTL's regardless of class
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000
++#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL   1001
++#define CSMI_SAS_RAID_SET_DATA_CHANGED       1002
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_RAID_SIGNATURE    "CSMIARY"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_RAID_TIMEOUT      60
++
++// RAID Types
++// (bRaidType)
++#define CSMI_SAS_RAID_TYPE_NONE     0
++#define CSMI_SAS_RAID_TYPE_0        1
++#define CSMI_SAS_RAID_TYPE_1        2
++#define CSMI_SAS_RAID_TYPE_10       3
++#define CSMI_SAS_RAID_TYPE_5        4
++#define CSMI_SAS_RAID_TYPE_15       5
++#define CSMI_SAS_RAID_TYPE_6        6
++#define CSMI_SAS_RAID_TYPE_50       7
++#define CSMI_SAS_RAID_TYPE_VOLUME   8
++#define CSMI_SAS_RAID_TYPE_1E       9
++#define CSMI_SAS_RAID_TYPE_OTHER    255
++// the last value 255 was already defined for other
++// so end is defined as 254
++#define CSMI_SAS_RAID_TYPE_END      254
++
++// RAID Status
++// (bStatus)
++#define CSMI_SAS_RAID_SET_STATUS_OK             0
++#define CSMI_SAS_RAID_SET_STATUS_DEGRADED       1
++#define CSMI_SAS_RAID_SET_STATUS_REBUILDING     2
++#define CSMI_SAS_RAID_SET_STATUS_FAILED         3
++#define CSMI_SAS_RAID_SET_STATUS_OFFLINE        4
++#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING   5
++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD         6
++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION  7
++
++// RAID Drive Count
++// (bDriveCount, 0xF1 to 0xFF are reserved)
++#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG   0xF1
++#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
++
++// RAID Data Type
++// (bDataType)
++#define CSMI_SAS_RAID_DATA_DRIVES           0
++#define CSMI_SAS_RAID_DATA_DEVICE_ID        1
++#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA  2
++
++// RAID Drive Status
++// (bDriveStatus)
++#define CSMI_SAS_DRIVE_STATUS_OK          0
++#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1
++#define CSMI_SAS_DRIVE_STATUS_FAILED      2
++#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3
++#define CSMI_SAS_DRIVE_STATUS_OFFLINE     4
++#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
++
++// RAID Drive Usage
++// (bDriveUsage)
++#define CSMI_SAS_DRIVE_CONFIG_NOT_USED      0
++#define CSMI_SAS_DRIVE_CONFIG_MEMBER        1
++#define CSMI_SAS_DRIVE_CONFIG_SPARE         2
++#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE  3
++
++// RAID Drive Type
++// (bDriveType)
++#define CSMI_SAS_DRIVE_TYPE_UNKNOWN         0
++#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
++#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS   2
++#define CSMI_SAS_DRIVE_TYPE_SATA            3
++#define CSMI_SAS_DRIVE_TYPE_SATA_PS         4
++#define CSMI_SAS_DRIVE_TYPE_OTHER           255
++
++// RAID Write Protect
++// (bWriteProtect)
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN     0
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED   0
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED     1
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED    2
++
++// RAID Cache Setting
++// (bCacheSetting)
++#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN             0
++#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED           0
++#define CSMI_SAS_RAID_SET_CACHE_ENABLED             1
++#define CSMI_SAS_RAID_SET_CACHE_DISABLED            2
++#define CSMI_SAS_RAID_SET_CACHE_CORRUPT             3
++
++// RAID Features
++// (uFeatures)
++#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION    0x00000001
++#define CSMI_SAS_RAID_FEATURE_REBUILD           0x00000002
++#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR      0x00000004
++#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR      0x00000008
++#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER      0x00000010
++#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN      0x00000020
++#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED     0x00000040
++
++// RAID Priority
++// (bDefaultTransformPriority, etc.)
++#define CSMI_SAS_PRIORITY_UNKNOWN   0
++#define CSMI_SAS_PRIORITY_UNCHANGED 0
++#define CSMI_SAS_PRIORITY_AUTO      1
++#define CSMI_SAS_PRIORITY_OFF       2
++#define CSMI_SAS_PRIORITY_LOW       3
++#define CSMI_SAS_PRIORITY_MEDIUM    4
++#define CSMI_SAS_PRIORITY_HIGH      5
++
++// RAID Transformation Rules
++// (uRaidSetTransformationRules)
++#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY     0x00000001
++#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS   0x00000002
++
++// RAID Cache Ratios Supported
++// (bCacheRatiosSupported)
++// from 0 to 100 defines the write to read ratio, 0 is 100% write
++#define CSMI_SAS_RAID_CACHE_RATIO_RANGE     101
++#define CSMI_SAS_RAID_CACHE_RATIO_FIXED     102
++#define CSMI_SAS_RAID_CACHE_RATIO_AUTO      103
++#define CSMI_SAS_RAID_CACHE_RATIO_END       255
++
++// RAID Cache Ratio Flag
++// (bCacheRatioFlag)
++#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE   0
++#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE    1
++
++// RAID Clear Configuration Signature
++// (bClearConfiguration)
++#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
++
++// RAID Failure Codes
++// (uFailCode)
++#define CSMI_SAS_FAIL_CODE_OK                           0
++#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID            1000
++#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID   1001
++#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID     1002
++#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID          1003
++#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID         1004
++#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID  1005
++#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID        1006
++#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID     1007
++#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID               1008
++#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID          1009
++#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID          1010
++#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID         1011
++#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID            1012
++#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID          1013
++#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID       1014
++#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID         1015
++#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID     1016
++
++#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT      2000
++#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN                2001
++
++#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION           3000
++
++// RAID Enumeration Types
++// (uEnumerationType)
++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE                0
++#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE               1
++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET       2
++#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE         3
++
++// RAID Extent Types
++// (bExtentType)
++#define CSMI_SAS_RAID_EXTENT_RESERVED       0
++#define CSMI_SAS_RAID_EXTENT_METADATA       1
++#define CSMI_SAS_RAID_EXTENT_ALLOCATED      2
++#define CSMI_SAS_RAID_EXTENT_UNALLOCATED    3
++
++// RAID Operation Types
++// (uOperationType)
++#define CSMI_SAS_RAID_SET_CREATE            0
++#define CSMI_SAS_RAID_SET_LABEL             1
++#define CSMI_SAS_RAID_SET_TRANSFORM         2
++#define CSMI_SAS_RAID_SET_DELETE            3
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT     4
++#define CSMI_SAS_RAID_SET_CACHE             5
++#define CSMI_SAS_RAID_SET_ONLINE_STATE      6
++#define CSMI_SAS_RAID_SET_SPARE             7
++
++// RAID Transform Types
++// (bTransformType)
++#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR    0
++#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0    1
++#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER    2
++#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET        3
++
++// RAID Online State
++// (bOnlineState)
++#define CSMI_SAS_RAID_SET_STATE_UNKNOWN     0
++#define CSMI_SAS_RAID_SET_STATE_ONLINE      1
++#define CSMI_SAS_RAID_SET_STATE_OFFLINE     2
++
++/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
++
++// Return codes for SAS IOCTL's
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS
++#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000
++#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001
++
++#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002
++#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003
++#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004
++#define CSMI_SAS_SELECT_PHY_OR_PORT          2005
++#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006
++#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007
++#define CSMI_SAS_CONNECTION_FAILED           2008
++
++#define CSMI_SAS_NO_SATA_DEVICE              2009
++#define CSMI_SAS_NO_SATA_SIGNATURE           2010
++#define CSMI_SAS_SCSI_EMULATION              2011
++#define CSMI_SAS_NOT_AN_END_DEVICE           2012
++#define CSMI_SAS_NO_SCSI_ADDRESS             2013
++#define CSMI_SAS_NO_DEVICE_ADDRESS           2014
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_SAS_SIGNATURE    "CSMISAS"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_SAS_TIMEOUT      60
++
++// Device types
++// (bDeviceType)
++
++#define CSMI_SAS_PHY_UNUSED               0x00
++#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00
++#define CSMI_SAS_END_DEVICE               0x10
++#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20
++#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30
++
++// Protocol options
++// (bInitiatorPortProtocol, bTargetPortProtocol)
++
++#define CSMI_SAS_PROTOCOL_SATA   0x01
++#define CSMI_SAS_PROTOCOL_SMP    0x02
++#define CSMI_SAS_PROTOCOL_STP    0x04
++#define CSMI_SAS_PROTOCOL_SSP    0x08
++
++// Negotiated and hardware link rates
++// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
++
++#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00
++#define CSMI_SAS_PHY_DISABLED       0x01
++#define CSMI_SAS_LINK_RATE_FAILED   0x02
++#define CSMI_SAS_SATA_SPINUP_HOLD   0x03
++#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
++#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
++#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
++#define CSMI_SAS_LINK_VIRTUAL       0x10
++
++// Discover state
++// (bAutoDiscover)
++
++#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00
++#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01
++#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02
++#define CSMI_SAS_DISCOVER_COMPLETE        0x03
++#define CSMI_SAS_DISCOVER_ERROR           0x04
++
++// Phy features
++
++#define CSMI_SAS_PHY_VIRTUAL_SMP          0x01
++
++// Programmed link rates
++// (bMinimumLinkRate, bMaximumLinkRate)
++// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
++
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09
++
++// Link rate
++// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
++
++#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00
++#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01
++
++// Signal class
++// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
++
++#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00
++#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01
++#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02
++#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03
++
++// Link error reset
++// (bResetCounts)
++
++#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00
++#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01
++
++// Phy identifier
++// (bPhyIdentifier)
++
++#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF
++
++// Port identifier
++// (bPortIdentifier)
++
++#define CSMI_SAS_IGNORE_PORT           0xFF
++
++// Programmed link rates
++// (bConnectionRate)
++
++#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00
++#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08
++#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09
++
++// Connection status
++// (bConnectionStatus)
++
++#define CSMI_SAS_OPEN_ACCEPT                          0
++#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1
++#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2
++#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3
++#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4
++#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5
++#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6
++#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7
++#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8
++#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9
++#define CSMI_SAS_OPEN_REJECT_RETRY                    10
++#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11
++#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12
++
++// SSP Status
++// (bSSPStatus)
++
++#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00
++#define CSMI_SAS_SSP_STATUS_WAITING     0x01
++#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02
++#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
++#define CSMI_SAS_SSP_STATUS_RETRY       0x04
++#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05
++
++// SSP Flags
++// (uFlags)
++
++#define CSMI_SAS_SSP_READ           0x00000001
++#define CSMI_SAS_SSP_WRITE          0x00000002
++#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004
++
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040
++
++// SSP Data present
++// (bDataPresent)
++
++#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00
++#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01
++#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02
++
++// STP Flags
++// (uFlags)
++
++#define CSMI_SAS_STP_READ           0x00000001
++#define CSMI_SAS_STP_WRITE          0x00000002
++#define CSMI_SAS_STP_UNSPECIFIED    0x00000004
++#define CSMI_SAS_STP_PIO            0x00000010
++#define CSMI_SAS_STP_DMA            0x00000020
++#define CSMI_SAS_STP_PACKET         0x00000040
++#define CSMI_SAS_STP_DMA_QUEUED     0x00000080
++#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100
++#define CSMI_SAS_STP_RESET_DEVICE   0x00000200
++
++// Task Management Flags
++// (uFlags)
++
++#define CSMI_SAS_TASK_IU               0x00000001
++#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002
++#define CSMI_SAS_SUPPRESS_RESULT       0x00000004
++
++// Task Management Functions
++// (bTaskManagement)
++
++#define CSMI_SAS_SSP_ABORT_TASK           0x01
++#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02
++#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04
++#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08
++#define CSMI_SAS_SSP_CLEAR_ACA            0x40
++#define CSMI_SAS_SSP_QUERY_TASK           0x80
++
++// Task Management Information
++// (uInformation)
++
++#define CSMI_SAS_SSP_TEST           1
++#define CSMI_SAS_SSP_EXCEEDED       2
++#define CSMI_SAS_SSP_DEMAND         3
++#define CSMI_SAS_SSP_TRIGGER        4
++
++// Connector Pinout Information
++// (uPinout)
++
++#define CSMI_SAS_CON_UNKNOWN              0x00000001
++#define CSMI_SAS_CON_SFF_8482             0x00000002
++#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100
++#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200
++#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400
++#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800
++#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000
++#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000
++#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000
++#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000
++
++// Connector Location Information
++// (bLocation)
++
++// same as uPinout above...
++// #define CSMI_SAS_CON_UNKNOWN              0x01
++#define CSMI_SAS_CON_INTERNAL             0x02
++#define CSMI_SAS_CON_EXTERNAL             0x04
++#define CSMI_SAS_CON_SWITCHABLE           0x08
++#define CSMI_SAS_CON_AUTO                 0x10
++#define CSMI_SAS_CON_NOT_PRESENT          0x20
++#define CSMI_SAS_CON_NOT_CONNECTED        0x80
++
++// Device location identification
++// (bIdentify)
++
++#define CSMI_SAS_LOCATE_UNKNOWN           0x00
++#define CSMI_SAS_LOCATE_FORCE_OFF         0x01
++#define CSMI_SAS_LOCATE_FORCE_ON          0x02
++
++// Location Valid flags
++// (uLocationFlags)
++
++#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001
++#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002
++#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004
++#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008
++#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010
++#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020
++#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040
++
++/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
++
++// Return codes for SAS Phy Control IOCTL's
++// (IoctlHeader.ReturnCode)
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_PHY_SIGNATURE    "CSMIPHY"
++
++// Phy Control Functions
++// (bFunction)
++
++// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL 
++// function defined in the SAS spec
++#define CSMI_SAS_PC_NOP                   0x00000000
++#define CSMI_SAS_PC_LINK_RESET            0x00000001
++#define CSMI_SAS_PC_HARD_RESET            0x00000002
++#define CSMI_SAS_PC_PHY_DISABLE           0x00000003
++// 0x04 to 0xFF reserved...
++#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100
++
++// Link Flags
++#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
++#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002
++#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004
++
++// Device Types for Phy Settings
++// (bType)
++#define CSMI_SAS_UNDEFINED 0x00
++#define CSMI_SAS_SATA      0x01
++#define CSMI_SAS_SAS       0x02
++
++// Transmitter Flags
++// (uTransmitterFlags)
++#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001
++
++// Receiver Flags
++// (uReceiverFlags)
++#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001
++
++// Pattern Flags
++// (uPatternFlags)
++// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
++#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002
++#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004
++#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008
++
++#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010
++#define CSMI_SAS_PHY_USER_PATTERN            0x00000020
++
++// Fixed Patterns
++// (bFixedPattern)
++#define CSMI_SAS_PHY_CJPAT                   0x00000001
++#define CSMI_SAS_PHY_ALIGN                   0x00000002
++
++// Type Flags
++// (bTypeFlags)
++#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01
++#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02
++#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04
++
++// Miscellaneous
++#define SLOT_NUMBER_UNKNOWN   0xFFFF
++
++/*************************************************************************/
++/* DATA STRUCTURES                                                       */
++/*************************************************************************/
++
++/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
++
++// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
++#pragma pack(8)
++
++// CC_CSMI_SAS_DRIVER_INFO
++
++typedef struct _CSMI_SAS_DRIVER_INFO {
++   __u8  szName[81];
++   __u8  szDescription[81];
++   __u16 usMajorRevision;
++   __u16 usMinorRevision;
++   __u16 usBuildRevision;
++   __u16 usReleaseRevision;
++   __u16 usCSMIMajorRevision;
++   __u16 usCSMIMinorRevision;
++} CSMI_SAS_DRIVER_INFO,
++  *PCSMI_SAS_DRIVER_INFO;
++
++typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_DRIVER_INFO Information;
++} CSMI_SAS_DRIVER_INFO_BUFFER,
++  *PCSMI_SAS_DRIVER_INFO_BUFFER;
++
++// CC_CSMI_SAS_CNTLR_CONFIGURATION
++
++typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
++   __u8  bBusNumber;
++   __u8  bDeviceNumber;
++   __u8  bFunctionNumber;
++   __u8  bReserved;
++} CSMI_SAS_PCI_BUS_ADDRESS,
++  *PCSMI_SAS_PCI_BUS_ADDRESS;
++
++typedef union _CSMI_SAS_IO_BUS_ADDRESS {
++   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
++   __u8  bReserved[32];
++} CSMI_SAS_IO_BUS_ADDRESS,
++  *PCSMI_SAS_IO_BUS_ADDRESS;
++
++typedef struct _CSMI_SAS_CNTLR_CONFIG {
++   __u32 uBaseIoAddress;
++   struct {
++      __u32 uLowPart;
++      __u32 uHighPart;
++   } BaseMemoryAddress;
++   __u32 uBoardID;
++   __u16 usSlotNumber;
++   __u8  bControllerClass;
++   __u8  bIoBusType;
++   CSMI_SAS_IO_BUS_ADDRESS BusAddress;
++   __u8  szSerialNumber[81];
++   __u16 usMajorRevision;
++   __u16 usMinorRevision;
++   __u16 usBuildRevision;
++   __u16 usReleaseRevision;
++   __u16 usBIOSMajorRevision;
++   __u16 usBIOSMinorRevision;
++   __u16 usBIOSBuildRevision;
++   __u16 usBIOSReleaseRevision;
++   __u32 uControllerFlags;
++   __u16 usRromMajorRevision;
++   __u16 usRromMinorRevision;
++   __u16 usRromBuildRevision;
++   __u16 usRromReleaseRevision;
++   __u16 usRromBIOSMajorRevision;
++   __u16 usRromBIOSMinorRevision;
++   __u16 usRromBIOSBuildRevision;
++   __u16 usRromBIOSReleaseRevision;
++   __u8  bReserved[7];
++} CSMI_SAS_CNTLR_CONFIG,
++  *PCSMI_SAS_CNTLR_CONFIG;
++
++typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CNTLR_CONFIG Configuration;
++} CSMI_SAS_CNTLR_CONFIG_BUFFER,
++  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
++
++// CC_CSMI_SAS_CNTLR_STATUS
++
++typedef struct _CSMI_SAS_CNTLR_STATUS {
++   __u32 uStatus;
++   __u32 uOfflineReason;
++   __u8  bReserved[28];
++} CSMI_SAS_CNTLR_STATUS,
++  *PCSMI_SAS_CNTLR_STATUS;
++
++typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CNTLR_STATUS Status;
++} CSMI_SAS_CNTLR_STATUS_BUFFER,
++  *PCSMI_SAS_CNTLR_STATUS_BUFFER;
++
++// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
++
++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
++   __u32 uBufferLength;
++   __u32 uDownloadFlags;
++   __u8  bReserved[32];
++   __u16 usStatus;
++   __u16 usSeverity;
++} CSMI_SAS_FIRMWARE_DOWNLOAD,
++  *PCSMI_SAS_FIRMWARE_DOWNLOAD;
++
++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_FIRMWARE_DOWNLOAD Information;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
++  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
++
++// CC_CSMI_SAS_RAID_INFO
++
++typedef struct _CSMI_SAS_RAID_INFO {
++   __u32 uNumRaidSets;
++   __u32 uMaxDrivesPerSet;
++   __u32 uMaxRaidSets;
++   __u8  bMaxRaidTypes;
++   __u8  bReservedByteFields[7];
++   __u64 ulMinRaidSetBlocks;
++   __u64 ulMaxRaidSetBlocks;
++   __u32 uMaxPhysicalDrives;
++   __u32 uMaxExtents;
++   __u32 uMaxModules;
++   __u32 uMaxTransformationMemory;
++   __u32 uChangeCount;
++   __u8  bReserved[44];
++} CSMI_SAS_RAID_INFO,
++  *PCSMI_SAS_RAID_INFO;
++
++typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_INFO Information;
++} CSMI_SAS_RAID_INFO_BUFFER,
++  *PCSMI_SAS_RAID_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_CONFIG
++
++typedef struct _CSMI_SAS_RAID_DRIVES {
++   __u8  bModel[40];
++   __u8  bFirmware[8];
++   __u8  bSerialNumber[40];
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bDriveStatus;
++   __u8  bDriveUsage;
++   __u8  bDriveType;
++   __u16 usBlockSize;
++   __u8  bReserved[15];
++   __u32 uDriveIndex;
++   __u64 ulTotalUserBlocks;
++} CSMI_SAS_RAID_DRIVES,
++  *PCSMI_SAS_RAID_DRIVES;
++
++typedef struct _CSMI_SAS_RAID_DEVICE_ID {
++   __u8  bDeviceIdentificationVPDPage[1];
++} CSMI_SAS_RAID_DEVICE_ID,
++  *PCSMI_SAS_RAID_DEVICE_ID;
++
++typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
++   __u8  bLabel[16];
++   __u8  bRaidSetLun[8];
++   __u8  bWriteProtection;
++   __u8  bCacheSetting;
++   __u8  bCacheRatio;
++   __u16 usBlockSize;
++   __u8  bReservedBytes[11];
++   __u64 ulRaidSetExtentOffset;
++   __u64 ulRaidSetBlocks;
++   __u32 uStripeSizeInBlocks;
++   __u32 uSectorsPerTrack;
++   __u8  bApplicationScratchPad[16];
++   __u32 uNumberOfHeads;
++   __u32 uNumberOfTracks;
++   __u8  bReserved[24];
++} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
++  *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
++
++typedef struct _CSMI_SAS_RAID_CONFIG {
++   __u32 uRaidSetIndex;
++   __u32 uCapacity;
++   __u32 uStripeSize;
++   __u8  bRaidType;
++   __u8  bStatus;
++   __u8  bInformation;
++   __u8  bDriveCount;
++   __u8  bDataType;
++   __u8  bReserved[15];
++   __u32 uChangeCount;
++   union {
++      CSMI_SAS_RAID_DRIVES Drives[1];
++      CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
++      CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
++   };
++} CSMI_SAS_RAID_CONFIG,
++   *PCSMI_SAS_RAID_CONFIG;
++
++typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_CONFIG Configuration;
++} CSMI_SAS_RAID_CONFIG_BUFFER,
++  *PCSMI_SAS_RAID_CONFIG_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_FEATURES
++
++typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
++  __u8  bRaidType;
++  __u8  bReservedBytes[7];
++  __u32 uSupportedStripeSizeMap;
++  __u8  bReserved[24];
++} CSMI_SAS_RAID_TYPE_DESCRIPTION, 
++  *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
++
++typedef struct _CSMI_SAS_RAID_FEATURES {
++   __u32 uFeatures;
++   __u8  bReservedFeatures[32];
++   __u8  bDefaultTransformPriority;
++   __u8  bTransformPriority;
++   __u8  bDefaultRebuildPriority;
++   __u8  bRebuildPriority;
++   __u8  bDefaultSurfaceScanPriority;
++   __u8  bSurfaceScanPriority;
++   __u16 usReserved;
++   __u32 uRaidSetTransformationRules;
++   __u32 uReserved[11];
++   CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
++   __u8  bCacheRatiosSupported[104];
++   __u32 uChangeCount;
++   __u8  bReserved[124];
++} CSMI_SAS_RAID_FEATURES,
++  *PCSMI_SAS_RAID_FEATURES;
++
++typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_FEATURES Information;
++} CSMI_SAS_RAID_FEATURES_BUFFER,
++  *PCSMI_SAS_RAID_FEATURES_BUFFER;
++
++// CC_CSMI_SAS_SET_RAID_CONTROL
++
++typedef struct _CSMI_SAS_RAID_CONTROL {
++   __u8  bTransformPriority;
++   __u8  bRebuildPriority;
++   __u8  bCacheRatioFlag;
++   __u8  bCacheRatio;
++   __u8  bSurfaceScanPriority;
++   __u8  bReservedBytes[15];
++   __u8  bClearConfiguration[8];
++   __u32 uChangeCount;
++   __u8  bReserved[88];
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++} CSMI_SAS_RAID_CONTROL,
++  *PCSMI_SAS_RAID_CONTROL;
++
++typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_CONTROL Information;
++} CSMI_SAS_RAID_CONTROL_BUFFER,
++  *PCSMI_SAS_RAID_CONTROL_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_ELEMENT
++
++typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
++   __u32 uDriveIndex;
++   __u8  bExtentType;
++   __u8  bReservedBytes[7];
++   __u64 ulExtentOffset;
++   __u64 ulExtentBlocks;
++   __u32 uRaidSetIndex;
++   __u8  bReserved[96];
++} CSMI_SAS_DRIVE_EXTENT_INFO, 
++  *PCSMI_SAS_DRIVE_EXTENT_INFO;
++
++typedef struct _CSMI_SAS_RAID_MODULE_INFO {
++   __u8  bReserved[128];
++} CSMI_SAS_RAID_MODULE_INFO, 
++  *PCSMI_SAS_RAID_MODULE_INFO;
++
++typedef struct _CSMI_SAS_DRIVE_LOCATION {
++   __u8  bConnector[16];
++   __u8  bBoxName[16];
++   __u32 uBay;
++   __u8  bReservedBytes[4];
++   __u8  bAttachedSASAddress[8];
++   __u8  bAttachedPhyIdentifier;
++   __u8  bReserved[79];
++} CSMI_SAS_DRIVE_LOCATION, 
++  *PCSMI_SAS_DRIVE_LOCATION;
++
++typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
++   __u8  bNegotiatedLinkRate[2];
++   __u8  bReserved[126];
++} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA, 
++  *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
++
++typedef struct _CSMI_SAS_DRIVE_INFO {
++   CSMI_SAS_RAID_DRIVES Device;
++   CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
++   CSMI_SAS_DRIVE_LOCATION Location; 
++   __u8  bReserved[16];
++} CSMI_SAS_DRIVE_INFO, 
++  *PCSMI_SAS_DRIVE_INFO;
++
++typedef struct _CSMI_SAS_RAID_ELEMENT { 
++   __u32 uEnumerationType;
++   __u32 uElementIndex;
++   __u32 uNumElements;
++   __u32 uChangeCount;
++   __u32 uSubElementIndex;
++   __u8  bReserved[32];
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++   union {
++       CSMI_SAS_DRIVE_INFO Drive;
++       CSMI_SAS_RAID_MODULE_INFO Module;
++       CSMI_SAS_DRIVE_EXTENT_INFO Extent;
++   } Element;
++} CSMI_SAS_RAID_ELEMENT,
++  *PCSMI_SAS_RAID_ELEMENT;
++
++typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_ELEMENT Information;
++} CSMI_SAS_RAID_ELEMENT_BUFFER,
++  *PCSMI_SAS_RAID_ELEMENT_BUFFER;
++
++// CC_CSMI_SAS_SET_RAID_OPERATION
++
++typedef struct _CSMI_SAS_RAID_SET_LIST {
++   __u32 uRaidSetIndex;
++   __u8  bExistingLun[8]; 
++   __u8  bNewLun[8]; 
++   __u8  bReserved[12];
++} CSMI_SAS_RAID_SET_LIST, 
++  *PCSMI_SAS_RAID_SET_LIST;
++
++typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
++   __u32 uDriveIndex;
++   __u8  bDriveUsage;
++   __u8  bReserved[27];
++} CSMI_SAS_RAID_SET_DRIVE_LIST, 
++  *PCSMI_SAS_RAID_SET_DRIVE_LIST;
++
++typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
++   __u32 uRaidSetIndex;
++   __u32 uDriveCount;
++   __u8  bApplicationScratchPad[16];
++   __u8  bReserved[104];  
++} CSMI_SAS_RAID_SET_SPARE_INFO, 
++  *PCSMI_SAS_RAID_SET_SPARE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bOnlineState;
++   __u8  bReserved[123];  
++} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO, 
++  *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bCacheSetting;
++   __u8  bCacheRatioFlag;
++   __u8  bCacheRatio;
++   __u8  bReserved[121];  
++} CSMI_SAS_RAID_SET_CACHE_INFO, 
++  *PCSMI_SAS_RAID_SET_CACHE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bWriteProtectSetting;
++   __u8  bReserved[123];  
++} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO, 
++  *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bReserved[124];  
++} CSMI_SAS_RAID_SET_DELETE_INFO, 
++  *PCSMI_SAS_RAID_SET_DELETE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
++   __u8  bRaidType;
++   __u8  bReservedBytes[7];
++   __u32 uStripeSize;
++   __u64 ulRaidSetBlocks;
++   __u64 ulRaidSetExtentOffset;
++   __u32 uDriveCount;
++   __u8  bReserved[96];
++} CSMI_SAS_RAID_SET_MODIFY_INFO, 
++  *PCSMI_SAS_RAID_SET_MODIFY_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
++   __u8  bTransformType;
++   __u8  bReservedBytes[3];
++   __u32 uRaidSetIndex;
++   __u8  bRaidType;
++   __u8  bReservedBytes2[11];
++   __u32 uAdditionalRaidSetIndex;
++   __u32 uRaidSetCount;
++   __u8  bApplicationScratchPad[16];
++   CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
++   __u8  bReserved[80];
++} CSMI_SAS_RAID_SET_TRANSFORM_INFO, 
++  *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bLabel[16];
++   __u8  bReserved[108];  
++} CSMI_SAS_RAID_SET_LABEL_INFO, 
++  *PCSMI_SAS_RAID_SET_LABEL_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
++   __u8  bRaidType;
++   __u8  bReservedBytes[7];
++   __u32 uStripeSize;
++   __u32 uTrackSectorCount;
++   __u64 ulRaidSetBlocks; 
++   __u64 ulRaidSetExtentOffset;
++   __u32 uDriveCount;
++   __u8  bLabel[16];
++   __u32 uRaidSetIndex;
++   __u8  bApplicationScratchPad[16];
++   __u32 uNumberOfHeads;
++   __u32 uNumberOfTracks;
++   __u8  bReserved[48];  
++} CSMI_SAS_RAID_SET_CREATE_INFO, 
++  *PCSMI_SAS_RAID_SET_CREATE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_OPERATION { 
++   __u32 uOperationType;
++   __u32 uChangeCount;
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++   __u8  bReserved[28];
++   union {
++       CSMI_SAS_RAID_SET_CREATE_INFO Create;
++       CSMI_SAS_RAID_SET_LABEL_INFO Label;
++       CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
++       CSMI_SAS_RAID_SET_DELETE_INFO Delete;
++       CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
++       CSMI_SAS_RAID_SET_CACHE_INFO Cache;
++       CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
++       CSMI_SAS_RAID_SET_SPARE_INFO Spare;
++   } Operation;
++   union {
++       CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
++       CSMI_SAS_RAID_SET_LIST RaidSetList[1];
++   } Parameters;
++} CSMI_SAS_RAID_SET_OPERATION,
++  *PCSMI_SAS_RAID_SET_OPERATION;
++
++typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_SET_OPERATION Information;
++} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
++  *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
++
++/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
++
++// CC_CSMI_SAS_GET_PHY_INFO
++
++typedef struct _CSMI_SAS_IDENTIFY {
++   __u8  bDeviceType;
++   __u8  bRestricted;
++   __u8  bInitiatorPortProtocol;
++   __u8  bTargetPortProtocol;
++   __u8  bRestricted2[8];
++   __u8  bSASAddress[8];
++   __u8  bPhyIdentifier;
++   __u8  bSignalClass;
++   __u8  bReserved[6];
++} CSMI_SAS_IDENTIFY,
++  *PCSMI_SAS_IDENTIFY;
++
++typedef struct _CSMI_SAS_PHY_ENTITY {
++   CSMI_SAS_IDENTIFY Identify;
++   __u8  bPortIdentifier;
++   __u8  bNegotiatedLinkRate;
++   __u8  bMinimumLinkRate;
++   __u8  bMaximumLinkRate;
++   __u8  bPhyChangeCount;
++   __u8  bAutoDiscover;
++   __u8  bPhyFeatures;
++   __u8  bReserved;
++   CSMI_SAS_IDENTIFY Attached;
++} CSMI_SAS_PHY_ENTITY,
++  *PCSMI_SAS_PHY_ENTITY;
++
++typedef struct _CSMI_SAS_PHY_INFO {
++   __u8  bNumberOfPhys;
++   __u8  bReserved[3];
++   CSMI_SAS_PHY_ENTITY Phy[32];
++} CSMI_SAS_PHY_INFO,
++  *PCSMI_SAS_PHY_INFO;
++
++typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_PHY_INFO Information;
++} CSMI_SAS_PHY_INFO_BUFFER,
++  *PCSMI_SAS_PHY_INFO_BUFFER;
++
++// CC_CSMI_SAS_SET_PHY_INFO
++
++typedef struct _CSMI_SAS_SET_PHY_INFO {
++   __u8  bPhyIdentifier;
++   __u8  bNegotiatedLinkRate;
++   __u8  bProgrammedMinimumLinkRate;
++   __u8  bProgrammedMaximumLinkRate;
++   __u8  bSignalClass;
++   __u8  bReserved[3];
++} CSMI_SAS_SET_PHY_INFO,
++  *PCSMI_SAS_SET_PHY_INFO;
++
++typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SET_PHY_INFO Information;
++} CSMI_SAS_SET_PHY_INFO_BUFFER,
++  *PCSMI_SAS_SET_PHY_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_LINK_ERRORS
++
++typedef struct _CSMI_SAS_LINK_ERRORS {
++   __u8  bPhyIdentifier;
++   __u8  bResetCounts;
++   __u8  bReserved[2];
++   __u32 uInvalidDwordCount;
++   __u32 uRunningDisparityErrorCount;
++   __u32 uLossOfDwordSyncCount;
++   __u32 uPhyResetProblemCount;
++} CSMI_SAS_LINK_ERRORS,
++  *PCSMI_SAS_LINK_ERRORS;
++
++typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_LINK_ERRORS Information;
++} CSMI_SAS_LINK_ERRORS_BUFFER,
++  *PCSMI_SAS_LINK_ERRORS_BUFFER;
++
++// CC_CSMI_SAS_SMP_PASSTHRU
++
++typedef struct _CSMI_SAS_SMP_REQUEST {
++   __u8  bFrameType;
++   __u8  bFunction;
++   __u8  bReserved[2];
++   __u8  bAdditionalRequestBytes[1016];
++} CSMI_SAS_SMP_REQUEST,
++  *PCSMI_SAS_SMP_REQUEST;
++
++typedef struct _CSMI_SAS_SMP_RESPONSE {
++   __u8  bFrameType;
++   __u8  bFunction;
++   __u8  bFunctionResult;
++   __u8  bReserved;
++   __u8  bAdditionalResponseBytes[1016];
++} CSMI_SAS_SMP_RESPONSE,
++  *PCSMI_SAS_SMP_RESPONSE;
++
++typedef struct _CSMI_SAS_SMP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u32 uRequestLength;
++   CSMI_SAS_SMP_REQUEST Request;
++   __u8  bConnectionStatus;
++   __u8  bReserved2[3];
++   __u32 uResponseBytes;
++   CSMI_SAS_SMP_RESPONSE Response;
++} CSMI_SAS_SMP_PASSTHRU,
++  *PCSMI_SAS_SMP_PASSTHRU;
++
++typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SMP_PASSTHRU Parameters;
++} CSMI_SAS_SMP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_SSP_PASSTHRU
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u8  bLun[8];
++   __u8  bCDBLength;
++   __u8  bAdditionalCDBLength;
++   __u8  bReserved2[2];
++   __u8  bCDB[16];
++   __u32 uFlags;
++   __u8  bAdditionalCDB[24];
++   __u32 uDataLength;
++} CSMI_SAS_SSP_PASSTHRU,
++  *PCSMI_SAS_SSP_PASSTHRU;
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
++   __u8  bConnectionStatus;
++   __u8  bSSPStatus;
++   __u8  bReserved[2];
++   __u8  bDataPresent;
++   __u8  bStatus;
++   __u8  bResponseLength[2];
++   __u8  bResponse[256];
++   __u32 uDataBytes;
++} CSMI_SAS_SSP_PASSTHRU_STATUS,
++  *PCSMI_SAS_SSP_PASSTHRU_STATUS;
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SSP_PASSTHRU Parameters;
++   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_SSP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_STP_PASSTHRU
++
++typedef struct _CSMI_SAS_STP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u8  bReserved2[4];
++   __u8  bCommandFIS[20];
++   __u32 uFlags;
++   __u32 uDataLength;
++} CSMI_SAS_STP_PASSTHRU,
++  *PCSMI_SAS_STP_PASSTHRU;
++
++typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
++   __u8  bConnectionStatus;
++   __u8  bReserved[3];
++   __u8  bStatusFIS[20];
++   __u32 uSCR[16];
++   __u32 uDataBytes;
++} CSMI_SAS_STP_PASSTHRU_STATUS,
++  *PCSMI_SAS_STP_PASSTHRU_STATUS;
++
++typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_STP_PASSTHRU Parameters;
++   CSMI_SAS_STP_PASSTHRU_STATUS Status;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_STP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_STP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_GET_SATA_SIGNATURE
++
++typedef struct _CSMI_SAS_SATA_SIGNATURE {
++   __u8  bPhyIdentifier;
++   __u8  bReserved[3];
++   __u8  bSignatureFIS[20];
++} CSMI_SAS_SATA_SIGNATURE,
++  *PCSMI_SAS_SATA_SIGNATURE;
++
++typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SATA_SIGNATURE Signature;
++} CSMI_SAS_SATA_SIGNATURE_BUFFER,
++  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
++
++// CC_CSMI_SAS_GET_SCSI_ADDRESS
++
++typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
++   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
++
++// CC_CSMI_SAS_GET_DEVICE_ADDRESS
++
++typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
++  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
++
++// CC_CSMI_SAS_TASK_MANAGEMENT
++
++typedef struct _CSMI_SAS_SSP_TASK_IU {
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u32 uFlags;
++   __u32 uQueueTag;
++   __u32 uReserved;
++   __u8  bTaskManagementFunction;
++   __u8  bReserved[7];
++   __u32 uInformation;
++} CSMI_SAS_SSP_TASK_IU,
++  *PCSMI_SAS_SSP_TASK_IU;
++
++typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SSP_TASK_IU Parameters;
++   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
++} CSMI_SAS_SSP_TASK_IU_BUFFER,
++  *PCSMI_SAS_SSP_TASK_IU_BUFFER;
++
++// CC_CSMI_SAS_GET_CONNECTOR_INFO
++
++typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
++   __u32 uPinout;
++   __u8  bConnector[16];
++   __u8  bLocation;
++   __u8  bReserved[15];
++} CSMI_SAS_CONNECTOR_INFO,
++  *PCSMI_SAS_CONNECTOR_INFO;
++
++typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CONNECTOR_INFO Reference[32];
++} CSMI_SAS_CONNECTOR_INFO_BUFFER,
++  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_LOCATION
++
++typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
++   __u32 bLocationFlags;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bEnclosureIdentifier[8];
++   __u8  bEnclosureName[32];
++   __u8  bBayPrefix[32];
++   __u8  bBayIdentifier;
++   __u8  bLocationState;
++   __u8  bReserved[2];
++} CSMI_SAS_LOCATION_IDENTIFIER,
++  *PCSMI_SAS_LOCATION_IDENTIFIER;
++
++typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u8  bIdentify;
++   __u8  bNumberOfLocationIdentifiers;
++   __u8  bLengthOfLocationIdentifier;
++   CSMI_SAS_LOCATION_IDENTIFIER Location[1];
++} CSMI_SAS_GET_LOCATION_BUFFER,
++  *PCSMI_SAS_GET_LOCATION_BUFFER;
++
++// CC_CSMI_SAS_PHY_CONTROL
++
++typedef struct _CSMI_SAS_CHARACTER {
++   __u8  bTypeFlags;
++   __u8  bValue;
++} CSMI_SAS_CHARACTER,
++  *PCSMI_SAS_CHARACTER;
++
++typedef struct _CSMI_SAS_PHY_CONTROL {
++   __u8  bType;
++   __u8  bRate;
++   __u8  bReserved[6];
++   __u32 uVendorUnique[8];
++   __u32 uTransmitterFlags;
++   __i8  bTransmitAmplitude;
++   __i8  bTransmitterPreemphasis;
++   __i8  bTransmitterSlewRate;
++   __i8  bTransmitterReserved[13];
++   __u8  bTransmitterVendorUnique[64];
++   __u32 uReceiverFlags;
++   __i8  bReceiverThreshold;
++   __i8  bReceiverEqualizationGain;
++   __i8  bReceiverReserved[14];
++   __u8  bReceiverVendorUnique[64];
++   __u32 uPatternFlags;
++   __u8  bFixedPattern;
++   __u8  bUserPatternLength;
++   __u8  bPatternReserved[6];
++   CSMI_SAS_CHARACTER UserPatternBuffer[16];
++} CSMI_SAS_PHY_CONTROL,
++  *PCSMI_SAS_PHY_CONTROL;
++
++typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u32 uFunction;
++   __u8  bPhyIdentifier;
++   __u16 usLengthOfControl;
++   __u8  bNumberOfControls;
++   __u8  bReserved[4];
++   __u32 uLinkFlags;
++   __u8  bSpinupRate;
++   __u8  bLinkReserved[7];
++   __u32 uVendorUnique[8];
++   CSMI_SAS_PHY_CONTROL Control[1];
++} CSMI_SAS_PHY_CONTROL_BUFFER,
++  *PCSMI_SAS_PHY_CONTROL_BUFFER;
++
++// EDN #pragma CSMI_SAS_END_PACK
++#pragma pack()
++
++#endif // _CSMI_SAS_H_
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/Makefile linux-2.6.9-55.0.12/drivers/message/fusion/Makefile
+--- linux-2.6.9-67.0.1/drivers/message/fusion/Makefile	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/Makefile	2007-11-02 09:10:23.000000000 +0100
+@@ -8,8 +8,6 @@
+ #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
+ #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+ #EXTRA_CFLAGS  += -DMPT_DEBUG_SAS
+-EXTRA_CFLAGS += -DCPQ_CIM
+-EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCTL
+ 
+ #
+ # driver/module specifics...
+@@ -31,6 +29,7 @@ EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCT
+ #
+ #  For mptctl:
+ #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
++CFLAGS_mptctl.o  += -DCPQ_CIM
+ #
+ #  For mptsas:
+ #CFLAGS_mptsas.o += -DMPT_DEBUG_HOTPLUG
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c	2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptbase.c,v 1.130 2003/05/07 14:08:30 Exp $
+  */
+@@ -93,8 +93,6 @@ MODULE_VERSION(MPT_LINUX_VERSION_COMMON)
+ char *mptbase = NULL;
+ 
+ /* Command line args */
+-
+-
+ int mpt_can_queue = 128;
+ module_param(mpt_can_queue, int, 0);
+ MODULE_PARM_DESC(mpt_can_queue, " Max IO depth per controller (default=128)");
+@@ -115,11 +113,6 @@ static int mpt_msi_enable = 0;
+ module_param(mpt_msi_enable, int, 0);
+ MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+ 
+-int mpt_enable_deadioc_detect = 0;
+-module_param(mpt_enable_deadioc_detect, int, 0);
+-MODULE_PARM_DESC(mpt_enable_deadioc_detect, "Detection of Dead IOC Enable (default=0)");
+-
+-//@@@@
+ #ifdef MFCNT
+ static int mfcounter = 0;
+ #define PRINT_MF_COUNT 20000
+@@ -163,13 +156,10 @@ static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq
+  */
+ static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
+ static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
+-int	mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
++static int	mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
+ 			u32 *req, int replyBytes, u16 *u16reply, int maxwait,
+ 			int sleepFlag);
+-int    	        mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+-int             mpt_writeSDP1(MPT_ADAPTER *hd, int portnum, int id, int flags);
+-void    mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr);
+-
++static int	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+ static void	mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+ static void	mpt_adapter_disable(MPT_ADAPTER *ioc);
+ static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
+@@ -187,7 +177,7 @@ static int	mpt_do_upload(MPT_ADAPTER *io
+ int		mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
+ static int	mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+ static int	KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+-int             mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
++static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
+ static int	PrimeIocFifos(MPT_ADAPTER *ioc);
+ static int	WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+ static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+@@ -197,6 +187,9 @@ static int	GetFcPortPage0(MPT_ADAPTER *i
+ static int	GetIoUnitPage2(MPT_ADAPTER *ioc);
+ static int	GetManufPage5(MPT_ADAPTER *ioc, int numPorts);
+ static int	GetManufPage0(MPT_ADAPTER *ioc);
++int		mpt_sas_get_info(MPT_ADAPTER *ioc);
++static void	mptbase_sas_process_event_data(MPT_ADAPTER *ioc,
++		    MpiEventDataSasDeviceStatusChange_t * pSasEventData);
+ int		mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+ static void	mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+ 		    MpiEventDataRaid_t * pRaidEventData);
+@@ -204,7 +197,6 @@ static int	mpt_GetScsiPortSettings(MPT_A
+ static int	mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
+ static void 	mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
+ static void 	mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
+-static void 	mpt_read_ioc_pg_6(MPT_ADAPTER *ioc);
+ static void	mpt_timer_expired(unsigned long data);
+ static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
+ static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+@@ -227,7 +219,6 @@ static void	mpt_sp_ioc_info(MPT_ADAPTER 
+ static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
+ static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
+ static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
+-static void	mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
+ 
+ /* module entry point */
+ static int  __init    fusion_init  (void);
+@@ -273,10 +264,10 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa
+ {
+ 	MPT_FRAME_HDR *mf = NULL;
+ 	MPT_FRAME_HDR *mr = NULL;
+-	int req_idx;
++	int req_idx = 0;
+ 	int cb_idx;
+ 
+-	dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply pa=%08x\n",
++	dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+ 				ioc->name, pa));
+ 
+ 	switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+@@ -312,9 +303,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa
+ 		break;
+ 	default:
+ 		cb_idx = 0;
+-		printk(MYIOC_s_WARN_FMT "%s: Invalid REPLY_TYPE in pa=%08x!\n",
+-			__FUNCTION__, ioc->name, pa);
+-//		BUG();
++		BUG();
+ 	}
+ 
+ 	/*  Check for (valid) IO callback!  */
+@@ -342,12 +331,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+ 
+ 	u32 reply_dma_low;
+ 	u16 ioc_stat;
+-#ifdef MPT_DEBUG_REPLY
+-	u8  function;
+-	MPT_FRAME_HDR *chain;
+-	int chain_idx, chain_number, next;
+-#endif
+-
+ 
+ 	/* non-TURBO reply!  Hmmm, something may be up...
+ 	 *  Newest turbo reply mechanism; get address
+@@ -367,44 +350,21 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+ 	cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+ 	mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+ 
+-	ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+-#ifdef MPT_DEBUG_REPLY
+-         if ((ioc_stat != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) && /* 0x0043 */
+-	      (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {    /* 0x0045 */
+-		function = mr->u.hdr.Function;
+-		dreplyprintk((MYIOC_s_WARN_FMT "non-TURBO reply context=%04x%04x Function=%x IOCStatus=%04x\n",
+-			ioc->name, cb_idx, req_idx, function, ioc_stat));
+-		DBG_DUMP_REPLY_FRAME(mr)
+-
+-		printk("Request:\n");
+-                DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf)
+-		chain_number = 1;
+-		chain_idx = ioc->ReqToChain[req_idx];
+-		while (chain_idx != MPT_HOST_NO_CHAIN) {
+-			next = ioc->ChainToChain[chain_idx];
+-			chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
+-				+ (chain_idx * ioc->req_sz));
+-			printk("Chain %d:\n", chain_number++);
+-                        DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, chain)
+-			chain_idx = next;
+-		}
+-	}
+-#endif
++	dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
++			ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
++	DBG_DUMP_REPLY_FRAME(mr)
+ 
+ 	 /*  Check/log IOC log info
+ 	 */
++	ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+ 	if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+ 		u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+ 		if (ioc->bus_type == FC)
+ 			mpt_fc_log_info(ioc, log_info);
+ 		else if (ioc->bus_type == SPI)
+ 			mpt_spi_log_info(ioc, log_info);
+-		else if (ioc->bus_type == SAS) {
+-			printk(MYIOC_s_INFO_FMT
+-				"IOCStatus=%04x LogInfo=%08x ",
+-				ioc->name, ioc_stat, log_info);
++		else if (ioc->bus_type == SAS)
+ 			mpt_sas_log_info(ioc, log_info);
+-		}
+ 	}
+ 	if (ioc_stat & MPI_IOCSTATUS_MASK) {
+ 		if (ioc->bus_type == SPI &&
+@@ -432,31 +392,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+ 	if (freeme)
+ 		mpt_free_msg_frame(ioc, mf);
+ 	mb();
+-if (ioc->CheckFcLinkSpeed &&
+-	    ioc->FcLinkSpeedCheckNeeded &&
+-	    ioc->FcLinkSpeedReqActive == NULL &&
+-	    (mf = mpt_get_msg_frame(mpt_base_index, ioc))) {
+-		pConfig_t	pConfigMsg;
+-		dma_addr_t	physAddr;
+-
+-		ioc->FcLinkSpeedCheckNeeded = 0;
+-		ioc->FcLinkSpeedReqActive = mf;
+-		pConfigMsg = (pConfig_t)mf;
+-		/* there's enough room, so FCPortPage0 will be put in the mf */
+-		physAddr = ioc->req_frames_dma + sizeof(pConfig_t) +
+-			(u8 *)mf - (u8 *)ioc->req_frames;
+-		memset(pConfigMsg, 0, ioc->req_sz);
+-		pConfigMsg->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-		pConfigMsg->Function = MPI_FUNCTION_CONFIG;
+-		pConfigMsg->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+-		pConfigMsg->Header.PageNumber = 0;
+-		pConfigMsg->Header.PageLength = sizeof(FCPortPage0_t) / 4;
+-		pConfigMsg->Header.PageVersion = MPI_FCPORTPAGE0_PAGEVERSION;
+-		mpt_add_sge((char *)&pConfigMsg->PageBufferSGE,
+-			MPT_SGE_FLAGS_SSIMPLE_READ + sizeof(FCPortPage0_t),
+-			physAddr);
+-		mpt_put_msg_frame(mpt_base_index, ioc, mf);
+-        }
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -543,17 +478,15 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+ 		}
+ 
+ 		/*
+-		 *	 EventNotificationReply is an exception
++		 *	Hmmm...  It seems that EventNotificationReply is an exception
+ 		 *	to the rule of one reply per request.
+ 		 */
+ 		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
+ 			freereq = 0;
+ 		} else {
+-                    devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns mf=%p evnp=%p\n", ioc->name, pEvReply, mf, ioc->evnp));
+-              if ( (MPT_FRAME_HDR *)ioc->evnp == mf ) {
+-                         ioc->evnp = NULL;
+-                   }
+- }
++			devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
++				ioc->name, pEvReply));
++		}
+ 
+ #ifdef CONFIG_PROC_FS
+ //		LogEvent(ioc, pEvReply);
+@@ -562,7 +495,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+ 	} else if (func == MPI_FUNCTION_EVENT_ACK) {
+ 		dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
+ 				ioc->name));
+-	} else if (func == MPI_FUNCTION_CONFIG ) {
++	} else if (func == MPI_FUNCTION_CONFIG) {
+ 		CONFIGPARMS *pCfg;
+ 		unsigned long flags;
+ 
+@@ -617,29 +550,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+ 			 */
+ 			pCfg->wait_done = 1;
+ 			wake_up(&mpt_waitq);
+-		}else if (mf == ioc->FcLinkSpeedReqActive) {
+-     pFCPortPage0_t  pFCPortPage0 = (pFCPortPage0_t)((u8 *)mf + sizeof(pConfig_t));
+-                u8 OldSpeed = ioc->FcLinkSpeed;
+-		u8 NewSpeed = pFCPortPage0->CurrentSpeed;
+-		u8 State = pFCPortPage0->PortState;
+-                ioc->FcLinkSpeedReqActive = NULL;
+-			if (State != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
+-			    NewSpeed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
+-				char	*old;
+-				char	*new;
+- old = OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
+- "Unknown";
+-new = NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
+-NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : "Unknown";
+-
+-if (OldSpeed == 0) { printk(MYIOC_s_NOTE_FMT "FC Link Established, Speed = %s\n", ioc->name, new);
+-	} else if (OldSpeed != NewSpeed)
+-{
+-printk(MYIOC_s_WARN_FMT "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",ioc->name, old, new);
+-}
+-ioc->FcLinkSpeed = NewSpeed;
+-}
+-}
++		}
+ 	} else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+ 		/* we should be always getting a reply frame */
+ 		memcpy(ioc->persist_reply_frame, reply,
+@@ -868,10 +779,6 @@ MPT_FRAME_HDR*
+ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
+ {
+ 	MPT_FRAME_HDR *mf;
+-        #ifdef MPT_DEBUG_FAIL
+-          u8      *mem;
+-        #endif
+-
+ 	unsigned long flags;
+ 	u16	 req_idx;	/* Request index */
+ 
+@@ -884,10 +791,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE
+ 
+ 	/* If interrupts are not attached, do not return a request frame */
+ 	if (!ioc->active)
+-       {
+-            printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame!!\n");
+ 		return NULL;
+-       }
+ 
+ 	spin_lock_irqsave(&ioc->FreeQlock, flags);
+ 	if (!list_empty(&ioc->FreeQ)) {
+@@ -907,36 +811,10 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE
+ #ifdef MFCNT
+ 		ioc->mfcnt++;
+ #endif
+-	} else {
+-#ifdef MPT_DEBUG_FAIL
+-dfailprintk((MYIOC_s_WARN_FMT "%s, No Free Message Frame!!\n",
+-     ioc->name,__FUNCTION__));
+-		mem = (u8 *) ioc->req_frames;
+-		for (req_idx = 0; req_idx < 10; req_idx++) {
+-	{
+-		u32 	*m = (u32 *)(mem);
+-		int	 ii, n;
+-
+-		printk(KERN_WARNING MYNAM ": %s: msg frame %d @ %p:\n" KERN_INFO " ",
+-				ioc->name, req_idx, m);
+-		n = ioc->req_sz/4;
+-		for (ii=0; ii<n; ii++) {
+-			if (ii && ((ii%8)==0))
+-				printk("\n");
+-			printk("%08x ", le32_to_cpu(m[ii]));
+-		}
+-		printk("\n");
+-          }
+-               mem += ioc->req_sz;
+-               }
+-#endif
+-
+-
+-
+-mf = NULL;
+-}
+-spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-
++	}
++	else
++		mf = NULL;
++	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ 
+ #ifdef MFCNT
+ 	if (mf == NULL)
+@@ -984,13 +862,13 @@ mpt_put_msg_frame(int handle, MPT_ADAPTE
+ 
+ 		printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
+ 				ioc->name, m);
+-		n = ioc->req_sz/4 ;
++		n = ioc->req_sz/4 - 1;
+ 		while (m[n] == 0)
+ 			n--;
+ 		for (ii=0; ii<=n; ii++) {
+ 			if (ii && ((ii%8)==0))
+ 				printk("\n" KERN_INFO " ");
+-			printk("%08x ", le32_to_cpu(m[ii]));
++			printk(" %08x", le32_to_cpu(m[ii]));
+ 		}
+ 		printk("\n");
+ 	}
+@@ -1074,14 +952,16 @@ mpt_add_sge(char *pAddr, u32 flagslength
+  *	Returns 0 for success, non-zero for failure.
+  */
+ int
+-mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, ulong timeout, int sleepFlag)
++mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
+ {
+-	int	r = 0;
++	int		 r = 0;
+ 	u8	*req_as_bytes;
+-	int	ii;
++	int	 ii;
+ 
+-	dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d\n",
+-		ioc->name, reqBytes));
++	/* State is known to be good upon entering
++	 * this function so issue the bus reset
++	 * request.
++	 */
+ 
+ 	/*
+ 	 * Emulate what mpt_put_msg_frame() does /wrt to sanity
+@@ -1089,16 +969,12 @@ mpt_send_handshake_request(int handle, M
+ 	 * is in proper (pre-alloc'd) request buffer range...
+ 	 */
+ 	ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+-	if (ii >= 0 && ii < ioc->req_depth) {
++	if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
+ 		MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
+ 		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
+ 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+ 	}
+ 
+-               ioc->tmPtr = (MPT_FRAME_HDR *)req;
+-               ioc->TMtimer.expires = jiffies + HZ*timeout;  /* seconds */
+-               add_timer(&ioc->TMtimer);
+-
+ 	/* Make sure there are no doorbells */
+ 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+ 
+@@ -1108,25 +984,20 @@ mpt_send_handshake_request(int handle, M
+ 
+ 	/* Wait for IOC doorbell int */
+ 	if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
+-		r= ii;
+-                goto mpt_send_handshake_failed;
++		return ii;
+ 	}
+ 
+ 	/* Read doorbell and check for active bit */
+-	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)){
+-		r= -5;
+-                goto mpt_send_handshake_failed;
+-           }
+-
++	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
++		return -5;
+ 
+ 	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
+ 		ioc->name, ii));
+ 
+ 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+ 
+-        if ((WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+-            r=-2;
+-             goto mpt_send_handshake_failed;
++	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
++		return -2;
+ 	}
+ 
+ 	/* Send request via doorbell handshake */
+@@ -1138,33 +1009,21 @@ mpt_send_handshake_request(int handle, M
+ 			(req_as_bytes[(ii*4) + 1] <<  8) |
+ 			(req_as_bytes[(ii*4) + 2] << 16) |
+ 			(req_as_bytes[(ii*4) + 3] << 24));
+-dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request word=%08x ii=%d\n",ioc->name, word, ii));
+-
+ 		CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+-		if ( WaitForDoorbellAck(ioc, 5, sleepFlag) < 0) {
++		if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ 			r = -3;
+-			goto mpt_send_handshake_failed;
++			break;
+ 		}
+ 	}
+ 
+-	dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d sent, WaitForDoorbellInt\n",
+-		ioc->name, reqBytes));
+-
+-	if ( WaitForDoorbellInt(ioc, 10, sleepFlag)< 0)
++	if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
++		r = 0;
++	else
+ 		r = -4;
+ 
+ 	/* Make sure there are no doorbells */
+ 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+ 
+-mpt_send_handshake_failed:
+-	if (r < 0) {
+-		del_timer(&ioc->TMtimer);
+-		ioc->tmPtr = NULL;
+-	}
+-	dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request r=%d\n",
+-		ioc->name, r));
+-
+-
+ 	return r;
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -1186,6 +1045,7 @@ mpt_send_handshake_failed:
+ static int
+ mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
+ {
++	int	 r = 0;
+ 
+ 	/* return if in use */
+ 	if (CHIPREG_READ32(&ioc->chip->Doorbell)
+@@ -1200,7 +1060,7 @@ mpt_host_page_access_control(MPT_ADAPTER
+ 		 (access_control_value<<12)));
+ 
+ 	/* Wait for IOC to clear Doorbell Status bit */
+-	if (( WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
++	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ 		return -2;
+ 	}else
+ 		return 0;
+@@ -1344,10 +1204,20 @@ mpt_bringup_adapter(MPT_ADAPTER *ioc, in
+ {
+ 	int r;
+ 
++	if(ioc->alt_ioc) {
++		if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
++			return r;
++	}
+ 
+ 	r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+ 	    CAN_SLEEP);
+ 
++	if(ioc->alt_ioc) {
++		spin_lock(&ioc->alt_ioc->initializing_hba_lock);
++		ioc->alt_ioc->initializing_hba_lock_flag=0;
++		spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
++	}
++
+ return r;
+ }
+ 
+@@ -1383,8 +1253,6 @@ mpt_attach(struct pci_dev *pdev, const s
+ 	u8		 revision;
+ 	u8		 pcixcmd;
+ 	static int	 mpt_ids = 0;
+-        unsigned long flags;
+-
+ #ifdef CONFIG_PROC_FS
+ 	struct proc_dir_entry *dent, *ent;
+ #endif
+@@ -1420,7 +1288,6 @@ mpt_attach(struct pci_dev *pdev, const s
+ 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
+ 
+ 	ioc->pcidev = pdev;
+-        ioc->IOCResetInProgress = 0;
+ 	ioc->diagPending = 0;
+ 	spin_lock_init(&ioc->diagLock);
+ 	spin_lock_init(&ioc->initializing_hba_lock);
+@@ -1596,17 +1463,10 @@ mpt_attach(struct pci_dev *pdev, const s
+ 	if(ioc->errata_flag_1064) {
+ 		pci_disable_io_access(pdev);
+ 	}
+-           if(ioc->bus_type == FC) {
+-               ioc->CheckFcLinkSpeed = 1;
+-               ioc->FcLinkSpeed = 0;
+-        }
+-
+ 
+ 	sprintf(ioc->name, "ioc%d", ioc->id);
+ 
+ 	spin_lock_init(&ioc->FreeQlock);
+-        spin_lock_init(&ioc->PendingMFlock);
+-
+ 
+ 	/* Disable all! */
+ 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+@@ -1659,43 +1519,22 @@ mpt_attach(struct pci_dev *pdev, const s
+ 	 */
+ 	mpt_detect_bound_ports(ioc, pdev);
+ 
+-if(mpt_enable_deadioc_detect){
+-/* The following list initializations is moved from PrimeIocFifos
+-                because the lists will not get initialize for non-operational
+-                IOCs and which cause a crash when the lists are accessed later
+-                */
+-/* Initialize the free chain Q.*/
+-
+-        INIT_LIST_HEAD(&ioc->FreeChainQ);
+-        spin_lock_irqsave(&ioc->FreeQlock, flags);
+-        INIT_LIST_HEAD(&ioc->FreeQ);
+-        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-        init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+-        INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+-
+-	/* Even If there is any error in IOC bringup, the IOC is allowed to
+-		be attached with MPT drivers, This change is done to support
+-		Firmware download boot functionality for FW dead IOC */
+-       mpt_bringup_adapter(ioc, CAN_SLEEP);
+-     }
+-
+-else {
+-        if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
+-            printk(KERN_WARNING MYNAM
+-               ": WARNING - %s did not initialize properly! (%d)\n",
+-               ioc->name, r);
+-               list_del(&ioc->list);
+-               free_irq(ioc->pci_irq, ioc);
+-               if (mpt_msi_enable == 1) {
+-                      pci_disable_msi(pdev);
+-               }
+-               iounmap(mem);
+-               kfree(ioc);
+-	       pci_set_drvdata(pdev, NULL);
+-               return r;
++	if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
++		printk(KERN_WARNING MYNAM
++		  ": WARNING - %s did not initialize properly! (%d)\n",
++		  ioc->name, r);
++
++		list_del(&ioc->list);
++		free_irq(ioc->pci_irq, ioc);
++		if (mpt_msi_enable == 1) {
++			pci_disable_msi(pdev);
++		}
++		iounmap(mem);
++		kfree(ioc);
++		pci_set_drvdata(pdev, NULL);
++		return r;
+ 	}
+ 
+-}
+ 	/* call per device driver probe entry point */
+ 	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ 		if(MptDeviceDriverHandlers[ii] &&
+@@ -1812,7 +1651,7 @@ mpt_suspend(struct pci_dev *pdev, pm_mes
+ #endif
+ 
+ 	/* put ioc into READY_STATE */
+-	if(mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
++	if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
+ 		printk(MYIOC_s_ERR_FMT
+ 		"pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
+ 	}
+@@ -1864,8 +1703,7 @@ mpt_resume(struct pci_dev *pdev)
+ 	if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
+ 		/* enable domain validation flags */
+ 		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+-			ioc->spi_data.dvStatus[ii] |= (MPT_SCSICFG_NEED_DV |
+-                                                             MPT_SCSICFG_DV_NOT_DONE);
++			ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
+ 		}
+ 	}
+ 
+@@ -1905,19 +1743,23 @@ mpt_resume(struct pci_dev *pdev)
+  *
+  *	Returns:
+  *		 0 for success
+- *		-1 if failed to get board READY
++ *		-1 if failed to get boardMODULE_VERSION(MPT_LINUX_VERSION_COMMON);
++ READY
+  *		-2 if READY but IOCFacts Failed
+  *		-3 if READY but PrimeIOCFifos Failed
+  *		-4 if READY but IOCInit Failed
+  */
+-int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+-{       unsigned long flags;
++static int
++mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
++{
+ 	int	 hard_reset_done = 0;
++	int	 alt_ioc_ready = 0;
+ 	int	 hard;
+ 	int	 rc = 0;
+ 	int	 ii;
++	int	 handlers;
+ 	int	 ret = 0;
+-
++	int	 reset_alt_ioc_active = 0;
+ 
+ 	printk(KERN_INFO MYNAM ": Initiating %s %s\n",
+ 			ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
+@@ -1926,15 +1768,13 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc
+ 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+ 	ioc->active = 0;
+ 
+-/* If an event notification has not returned
+- * its request frame,
+- * free resources associated with this request.
+- */
+-        if (ioc->evnp) {
+-            drsprintk((MYIOC_s_WARN_FMT "do_ioc_recovery: freeing evnp=%p\n",
+-                 ioc->name, ioc->evnp));
+-            mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)ioc->evnp);
+-            ioc->evnp = NULL;
++	if (ioc->alt_ioc) {
++		if (ioc->alt_ioc->active)
++			reset_alt_ioc_active = 1;
++
++		/* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
++		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
++		ioc->alt_ioc->active = 0;
+ 	}
+ 
+ 	hard = 1;
+@@ -1945,39 +1785,68 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc
+ 		if (hard_reset_done == -4) {
+ 			printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
+ 					ioc->name);
++
++			if (reset_alt_ioc_active && ioc->alt_ioc) {
++				/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
++				dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
++						ioc->alt_ioc->name));
++				CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
++				ioc->alt_ioc->active = 1;
++			}
++
+ 		} else {
+ 			printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
+ 					ioc->name);
+ 		}
+-
+-               spin_lock_irqsave(&ioc->diagLock, flags);
+-               ioc->IOCResetInProgress = 0;
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+ 		return -1;
+ 	}
+ 
++	/* hard_reset_done = 0 if a soft reset was performed
++	 * and 1 if a hard reset was performed.
++	 */
++	if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
++		if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
++			alt_ioc_ready = 1;
++		else
++			printk(KERN_WARNING MYNAM
++					": alt-%s: Not ready WARNING!\n",
++					ioc->alt_ioc->name);
++	}
++
++	for (ii=0; ii<5; ii++) {
++		/* Get IOC facts! Allow 5 retries */
++		if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
++			break;
++	}
+ 
+-if (reason == MPT_HOSTEVENT_IOC_BRINGUP ||
+-                        mpt_enable_deadioc_detect){
+-             for (ii=0; ii<5; ii++) {
+-                /* Get IOC facts! Allow 5 retries */
+-                   if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
+-                               break;
+-}
+ 
++	if (ii == 5) {
++		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
++		ret = -2;
++	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
++		MptDisplayIocCapabilities(ioc);
++	}
+ 
+-if(ii==5) {
+-dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name , rc));
+-             ret = -2;
+-        } else {
+-       if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
+-         MptDisplayIocCapabilities(ioc);
++	if (alt_ioc_ready) {
++		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
++			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
++			/* Retry - alt IOC was initialized once
++			 */
++			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
++		}
++		if (rc) {
++			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
++			alt_ioc_ready = 0;
++			reset_alt_ioc_active = 0;
++		} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
++			MptDisplayIocCapabilities(ioc->alt_ioc);
+ 		}
+ 	}
+ 
+ 	/* Prime reply & request queues!
+ 	 * (mucho alloc's) Must be done prior to
+ 	 * init as upper addresses are needed for init.
++	 * If fails, continue with alt-ioc processing
+ 	 */
+ 	if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
+ 		ret = -3;
+@@ -1987,6 +1856,23 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 	 */
+ 	if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
+ 		ret = -4;
++// NEW!
++	if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
++		printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
++				ioc->alt_ioc->name, rc);
++		alt_ioc_ready = 0;
++		reset_alt_ioc_active = 0;
++	}
++
++	if (alt_ioc_ready) {
++		if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
++			alt_ioc_ready = 0;
++			reset_alt_ioc_active = 0;
++			printk(KERN_WARNING MYNAM
++				": alt-%s: (%d) init failure WARNING!\n",
++					ioc->alt_ioc->name, rc);
++		}
++	}
+ 
+ 	if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
+ 		if (ioc->upload_fw) {
+@@ -2024,6 +1910,13 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 		ioc->active = 1;
+ 	}
+ 
++	if (reset_alt_ioc_active && ioc->alt_ioc) {
++		/* (re)Enable alt-IOC! (reply interrupt) */
++		dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
++				ioc->alt_ioc->name));
++		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
++		ioc->alt_ioc->active = 1;
++	}
+ 
+ 	/*  Enable MPT base driver management of EventNotification
+ 	 *  and EventAck handling.
+@@ -2031,6 +1924,9 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 	if ((ret == 0) && (!ioc->facts.EventState))
+ 		(void) SendEventNotification(ioc, 1);	/* 1=Enable EventNotification */
+ 
++	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
++		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
++
+ 	/*	Add additional "reason" check before call to GetLanConfigPages
+ 	 *	(combined with GetIoUnitPage2 call).  This prevents a somewhat
+ 	 *	recursive scenario; GetLanConfigPages times out, timer expired
+@@ -2038,30 +1934,32 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 	 *	and we try GetLanConfigPages again...
+ 	 */
+ 	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+-
+-		/*
+-		 * Initalize link list for inactive raid volumes.
+-		 */
+-		init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+-		INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+-
+ 		if (ioc->bus_type == SAS) {
++
+ 			/*
+ 			 * Pre-fetch SAS Address for each port
+ 			 */
+ 			GetManufPage5(ioc, ioc->facts.NumberOfPorts);
+ 
++			/*
++			 * Pre-fetch Serial number for the board.
++			 */
++			GetManufPage0(ioc);
++
++			/*
++			 * Pre-fetch Hw Link Rates. (These may get
++			 * overwritten so need to save them.)
++			 * Save other SAS data needed for Ioctls.
++			 */
++			mpt_sas_get_info(ioc);
++
+ 			/* clear persistency table */
+ 			if(ioc->facts.IOCExceptions &
+ 			    MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+ 				ret = mptbase_sas_persist_operation(ioc,
+ 				    MPI_SAS_OP_CLEAR_NOT_PRESENT);
+-				if(ret != 0){
+-                                 spin_lock_irqsave(&ioc->diagLock, flags);
+-                                       ioc->IOCResetInProgress = 0;
+-                                       spin_unlock_irqrestore(&ioc->diagLock, flags);
++				if(ret != 0)
+ 					return -1;
+-                                        }
+ 			}
+ 
+ 			/* Find IM volumes
+@@ -2118,11 +2016,6 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 		}
+ 
+ 		GetIoUnitPage2(ioc);
+-
+-		/*
+-		 * Pre-fetch Serial number for the board.
+-		 */
+-		GetManufPage0(ioc);
+ 	}
+ 
+ 	/*
+@@ -2131,35 +2024,26 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+ 	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
+ 	 * MptResetHandlers[] registered yet.
+ 	 */
+-	         if (ret == 0) {
+-                       rc = 0;
+-
+-               for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+-                         if (MptResetHandlers[ii]) {
+-       drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\ n",ioc->name, ii));
+-
++	if (hard_reset_done) {
++		rc = handlers = 0;
++		for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
++			if ((ret == 0) && MptResetHandlers[ii]) {
++				dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
++						ioc->name, ii));
+ 				rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
++				handlers++;
++			}
+ 
++			if (alt_ioc_ready && MptResetHandlers[ii]) {
++				drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
++						ioc->name, ioc->alt_ioc->name, ii));
++				rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
++				handlers++;
+ 			}
+ 		}
++		/* FIXME?  Examine results here? */
+ 	}
+ 
+-if (ioc->bus_type == FC) {
+-		ioc->FcLinkSpeedCheckNeeded = 1;
+-	}
+-
+-	if (ioc->bus_type == SPI) {
+-		drsprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n",
+-			ioc->name, __FUNCTION__));
+-		dnegoprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n",
+-			ioc->name, __FUNCTION__));
+-		mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM));
+-	}
+-
+-	spin_lock_irqsave(&ioc->diagLock, flags);
+-	ioc->IOCResetInProgress = 0;
+-	spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+ 	return ret;
+ }
+ 
+@@ -2224,11 +2108,9 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
+ static void
+ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ {
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice		*pTarget;
++	sas_device_info_t *sasDevice, * pNext;
+ 	int sz;
+ 	int ret, ii;
+-	int bus, id;
+ 	void *			request_data;
+ 	dma_addr_t		request_data_dma;
+ 	u32			request_data_sz;
+@@ -2253,7 +2135,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 		if ( request_data ) {
+ 			request_data_sz = ioc->DiagBuffer_sz[ii];
+ 			request_data_dma = ioc->DiagBuffer_dma[ii];
+-			dexitprintk((KERN_INFO MYNAM ": %s: free DiagBuffer[%d] @ %p, sz=%d bytes\n",
++			dexitprintk((KERN_INFO MYNAM ": %s free DiagBuffer[%d] @ %p, sz=%d bytes\n",
+ 		 		ioc->name, ii, request_data, request_data_sz));
+ 			pci_free_consistent(ioc->pcidev, request_data_sz,
+ 				request_data,
+@@ -2264,7 +2146,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 	}
+ 	if (ioc->alloc != NULL) {
+ 		sz = ioc->alloc_sz;
+-		dexitprintk((KERN_INFO MYNAM ": %s: free alloc @ %p, sz=%d bytes\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free alloc @ %p, sz=%d bytes\n",
+ 		 	ioc->name, ioc->alloc, ioc->alloc_sz));
+ 		pci_free_consistent(ioc->pcidev, sz,
+ 				ioc->alloc, ioc->alloc_dma);
+@@ -2276,7 +2158,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 
+ 	if (ioc->sense_buf_pool != NULL) {
+ 		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+-		dexitprintk((KERN_INFO MYNAM ": %s: free sense_buf_pool @ %p, sz=%d bytes\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free sense_buf_pool @ %p, sz=%d bytes\n",
+ 		 	ioc->name, ioc->sense_buf_pool, sz));
+ 		pci_free_consistent(ioc->pcidev, sz,
+ 				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+@@ -2286,7 +2168,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 
+ 	if (ioc->events != NULL){
+ 		sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+-		dexitprintk((KERN_INFO MYNAM ": %s: free events @ %p, sz=%d bytes\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free events @ %p, sz=%d bytes\n",
+ 		 	ioc->name, ioc->events, sz));
+ 		kfree(ioc->events);
+ 		ioc->events = NULL;
+@@ -2295,7 +2177,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 
+ 	if (ioc->cached_fw != NULL) {
+ 		sz = ioc->facts.FWImageSize;
+-		dexitprintk((KERN_INFO MYNAM ": %s: free cached_fw @ %p, sz=%d bytes\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free cached_fw @ %p, sz=%d bytes\n",
+ 		 	ioc->name, ioc->cached_fw, sz));
+ 		pci_free_consistent(ioc->pcidev, sz,
+ 			ioc->cached_fw, ioc->cached_fw_dma);
+@@ -2304,29 +2186,22 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 	}
+ 
+ 	if (ioc->spi_data.nvram != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.nvram @ %p\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free spi_data.nvram @ %p\n",
+ 		 	ioc->name, ioc->spi_data.nvram));
+ 		kfree(ioc->spi_data.nvram);
+ 		ioc->spi_data.nvram = NULL;
+ 	}
+ 
+ 	if (ioc->raid_data.pIocPg3 != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg3 @ %p\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg3 @ %p\n",
+ 		 	ioc->name, ioc->raid_data.pIocPg3));
+ 		kfree(ioc->raid_data.pIocPg3);
+ 		ioc->raid_data.pIocPg3 = NULL;
+ 	}
+ 
+-	if (ioc->raid_data.pIocPg6 != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free raid_data.pIocPg6 @ %p\n",
+-			ioc->name, ioc->raid_data.pIocPg6));
+-		kfree(ioc->raid_data.pIocPg6);
+-		ioc->raid_data.pIocPg6 = NULL;
+-	}
+-
+ 	if (ioc->spi_data.pIocPg4 != NULL) {
+ 		sz = ioc->spi_data.IocPg4Sz;
+-		dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg4 @ %p size=%d\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg4 @ %p size=%d\n",
+ 		 	ioc->name, ioc->spi_data.pIocPg4, sz));
+ 		pci_free_consistent(ioc->pcidev, sz,
+ 			ioc->spi_data.pIocPg4,
+@@ -2336,41 +2211,38 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 	}
+ 
+ 	if (ioc->ReqToChain != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free ReqToChain @ %p\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free ReqToChain @ %p\n",
+ 		 	ioc->name, ioc->ReqToChain));
+ 		kfree(ioc->ReqToChain);
+ 		ioc->ReqToChain = NULL;
+ 	}
+ 
+ 	if (ioc->RequestNB != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free RequestNB @ %p\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free RequestNB @ %p\n",
+ 		 	ioc->name, ioc->RequestNB));
+ 		kfree(ioc->RequestNB);
+ 		ioc->RequestNB = NULL;
+ 	}
+ 
+ 	if (ioc->ChainToChain != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free ChainToChain @ %p\n",
++		dexitprintk((KERN_INFO MYNAM ": %s free ChainToChain @ %p\n",
+ 		 	ioc->name, ioc->ChainToChain));
+ 		kfree(ioc->ChainToChain);
+ 		ioc->ChainToChain = NULL;
+ 	}
+ 
+-	mpt_inactive_raid_list_free(ioc);
++	list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) {
++		list_del(&sasDevice->list);
++		dexitprintk((KERN_INFO MYNAM ": %s free sasDevice @ %p\n",
++		 	ioc->name, sasDevice));
++		kfree(sasDevice);
++	}
+ 
+-	for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-		if ((pMptTarget = ioc->Target_List[bus])) {
+-			for (id = 0; id < ioc->DevicesPerBus; id++) {
+-				if ((pTarget = pMptTarget->Target[id])) {
+-					dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d id=%d pTarget=%p\n",
+-						ioc->name, bus, id, pTarget));
+-					kfree (pTarget);
+-				}
+-			}
+-			dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d pMptTarget=%p\n",
+-				ioc->name, bus, pMptTarget));
+-			kfree (pMptTarget);
+-		}
++	if (ioc->sasPhyInfo != NULL) {
++		dexitprintk((KERN_INFO MYNAM ": %s free sasPhyInfo @ %p\n",
++		 	ioc->name, ioc->sasPhyInfo));
++		kfree(ioc->sasPhyInfo);
++		ioc->sasPhyInfo = NULL;
+ 	}
+ 
+ /* emoore@lsil.com : Host Page Buffer Suport, start */
+@@ -2381,7 +2253,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ 			   ": %s: host page buffers free failed (%d)!\n",
+ 			    __FUNCTION__, ret);
+ 		}
+-		dexitprintk((KERN_INFO MYNAM ": %s: HostPageBuffer free  @ %p, sz=%d bytes\n",
++		dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
+ 		 	ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+ 		pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+ 				ioc->HostPageBuffer,
+@@ -2441,7 +2313,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
+ 	dexitprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+ 		ioc->name, sz_first-sz_last+(int)sizeof(MPT_ADAPTER), sz_first));
+ 	dexitprintk((KERN_INFO MYNAM ": %s: sz_first=%d sz_last=%d sizeof(MPT_ADAPTER)=%d\n",
+-		ioc->name, sz_first, sz_last, (int)sizeof(MPT_ADAPTER)));
++		ioc->name, sz_first, sz_last, sizeof(MPT_ADAPTER)));
+ 
+ 	if (ioc->alt_ioc)
+ 		ioc->alt_ioc->alt_ioc = NULL;
+@@ -2521,17 +2393,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
+ 
+ 	/* Get current [raw] IOC state  */
+ 	ioc_state = mpt_GetIocState(ioc, 0);
+-	drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
++	dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
+ 
+ 	for ( ii = 0; ii < MPI_DIAG_BUF_TYPE_COUNT; ii++) {
+ 		ioc->DiagBuffer[ii] = NULL;
+ 		ioc->DiagBuffer_Status[ii] = 0;
+ 	}
+-if (ioc->bus_type == FC) {
+-      ioc->FcLinkSpeedCheckNeeded = 0;
+-      ioc->FcLinkSpeedReqActive = NULL;
+-}
+-
+ 
+ 	/*
+ 	 *	Check to see if IOC got left/stuck in doorbell handshake
+@@ -2544,12 +2411,9 @@ if (ioc->bus_type == FC) {
+ 	}
+ 
+ 	/* Is it already READY? */
+-	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)  {
+-drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady ioc_state=%08x = READY\n", ioc->name, ioc_state));
+-             /* Dont return for SAS IOCs */
+-             if (ioc->bus_type != SAS)
+-               return 0;
+-              }
++	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) 
++		return 0;
++
+ 	/*
+ 	 *	Check to see if IOC is in FAULT state.
+ 	 */
+@@ -2581,7 +2445,7 @@ drsprintk((KERN_INFO MYNAM ": %s : MakeI
+ 			return -4;
+ 		else {
+ 			if ((statefault == 0 ) && (force == 0)) {
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
++				if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
+ 					return 0;
+ 			}
+ 			statefault = 3;
+@@ -2604,7 +2468,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+ 			 *  BIOS or previous driver load left IOC in OP state.
+ 			 *  Reset messaging FIFOs.
+ 			 */
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
++			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
+ 				printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
+ 				return -2;
+ 			}
+@@ -2613,7 +2477,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+ 			 *  Something is wrong.  Try to get IOC back
+ 			 *  to a known state.
+ 			 */
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
++			if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
+ 				printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
+ 				return -3;
+ 			}
+@@ -2629,7 +2493,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+ 		if (sleepFlag == CAN_SLEEP)
+ 			msleep_interruptible(1);
+ 		else
+-			MPT_MDELAY(1);  /* 1 msec delay */
++			MPT_MDELAY(1);	/* 1 msec delay */
+ 
+ 	}
+ 
+@@ -2766,9 +2630,6 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
+ 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
+ 
+ 		facts->ProductID = le16_to_cpu(facts->ProductID);
+-		if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+-		    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+-			ioc->ir_firmware = 1;
+ 		facts->CurrentHostMfaHighAddr =
+ 				le32_to_cpu(facts->CurrentHostMfaHighAddr);
+ 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
+@@ -2814,9 +2675,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
+ 		dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+ 					ioc->name, vv, shiftFactor, r));
+ 
+-/* Allow dead IOCs to get detected after FWDLB*/
+- if (reason == MPT_HOSTEVENT_IOC_BRINGUP ||mpt_enable_deadioc_detect) {
+-
++		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+ 			/*
+ 			 * Set values for this IOC's request & reply frame sizes,
+ 			 * and request & reply queue depths...
+@@ -2870,7 +2729,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
+ 	int			 ii;
+ 	int			 req_sz;
+ 	int			 reply_sz;
+-	int			 max_id;
+ 
+ 	/* IOC *must* NOT be in RESET state! */
+ 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
+@@ -2913,31 +2771,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
+ 	pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
+ 	pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
+ 	pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
+-
+-	switch (ioc->bus_type) {
+-	case SAS:
+-		max_id = pfacts->PortSCSIID;
+-		break;
+-	case FC:
+-		max_id = pfacts->MaxDevices;
+-		break;
+-	case SPI:
+-	default:
+-		max_id = MPT_MAX_SCSI_DEVICES;
+-		break;
+-	}
+-
+-	ioc->DevicesPerBus = (max_id > 255) ? 256 : max_id;
+-	ioc->NumberOfBuses = (ioc->DevicesPerBus < 256) ? 1 : max_id/256;
+-	if ( ioc->NumberOfBuses > MPT_MAX_BUSES ) {
+-		dinitprintk((MYIOC_s_WARN_FMT "NumberOfBuses=%d > MPT_MAX_BUSES=%d\n",
+-		   ioc->name, ioc->NumberOfBuses, MPT_MAX_BUSES));
+-		ioc->NumberOfBuses = MPT_MAX_BUSES;
+-	}
+-
+-	dinitprintk((MYIOC_s_WARN_FMT "Buses=%d MaxDevices=%d DevicesPerBus=%d\n",
+-		   ioc->name, ioc->NumberOfBuses, max_id, ioc->DevicesPerBus));
+-
+ 	pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
+ 	pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
+ 	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
+@@ -2983,11 +2816,15 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
+ 	dinitprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+ 		   ioc->name, ioc->upload_fw, ioc->facts.Flags));
+ 
+-	ioc_init.MaxDevices = ioc->DevicesPerBus;
+-	ioc_init.MaxBuses = ioc->NumberOfBuses;
+-
+-	dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevices=%d MaxBuses=%d\n",
+-		   ioc->name, ioc_init.MaxDevices, ioc_init.MaxBuses));
++	if(ioc->bus_type == SAS)
++		ioc_init.MaxDevices = ioc->facts.MaxDevices;
++	else if(ioc->bus_type == FC)
++		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
++	else
++		ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
++	ioc_init.MaxBuses = MPT_MAX_BUS;
++	dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevice=%d\n",
++		   ioc->name, ioc_init.MaxDevices));
+ 	dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+ 		   ioc->name, ioc->facts.MsgVersion));
+ /* emoore@lsil.com : Host Page Buffer Suport, start */
+@@ -3110,7 +2947,9 @@ SendPortEnable(MPT_ADAPTER *ioc, int por
+ 
+ 	/* RAID FW may take a long time to enable
+ 	 */
+-	if (ioc->ir_firmware || ioc->bus_type == SAS) {
++	if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
++	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
++	    (ioc->bus_type == SAS)) {
+ 		rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+ 		(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+ 		300 /*seconds*/, sleepFlag);
+@@ -3151,7 +2990,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
+ 	int sz;
+ 
+ 	sz = ioc->facts.FWImageSize;
+-	dinitprintk((KERN_INFO MYNAM ": free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
++	dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+ 		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+ 	pci_free_consistent(ioc->pcidev, sz,
+ 			ioc->cached_fw, ioc->cached_fw_dma);
+@@ -3285,43 +3124,14 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
+ 	u32			 diag0val;
+ 	int			 count;
+ 	u32			*ptrFw;
+-	u32			 diagRwData,doorbell;
++	u32			 diagRwData;
+ 	u32			 nextImage;
+ 	u32			 load_addr;
++	u32 			 ioc_state=0;
+ 
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: pFwHeader=%p\n",ioc->name, pFwHeader));
+-	nextImage = pFwHeader->NextImageHeaderOffset;
+-	if (ioc->bus_type == SAS) {
+-		while (nextImage) {
+-			if ( (pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage)) ) {
+-				ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p ImageType=%x\n",
+-					ioc->name, nextImage, pExtImage,
+-					pExtImage->ImageType));
+-			} else {
+-				ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p is NULL!\n",
+-					ioc->name, nextImage, pExtImage));
+-				return -EFAULT;
+-			}
+-
+-			if ( pExtImage->ImageType == MPI_EXT_IMAGE_TYPE_BOOTLOADER ) {
+-				fwSize = (pExtImage->ImageSize + 3)/4;
+-				ptrFw = (u32 *) pExtImage;
+-				load_addr = pExtImage->LoadStartAddress;
+-				goto imageFound;
+-			}
+-			nextImage = pExtImage->NextImageHeaderOffset;
+-		}
+-		ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS BOOTLOADER not found\n",
+-			ioc->name));
+-		/* Allow this image to be downloaded */
+-	}
+-	fwSize = (pFwHeader->ImageSize + 3)/4;
+-	ptrFw = (u32 *) pFwHeader;
+-	load_addr = pFwHeader->LoadStartAddress;
++	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
++				ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
+ 
+-imageFound:
+-	ddlprintk((MYIOC_s_WARN_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p load_addr=%x\n",
+-		ioc->name, fwSize, fwSize, ptrFw, load_addr));
+ 
+ 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+ 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+@@ -3345,7 +3155,7 @@ imageFound:
+ 	for (count = 0; count < 30; count ++) {
+ 		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+ 		if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+-                      ddlprintk((MYIOC_s_WARN_FMT "RESET_ADAPTER cleared, count=%d\n",
++			ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
+ 				ioc->name, count));
+ 			break;
+ 		}
+@@ -3357,7 +3167,7 @@ imageFound:
+ 	}
+ 
+ 	if ( count == 30 ) {
+-		ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
++		ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
+ 		ioc->name, diag0val));
+ 		return -3;
+ 	}
+@@ -3370,9 +3180,10 @@ imageFound:
+ 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+ 
+ 	/* Set the DiagRwEn and Disable ARM bits */
++	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
+ 
+-        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
++	fwSize = (pFwHeader->ImageSize + 3)/4;
++	ptrFw = (u32 *) pFwHeader;
+ 
+ 	/* Write the LoadStartAddress to the DiagRw Address Register
+ 	 * using Programmed IO
+@@ -3380,28 +3191,26 @@ CHIPREG_WRITE32(&ioc->chip->Diagnostic, 
+ 	if(ioc->errata_flag_1064) {
+ 		pci_enable_io_access(ioc->pcidev);
+ 	}
+-CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
++	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
++	ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
++		ioc->name, pFwHeader->LoadStartAddress));
+ 
+-ddlprintk((MYIOC_s_WARN_FMT "LoadStart addr written 0x%x \n",ioc->name, load_addr));
+-ddlprintk((MYIOC_s_WARN_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n",
+-                                ioc->name, fwSize*4, fwSize*4, ptrFw));
++	ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n",
++				ioc->name, fwSize*4, fwSize*4, ptrFw));
+ 	while (fwSize--) {
+ 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
+ 	}
+ 
+-	if (ioc->bus_type == SAS) {
+-		pFwHeader->IopResetVectorValue = load_addr + 0x18;
+-	} else {
+-
+-		while (nextImage) {
+-			pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
++	nextImage = pFwHeader->NextImageHeaderOffset;
++	while (nextImage) {
++		pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
+ 
+ 		load_addr = pExtImage->LoadStartAddress;
+ 
+ 		fwSize = (pExtImage->ImageSize + 3) >> 2;
+ 		ptrFw = (u32 *)pExtImage;
+ 
+-		ddlprintk((MYIOC_s_WARN_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
++		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+ 						ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
+ 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
+ 
+@@ -3411,18 +3220,20 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+ 		nextImage = pExtImage->NextImageHeaderOffset;
+ 	}
+ 
+- }
+ 	/* Write the IopResetVectorRegAddr */
+-	ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Addr=%x! \n", ioc->name, 	pFwHeader->IopResetRegAddr));
++	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, 	pFwHeader->IopResetRegAddr));
+ 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
+ 
+ 	/* Write the IopResetVectorValue */
+-	ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
++	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
+ 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
+ 
++	/* Clear the internal flash bad bit - autoincrementing register,
++	 * so must do two writes.
++	 */
+ 	if (ioc->bus_type == SPI) {
+ 		/*
+-		 * 1030 H/W errata, workaround to access
++		 * 1030 and 1035 H/W errata, workaround to access
+ 		 * the ClearFlashBadSignatureBit
+ 		 */
+ 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+@@ -3431,6 +3242,16 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+ 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+ 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+ 
++	} else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
++		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
++		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
++		    MPI_DIAG_CLEAR_FLASH_BAD_SIG);
++
++		/* wait 1 msec */
++		if (sleepFlag == CAN_SLEEP)
++			msleep_interruptible(1);
++		else
++			MPT_MDELAY(1);
+ 	}
+ 
+ 	if(ioc->errata_flag_1064) {
+@@ -3438,77 +3259,48 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+ 	}
+ 
+ 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-	ddlprintk((MYIOC_s_WARN_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
++	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
+ 		ioc->name, diag0val));
+-
+-diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n",
++	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
++	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+ 		ioc->name, diag0val));
+ 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+ 
+-if (ioc->bus_type == SAS ) {
+-/* wait 1 sec */
+-if (sleepFlag == CAN_SLEEP)
+-{
+-msleep_interruptible(1000);
+-
+-}
+-else
+-MPT_MDELAY(1000);
+-
+-
+-
++	/* Write 0xFF to reset the sequencer */
++	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+ 
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: diag0val=%x, turning off RW_ENABLE\n"
+-            ioc->name, diag0val));
+-diag0val &= ~(MPI_DIAG_RW_ENABLE);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n",
+-                   ioc->name, diag0val));
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-if (diag0val & MPI_DIAG_FLASH_BAD_SIG) {
+-diag0val |= MPI_DIAG_CLEAR_FLASH_BAD_SIG;
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
++	if (ioc->bus_type == SAS) {
++		ioc_state = mpt_GetIocState(ioc, 0);
++		if ( (GetIocFacts(ioc, sleepFlag,
++				MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
++			ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
++					ioc->name, ioc_state));
++			return -EFAULT;
+ 		}
+-diag0val &= ~(MPI_DIAG_DISABLE_ARM);
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-CHIPREG_WRITE32(&ioc->chip->DiagRwAddress, 0x3f000004);
+ 	}
+-/* Write 0xFF to reset the sequencer */
+-CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+-
+-        for (count = 0; count < 30; count ++) {
+-           doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+-           doorbell &= MPI_IOC_STATE_MASK;
+-
+-                   if (doorbell == MPI_IOC_STATE_READY) {
+ 
++	for (count=0; count<HZ*20; count++) {
++		if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
++			ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
++					ioc->name, count, ioc_state));
+ 			if (ioc->bus_type == SAS) {
+ 				return 0;
+ 			}
+-
+-
+-	if ((SendIocInit(ioc, sleepFlag)) != 0) {
+-				ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit failed\n",
++			if ((SendIocInit(ioc, sleepFlag)) != 0) {
++				ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+ 					ioc->name));
+ 				return -EFAULT;
+ 			}
+-			ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit successful\n",
++			ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+ 					ioc->name));
+ 			return 0;
+ 		}
+-       ddlprintk((MYIOC_s_WARN_FMT "downloadboot: looking for READY STATE:doorbell=%x count=%d\n",ioc->name, doorbell, count));
+-                     /* wait 1 sec */
+-
+ 		if (sleepFlag == CAN_SLEEP)
+-			msleep_interruptible(1000);
++			msleep_interruptible(10);
+ 		else
+-			MPT_MDELAY(1000);
++			MPT_MDELAY(10);
+ 	}
+-	ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! IocState=%x\n",
++	ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
+ 		ioc->name, ioc_state));
+ 	return -EFAULT;
+ }
+@@ -3552,7 +3344,8 @@ KickStart(MPT_ADAPTER *ioc, int force, i
+ 		/* Always issue a Msg Unit Reset first. This will clear some
+ 		 * SCSI bus hang conditions.
+ 		 */
+-            mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
++		SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
++
+ 		if (sleepFlag == CAN_SLEEP)
+ 			msleep_interruptible(1000);
+ 		else
+@@ -3624,26 +3417,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+ 			msleep_interruptible(1);
+ 		else
+ 			MPT_MDELAY(1);
+-/*
+-		 * Call each currently registered protocol IOC reset handler
+-		 * with post-reset indication.
+-		 * NOTE: If we're doing _IOC_BRINGUP, there can be no
+-		 * MptResetHandlers[] registered yet.
+- */
+-                  {
+-                      int	 ii;
+-                      int        r=0;
+-
+-                  for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+-                              if (MptResetHandlers[ii]) {
+-  drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",ioc->name, ii));
+-  r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+-
+-   }
+-}
+-/* FIXME?  Examine results here? */
+-
+-}
+ 
+ 		for (count = 0; count < 60; count ++) {
+ 			doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+@@ -3746,11 +3519,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+ 
+ 			for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+ 				if (MptResetHandlers[ii]) {
+-					drsprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
++					dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
+ 							ioc->name, ii));
+ 					r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
+ 					if (ioc->alt_ioc) {
+-						drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
++						dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
+ 								ioc->name, ioc->alt_ioc->name, ii));
+ 						r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
+ 					}
+@@ -3901,31 +3674,18 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+  *
+  *	Returns 0 for success, non-zero for failure.
+  */
+-int
+-mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
++static int
++SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
+ {
+-        unsigned long flags;
+ 	int r;
+-	u32 state, Doorbell;
++	u32 state;
+ 	int cntdn, count;
+ 
+-Doorbell = (reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
+-
+-drsprintk((MYIOC_s_WARN_FMT ": %s: reset_type=%02x Doorbell=%08x!\n",
+-ioc->name, __FUNCTION__, reset_type, Doorbell));
+-CHIPREG_WRITE32(&ioc->chip->Doorbell, Doorbell);
+-
+-if ((r = WaitForDoorbellAck(ioc, 15, sleepFlag)) < 0){
+-                drsprintk((MYIOC_s_WARN_FMT ": %s: WaitForDoorbellAck failed r=%d after IOC Rese
+-t type=%02x!\n",
+-                        ioc->name, __FUNCTION__, r, reset_type));
+- return r;
+-}
+-
+-spin_lock_irqsave(&ioc->diagLock, flags);
+-ioc->IOCResetInProgress = 1;
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
++	drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
++			ioc->name, reset_type));
++	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
++	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
++		return r;
+ 
+ 	/* FW ACK'd request, wait for READY state
+ 	 */
+@@ -3950,13 +3710,13 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 			MPT_MDELAY(1);	/* 1 msec delay */
+ 	}
+ 
++	/* TODO!
++	 *  Cleanup all event stuff for this IOC; re-issue EventNotification
++	 *  request if needed.
++	 */
+ 	if (ioc->facts.Function)
+ 		ioc->facts.EventState = 0;
+-spin_lock_irqsave(&ioc->diagLock, flags);
+-ioc->IOCResetInProgress = 0;
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-drsprintk((MYIOC_s_WARN_FMT ": %s: IOC reset completed successfully state=%08x count=%d\ n",
+-ioc->name, __FUNCTION__, state, count));
++
+ 	return 0;
+ }
+ 
+@@ -4044,9 +3804,8 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 	unsigned long flags;
+ 	dma_addr_t alloc_dma;
+ 	u8 *mem;
+-	int i, reply_sz, req_sz, sz, total_size, num_chain, total_num_chain;
+-        int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size;
+-	int max_sg_tablesize;
++	int i, reply_sz, sz, total_size, num_chain, total_num_chain;
++	int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size;
+ 
+ 	/*  Prime reply FIFO...  */
+ 
+@@ -4073,13 +3832,12 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 			" numSGE=%d MaxChainDepth=%d maxSGEs=%d mpt_sg_tablesize=%d\n",
+ 			ioc->name, ioc->req_sz, SGE_size, scale, num_sge, numSGE, 
+ 			ioc->facts.MaxChainDepth, maxSGEs, mpt_sg_tablesize));
+-		max_sg_tablesize = mpt_sg_tablesize;
+-		if (max_sg_tablesize > maxSGEs) {
+-			max_sg_tablesize = maxSGEs;
+-			dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now\n",
+-				ioc->name, max_sg_tablesize));
+-		} else if (max_sg_tablesize < maxSGEs) {
+-			numSGE = max_sg_tablesize - num_sge;
++		if (mpt_sg_tablesize > maxSGEs) {
++			mpt_sg_tablesize = maxSGEs;
++			dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now\n",
++				ioc->name, mpt_sg_tablesize));
++		} else if (mpt_sg_tablesize < maxSGEs) {
++			numSGE = mpt_sg_tablesize - num_sge;
+ 			dinitprintk((KERN_INFO MYNAM ": %s numSGE=%d now\n",
+ 				ioc->name, numSGE));
+ 		}
+@@ -4099,12 +3857,11 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 
+ 		numSGE = scale1 * (total_num_chain-1);
+ 		maxSGEs = num_sge + numSGE;
+-		if (max_sg_tablesize > maxSGEs) {
+-			max_sg_tablesize = maxSGEs;
+-			dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n",
+-				ioc->name, max_sg_tablesize, maxSGEs, numSGE));
++		if (mpt_sg_tablesize > maxSGEs) {
++			mpt_sg_tablesize = maxSGEs;
++			dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n",
++				ioc->name, mpt_sg_tablesize, maxSGEs, numSGE));
+ 		}
+-		ioc->sg_tablesize = max_sg_tablesize;
+ 
+ 		dinitprintk((KERN_INFO MYNAM ": %s req_depth=%d max num_chain=%d mpt_chain_alloc_percent=%d total_num_chain=%d\n",
+ 			ioc->name, ioc->req_depth, num_chain, mpt_chain_alloc_percent, total_num_chain));
+@@ -4116,17 +3873,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 		dinitprintk((KERN_INFO MYNAM ": %s Total ReplyBuffer sz=%d[%x] bytes\n",
+ 			 	ioc->name, reply_sz, reply_sz));
+ 
+-                req_sz = ioc->req_sz;
+-                sz = (req_sz * ioc->req_depth);
+-
+-	dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+-				ioc->name, req_sz, ioc->req_depth));
+-
++		sz = (ioc->req_sz * ioc->req_depth);
++		dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n",
++			 	ioc->name, ioc->req_sz, ioc->req_depth));
+ 		dinitprintk((KERN_INFO MYNAM ": %s Total RequestBuffer sz=%d[%x] bytes\n",
+ 			 	ioc->name, sz, sz));
+ 		total_size += sz;
+ 
+-		sz = total_num_chain *req_sz; /* chain buffer pool size */
++		sz = total_num_chain * ioc->req_sz; /* chain buffer pool size */
+ 		dinitprintk((KERN_INFO MYNAM ": %s Total ChainBuffer sz=%d[%x] bytes total_num_chain=%d\n",
+ 			 	ioc->name, sz, sz, total_num_chain));
+ 
+@@ -4182,14 +3936,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ #endif
+ 
+ 		for (i = 0; i < ioc->req_depth; i++) {
+-			alloc_dma += req_sz;
+-			mem += req_sz;
++			alloc_dma += ioc->req_sz;
++			mem += ioc->req_sz;
+ 		}
+ 
+ 		ioc->ChainBuffer = mem;
+ 		ioc->ChainBufferDMA = alloc_dma;
+ 
+-		dinitprintk((KERN_INFO MYNAM ": %s ChainBuffers @ %p(%p)\n",
++		dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
+ 			ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
+ 
+ 		/* Initialize the free chain Q.
+@@ -4197,6 +3951,10 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 
+ 		INIT_LIST_HEAD(&ioc->FreeChainQ);
+ 
++		/* initialize the SAS device list */
++
++		INIT_LIST_HEAD(&ioc->sasDeviceList);
++
+ 		/* Post the chain buffers to the FreeChainQ.
+ 	 	*/
+ 		mem = (u8 *)ioc->ChainBuffer;
+@@ -4205,7 +3963,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 			list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
+ //			dinitprintk((MYIOC_s_INFO_FMT "Adding %p to FreeChainQ at %d\n",
+  //				ioc->name, mf, i));
+-			mem += req_sz;
++			mem += ioc->req_sz;
+ 		}
+ 
+ 		/* Initialize Request frames linked list
+@@ -4220,7 +3978,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ 
+ 			/*  Queue REQUESTs *internally*!  */
+ 			list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+-			mem += req_sz;
++			mem += ioc->req_sz;
+ 		}
+ 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ 
+@@ -4293,7 +4051,8 @@ out_fail:
+  *
+  *	Returns 0 for success, non-zero for failure.
+  */
+-int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
++static int
++mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
+ 		int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+ {
+ 	MPIDefaultReply_t *mptReply;
+@@ -4412,7 +4171,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
+ 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+ 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+ 				break;
+-			msleep_interruptible(10);
++			msleep_interruptible(1);
+ 			count++;
+ 		}
+ 	} else {
+@@ -4420,7 +4179,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
+ 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+ 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+ 				break;
+-                          udelay(1000);
++			MPT_MDELAY(1);
+ 			count++;
+ 		}
+ 	}
+@@ -4461,7 +4220,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
+ 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+ 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+ 				break;
+-			msleep_interruptible(10);
++			msleep_interruptible(1);
+ 			count++;
+ 		}
+ 	} else {
+@@ -4469,7 +4228,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
+ 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+ 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+ 				break;
+-                          udelay(1000);
++			MPT_MDELAY(1);
+ 			count++;
+ 		}
+ 	}
+@@ -4944,40 +4703,481 @@ GetManufPage0_exit:
+ 	return rc;
+ }
+ 
++
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+- *	mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
++ *	mpt_sas_get_info - Fetch Hw Max and Min Link Rates.  These values
++ *               get overwritten, so must be saved at init time.
+  *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@sas_address: 64bit SAS Address for operation.
+- *	@target_id: specified target for operation
+- *	@bus: specified bus for operation
+- *	@persist_opcode: see below
+- *
+- *	MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+- *		devices not currently present.
+- *	MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+- *
+- *	NOTE: Don't use not this function during interrupt time.
++ *	@numPorts: number of ports for this IOC
+  *
+- *	Returns: 0 for success, non-zero error
++ *	Return: 0 for success
++ *	-ENOMEM if no memory available
++ *		-EPERM if not allowed due to ISR context
++ *		-EAGAIN if no msg frames currently available
++ *		-EFAULT for non-successful reply or no reply (timeout)
+  */
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ int
+-mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
++mpt_sas_get_info(MPT_ADAPTER *ioc)
+ {
+-	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
+-	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
+-	MPT_FRAME_HDR			*mf = NULL;
+-	MPIHeader_t			*mpi_hdr;
++	ConfigExtendedPageHeader_t hdr;
++	CONFIGPARMS		cfg;
++	SasIOUnitPage0_t	*sasIoUnitPg0=NULL;
++	dma_addr_t		sasIoUnitPg0_dma;
++	SasPhyPage0_t		*sasPhyPg0=NULL;
++	dma_addr_t		sasPhyPg0_dma;
++	SasDevicePage0_t	*sasDevicePg0=NULL;
++	dma_addr_t		sasDevicePg0_dma;
++	sas_device_info_t	*sasDevice;
++	u32			devHandle;
++	int			sasIoUnitPg0_data_sz=0;
++	int			sasPhyPg0_data_sz=0;
++	int			sasDevicePg0_data_sz=0;
++	int			sz;
++	int		        rc;
++	int			ii;
++	int			phyCounter;
++	u8			*mem;
++	u64			SASAddress64;
++	char 			*ds = NULL;
+ 
++	/* Issue a config request to get the number of phys
++	 */
++	ioc->sasPhyInfo=NULL;
+ 
+-	/* insure garbage is not sent to fw */
+-	switch(persist_opcode) {
++	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+ 
+-	case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+-	case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+-		break;
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.physAddr = -1;
++	cfg.pageAddr = 0;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = 10;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		goto mpt_sas_get_info_exit;
++	}
++
++	if (hdr.ExtPageLength == 0) {
++		rc = -EFAULT;
++		goto mpt_sas_get_info_exit;
++	}
++
++	sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++	sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++	    sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++	if (!sasIoUnitPg0) {
++		rc = -ENOMEM;
++		goto mpt_sas_get_info_exit;
++	}
++
++	memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++	cfg.physAddr = sasIoUnitPg0_dma;
++	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++	if ((rc = mpt_config(ioc, &cfg)) != 0) {
++		goto mpt_sas_get_info_exit;
++	}
++
++	/* save the data */
++	ioc->numPhys = sasIoUnitPg0->NumPhys;
++
++	dsasprintk((MYIOC_s_INFO_FMT "Number of PHYS=%d\n",
++	    ioc->name, sasIoUnitPg0->NumPhys));
++
++	sz = ioc->numPhys * sizeof (sas_phy_info_t);
++
++	if ((mem = kmalloc(sz, GFP_ATOMIC)) == NULL) {
++		rc = -ENOMEM;
++		goto mpt_sas_get_info_exit;
++	}
++
++	memset(mem, 0, sz);
++	ioc->alloc_total += sz;
++	ioc->sasPhyInfo = (sas_phy_info_t *) mem;
++
++	/* Issue a config request to get phy information. */
++	hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++	hdr.ExtPageLength = 0;
++	hdr.PageNumber = 0;
++	hdr.Reserved1 = 0;
++	hdr.Reserved2 = 0;
++	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++	cfg.cfghdr.ehdr = &hdr;
++	cfg.dir = 0;	/* read */
++	cfg.timeout = 10;
++
++	/* Fill in information for each phy. */
++	for (ii = 0; ii < ioc->numPhys; ii++) {
++
++		/* Get Phy Pg 0 for each Phy. */
++		cfg.pageAddr = ii;
++		cfg.physAddr = -1;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++			goto mpt_sas_get_info_exit;
++		}
++
++		if (hdr.ExtPageLength == 0) {
++			rc = -EFAULT;
++			goto mpt_sas_get_info_exit;
++		}
++
++		sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++		sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
++		    ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
++		if (!sasPhyPg0) {
++			rc = -ENOMEM;
++			goto mpt_sas_get_info_exit;
++		}
++
++		memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++		cfg.physAddr = sasPhyPg0_dma;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++		/* Save HwLinkRate.
++		 * It may be modified accidently via FW
++		 */
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++			goto mpt_sas_get_info_exit;
++		}
++
++		ioc->sasPhyInfo[ii].hwLinkRate = sasPhyPg0->HwLinkRate;
++		ioc->sasPhyInfo[ii].phyId = ii;
++		ioc->sasPhyInfo[ii].port = sasIoUnitPg0->PhyData[ii].Port;
++		ioc->sasPhyInfo[ii].ControllerDevHandle =
++		    le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
++		ioc->sasPhyInfo[ii].PortFlags =
++		    sasIoUnitPg0->PhyData[ii].PortFlags;
++		ioc->sasPhyInfo[ii].PhyFlags =
++		    sasIoUnitPg0->PhyData[ii].PhyFlags;
++		ioc->sasPhyInfo[ii].NegotiatedLinkRate =
++		    sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate;
++		ioc->sasPhyInfo[ii].ControllerPhyDeviceInfo =
++		    le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo);
++
++		memcpy(&SASAddress64,&sasPhyPg0->SASAddress,sizeof(sasPhyPg0->SASAddress));
++		le64_to_cpus(&SASAddress64);
++		if (SASAddress64) {
++			dsasprintk(("---- SAS PHY PAGE 0 ------------\n"));
++			dsasprintk(("Handle=0x%X\n",
++			    le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
++			dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++			dsasprintk(("Attached PHY Identifier=0x%X\n",
++			    sasPhyPg0->AttachedPhyIdentifier));
++			dsasprintk(("Attached Device Info=0x%X\n",
++			    le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
++			dsasprintk(("Programmed Link Rate=0x%X\n",
++			    sasPhyPg0->ProgrammedLinkRate));
++			dsasprintk(("Hardware Link Rate=0x%X\n",
++			    ioc->sasPhyInfo[ii].hwLinkRate));
++			dsasprintk(("Change Count=0x%X\n",
++			    sasPhyPg0->ChangeCount));
++			dsasprintk(("PHY Info=0x%X\n",
++			    le32_to_cpu(sasPhyPg0->PhyInfo)));
++			dsasprintk(("\n"));
++		}
++
++		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++		sasPhyPg0=NULL;
++	}
++
++
++	/* Get all Device info and store in linked list. */
++	devHandle = 0xFFFF;
++	phyCounter=0;
++	while(1) {
++		/* Get SAS device page 0 */
++
++		hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
++		hdr.ExtPageLength = 0;
++		hdr.PageNumber = 0;
++		hdr.Reserved1 = 0;
++		hdr.Reserved2 = 0;
++		hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++		hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++		cfg.cfghdr.ehdr = &hdr;
++		cfg.physAddr = -1;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++		cfg.dir = 0;	/* read */
++		cfg.timeout = 10;
++
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++			goto mpt_sas_get_info_exit;
++		}
++
++		if (hdr.ExtPageLength == 0) {
++			rc = -EFAULT;
++			goto mpt_sas_get_info_exit;
++		}
++
++		sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
++		sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
++		    ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
++		if (!sasDevicePg0) {
++			rc = -ENOMEM;
++			goto mpt_sas_get_info_exit;
++		}
++
++		memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
++		cfg.physAddr = sasDevicePg0_dma;
++		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++		cfg.pageAddr = devHandle;
++
++		if ((rc = mpt_config(ioc, &cfg)) != 0) {
++
++		/*
++		 * break from the while loop when this fails
++		 * which means we have discovered all devices
++		 */
++			rc=0;
++			goto mpt_sas_get_info_exit;
++		}
++
++		dsasprintk(("---- SAS DEVICE PAGE 0 ---------\n"));
++		dsasprintk(("Handle=0x%X\n",le16_to_cpu(sasDevicePg0->DevHandle)));
++		dsasprintk(("Enclosure Handle=0x%X\n",le16_to_cpu(sasDevicePg0->EnclosureHandle)));
++		dsasprintk(("Slot=0x%X\n",le16_to_cpu(sasDevicePg0->Slot)));
++		memcpy(&SASAddress64,&sasDevicePg0->SASAddress,sizeof(sasDevicePg0->SASAddress));
++		le64_to_cpus(&SASAddress64);
++		dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++		dsasprintk(("Target ID=0x%X\n",sasDevicePg0->TargetID));
++		dsasprintk(("Bus=0x%X\n",sasDevicePg0->Bus));
++		dsasprintk(("PhyNum=0x%X\n",sasDevicePg0->PhyNum));
++		dsasprintk(("AccessStatus=0x%X\n",le16_to_cpu(sasDevicePg0->AccessStatus)));
++		dsasprintk(("Device Info=0x%X\n",le32_to_cpu(sasDevicePg0->DeviceInfo)));
++		dsasprintk(("Flags=0x%X\n",le16_to_cpu(sasDevicePg0->Flags)));
++		dsasprintk(("Physical Port=0x%X\n",sasDevicePg0->PhysicalPort));
++		dsasprintk(("\n"));
++
++		if(phyCounter < ioc->numPhys) {
++			ioc->sasPhyInfo[phyCounter].SASAddress = SASAddress64;
++			ioc->sasPhyInfo[phyCounter].devHandle =
++				le16_to_cpu(sasDevicePg0->DevHandle);
++			phyCounter++;
++		}else {
++			if (le32_to_cpu(sasDevicePg0->DeviceInfo) &
++			    (MPI_SAS_DEVICE_INFO_SSP_TARGET |
++			     MPI_SAS_DEVICE_INFO_STP_TARGET |
++			     MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
++
++				if ((sasDevice = kmalloc(sizeof (sas_device_info_t),
++				    GFP_ATOMIC)) == NULL) {
++					rc = -ENOMEM;
++					goto mpt_sas_get_info_exit;
++				}
++
++				memset(sasDevice, 0, sizeof (sas_device_info_t));
++				ioc->alloc_total += sizeof (sas_device_info_t);
++				list_add_tail(&sasDevice->list, &ioc->sasDeviceList);
++				sasDevice->SASAddress = SASAddress64;
++				sasDevice->TargetId = sasDevicePg0->TargetID;
++				sasDevice->Bus = sasDevicePg0->Bus;
++				sasDevice->DeviceInfo =
++				  le32_to_cpu(sasDevicePg0->DeviceInfo);
++				sasDevice->DevHandle =
++				   le16_to_cpu(sasDevicePg0->DevHandle);
++				sasDevice->Flags =
++				    le16_to_cpu(sasDevicePg0->Flags);
++				sasDevice->PhyNum = sasDevicePg0->PhyNum;
++				sasDevice->PhysicalPort =
++				    sasDevicePg0->PhysicalPort;
++				if(sasDevice->DeviceInfo &
++				    MPI_SAS_DEVICE_INFO_SSP_TARGET)
++					ds = "sas";
++				if(sasDevice->DeviceInfo &
++				    MPI_SAS_DEVICE_INFO_STP_TARGET)
++					ds = "stp";
++				if(sasDevice->DeviceInfo &
++				    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++					ds = "sata";
++				dsasprintk(( 
++					"Inserting %s device, channel %d, id %d, phy %d\n\n",
++					ds,sasDevice->Bus,
++					sasDevice->TargetId,
++					sasDevicePg0->PhyNum));
++			}
++		}
++
++		devHandle = (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
++			<< MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
++			le16_to_cpu(sasDevicePg0->DevHandle);
++
++		pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++			    (u8 *) sasDevicePg0, sasDevicePg0_dma);
++
++		sasDevicePg0=NULL;
++
++	};
++
++mpt_sas_get_info_exit:
++
++
++	if (sasPhyPg0)
++		pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++		    (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++	if (sasIoUnitPg0)
++		pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++		    (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++	if (sasDevicePg0)
++		pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++			    (u8 *) sasDevicePg0, sasDevicePg0_dma);
++
++	return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++
++static void
++mptbase_sas_process_event_data(MPT_ADAPTER *ioc,
++    MpiEventDataSasDeviceStatusChange_t * pSasEventData)
++{
++	sas_device_info_t	*sasDevice;
++	int 			ii;
++	char			*ds=NULL;
++
++	switch(pSasEventData->ReasonCode) {
++	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
++
++		// sanity check so we are not adding a target that is already in the list.
++		list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++			if (pSasEventData->TargetID ==
++			    sasDevice->TargetId)
++				return;
++				break; 
++		}
++
++		if ((le32_to_cpu(pSasEventData->DeviceInfo) &
++		    (MPI_SAS_DEVICE_INFO_SSP_TARGET |
++		     MPI_SAS_DEVICE_INFO_STP_TARGET |
++		     MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) {
++			break;
++		}
++
++		if ((sasDevice = kmalloc(sizeof (sas_device_info_t),
++		    GFP_ATOMIC)) == NULL) {
++			break;
++		}
++
++		memset(sasDevice, 0, sizeof (sas_device_info_t));
++		list_add_tail(&sasDevice->list, &ioc->sasDeviceList);
++		ioc->alloc_total += sizeof (sas_device_info_t);
++
++		memcpy(&sasDevice->SASAddress,&pSasEventData->SASAddress,sizeof(u64));
++		le64_to_cpus(&sasDevice->SASAddress);
++		sasDevice->TargetId = pSasEventData->TargetID;
++		sasDevice->Bus = pSasEventData->Bus;
++		sasDevice->DeviceInfo =
++		    le32_to_cpu(pSasEventData->DeviceInfo);
++		sasDevice->DevHandle =
++		    le16_to_cpu(pSasEventData->DevHandle);
++		sasDevice->PhyNum = pSasEventData->PhyNum;
++		pSasEventData->ParentDevHandle =
++		    le16_to_cpu(pSasEventData->ParentDevHandle);
++
++		for(ii=0;ii<ioc->numPhys;ii++) {
++			if(pSasEventData->ParentDevHandle ==
++			    ioc->sasPhyInfo[ii].ControllerDevHandle) {
++				sasDevice->PhysicalPort =
++				    ioc->sasPhyInfo[ii].port;
++			}
++		}
++
++		if(sasDevice->DeviceInfo &
++		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
++			ds = "sas";
++		if(sasDevice->DeviceInfo &
++		    MPI_SAS_DEVICE_INFO_STP_TARGET)
++			ds = "stp";
++		if(sasDevice->DeviceInfo &
++		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++			ds = "sata";
++		dsasprintk(( 
++			"Inserting %s device, channel %d, id %d, phy %d\n\n",
++			ds,sasDevice->Bus,
++			sasDevice->TargetId,
++			sasDevice->PhyNum));
++		dsasprintk(("SAS Address=0x%llX\n",sasDevice->SASAddress));
++		dsasprintk(("Device Info=0x%X\n",sasDevice->DeviceInfo));
++		dsasprintk(("Physical Port=0x%X\n",sasDevice->PhysicalPort));
++		dsasprintk(("\n"));
++
++		break;
++
++	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
++
++		list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++			if (le16_to_cpu(pSasEventData->DevHandle) ==
++			    sasDevice->DevHandle) {
++
++				dsasprintk(("Removing device from link list!!!\n\n"));
++				list_del(&sasDevice->list);
++				kfree(sasDevice);
++				ioc->alloc_total -= sizeof (sas_device_info_t);
++				break;
++			}
++		}
++		break;
++
++	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
++	case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
++	case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
++	default:
++		break;
++	}
++
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*
++ *	mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
++ *	@ioc: Pointer to MPT_ADAPTER structure
++ *	@sas_address: 64bit SAS Address for operation.
++ *	@target_id: specified target for operation
++ *	@bus: specified bus for operation
++ *	@persist_opcode: see below
++ *
++ *	MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
++ *		devices not currently present.
++ *	MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
++ *
++ *	NOTE: Don't use not this function during interrupt time.
++ *
++ *	Returns: 0 for success, non-zero error
++ */
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++int
++mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
++{
++	SasIoUnitControlRequest_t	*sasIoUnitCntrReq;
++	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
++	MPT_FRAME_HDR			*mf = NULL;
++	MPIHeader_t			*mpi_hdr;
++
++
++	/* insure garbage is not sent to fw */
++	switch(persist_opcode) {
++
++	case MPI_SAS_OP_CLEAR_NOT_PRESENT:
++	case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
++		break;
+ 
+ 	default:
+ 		return -1;
+@@ -4992,7 +5192,7 @@ mptbase_sas_persist_operation(MPT_ADAPTE
+ 		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+ 		    ioc->name,__FUNCTION__));
+ 		return -1;
+-        }
++	}
+ 
+ 	mpi_hdr = (MPIHeader_t *) mf;
+ 	sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+@@ -5303,7 +5503,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
+ 
+ 				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
+ 					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
+-					ddvprintk((KERN_INFO MYNAM ": %s noQas due to Capabilities=%x\n",
++					ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+ 						ioc->name, pPP0->Capabilities));
+ 				}
+ 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
+@@ -5452,188 +5652,6 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
+ 	return 0;
+ }
+ 
+-/**
+- *	mpt_raid_phys_disk_pg0 - returns phys disk page zero
+- *	@ioc: Pointer to a Adapter Structure
+- *	@phys_disk_num: io unit unique phys disk num generated by the ioc
+- *	@phys_disk: requested payload data returned
+- *
+- *	Return:
+- *	0 on success
+- *	-EFAULT if read of config page header fails or data pointer not NULL
+- *	-ENOMEM if pci_alloc failed
+- **/
+-int
+-mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+-{
+-	CONFIGPARMS		 	cfg;
+-	ConfigPageHeader_t	 	hdr;
+-	dma_addr_t			dma_handle;
+-	pRaidPhysDiskPage0_t		buffer = NULL;
+-	int				rc;
+-
+-	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		rc = -EFAULT;
+-		goto out;
+-	}
+-
+-	if (!hdr.PageLength) {
+-		rc = -EFAULT;
+-		goto out;
+-	}
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-	    &dma_handle);
+-
+-	if (!buffer) {
+-		rc = -ENOMEM;
+-		goto out;
+-	}
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	cfg.pageAddr = phys_disk_num;
+-
+-	if (mpt_config(ioc, &cfg) != 0) {
+-		rc = -EFAULT;
+-		goto out;
+-	}
+-
+-	rc = 0;
+-	memcpy(phys_disk, buffer, sizeof(*buffer));
+-	phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
+-
+- out:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-		    dma_handle);
+-
+-	return rc;
+-}
+-
+-/**
+- * mpt_inactive_raid_list_free
+- *
+- * This clears this link list.
+- *
+- * @ioc - pointer to per adapter structure
+- *
+- **/
+-static void
+-mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+-{
+-	struct inactive_raid_component_info *component_info, *pNext;
+-
+-	if (list_empty(&ioc->raid_data.inactive_list))
+-		return;
+-
+-	down(&ioc->raid_data.inactive_list_mutex);
+-	list_for_each_entry_safe(component_info, pNext,
+-	    &ioc->raid_data.inactive_list, list) {
+-		list_del(&component_info->list);
+-		kfree(component_info);
+-	}
+-	up(&ioc->raid_data.inactive_list_mutex);
+-}
+-
+-/**
+- * mpt_inactive_raid_volumes
+- *
+- * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
+- *
+- * @ioc - pointer to per adapter structure
+- * @channel - volume channel
+- * @id - volume target id
+- *
+- *
+- **/
+-static void
+-mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	CONFIGPARMS			cfg;
+-	ConfigPageHeader_t		hdr;
+-	dma_addr_t			dma_handle;
+-	pRaidVolumePage0_t		buffer = NULL;
+-	int				i;
+-	RaidPhysDiskPage0_t 		phys_disk;
+-	struct inactive_raid_component_info *component_info;
+-	int				handle_inactive_volumes;
+-
+-	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-	cfg.pageAddr = (channel << 8) + id;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto out;
+-
+-	if (!hdr.PageLength)
+-		goto out;
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-	    &dma_handle);
+-
+-	if (!buffer)
+-		goto out;
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto out;
+-
+-	if (!buffer->NumPhysDisks)
+-		goto out;
+-
+-	handle_inactive_volumes =
+-	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
+-	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
+-	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
+-	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
+-
+-	if (!handle_inactive_volumes)
+-		goto out;
+-
+-	down(&ioc->raid_data.inactive_list_mutex);
+-	for (i = 0; i < buffer->NumPhysDisks; i++) {
+-		if(mpt_raid_phys_disk_pg0(ioc,
+-		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+-			continue;
+-
+-		if ((component_info = kmalloc(sizeof (*component_info),
+-		 GFP_KERNEL)) == NULL)
+-			continue;
+-
+-		component_info->volumeID = id;
+-		component_info->volumeBus = channel;
+-		component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
+-		component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
+-		component_info->d.PhysDiskID = phys_disk.PhysDiskID;
+-		component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
+-
+-		list_add_tail(&component_info->list,
+-		    &ioc->raid_data.inactive_list);
+-	}
+-	up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-		    dma_handle);
+-}
+-
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
+@@ -5657,16 +5675,8 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
+ 	int			 jj;
+ 	int			 rc = 0;
+ 	int			 iocpage2sz;
+-
+-	if (!ioc->ir_firmware)
+-		return 0;
+-
+-	/* Free the old page
+-	 */
+-	kfree(ioc->raid_data.pIocPg2);
+-	ioc->raid_data.pIocPg2 = NULL;
+-	mpt_inactive_raid_list_free(ioc);
+-	ioc->raid_data.isRaid = 0;
++	u8			 nVols, nPhys;
++	u8			 vid, vbus, vioc;
+ 
+ 	/* Read IOCP2 header then the page.
+ 	 */
+@@ -5696,35 +5706,53 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
+ 	if (mpt_config(ioc, &cfg) != 0)
+ 		goto done_and_free;
+ 
+-	mem = kmalloc(iocpage2sz, GFP_ATOMIC);
+-	if (!mem)
+-		goto done_and_free;
+-
++	if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
++		mem = kmalloc(iocpage2sz, GFP_ATOMIC);
++		if (mem) {
++			ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
++		} else {
++			goto done_and_free;
++		}
++	}
+ 	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+-	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
+ 
+ 	/* Identify RAID Volume Id's */
+-	if (pIoc2->NumActiveVolumes) {
+-
+-		pIocRv = pIoc2->RaidVolume;
+-		/*
+-		 * WARNING - ioc->raid_data.isRaid
+-		 * doesn't consider channels
++	nVols = pIoc2->NumActiveVolumes;
++	if ( nVols == 0) {
++		/* No RAID Volume.
+ 		 */
+-		for (jj = 0; jj < pIoc2->NumActiveVolumes; jj++, pIocRv++) {
+-			if (pIocRv->VolumeBus)
+-				continue;
+-			ioc->raid_data.isRaid |= (1 << pIocRv->VolumeID);
+-			mpt_inactive_raid_volumes(ioc,
+-			    pIoc2->RaidVolume[jj].VolumeBus,
+-			    pIoc2->RaidVolume[jj].VolumeID);
++		goto done_and_free;
++	} else {
++		/* At least 1 RAID Volume
++		 */
++		pIocRv = pIoc2->RaidVolume;
++		ioc->raid_data.isRaid = 0;
++		for (jj = 0; jj < nVols; jj++, pIocRv++) {
++			vid = pIocRv->VolumeID;
++			vbus = pIocRv->VolumeBus;
++			vioc = pIocRv->VolumeIOC;
++
++			/* find the match
++			 */
++			if (vbus == 0) {
++				ioc->raid_data.isRaid |= (1 << vid);
++			} else {
++				/* Error! Always bus 0
++				 */
++			}
+ 		}
+-	             mpt_read_ioc_pg_3(ioc);
+-                     mpt_read_ioc_pg_6(ioc);
+-        }
++	}
+ 
++	/* Identify Hidden Physical Disk Id's */
++	nPhys = pIoc2->NumActivePhysDisks;
++	if (nPhys == 0) {
++		/* No physical disks.
++		 */
++	} else {
++		mpt_read_ioc_pg_3(ioc);
++	}
+ 
+- done_and_free:
++done_and_free:
+ 	pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
+ 
+ 	return rc;
+@@ -5845,65 +5873,6 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
+ }
+ 
+ static void
+-mpt_read_ioc_pg_6(MPT_ADAPTER *ioc)
+-{
+-	IOCPage6_t		*pIoc6;
+-	u8			*mem;
+-	CONFIGPARMS		 cfg;
+-	ConfigPageHeader_t	 header;
+-	dma_addr_t		 ioc6_dma;
+-	int			 iocpage6sz = 0;
+-
+-	/* Free the old page
+-	 */
+-	if (ioc->raid_data.pIocPg6) {
+-		kfree(ioc->raid_data.pIocPg6);
+-		ioc->raid_data.pIocPg6 = NULL;
+-	}
+-
+-	/* There is at least one physical disk.
+-	 * Read and save IOC Page 3
+-	 */
+-	header.PageVersion = 0;
+-	header.PageLength = 0;
+-	header.PageNumber = 6;
+-	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-	cfg.cfghdr.hdr = &header;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;
+-	cfg.timeout = 0;
+-	if (mpt_config(ioc, &cfg) != 0)
+-		return;
+-
+-	if (header.PageLength == 0)
+-		return;
+-
+-	/* Read Header good, alloc memory
+-	 */
+-	iocpage6sz = header.PageLength * 4;
+-	pIoc6 = pci_alloc_consistent(ioc->pcidev, iocpage6sz, &ioc6_dma);
+-	if (!pIoc6)
+-		return;
+-
+-	/* Read the Page and save the data
+-	 * into malloc'd memory.
+-	 */
+-	cfg.physAddr = ioc6_dma;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-	if (mpt_config(ioc, &cfg) == 0) {
+-		mem = kmalloc(iocpage6sz, GFP_ATOMIC);
+-		if (mem) {
+-			memcpy(mem, (u8 *)pIoc6, iocpage6sz);
+-			ioc->raid_data.pIocPg6 = (IOCPage6_t *) mem;
+-		}
+-	}
+-
+-	pci_free_consistent(ioc->pcidev, iocpage6sz, pIoc6, ioc6_dma);
+-}
+-
+-static void
+ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
+ {
+ 	IOCPage1_t		*pIoc1;
+@@ -6007,12 +5976,13 @@ SendEventNotification(MPT_ADAPTER *ioc, 
+ 		    ioc->name,__FUNCTION__));
+ 		return 0;
+ 	}
+-	ioc->evnp = evnp;
+-        memset(evnp, 0, sizeof(*evnp));
++	memset(evnp, 0, sizeof(*evnp));
+ 
+ 	devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
+ 
+ 	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
++	evnp->ChainOffset = 0;
++	evnp->MsgFlags = 0;
+ 	evnp->Switch = EvSwitch;
+ 
+ 	mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
+@@ -6037,10 +6007,13 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
+ 		return -1;
+ 	}
+ 
+-	devtprintk((MYIOC_s_INFO__FMT "Sending EventAck\n", ioc->name));
+-        memset(pAck, 0, sizeof(*pAck));
++	devtprintk((MYIOC_s_WARN_FMT "Sending EventAck\n", ioc->name));
+ 
+ 	pAck->Function     = MPI_FUNCTION_EVENT_ACK;
++	pAck->ChainOffset  = 0;
++	pAck->Reserved[0]  = pAck->Reserved[1] = 0;
++	pAck->MsgFlags     = 0;
++	pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
+ 	pAck->Event        = evnp->Event;
+ 	pAck->EventContext = evnp->EventContext;
+ 	DBG_DUMP_EVENT_REQUEST_FRAME(pAck);
+@@ -6080,7 +6053,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
+ 	 */
+ 	in_isr = in_interrupt();
+ 	if (in_isr) {
+-		dfailprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
++		dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
+ 				ioc->name));
+ 		return -EPERM;
+ 	}
+@@ -6607,12 +6580,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+ 	 * mpt_do_ioc_recovery at any instant in time.
+ 	 */
+ 	spin_lock_irqsave(&ioc->diagLock, flags);
+-	   if (ioc->IOCResetInProgress){
++	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
+ 		spin_unlock_irqrestore(&ioc->diagLock, flags);
+-	dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: IOCResetInProgress!\n",
+-              ioc->name));
+-
+-                return 0;
++		return 0;
++	} else {
++		ioc->diagPending = 1;
+ 	}
+ 	spin_unlock_irqrestore(&ioc->diagLock, flags);
+ 
+@@ -6633,6 +6605,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+ 				dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
+ 						ioc->name, ii));
+ 				r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
++				if (ioc->alt_ioc) {
++					dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
++							ioc->name, ioc->alt_ioc->name, ii));
++					r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
++				}
+ 			}
+ 		}
+ 	}
+@@ -6642,307 +6619,23 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+ 			rc, ioc->name);
+ 	}
+ 	ioc->reload_fw = 0;
++	if (ioc->alt_ioc)
++		ioc->alt_ioc->reload_fw = 0;
+ 
+-	if (ioc->alt_ioc) {
+-  dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler alt_ioc: checking IOCResetInProgress=%d\n",
+-			ioc->alt_ioc->name, ioc->alt_ioc->IOCResetInProgress));
+-	spin_lock_irqsave(&ioc->alt_ioc->diagLock, flags);
+-
+-if (ioc->alt_ioc->IOCResetInProgress) {
+- dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: alt_ioc IOCResetInProgress!\n", ioc->alt_ioc->name));
+-
+-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags);
+-return 0;
+-}
+-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags);
+-if ((rc = mpt_do_ioc_recovery(ioc->alt_ioc, MPT_HOSTEVENT_IOC_RECOVER,
+-sleepFlag)) != 0) {
+-printk(KERN_WARNING MYNAM ": WARNING - alt_%s mpt_do_ioc_recovery failed rc=%x\n", ioc->name,   rc );
+-     }
+-ioc->alt_ioc->reload_fw = 0;
+-}
+-
++	spin_lock_irqsave(&ioc->diagLock, flags);
++	ioc->diagPending = 0;
++	if (ioc->alt_ioc)
++		ioc->alt_ioc->diagPending = 0;
++	spin_unlock_irqrestore(&ioc->diagLock, flags);
+ 
+ 	dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
+ 
+ 	return rc;
+ }
+ 
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*	mpt_writeSDP1  - write SCSI Device Page 1
+- *	@ioc: Pointer to a SCSI Host Adapter Structure
+- *	@portnum: IOC port number
+- *	@id: writeSDP1 for single ID
+- *	@flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
+- *
+- *	Return: -EFAULT if read of config page header fails
+- *		or 0 if success.
+- *
+- *	Remark: If a target has been found, the settings from the
+- *		target structure are used, else the device is set
+- *		to async/narrow.
+- *
+- *	Remark: Called during init and after a FW reload.
+- *	Remark: We do not wait for a return, write pages sequentially.
+- */
+-int
+-mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags)
+-{
+-	Config_t		*pReq;
+-	SCSIDevicePage1_t	*pData;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice		*pTarget;
+-	MPT_FRAME_HDR		*mf;
+-	dma_addr_t		 dataDma;
+-	u16			 req_idx;
+-	u32			 frameOffset;
+-	u32			 requested, configuration, flagsLength;
+-	int			 ii, nvram;
+-	int			 loop_id, loop_end;
+-	u8			 width;
+-	u8			 factor;
+-	u8			 offset;
+-	u8			 bus = 0;
+-	u8			 negoFlags;
+-	u8			 maxwidth, maxoffset, maxfactor;
+-
+-	if ((pMptTarget = ioc->Target_List[0]) == NULL)
+-		return 0;
+-
+-	if (ioc->spi_data.sdp1length == 0)
+-		return 0;
+-
+-	if (flags & MPT_SCSICFG_ALL_IDS) {
+-		loop_id = 0;
+-		loop_end = ioc->DevicesPerBus;
+-	} else {
+-		loop_id = id;
+-		loop_end = id+1;
+-	}
+-
+-	for (; loop_id < loop_end; loop_id++) {
+-
+-		if (loop_id == ioc->pfacts[portnum].PortSCSIID)
+-			continue;
+-
+-
+-		pTarget = pMptTarget->Target[loop_id];
+-
+-		/* Use NVRAM to get adapter and target maximums
+-		 * Data over-riden by target structure information, if present
+-		 */
+-		maxwidth = ioc->spi_data.maxBusWidth;
+-		maxoffset = ioc->spi_data.maxSyncOffset;
+-		maxfactor = ioc->spi_data.minSyncFactor;
+-		if (ioc->spi_data.nvram && (ioc->spi_data.nvram[loop_id] != MPT_HOST_NVRAM_INVALID)) {
+-			nvram = ioc->spi_data.nvram[loop_id];
+-
+-			if (maxwidth)
+-				maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+-
+-			if (maxoffset > 0) {
+-				maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+-				if (maxfactor == 0) {
+-					/* Key for async */
+-					maxfactor = MPT_ASYNC;
+-					maxoffset = 0;
+-				} else if (maxfactor < ioc->spi_data.minSyncFactor) {
+-					maxfactor = ioc->spi_data.minSyncFactor;
+-				}
+-			} else
+-				maxfactor = MPT_ASYNC;
+-		}
+-
+-		/* Set the negotiation flags.
+-		 */
+-		negoFlags = ioc->spi_data.noQas;
+-		if (!maxwidth)
+-			negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+-
+-		if (!maxoffset)
+-			negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+-
+-		if (flags & MPT_SCSICFG_USE_NVRAM) {
+-			width = maxwidth;
+-			factor = maxfactor;
+-			offset = maxoffset;
+-			dnegoprintk(("%s: writeSDP1: USE_NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				ioc->name, loop_id, width, factor, offset, negoFlags));
+-		} else {
+-			width = 0;
+-			factor = MPT_ASYNC;
+-			offset = 0;
+-			//negoFlags = 0;
+-			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
+-			dnegoprintk(("%s: writeSDP1: !USE_NVRAM: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				ioc->name, loop_id, width, factor, offset, negoFlags));
+-		}
+-
+-		/* If id is not a raid volume, get the updated
+-		 * transmission settings from the target structure.
+-		 */
+-		if ( pTarget && !pTarget->raidVolume) {
+-			width = pTarget->maxWidth;
+-			factor = pTarget->minSyncFactor;
+-			offset = pTarget->maxOffset;
+-			negoFlags |= pTarget->negoFlags;
+-			dnegoprintk(("%s: writeSDP1: NOT RAID id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				ioc->name, loop_id, width, factor, offset, negoFlags));
+-		}
+-
+-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-		/* Force to async and narrow if DV has not been executed
+-		 * for this ID
+-		 */
+-		if ((ioc->spi_data.dvStatus[loop_id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
+-			width = 0;
+-			factor = MPT_ASYNC;
+-			offset = 0;
+-			dnegoprintk(("%s: writeSDP1: DV_NOT_DONE: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				ioc->name, loop_id, width, factor, offset, negoFlags));
+-		}
+-#endif
+-
+-		if (flags & MPT_SCSICFG_BLK_NEGO) {
+-			negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
+-			dnegoprintk(("%s: writeSDP1: BLK_NEGO id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				ioc->name, loop_id, width, factor, offset, negoFlags));
+-		}
+-
+-		mpt_setSDP1parameters(width, factor, offset, negoFlags,
+-				&requested, &configuration);
+-
+-		/* Get a MF for this command.
+-		 */
+-		if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+-			dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-			    ioc->name,__FUNCTION__));
+-			return -EAGAIN;
+-		}
+-
+-		/* Set the request and the data pointers.
+-		 * Request takes: 36 bytes (32 bit SGE)
+-		 * SCSI Device Page 1 requires 16 bytes
+-		 * 40 + 16 <= size of SCSI IO Request = 56 bytes
+-		 * and MF size >= 64 bytes.
+-		 * Place data at end of MF.
+-		 */
+-		pReq = (Config_t *)mf;
+-
+-		req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-		frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
+-
+-		pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
+-		dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
+-
+-		/* Complete the request frame (same for all requests).
+-		 */
+-		pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-		pReq->Reserved = 0;
+-		pReq->ChainOffset = 0;
+-		pReq->Function = MPI_FUNCTION_CONFIG;
+-		pReq->ExtPageLength = 0;
+-		pReq->ExtPageType = 0;
+-		pReq->MsgFlags = 0;
+-		for (ii=0; ii < 8; ii++) {
+-			pReq->Reserved2[ii] = 0;
+-		}
+-		pReq->Header.PageVersion = ioc->spi_data.sdp1version;
+-		pReq->Header.PageLength = ioc->spi_data.sdp1length;
+-		pReq->Header.PageNumber = 1;
+-		pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+-		pReq->PageAddress = cpu_to_le32(loop_id | (bus << 8 ));
+-
+-		/* Add a SGE to the config request.
+-		 */
+-		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
+-
+-		mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+-
+-		/* Set up the common data portion
+-		 */
+-		pData->Header.PageVersion = pReq->Header.PageVersion;
+-		pData->Header.PageLength = pReq->Header.PageLength;
+-		pData->Header.PageNumber = pReq->Header.PageNumber;
+-		pData->Header.PageType = pReq->Header.PageType;
+-		pData->RequestedParameters = cpu_to_le32(requested);
+-		pData->Reserved = 0;
+-		pData->Configuration = cpu_to_le32(configuration);
+-
+-		if ( pTarget ) {
+-			if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) {
+-				pTarget->last_lun = MPT_LAST_LUN;
+-			} else {
+-				pTarget->last_lun = MPT_NON_IU_LAST_LUN;
+-			}
+-			dsprintk((MYIOC_s_INFO_FMT
+-				"writeSDP1: last_lun=%d on id=%d\n",
+-				ioc->name, pTarget->last_lun, loop_id));
+-		}
+-
+-		dnegoprintk((MYIOC_s_INFO_FMT
+-			"write SDP1: id=%d pgaddr=0x%x requested=%08x configuration=%08x\n",
+-				ioc->name, loop_id, (loop_id | (bus<<8)),
+-				requested, configuration));
+-
+-		mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+-	}
+-	return 0;
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*	mpt_setSDP1parameters  - set SDP1 Requested and Configuration
+- *	fields based on width, factor, offset and flags parameters.
+- *	@width: bus width
+- *	@factor: sync factor
+- *	@offset: sync offset
+- *	@flags: flags to block WDTR or SDTR negotiation
+- *	@requestedPtr: pointer to SDP1 Requested value (updated)
+- *	@configurationPtr: pointer to SDP1 Configuration value (updated)
+- *
+- *	Return: None.
+- *
+- *	Remark: Called by writeSDP1 and _dv_params
+- */
+-void
+-mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr)
+-{
+-	u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
+-	u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
+-
+-	*configurationPtr = 0;
+-	*requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
+-	*requestedPtr |= (offset << 16) | (factor << 8);
+-
+-	if (width && offset && !nowide && !nosync) {
+-		if (factor < MPT_ULTRA160) {
+-			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
+-			if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
+-				*requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
+-			if (flags & MPT_TAPE_NEGO_IDP)
+-				*requestedPtr |= 0x08000000;
+-		} else if (factor < MPT_ULTRA2) {
+-			*requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
+-		}
+-	}
+-
+-	if (nowide)
+-		*configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
+-
+-	if (nosync)
+-		*configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
+-
+-	return;
+-}
+-
+ # define EVENT_DESCR_STR_SZ		100
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-
+-
+-
+-
+-
+ static void
+ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
+ {
+@@ -6969,6 +6662,9 @@ EventDescriptionStr(u8 event, u32 evData
+ 		break;
+ 	case MPI_EVENT_RESCAN:
+ 		ds = "Bus Rescan Event";
++		/* Ok, do we need to do anything here? As far as
++		   I can tell, this is when a new device gets added
++		   to the loop. */
+ 		break;
+ 	case MPI_EVENT_LINK_STATUS_CHANGE:
+ 		if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
+@@ -6980,9 +6676,9 @@ EventDescriptionStr(u8 event, u32 evData
+ 		if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
+ 			ds = "Loop State(LIP) Change";
+ 		else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
+-			ds = "Loop State(LPE) Change";		/* ??? */
++			ds = "Loop State(LPE) Change";			/* ??? */
+ 		else
+-			ds = "Loop State(LPB) Change";		/* ??? */
++			ds = "Loop State(LPB) Change";			/* ??? */
+ 		break;
+ 	case MPI_EVENT_LOGOUT:
+ 		ds = "Logout";
+@@ -6995,6 +6691,9 @@ EventDescriptionStr(u8 event, u32 evData
+ 		break;
+ 	case MPI_EVENT_INTEGRATED_RAID:
+ 	{
++#if defined(CPQ_CIM)
++        ioc->csmi_change_count++;
++#endif
+ 		u8 ReasonCode = (u8)(evData0 >> 16);
+ 		switch (ReasonCode) {
+ 		case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+@@ -7044,65 +6743,36 @@ EventDescriptionStr(u8 event, u32 evData
+ 		break;
+ 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ 	{
+-		u8 id = (u8)(evData0);
+-		u8 channel = (u8)(evData0 >> 8);
++        u8 id = (u8)(evData0);
+ 		u8 ReasonCode = (u8)(evData0 >> 16);
+ 		switch (ReasonCode) {
+ 		case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+ 			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Added: "
+-			    "id=%d channel=%d", id, channel);
++			    "SAS Device Status Change: Added: id=%d", id);
+ 			break;
+ 		case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+ 			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Deleted: "
+-			    "id=%d channel=%d", id, channel);
++			    "SAS Device Status Change: Deleted: id=%d", id);
+ 			break;
+ 		case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+ 			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: SMART Data: "
+-			    "id=%d channel=%d", id, channel);
++			    "SAS Device Status Change: SMART Data: id=%d",
++			    id);
+ 			break;
+ 		case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+ 			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: No Persistancy: "
+-			    "id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Unsupported Device "
+-			    "Discovered : id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Internal Device "
+-			    "Reset : id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Internal Task "
+-			    "Abort : id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Internal Abort "
+-			    "Task Set : id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Internal Clear "
+-			    "Task Set : id=%d channel=%d", id, channel);
+-			break;
+-		case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Internal Query "
+-			    "Task : id=%d channel=%d", id, channel);
++			    "SAS Device Status Change: No Persistancy "
++			    "Added: id=%d", id);
+ 			break;
++        case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
++            snprintf(evStr, EVENT_DESCR_STR_SZ,
++                "SAS Device Status Change: Internal Device Reset: "
++                "id=%d", id);
++            break;
+ 		default:
+ 			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS Device Status Change: Unknown: "
+-			    "id=%d channel=%d", id, channel);
+-			break;
++			    "SAS Device Status Change: Unknown: id=%d", id);
++			break;		
+ 		}
+ 		break;
+ 	}
+@@ -7205,86 +6875,15 @@ EventDescriptionStr(u8 event, u32 evData
+ 	}
+ 	case MPI_EVENT_SAS_DISCOVERY:
+ 	{
+-		if (evData0)
+-			ds = "SAS Discovery: Start";
+-		else
+-			ds = "SAS Discovery: Stop";
++		char buf[40];
++		sprintf(buf,"SAS Discovery: Condition=0x%x:",evData0);
++		ds = buf;
+ 		break;
+ 	}
+ 	case MPI_EVENT_LOG_ENTRY_ADDED:
+ 		ds = "SAS Log Entry Added";
+ 		break;
+ 
+-	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+-	{
+-		u8 phy_num = (u8)(evData0);
+-		u8 port_num = (u8)(evData0 >> 8);
+-		u8 port_width = (u8)(evData0 >> 16);
+-		u8 primative = (u8)(evData0 >> 24);
+-		snprintf(evStr, EVENT_DESCR_STR_SZ,
+-		    "SAS Broadcase Primative: phy=%d port=%d "
+-		    "width=%d primative=0x%02x",
+-		    phy_num, port_num, port_width, primative);
+-		break;
+-	}
+-
+-	case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+-	{
+-		u8 reason = (u8)(evData0);
+-		u8 port_num = (u8)(evData0 >> 8);
+-		u16 handle = le16_to_cpu(evData0 >> 16);
+-
+-		snprintf(evStr, EVENT_DESCR_STR_SZ,
+-		    "SAS Initiator Device Status Change: reason=0x%02x "
+-		    "port=%d handle=0x%04x",
+-		    reason, port_num, handle);
+-		break;
+-	}
+-
+-	case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
+-	{
+-		u8 max_init = (u8)(evData0);
+-		u8 current_init = (u8)(evData0 >> 8);
+-
+-		snprintf(evStr, EVENT_DESCR_STR_SZ,
+-		    "SAS Initiator Device Table Overflow: max initiators=%02d "
+-		    "current initators=%02d",
+-		    max_init, current_init);
+-		break;
+-	}
+-	case MPI_EVENT_SAS_SMP_ERROR:
+-	{
+-		u8 status = (u8)(evData0);
+-		u8 port_num = (u8)(evData0 >> 8);
+-		u8 result = (u8)(evData0 >> 16);
+-
+-		if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d result=0x%02x",
+-			    port_num, result);
+-		else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d : CRC Error",
+-			    port_num);
+-		else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d : Timeout",
+-			    port_num);
+-		else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d : No Destination",
+-			    port_num);
+-		else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d : Bad Destination",
+-			    port_num);
+-		else
+-			snprintf(evStr, EVENT_DESCR_STR_SZ,
+-			    "SAS SMP Error: port=%d : status=0x%02x",
+-			    port_num, status);
+-		break;
+-	}
+-
+ 	/*
+ 	 *  MPT base "custom" events may be added here...
+ 	 */
+@@ -7329,20 +6928,24 @@ ProcessEventNotification(MPT_ADAPTER *io
+ 	}
+ 
+ 	EventDescriptionStr(event, evData0, evStr);
+-	devtprintk((MYIOC_s_WARN_FMT "MPT event:(%02Xh) : %s\n",
+-	    ioc->name, event, evStr));
++	devtprintk((MYIOC_s_WARN_FMT "MPT Event=%02Xh (%s) detected!\n",
++			ioc->name, event, evStr));
++
+ #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+-       printk(KERN_WARN MYNAM ": Event data:\n" KERN_INFO);
+-       for (ii = 0; ii < evDataLen; ii++)
+-               printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
+-       printk("\n");
++	printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
++	for (ii = 0; ii < evDataLen; ii++)
++		printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
++	printk("\n");
+ #endif
+ 
+-
+-       /*
++	/*
+ 	 *  Do general / base driver event processing
+ 	 */
+ 	switch(event) {
++	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: /* 0F */
++		mptbase_sas_process_event_data(ioc,
++		    (MpiEventDataSasDeviceStatusChange_t *)pEventReply->Data);
++		break;
+ 	case MPI_EVENT_EVENT_CHANGE:		/* 0A */
+ 		if (evDataLen) {
+ 			u8 evState = evData0 & 0xFF;
+@@ -7359,11 +6962,6 @@ ProcessEventNotification(MPT_ADAPTER *io
+ 		mptbase_raid_process_event_data(ioc,
+ 		    (MpiEventDataRaid_t *)pEventReply->Data);
+ 		break;
+-case MPI_EVENT_RESCAN:
+-case MPI_EVENT_LINK_STATUS_CHANGE:
+-ioc->FcLinkSpeedCheckNeeded = 1;
+-break;
+-
+ 	default:
+ 		break;
+ 	}
+@@ -7396,10 +6994,9 @@ break;
+ 	 */
+ 	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+ 		if (MptEvHandlers[ii]) {
+-		devtprintk((MYIOC_s_WARN_FMT "Routing Event to event handler #%d\n",
+-                                 ioc->name, ii));
+-
+-                       r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
++			devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
++					ioc->name, ii));
++			r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
+ 			handlers++;
+ 		}
+ 	}
+@@ -7412,7 +7009,7 @@ break;
+ 		devtprintk((MYIOC_s_WARN_FMT
+ 			"EventAck required\n",ioc->name));
+ 		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
+-			devtprintk((MYIOC_s_INFO_FMT "SendEventAck returned %d\n",
++			devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+ 					ioc->name, ii));
+ 		}
+ 	}
+@@ -7599,14 +7196,20 @@ union loginfo_type {
+ 	}
+ 
+ 	if (code_desc != NULL)
+-		printk("Originator={%s}, Code={%s},"
++		printk(MYIOC_s_INFO_FMT
++			"LogInfo(0x%08x): Originator={%s}, Code={%s},"
+ 			" SubCode(0x%04x)\n",
++			ioc->name,
++			log_info,
+ 			originator_str[sas_loginfo.dw.originator],
+ 			code_desc,
+ 			sas_loginfo.dw.subcode);
+ 	else
+-		printk("Originator={%s}, Code=(0x%02x),"
++		printk(MYIOC_s_INFO_FMT
++			"LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+ 			" SubCode(0x%04x)\n",
++			ioc->name,
++			log_info,
+ 			originator_str[sas_loginfo.dw.originator],
+ 			sas_loginfo.dw.code,
+ 			sas_loginfo.dw.subcode);
+@@ -7625,12 +7228,7 @@ static void
+ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+ {
+ 	u32 status = ioc_status & MPI_IOCSTATUS_MASK;
+-	char *desc = NULL;
+-
+-	SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
+-	U8 cdb = pScsiReq->CDB[0];
+-	U8 id = pScsiReq->TargetID;
+-	U8 lun = pScsiReq->LUN[1];
++	char *desc = "";
+ 
+ 	switch (status) {
+ 	case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
+@@ -7639,8 +7237,6 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+ 
+ 	case MPI_IOCSTATUS_BUSY: /* 0x0002 */
+ 		desc = "Busy";
+-                ddvprintk (("%s IOCSTATUS_BUSY", ioc->name));
+-                DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf)
+ 		break;
+ 
+ 	case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
+@@ -7692,11 +7288,11 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+ 
+ 	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+ 	  {
+-#ifdef MPT_DEBUG_REPLY
++		SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
++		U8 cdb = pScsiReq->CDB[0];
+ 		if (cdb != 0x12) { /* Inquiry is issued for device scanning */
+ 			desc = "SCSI Device Not There";
+ 		}
+-#endif
+ 		break;
+ 	  }
+ 
+@@ -7742,16 +7338,8 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+ 		desc = "Others";
+ 		break;
+ 	}
+-	if (desc != NULL) {
+-		U8 function = pScsiReq->Function;
+-		if (function == MPI_FUNCTION_SCSI_IO_REQUEST ||
+-		    function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+-			printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on CDB=%x id=%d lun=%d\n", ioc->name, status, desc, cdb, id, lun);
+-		} else {
+-			printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on Function=%02x\n", ioc->name, status, desc, function);
+-		}
+-		 DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf)
+-	}
++	if (desc != "")
++		printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -7770,6 +7358,7 @@ mpt_poll_interrupt(MPT_ADAPTER *ioc)
+ 	if (intstat & MPI_HIS_REPLY_MESSAGE_INTERRUPT)
+ 		mpt_interrupt(0, ioc, NULL);
+ }
++
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ EXPORT_SYMBOL(mpt_attach);
+ EXPORT_SYMBOL(mpt_detach);
+@@ -7779,6 +7368,7 @@ EXPORT_SYMBOL(mpt_suspend);
+ #endif
+ EXPORT_SYMBOL(ioc_list);
+ EXPORT_SYMBOL(mpt_can_queue);
++EXPORT_SYMBOL(mpt_sg_tablesize);
+ EXPORT_SYMBOL(mpt_proc_root_dir);
+ EXPORT_SYMBOL(mpt_register);
+ EXPORT_SYMBOL(mpt_deregister);
+@@ -7800,21 +7390,16 @@ EXPORT_SYMBOL(mpt_print_ioc_summary);
+ EXPORT_SYMBOL(mpt_lan_index);
+ EXPORT_SYMBOL(mpt_stm_index);
+ EXPORT_SYMBOL(mpt_HardResetHandler);
+-EXPORT_SYMBOL(mpt_SendIocReset);
+-EXPORT_SYMBOL(mpt_do_ioc_recovery);
+-EXPORT_SYMBOL(mpt_writeSDP1);
+-EXPORT_SYMBOL(mpt_setSDP1parameters);
+ EXPORT_SYMBOL(mpt_config);
+ EXPORT_SYMBOL(mpt_findImVolumes);
+ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
+ EXPORT_SYMBOL(mpt_alloc_fw_memory);
+ EXPORT_SYMBOL(mpt_free_fw_memory);
+ EXPORT_SYMBOL(mptbase_sas_persist_operation);
++EXPORT_SYMBOL(mpt_sas_get_info);
+ EXPORT_SYMBOL_GPL(mpt_poll_interrupt);
+ EXPORT_SYMBOL(mpt_alt_ioc_wait);
+-EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
+-EXPORT_SYMBOL(mpt_enable_deadioc_detect);
+-EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
++
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h	2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (    mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptbase.h,v 1.149 2003/05/07 14:08:31 Exp $
+  */
+@@ -78,14 +78,14 @@
+ #endif
+ 
+ #ifndef COPYRIGHT
+-#define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
++#define COPYRIGHT	"Copyright (c) 1999-2006 " MODULEAUTHOR
+ #endif
+ 
+-#define MPT_LINUX_VERSION_COMMON	"3.02.99.00rh"
+-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.02.99.00rh"
++#define MPT_LINUX_VERSION_COMMON	"3.02.73rh"
++#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.02.73rh"
+ #define MPT_LINUX_MAJOR_VERSION		3
+ #define MPT_LINUX_MINOR_VERSION		02
+-#define MPT_LINUX_BUILD_VERSION		99
++#define MPT_LINUX_BUILD_VERSION		73
+ #define MPT_LINUX_RELEASE_VERSION	00
+ #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
+ 
+@@ -96,8 +96,10 @@
+ /*
+  *  Fusion MPT(linux) driver configurable stuff...
+  */
++#define MPT_MAX_ADAPTERS		18
+ #define MPT_MAX_PROTOCOL_DRIVERS	16
+-#define MPT_MAX_BUSES			8
++#define MPT_MAX_BUS			1	/* Do not change */
++#define MPT_MAX_FC_DEVICES		255
+ #define MPT_MAX_SCSI_DEVICES		16
+ #define MPT_LAST_LUN			255
+ #define MPT_NON_IU_LAST_LUN		63
+@@ -137,9 +139,6 @@
+ #define	 CAN_SLEEP			1
+ #define  NO_SLEEP			0
+ 
+-#define MPT_HZ                         1000
+-#define MPT_JIFFY                      100
+-
+ #define MPT_COALESCING_TIMEOUT		0x10
+ 
+ /*
+@@ -170,9 +169,7 @@
+ /*
+  * Default MAX_SGE value.  Can be changed by using mptbase sg_count parameter.
+  */
+-#ifndef CONFIG_FUSION_MAX_SGE
+-#define CONFIG_FUSION_MAX_SGE  128
+-#endif
++#define MPT_SCSI_SG_DEPTH	128
+ 
+ #ifdef __KERNEL__	/* { */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -218,6 +215,8 @@ typedef union _MPT_FRAME_TRACKER {
+ 	struct {
+ 		struct list_head        list;
+ 		u32			 arg1;
++		u32			 pad;
++		void			*argp1;
+ 	} linkage;
+ 	/*
+ 	 * NOTE: When request frames are free, on the linkage structure
+@@ -277,12 +276,6 @@ typedef struct _MPT_FRAME_HDR {
+ 	} u;
+ } MPT_FRAME_HDR;
+ 
+-typedef struct _MPT_LINKAGE {
+-		struct list_head        list;
+-		MPT_FRAME_HDR		*mf;
+-} MPT_LINKAGE;
+-
+-
+ #define MPT_REQ_MSGFLAGS_DROPME		0x80
+ 
+ typedef struct _MPT_SGL_HDR {
+@@ -336,31 +329,15 @@ typedef struct _SYSIF_REGS
+ #define MPT_TARGET_NO_NEGO_QAS		0x04
+ #define MPT_TAPE_NEGO_IDP     		0x08
+ 
+-#if defined(CPQ_CIM)
+-struct sas_mapping{
+-	u8			id;
+-	u8			channel;
+-};
+-
+-struct sas_device_info {
+-	struct list_head 	list;
+-	struct sas_mapping	os;	/* operating system mapping*/
+-	struct sas_mapping	fw;	/* firmware mapping */
+-	u64			sas_address;
+-	u32			device_info; /* specific bits for devices */
+-	u8			is_logical_volume; /* is this logical volume */
+-	u8			is_cached;	/* cached data for a removed device */
+-};
+-#endif
+-
+ /*
+  *	VirtDevice - FC LUN device or SCSI target device
+  */
+ typedef struct _VirtDevice {
+-        struct _MPT_ADAPTER	*ioc;
++	struct scsi_device	*device;
+ 	u16			 tflags;
+-	u8			 id;
+-	u8			 bus;
++	u8			 ioc_id;
++	u8			 target_id;
++	u8			 bus_id;
+ 	u8			 minSyncFactor;	/* 0xFF is async */
+ 	u8			 maxOffset;	/* 0 if async */
+ 	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
+@@ -385,13 +362,9 @@ typedef struct _VirtDevice {
+ 	u8			 pad2[4];
+ 	U64			 WWPN;
+ 	U64			 WWNN;
+-       struct work_struct        dvTask;
+-       u8			 configured_lun;
++	u8			 configured_lun;
+ } VirtDevice;
+ 
+-typedef struct _MPT_DEVICE {
+-	VirtDevice	*Target[0];
+-} MPT_DEVICE;
+ /*
+  *  Fibre Channel (SCSI) target device and associated defines...
+  */
+@@ -440,6 +413,7 @@ do { \
+ #define MPT_IOCTL_STATUS_SENSE_VALID	0x08	/* Sense data is valid */
+ #define MPT_IOCTL_STATUS_COMMAND_GOOD	0x10	/* Command Status GOOD */
+ #define MPT_IOCTL_STATUS_TMTIMER_ACTIVE	0x20	/* The TM timer is running */
++#define MPT_IOCTL_STATUS_TM_FAILED	0x40	/* User TM request failed */
+ 
+ #define MPTCTL_RESET_OK			0x01	/* Issue Bus Reset */
+ 
+@@ -448,10 +422,10 @@ typedef struct _MPT_IOCTL {
+ 	u8			 ReplyFrame[MPT_DEFAULT_FRAME_SIZE];	/* reply frame data */
+ 	u8			 sense[MPT_SENSE_BUFFER_ALLOC];
+ 	int			 wait_done;	/* wake-up value for this ioc */
++	u8			 rsvd;
+ 	u8			 status;	/* current command status */
+ 	u8			 reset;		/* 1 if bus reset allowed */
+-	u8			 bus;		/* bus */
+-	u8			 id;		/* id for reset */
++	u8			 target;	/* target for reset */
+ 	struct semaphore	 sem_ioc;
+ } MPT_IOCTL;
+ 
+@@ -462,7 +436,7 @@ typedef struct _MPT_IOCTL {
+ typedef struct _mpt_ioctl_events {
+ 	u32	event;		/* Specified by define above */
+ 	u32	eventContext;	/* Index or counter */
+-	u32	data[2];	/* First 8 bytes of Event Data */
++	int	data[2];	/* First 8 bytes of Event Data */
+ } MPT_IOCTL_EVENTS;
+ 
+ /*
+@@ -477,14 +451,14 @@ typedef struct _mpt_ioctl_events {
+ 						/* dvStatus defines: */
+ #define MPT_SCSICFG_NEGOTIATE		0x01	/* Negotiate on next IO */
+ #define MPT_SCSICFG_NEED_DV		0x02	/* Schedule DV */
+-#define MPT_SCSICFG_DV_IN_PROGRESS	0x04	/* DV on this physical id*/
++#define MPT_SCSICFG_DV_PENDING		0x04	/* DV on this physical id pending */
+ #define MPT_SCSICFG_DV_NOT_DONE		0x08	/* DV has not been performed */
+-#define MPT_SCSICFG_PHYSDISK_DV_ONLY	0x10	/* DV only on this PhysDisk*/
+-#define MPT_SCSICFG_BLK_NEGO		0x20	/* WriteSDP1 with WDTR and SDTR disabled*/
+-#define MPT_SCSICFG_RELOAD_IOC_PG3	0x40	/* IOC Pg 3 data is obsolete */
++#define MPT_SCSICFG_BLK_NEGO		0x10	/* WriteSDP1 with WDTR and SDTR disabled */
++#define MPT_SCSICFG_RELOAD_IOC_PG3	0x20	/* IOC Pg 3 data is obsolete */
+ 						/* Args passed to writeSDP1: */
+ #define MPT_SCSICFG_USE_NVRAM		0x01	/* WriteSDP1 using NVRAM */
+ #define MPT_SCSICFG_ALL_IDS		0x02	/* WriteSDP1 to all IDS */
++/* #define MPT_SCSICFG_BLK_NEGO		0x10	   WriteSDP1 with WDTR and SDTR disabled */
+ 
+ typedef	struct _SpiCfgData {
+ 	u32		 PortFlags;
+@@ -520,36 +494,48 @@ typedef	struct _SasCfgData {
+ 						 * automatic clearing.
+ 						 */
+ 	u8		mpt_sas_hot_plug_enable;  /* disables hot swap device remove support */
+-    ManufacturingPage7_t    *pManufPg7; /* Connector Info on SAS controllers */
+ }SasCfgData;
+ 
+-/*
+- * Inactive volume link list of raid component data
+- * @inactive_list
+- */
+-struct inactive_raid_component_info {
+-	struct 	 list_head list;
+-	u8		 volumeID;		/* volume target id */
+-	u8		 volumeBus;		/* volume channel */
+-	IOC_3_PHYS_DISK	 d;			/* phys disk info */
+-};
+-
+ typedef	struct _RaidCfgData {
+ 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */
+ 	IOCPage3_t	*pIocPg3;		/* table of physical disks */
+-	IOCPage6_t	*pIocPg6;       /* table of IR static data */
+-	int		 isRaid;		    /* bit field, 1 if RAID */
+-	struct semaphore	inactive_list_mutex;
+-	struct list_head	inactive_list; /* link list for physical
+-						disk that belong in
+-						inactive volumes */
++	int		 isRaid;		/* bit field, 1 if RAID */
+ } RaidCfgData;
+ 
+ /*
+- *  Adapter Structure - pci_dev specific.
++ * sas device info link list
+  */
++typedef struct _sas_device_info {
++	struct list_head list;
++	u64	SASAddress;
++	u8	TargetId;
++	u8	Bus;
++	u8	PhysicalPort;
++	u8	PhyNum;
++	u32	DeviceInfo;
++	u16	DevHandle;
++	u16	Flags;
++} sas_device_info_t;
++
++/*
++ * hba phy info array
++ */
++typedef struct _sas_phy_info {
++	u64     SASAddress;
++	u8	port;
++	u8	PortFlags;
++	u8	PhyFlags;
++	u8	NegotiatedLinkRate;
++	u16	ControllerDevHandle;
++	u16	devHandle;
++	u32	ControllerPhyDeviceInfo;
++	u8	phyId;
++	u8	hwLinkRate;
++	u8	reserved;
++} sas_phy_info_t;
++
+ /*
+- *  Adapter Structure - pci_dev specific.
++ *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
+  */
+ typedef struct _MPT_ADAPTER
+ {
+@@ -561,18 +547,13 @@ typedef struct _MPT_ADAPTER
+ 	SYSIF_REGS __iomem	*pio_chip;	/* Programmed IO (downloadboot) */
+ 	u8			 bus_type;	/* Parallel SCSI i/f */
+ 	u8			 pci_slot_number; /* ioc page 1 - pci slot number */
+-	u8			 ir_firmware; /* =1 if IR firmware detected */
+ 	u16			 deviceID;
+ 	u32			 mem_phys;	/* == f4020000 (mmap) */
+ 	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
+ 	int			 mem_size;	/* mmap memory size */
+-	int			 sg_tablesize;  /* max SGE's per IO */
+-	int			 NumberOfBuses;
+-	int			 DevicesPerBus;
+ 	int			 alloc_total;
+ 	u32			 last_state;
+ 	int			 active;
+-	struct _MPT_DEVICE 	*Target_List[MPT_MAX_BUSES];
+ 	u8			*alloc;		/* frames alloc ptr */
+ 	dma_addr_t		 alloc_dma;
+ 	u32			 alloc_sz;
+@@ -600,12 +581,7 @@ typedef struct _MPT_ADAPTER
+ 	int			 req_depth;	/* Number of request frames */
+ 	int			 req_sz;	/* Request frame size (bytes) */
+ 	spinlock_t		 FreeQlock;
+-	spinlock_t		 PendingMFlock;
+ 	struct list_head	 FreeQ;
+-	MPT_FRAME_HDR		*PendingMF;
+-	struct scsi_cmnd	*PendingSCpnt;
+-	struct timer_list	  TMtimer;	/* Timer for TM commands ONLY */
+-	MPT_FRAME_HDR		 *tmPtr;	/* Ptr to TM request*/
+ 		/* Pool of SCSI sense buffers for commands coming from
+ 		 * the SCSI mid-layer.  We have one 256 byte sense buffer
+ 		 * for each REQ entry.
+@@ -638,12 +614,10 @@ typedef struct _MPT_ADAPTER
+ 	struct _MPT_ADAPTER	*alt_ioc;	/* ptr to 929 bound adapter port */
+ 	spinlock_t		 diagLock;	/* diagnostic reset lock */
+ 	int			 diagPending;
+-	int                      IOCResetInProgress;
+ 	u32			 biosVersion;	/* BIOS version from IO Unit Page 2 */
+ 	int			 eventTypes;	/* Event logging parameters */
+ 	int			 eventContext;	/* Next event context */
+ 	struct _mpt_ioctl_events *events;	/* pointer to event log */
+-	EventNotification_t	*evnp;		/* event message frame pointer */
+ 	u8			*cached_fw;	/* Pointer to FW */
+ 	dma_addr_t	 	cached_fw_dma;
+ 	struct list_head	 configQ;	/* linked list of config. requests */
+@@ -662,12 +636,10 @@ typedef struct _MPT_ADAPTER
+ /* emoore@lsil.com - sas support - start */
+ 	U64			 sas_port_WWID[4];
+ 	u8			 BoardTracerNumber[16];
++	u8			 numPhys;
+ 	u16			 vendorID;
+-#if defined(CPQ_CIM)
+-	struct list_head	 sas_device_info_list;
+-	struct semaphore	 sas_device_info_mutex;
+-	u32			 num_ports;
+-#endif
++	sas_phy_info_t		 *sasPhyInfo;
++	struct list_head	 sasDeviceList;
+ 	struct semaphore	 hot_plug_semaphore;
+ 	struct work_struct	 mptscsih_persistTask;
+ 	struct timer_list	 persist_timer;	/* persist table timer */
+@@ -680,7 +652,7 @@ typedef struct _MPT_ADAPTER
+ 	u32           		 PciState[64];     /* save PCI state to this area */
+ #endif
+ #if defined(CPQ_CIM)
+-	u32         csmi_change_count;    /* count to track all IR events for CSMI */
++    u32         csmi_change_count;    /* count to track all IR events for CSMI */
+ #endif
+ 	/*  
+ 	 * Description: errata_flag_1064
+@@ -694,11 +666,7 @@ typedef struct _MPT_ADAPTER
+ 	u8			 upload_fw;	/* If set, do a fw upload */
+ 	u8			 reload_fw;	/* Force a FW Reload on next reset */
+ 	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
+-	u8			 pad1;
+-	u8			 CheckFcLinkSpeed;
+-	u8			 FcLinkSpeedCheckNeeded;
+-	u8			 FcLinkSpeed;
+-	MPT_FRAME_HDR		*FcLinkSpeedReqActive;
++	u8			 pad1[4];
+ 	int			 DoneCtx;
+ 	int			 TaskCtx;
+ 	int			 InternalCtx;
+@@ -811,25 +779,6 @@ typedef struct _mpt_sge {
+ #define DBG_DUMP_EVENT_REQUEST_FRAME(mfp)
+ #endif
+ 
+-#ifdef MPT_DEBUG_PEND
+-#define dpendprintk(x)  printk x
+-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp) \
+-	{	int  i, n = ioc->req_sz/4;						\
+-		u32 *m = (u32 *)(mfp);					\
+-		for (i=0; i<n; i++) {					\
+-			if (i && ((i%8)==0))				\
+-				printk("\n");				\
+-			printk("%08x ", le32_to_cpu(m[i]));		\
+-		}							\
+-		printk("\n");						\
+-	}
+-#else
+-#define dpendprintk(x)
+-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp)
+-#endif
+-
+-
+-
+ #ifdef MPT_DEBUG_HOTPLUG
+ #define dhotpprintk(x)  printk x
+ #else
+@@ -838,51 +787,16 @@ typedef struct _mpt_sge {
+ 
+ #ifdef MPT_DEBUG_RESET
+ #define drsprintk(x)  printk x
+-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp) \
+-       {       int  i, n = ioc->req_sz/4;                                              \
+-               u32 *m = (u32 *)(mfp);                                  \
+-               for (i=0; i<n; i++) {                                   \
+-                       if (i && ((i%8)==0))                            \
+-                               printk("\n");                           \
+-                       printk("%08x ", le32_to_cpu(m[i]));             \
+-               }                                                       \
+-               printk("\n");                                           \
+-       }
+ #else
+ #define drsprintk(x)
+-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp)
+ #endif
+ 
+ //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
+ #if defined(MPT_DEBUG_MSG_FRAME)
+ #define dmfprintk(x)  printk x
+-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp) \
+-	{	int  i, n = ioc->req_sz/4;
+-		u32 *m = (u32 *)(mfp);					\
+-		for (i=0; i<n; i++) {					\
+-			if (i && ((i%8)==0))				\
+-				printk("\n");				\
+-			printk("%08x ", le32_to_cpu(m[i]));		\
+-		}							\
+-		printk("\n");						\
+-	}
+-#else
+-#define dmfprintk(x)
+-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp)
+-#endif
+-
+-#if defined(MPT_DEBUG_IOS)
+-#define dioprintk(x)  printk x
+-#else
+-#define dioprintk(x)
+-#endif
+-
+-
+-#if defined(MPT_DEBUG_CSMI)
+-#define DBG_DUMP_CSMI_FRAME(mfp) \
++#define DBG_DUMP_REQUEST_FRAME(mfp) \
+ 	{	int  i, n = 24;						\
+ 		u32 *m = (u32 *)(mfp);					\
+-		printk("CSMI MessageFrame:\n");			\
+ 		for (i=0; i<n; i++) {					\
+ 			if (i && ((i%8)==0))				\
+ 				printk("\n");				\
+@@ -891,7 +805,8 @@ typedef struct _mpt_sge {
+ 		printk("\n");						\
+ 	}
+ #else
+-#define DBG_DUMP_CSMI_FRAME(mfp)
++#define dmfprintk(x)
++#define DBG_DUMP_REQUEST_FRAME(mfp)
+ #endif
+ 
+ #ifdef MPT_DEBUG_SG
+@@ -918,22 +833,28 @@ typedef struct _mpt_sge {
+ #define dnegoprintk(x)
+ #endif
+ 
++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
++#define ddvtprintk(x)  printk x
++#else
++#define ddvtprintk(x)
++#endif
++
+ #ifdef MPT_DEBUG_IOCTL
+ #define dctlprintk(x) printk x
+ #else
+ #define dctlprintk(x)
+ #endif
+ 
+-#ifdef MPT_DEBUG_SAS
+-#define dsasprintk(x) printk x
++#ifdef MPT_DEBUG_REPLY
++#define dreplyprintk(x) printk x
+ #else
+-#define dsasprintk(x)
++#define dreplyprintk(x)
+ #endif
+ 
+-#ifdef MPT_DEBUG_CSMISAS
+-#define dcsmisasprintk(x) printk x
++#ifdef MPT_DEBUG_SAS
++#define dsasprintk(x) printk x
+ #else
+-#define dcsmisasprintk(x)
++#define dsasprintk(x)
+ #endif
+ 
+ #ifdef MPT_DEBUG_TM
+@@ -988,8 +909,7 @@ typedef struct _mpt_sge {
+ #define MPT_INDEX_2_RFPTR(ioc,idx) \
+ 	(MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) )
+ 
+-#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE)
+-#define dreplyprintk(x) printk x
++#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE)
+ #define DBG_DUMP_REPLY_FRAME(mfp) \
+ 	{	u32 *m = (u32 *)(mfp);					\
+ 		int  i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16;	\
+@@ -1006,36 +926,9 @@ typedef struct _mpt_sge {
+ 			printk(" %08x", le32_to_cpu(m[i]));		\
+ 		printk("\n");						\
+ 	}
+-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp) \
+-	{	int  i, n = ioc->req_sz/4;;						\
+-		u32 *m = (u32 *)(mfp);					\
+-		for (i=0; i<n; i++) {					\
+-			if (i && ((i%8)==0))				\
+-				printk("\n");				\
+-			printk("%08x ", le32_to_cpu(m[i]));		\
+-		}							\
+-		printk("\n");						\
+-	}
+-#define DBG_DUMP_SENSE_DATA(mfp) \
+-	{	int  i, n = 8;						\
+-		u32 *m = (u32 *)(mfp);					\
+-		printk(KERN_INFO "SENSE DATA: ");					\
+-		for (i=0; i<n; i++)					\
+-			printk(" %08x", le32_to_cpu(m[i]));		\
+-		printk("\n");						\
+-	}
+ #else
+-#define dreplyprintk(x)
+ #define DBG_DUMP_REPLY_FRAME(mfp)
+ #define DBG_DUMP_REQUEST_FRAME_HDR(mfp)
+-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp)
+-#define DBG_DUMP_SENSE_DATA(mfp)
+-#endif
+-
+-#if defined (MPT_DEBUG_ERROR) || defined(MPT_DEBUG_REPLY)
+-#define derrprintk(x) printk x
+-#else
+-#define derrprintk(x)
+ #endif
+ 
+ 
+@@ -1095,34 +988,32 @@ typedef struct _MPT_SCSI_HOST {
+ 	u32			  pad0;
+ 	struct scsi_cmnd	**ScsiLookup;
+ 	struct scsi_device 	 *device;
++	VirtDevice		**Targets;
+ 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
+-	struct timer_list	  InternalCmdTimer;
++	struct timer_list	  timer;
+ 		/* Pool of memory for holding SCpnts before doing
+ 		 * OS callbacks. freeQ is the free pool.
+ 		 */
+ 	u8			  tmPending;
+ 	u8			  resetPending;
++	u8			  negoNvram;		/* DV disabled, nego NVRAM */
++	u8			  pad1;
+ 	u8                        tmState;
+-	u8			  rsvd[4];
++	u8			  rsvd[2];
+ 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
+ 	struct scsi_cmnd	 *abortSCpnt;
+ 	MPT_LOCAL_REPLY		  localReply;		/* internal cmd reply struct */
+ 	unsigned long		  hard_resets;		/* driver forced bus resets count */
+ 	unsigned long		  soft_resets;		/* fw/external bus resets count */
+ 	unsigned long		  timeouts;		/* cmd timeouts */
+-	ushort			  sel_timeout[MPT_MAX_SCSI_DEVICES];
++	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
+ 	char 			  *info_kbuf;
+ 	wait_queue_head_t	  scandv_waitq;
+ 	int			  scandv_wait_done;
+-	wait_queue_head_t	  TM_waitq;
+-	int			  TM_wait_done;
+ 	long			  last_queue_full;
+-	u8			  mpt_pq_filter;
+-	u16			  tm_iocstatus;
+-	struct list_head	  target_reset_list;
++	u8		 	  mpt_pq_filter;
+ } MPT_SCSI_HOST;
+ 
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  *	More Dynamic Multi-Pathing stuff...
+@@ -1176,29 +1067,20 @@ extern void	 mpt_free_msg_frame(MPT_ADAP
+ extern void	 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+ extern void	 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
+ 
+-extern int	 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes,
+-u32 *req, ulong timeout, int sleepFlag);
+-
++extern int	 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
+ extern int	 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
+ extern u32	 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
+ extern void	 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
+ extern int	 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
+-
+-extern int       mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
+-extern void      mptscsih_TM_timeout(unsigned long data);
+-
+ extern int	 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
+-extern int       mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+-extern int       mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags);
+-extern void  mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr);
+ extern void	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
+ extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
+ extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
+ extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+ extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
++extern int	 mpt_sas_get_info(MPT_ADAPTER *ioc);
++extern void	 mpt_poll_interrupt(MPT_ADAPTER *ioc);
+ extern int	 mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
+-extern void      mpt_poll_interrupt(MPT_ADAPTER *ioc);
+-extern int 	 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
+ 
+ /*
+  *  Public data decl's...
+@@ -1237,7 +1119,7 @@ extern int		mpt_sg_tablesize;
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #endif		/* } __KERNEL__ */
+ 
+-#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc__)
++#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__)
+ #define CAST_U32_TO_PTR(x)	((void *)(u64)x)
+ #define CAST_PTR_TO_U32(x)	((u32)(u64)x)
+ #else
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c	2007-11-02 09:10:23.000000000 +0100
+@@ -4,8 +4,8 @@
+  *      For use with LSI Logic PCI chip/adapters
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -57,6 +57,9 @@
+ #include <linux/miscdevice.h>
+ #include <linux/smp_lock.h>
+ #include <linux/compat.h>
++#if defined(CPQ_CIM)
++#include "csmisas.h"
++#endif // CPQ_CIM
+ 
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+@@ -67,16 +70,11 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_tcq.h>
+ 
+-#define COPYRIGHT	"Copyright (c) 1999-2007 LSI Logic Corporation"
++#define COPYRIGHT	"Copyright (c) 1999-2005 LSI Logic Corporation"
+ #define MODULEAUTHOR	"LSI Logic Corporation"
+ #include "mptbase.h"
+ #include "mptctl.h"
+ 
+-#if defined(CPQ_CIM)
+-#include "mptsas.h"
+-#include "csmi/csmisas.h"
+-#endif // CPQ_CIM
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #define my_NAME		"Fusion MPT misc device (ioctl) driver"
+ #define my_VERSION	MPT_LINUX_VERSION_COMMON
+@@ -85,12 +83,10 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ 
+ extern	int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
+-extern int	mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag);
+ 
+ static int mptctl_id = -1;
+ 
+@@ -119,10 +115,6 @@ static int mptctl_eventenable(unsigned l
+ static int mptctl_eventreport(unsigned long arg);
+ static int mptctl_replace_fw(unsigned long arg);
+ 
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-static int mptctl_hba_pciinfo(unsigned long arg);
+-#endif
+-
+ static int mptctl_do_reset(unsigned long arg);
+ static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
+ static int mptctl_hp_targetinfo(unsigned long arg);
+@@ -133,29 +125,27 @@ static int mptctl_unregister_diag_buffer
+ static int mptctl_query_diag_buffer(unsigned long arg);
+ static int mptctl_read_diag_buffer(unsigned long arg);
+ #if defined(CPQ_CIM)
+-static int csmisas_get_driver_info(unsigned long arg);
+-static int csmisas_get_cntlr_status(unsigned long arg);
+-static int csmisas_get_cntlr_config(unsigned long arg);
+-static int csmisas_get_phy_info(unsigned long arg);
+-static int csmisas_get_scsi_address(unsigned long arg);
+-static int csmisas_get_link_errors(unsigned long arg);
+-static int csmisas_smp_passthru(unsigned long arg);
+-static int csmisas_firmware_download(unsigned long arg);
+-static int csmisas_get_raid_info(unsigned long arg);
+-static int csmisas_get_raid_config(unsigned long arg);
+-static int csmisas_get_raid_features(unsigned long arg);
+-static int csmisas_set_raid_control(unsigned long arg);
+-static int csmisas_get_raid_element(unsigned long arg);
+-static int csmisas_set_raid_operation(unsigned long arg);
+-static int csmisas_set_phy_info(unsigned long arg);
+-static int csmisas_ssp_passthru(unsigned long arg);
+-static int csmisas_stp_passthru(unsigned long arg);
+-static int csmisas_get_sata_signature(unsigned long arg);
+-static int csmisas_get_device_address(unsigned long arg);
+-static int csmisas_task_managment(unsigned long arg);
+-static int csmisas_phy_control(unsigned long arg);
+-static int csmisas_get_connector_info(unsigned long arg);
+-static int csmisas_get_location(unsigned long arg);
++static int mptctl_csmi_sas_get_driver_info(unsigned long arg);
++static int mptctl_csmi_sas_get_cntlr_status(unsigned long arg);
++static int mptctl_csmi_sas_get_cntlr_config(unsigned long arg);
++static int mptctl_csmi_sas_get_phy_info(unsigned long arg);
++static int mptctl_csmi_sas_get_scsi_address(unsigned long arg);
++static int mptctl_csmi_sas_get_link_errors(unsigned long arg);
++static int mptctl_csmi_sas_smp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_firmware_download(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_info(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_config(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_features(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_control(unsigned long arg);
++static int mptctl_csmi_sas_set_phy_info(unsigned long arg);
++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_stp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_get_sata_signature(unsigned long arg);
++static int mptctl_csmi_sas_get_device_address(unsigned long arg);
++static int mptctl_csmi_sas_task_managment(unsigned long arg);
++static int mptctl_csmi_sas_phy_control(unsigned long arg);
++static int mptctl_csmi_sas_get_connector_info(unsigned long arg);
++static int mptctl_csmi_sas_get_location(unsigned long arg);
+ #endif // CPQ_CIM
+ 
+ static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+@@ -230,7 +220,7 @@ static inline int
+ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
+ {
+ 	int rc = 0;
+-	dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
++	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
+ 
+ 	if (nonblock) {
+ 		if (down_trylock(&ioc->ioctl->sem_ioc))
+@@ -239,7 +229,7 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
+ 		if (down_interruptible(&ioc->ioctl->sem_ioc))
+ 			rc = -ERESTARTSYS;
+ 	}
+-	dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down return %d\n", rc));
++	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
+ 	return rc;
+ }
+ 
+@@ -304,17 +294,9 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
+ 
+ 		if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+ 			(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+-
+-			dcsmisasprintk(("\tiocstatus = 0x%x, "
+-				"scsi_status = 0x%x, scsi_state = 0x%x\n",
+-				reply->u.sreply.IOCStatus,
+-				reply->u.sreply.SCSIStatus,
+-				reply->u.sreply.SCSIState));
+-
+ 			ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+ 
+ 			if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
+-                                (iocStatus == MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH) ||
+ 				(iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
+ 				ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+ 			}
+@@ -438,8 +420,8 @@ mptctl_bus_reset(MPT_IOCTL *ioctl)
+ 			ioctl->ioc->name, mf));
+ 
+ 	pScsiTm = (SCSITaskMgmt_t *) mf;
+-	pScsiTm->TargetID = ioctl->id;
+-	pScsiTm->Bus = ioctl->bus;
++	pScsiTm->TargetID = ioctl->target;
++	pScsiTm->Bus = hd->port;	/* 0 */
+ 	pScsiTm->ChainOffset = 0;
+ 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+ 	pScsiTm->Reserved = 0;
+@@ -460,7 +442,7 @@ mptctl_bus_reset(MPT_IOCTL *ioctl)
+ 
+ 	ioctl->wait_done=0;
+ 	if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
+-	    sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,10, CAN_SLEEP)) != 0) {
++	     sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+ 		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+ 			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+ 			hd->ioc, mf));
+@@ -652,7 +634,7 @@ __mptctl_ioctl(struct file *file, unsign
+ 	dctlprintk(("mptctl_ioctl() called with cmd=%x\n", cmd));
+ 
+ 	if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
+-		printk(KERN_ERR "%s: mptctl_ioctl() @%d - "
++		printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
+ 				"Unable to copy mpt_ioctl_header data @ %p\n",
+ 				__FILE__, __LINE__, uhdr);
+ 		return -EFAULT;
+@@ -693,38 +675,28 @@ __mptctl_ioctl(struct file *file, unsign
+ 		return mptctl_query_diag_buffer(arg);
+ 	} else if (cmd == MPTDIAGUNREGISTER) {
+ 		return mptctl_unregister_diag_buffer(arg);
+-
+-	}
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-	 else if (cmd == MPTHBAPCIINFO) {
+-		return mptctl_hba_pciinfo(arg);
+ 	}
+-#endif
+ 
+ #if defined(CPQ_CIM)
+ 	else if (cmd == CC_CSMI_SAS_GET_DRIVER_INFO) {
+-		return csmisas_get_driver_info(arg);
++		return mptctl_csmi_sas_get_driver_info(arg);
+ 	} else if (cmd == CC_CSMI_SAS_GET_CNTLR_CONFIG) {
+-		return csmisas_get_cntlr_config(arg);
++		return mptctl_csmi_sas_get_cntlr_config(arg);
+ 	} else if (cmd == CC_CSMI_SAS_GET_CNTLR_STATUS) {
+-		return csmisas_get_cntlr_status(arg);
++		return mptctl_csmi_sas_get_cntlr_status(arg);
+ 	} else if (cmd == CC_CSMI_SAS_GET_SCSI_ADDRESS) {
+-		return csmisas_get_scsi_address(arg);
++		return mptctl_csmi_sas_get_scsi_address(arg);
+ 	} else if (cmd == CC_CSMI_SAS_GET_DEVICE_ADDRESS){
+-		return csmisas_get_device_address(arg);
++		return mptctl_csmi_sas_get_device_address(arg);
+ 	}
+ #endif // CPQ_CIM
+ 
+-	dctlprintk(("mptctl_ioctl() called with cmd=%x, interrupt required\n", cmd));
+ 	/* All of these commands require an interrupt or
+ 	 * are unknown/illegal.
+ 	 */
+-	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) {
+-		dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, syscall_down failed\n", cmd, ret));
++	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+ 		return ret;
+-	}
+ 
+-	dctlprintk(("mptctl_ioctl() called with cmd=%x, syscall_down completed\n", cmd));
+ 	if (cmd == MPTFWDOWNLOAD)
+ 		ret = mptctl_fw_download(arg);
+ 	else if (cmd == MPTFWDOWNLOADBOOT)
+@@ -745,41 +717,37 @@ __mptctl_ioctl(struct file *file, unsign
+ 		ret = mptctl_read_diag_buffer(arg);
+ #if defined(CPQ_CIM)
+ 	else if (cmd == CC_CSMI_SAS_GET_PHY_INFO)
+-		ret = csmisas_get_phy_info(arg);
++		ret = mptctl_csmi_sas_get_phy_info(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_SATA_SIGNATURE)
+-		ret = csmisas_get_sata_signature(arg);
++		ret = mptctl_csmi_sas_get_sata_signature(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_LINK_ERRORS)
+-		ret = csmisas_get_link_errors(arg);
++		ret = mptctl_csmi_sas_get_link_errors(arg);
+ 	else if (cmd == CC_CSMI_SAS_SMP_PASSTHRU)
+-		ret = csmisas_smp_passthru(arg);
++		ret = mptctl_csmi_sas_smp_passthru(arg);
+ 	else if (cmd == CC_CSMI_SAS_SSP_PASSTHRU)
+-		ret = csmisas_ssp_passthru(arg);
++		ret = mptctl_csmi_sas_ssp_passthru(arg);
+ 	else if (cmd == CC_CSMI_SAS_FIRMWARE_DOWNLOAD)
+-		ret = csmisas_firmware_download(arg);
++		ret = mptctl_csmi_sas_firmware_download(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_RAID_INFO)
+-		ret = csmisas_get_raid_info(arg);
++		ret = mptctl_csmi_sas_get_raid_info(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_RAID_CONFIG)
+-		ret = csmisas_get_raid_config(arg);
+-	else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
+-		ret = csmisas_get_raid_features(arg);
+-	else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
+-		ret = csmisas_set_raid_control(arg);
+-	else if (cmd == CC_CSMI_SAS_GET_RAID_ELEMENT)
+-		ret = csmisas_get_raid_element(arg);
+-	else if (cmd == CC_CSMI_SAS_SET_RAID_OPERATION)
+-		ret = csmisas_set_raid_operation(arg);
++		ret = mptctl_csmi_sas_get_raid_config(arg);
++    else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
++		ret = mptctl_csmi_sas_get_raid_features(arg);
++    else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
++		ret = mptctl_csmi_sas_get_raid_control(arg);
+ 	else if (cmd == CC_CSMI_SAS_SET_PHY_INFO)
+-		ret = csmisas_set_phy_info(arg);
++		ret = mptctl_csmi_sas_set_phy_info(arg);
+ 	else if (cmd == CC_CSMI_SAS_STP_PASSTHRU)
+-		ret = csmisas_stp_passthru(arg);
++		ret = mptctl_csmi_sas_stp_passthru(arg);
+ 	else if (cmd == CC_CSMI_SAS_TASK_MANAGEMENT)
+-		ret = csmisas_task_managment(arg);
++		ret = mptctl_csmi_sas_task_managment(arg);
+ 	else if (cmd == CC_CSMI_SAS_PHY_CONTROL)
+-		ret = csmisas_phy_control(arg);
++		ret = mptctl_csmi_sas_phy_control(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_CONNECTOR_INFO)
+-		ret = csmisas_get_connector_info(arg);
++		ret = mptctl_csmi_sas_get_connector_info(arg);
+ 	else if (cmd == CC_CSMI_SAS_GET_LOCATION)
+-		ret = csmisas_get_location(arg);
++		ret = mptctl_csmi_sas_get_location(arg);
+ #endif // CPQ_CIM
+ 	else {
+ 		dctlprintk(("mptctl_ioctl() cmd=%x not found\n", cmd));
+@@ -788,7 +756,6 @@ __mptctl_ioctl(struct file *file, unsign
+ 
+ 	up(&iocp->ioctl->sem_ioc);
+ 
+-	dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, up completed\n", cmd, ret));
+ 	return ret;
+ }
+ 
+@@ -813,7 +780,7 @@ static int mptctl_do_reset(unsigned long
+ 	dctlprintk(("mptctl_do_reset called.\n"));
+ 
+ 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
+-		printk(KERN_ERR "%s@%d: mptctl_do_reset - "
++		printk(KERN_ERR "%s@%d::mptctl_do_reset - "
+ 				"Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
+ 				__FILE__, __LINE__, urinfo);
+ 		return -EFAULT;
+@@ -858,7 +825,7 @@ mptctl_fw_download(unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
+ 	if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
+-		printk(KERN_ERR "%s@%d: _ioctl_fwdl - "
++		printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+ 				"Unable to copy mpt_fw_xfer struct @ %p\n",
+ 				__FILE__, __LINE__, ufwdl);
+ 		return -EFAULT;
+@@ -1014,7 +981,7 @@ mptctl_do_fw_download(int ioc, char __us
+ 			mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
+ 			n++;
+ 			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
+-				printk(KERN_ERR "%s@%d: _ioctl_fwdl - "
++				printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+ 						"Unable to copy f/w buffer hunk#%d @ %p\n",
+ 						__FILE__, __LINE__, n, ufwbuf);
+ 				goto fwdl_out;
+@@ -1040,9 +1007,6 @@ mptctl_do_fw_download(int ioc, char __us
+ 	 * Finally, perform firmware download.
+ 	 */
+ 	ReplyMsg = NULL;
+-	iocp->ioctl->wait_done = 0;
+-	INITIALIZE_IOCTL_STATUS(iocp->ioctl->status)
+-
+ 	mpt_put_msg_frame(mptctl_id, iocp, mf);
+ 
+ 	/* Now wait for the command to complete */
+@@ -1075,7 +1039,7 @@ mptctl_do_fw_download(int ioc, char __us
+ 		printk(KERN_WARNING MYNAM ": (try again later?)\n");
+ 		return -EBUSY;
+ 	} else {
+-		printk(KERN_WARNING MYNAM ": ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
++		printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
+ 				    iocp->name, iocstat);
+ 		printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");
+ 		return -ENOMSG;
+@@ -1111,7 +1075,7 @@ mptctl_fw_downloadboot(unsigned long arg
+ 
+ 	dctlprintk(("mptctl_fwdlboot called. mptctl_id = %xh\n", mptctl_id)); //tc
+ 	if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
+-		printk(KERN_ERR "%s@%d: _ioctl_fwdl - "
++		printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+ 				"Unable to copy mpt_fw_xfer struct @ %p\n",
+ 				__FILE__, __LINE__, ufwdl);
+ 		return -EFAULT;
+@@ -1149,20 +1113,11 @@ mptctl_do_fw_downloadboot(int ioc_num, c
+ 		return -ENODEV; /* (-6) No such device or address */
+ 	}
+ 
+-	pbuf = (char *)__get_free_pages(GFP_KERNEL, get_order(fwlen));
+-       if (pbuf==NULL) {
+-               printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - "
+-                               "Unable to allocate memory\n",
+-                               __FILE__, __LINE__);
+-               return -ENOMEM;
+-       }
+-
+-
+-if (copy_from_user(pbuf, ufwbuf, fwlen)) {
+-		printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - "
++	pbuf = kmalloc(fwlen, GFP_KERNEL);
++	if (copy_from_user(pbuf, ufwbuf, fwlen)) {
++		printk(KERN_ERR "%s@%d::_ioctl_fwdlboot - "
+ 				"Unable to copy mpt_fw @ %p\n",
+ 				__FILE__, __LINE__, (void*)ufwbuf);
+-free_pages((unsigned long)pbuf, get_order(fwlen));
+ 		return -EFAULT;
+ 	}
+ 
+@@ -1171,10 +1126,7 @@ free_pages((unsigned long)pbuf, get_orde
+ 
+ 	rc = mpt_downloadboot(ioc, (MpiFwHeader_t *)pbuf, CAN_SLEEP);
+ 	ddlprintk((MYIOC_s_INFO_FMT "mptctl_do_fw_downloadboot rc=%x\n",
+-
+ 				ioc->name, rc));
+-#if 0
+-
+ 	if ( (rc == 0) && (ioc->bus_type == SAS) ) {
+ /*		if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0)
+ 			return rc; */
+@@ -1194,12 +1146,10 @@ free_pages((unsigned long)pbuf, get_orde
+ 			ioc->name));
+ 		} */
+ 	}
+-#endif
+-free_pages((unsigned long)pbuf, get_order(fwlen));
++	kfree(pbuf);
+ 	return rc;
+ }
+ 
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  * SGE Allocation routine
+@@ -1278,9 +1228,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
+ 		if (buflist[buflist_ent].kptr == NULL) {
+ 			alloc_sz = alloc_sz / 2;
+ 			if (alloc_sz == 0) {
+-				printk(KERN_WARNING MYNAM ": -SG: No can do - "
++				printk(KERN_WARNING MYNAM "-SG: No can do - "
+ 						    "not enough memory!   :-(\n");
+-				printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n",
++				printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+ 						    numfrags);
+ 				goto free_and_fail;
+ 			}
+@@ -1304,17 +1254,17 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
+ 
+ 		/* Need to chain? */
+ 		if (fragcnt == sg_spill) {
+-			printk(KERN_WARNING MYNAM ": -SG: No can do - " "Chain required!   :-(\n");
+-			printk(KERN_WARNING MYNAM ": (freeing %d frags)\n", numfrags);
++			printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required!   :-(\n");
++			printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags);
+ 			goto free_and_fail;
+ 		}
+ 
+ 		/* overflow check... */
+ 		if (numfrags*8 > MAX_SGL_BYTES){
+ 			/* GRRRRR... */
+-			printk(KERN_WARNING MYNAM ": -SG: No can do - "
++			printk(KERN_WARNING MYNAM "-SG: No can do - "
+ 					    "too many SG frags!   :-(\n");
+-			printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n",
++			printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+ 					    numfrags);
+ 			goto free_and_fail;
+ 		}
+@@ -1435,16 +1385,18 @@ mptctl_getiocinfo (unsigned long arg, un
+ 	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
+ 	struct mpt_ioctl_iocinfo *karg;
+ 	MPT_ADAPTER		*ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice		*pTarget;
+ 	struct pci_dev		*pdev;
++	struct Scsi_Host	*sh;
++	MPT_SCSI_HOST		*hd;
+ 	int			iocnum;
+ 	int			numDevices = 0;
+-	int			id, bus;
++	unsigned int		max_id;
++	int			ii;
+ 	unsigned int		port;
+ 	int			cim_rev;
+ 	u8			revision;
+ 
++	dctlprintk(("mptctl_getiocinfo called.\n"));
+ 	/* Add of PCI INFO results in unaligned access for
+ 	 * IA64 and Sparc. Reset long to int. Return no PCI
+ 	 * data for obsolete format.
+@@ -1457,20 +1409,18 @@ mptctl_getiocinfo (unsigned long arg, un
+ 		cim_rev = 2;
+ 	else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))
+ 		cim_rev = 0;	/* obsolete */
+-	else {
+-		dctlprintk(("mptctl_getiocinfo called.i Invalid data_size=%d\n", data_size));
++	else
+ 		return -EFAULT;
+-	}
+ 
+ 	karg = kmalloc(data_size, GFP_KERNEL);
+ 	if (karg == NULL) {
+-		printk(KERN_ERR "%s: mpt_ioctl_iocinfo() @%d - no memory available!\n",
++		printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
+ 				__FILE__, __LINE__);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	if (copy_from_user(karg, uarg, data_size)) {
+-		printk(KERN_ERR "%s@%d: mptctl_getiocinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+ 			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
+ 				__FILE__, __LINE__, (void*)uarg);
+ 		kfree(karg);
+@@ -1484,11 +1434,10 @@ mptctl_getiocinfo (unsigned long arg, un
+ 		kfree(karg);
+ 		return -ENODEV;
+ 	}
+-	dctlprintk(("ioc%d: mptctl_getiocinfo called.\n", iocnum));
+ 
+ 	/* Verify the data transfer size is correct. */
+ 	if (karg->hdr.maxDataSize != data_size) {
+-		printk(KERN_ERR "%s@%d: mptctl_getiocinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+ 			"Structure size mismatch. Command not completed.\n",
+ 				__FILE__, __LINE__);
+ 		kfree(karg);
+@@ -1535,11 +1484,18 @@ mptctl_getiocinfo (unsigned long arg, un
+ 
+ 	/* Get number of devices
+          */
+-	for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-		if ((pMptTarget = ioc->Target_List[bus])) {
+-			for (id = 0; id < ioc->DevicesPerBus; id++) {
+-				pTarget = pMptTarget->Target[id];
+-				if (pTarget)
++	if ((sh = ioc->sh) != NULL) {
++		 /* sh->max_id = maximum target ID + 1
++		 */
++		max_id = sh->max_id - 1;
++		hd = (MPT_SCSI_HOST *) sh->hostdata;
++
++		/* Check all of the target structures and
++		 * keep a counter.
++		 */
++		if (hd && hd->Targets) {
++			for (ii = 0; ii <= max_id; ii++) {
++				if (hd->Targets[ii])
+ 					numDevices++;
+ 			}
+ 		}
+@@ -1563,7 +1519,7 @@ mptctl_getiocinfo (unsigned long arg, un
+ 	/* Copy the data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user((char __user *)arg, karg, data_size)) {
+-		printk(KERN_ERR "%s@%d: mptctl_getiocinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+ 			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		kfree(karg);
+@@ -1590,22 +1546,25 @@ mptctl_gettargetinfo (unsigned long arg)
+ 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
+ 	struct mpt_ioctl_targetinfo karg;
+ 	MPT_ADAPTER		*ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice		*pTarget;
++	struct Scsi_Host	*sh;
++	MPT_SCSI_HOST		*hd;
++	VirtDevice		*vdev;
+ 	char			*pmem;
+ 	int			*pdata;
+ 	IOCPage2_t		*pIoc2;
+ 	IOCPage3_t		*pIoc3;
+ 	int			iocnum;
+ 	int			numDevices = 0;
++	unsigned int		max_id;
+ 	int			id, jj, indexed_lun, lun_index;
+ 	u32			lun;
+ 	int			maxWordsLeft;
+ 	int			numBytes;
+-	u8			port, devType, bus;
++	u8			port, devType, bus_id;
+ 
++	dctlprintk(("mptctl_gettargetinfo called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
+-		printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+ 			"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1618,7 +1577,6 @@ mptctl_gettargetinfo (unsigned long arg)
+ 		return -ENODEV;
+ 	}
+ 
+-	dctlprintk(("ioc%ds: mptctl_gettargetinfo called.\n", iocnum));
+ 	/* Get the port number and set the maximum number of bytes
+ 	 * in the returned structure.
+ 	 * Ignore the port setting.
+@@ -1628,7 +1586,7 @@ mptctl_gettargetinfo (unsigned long arg)
+ 	port = karg.hdr.port;
+ 
+ 	if (maxWordsLeft <= 0) {
+-		printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n",
++		printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
+ 				__FILE__, __LINE__);
+ 		return -ENOMEM;
+ 	}
+@@ -1649,7 +1607,7 @@ mptctl_gettargetinfo (unsigned long arg)
+ 	 */
+ 	pmem = kmalloc(numBytes, GFP_KERNEL);
+ 	if (pmem == NULL) {
+-		printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n",
++		printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
+ 				__FILE__, __LINE__);
+ 		return -ENOMEM;
+ 	}
+@@ -1658,68 +1616,71 @@ mptctl_gettargetinfo (unsigned long arg)
+ 
+ 	/* Get number of devices
+          */
+-	/* Check all of the target structures.
+-	 * Save the Id and increment the counter,
+-	 * if ptr non-null.
+-	 */
+-	mpt_findImVolumes(ioc);
+-	pIoc2 = ioc->raid_data.pIocPg2;
+-	for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-		for ( id = 0; id < ioc->DevicesPerBus; ) {
+-			if ( pIoc2 && pIoc2->NumActiveVolumes ) {
+-				if ( id == pIoc2->RaidVolume[0].VolumeID ) {
+-					if (maxWordsLeft <= 0) {
+-						printk(KERN_ERR "mptctl_gettargetinfo - "
+-		"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
+-						goto data_space_full;
+-					}
+-					if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
+-						devType = 0x80;
+-					else
+-						devType = 0xC0;
+-					if ( bus == pIoc2->RaidVolume[0].VolumeBus) {
+-						numDevices++;
+-						*pdata = ( (devType << 24) | (bus<< 8) | id );
++	if ((sh = ioc->sh) != NULL) {
++
++		max_id = sh->max_id - 1;
++		hd = (MPT_SCSI_HOST *) sh->hostdata;
++
++		/* Check all of the target structures.
++		 * Save the Id and increment the counter,
++		 * if ptr non-null.
++		 * sh->max_id = maximum target ID + 1
++		 */
++		if (hd && hd->Targets) {
++			mpt_findImVolumes(ioc);
++			pIoc2 = ioc->raid_data.pIocPg2;
++			for ( id = 0; id <= max_id; ) {
++				if ( pIoc2 && pIoc2->NumActiveVolumes ) {
++					if ( id == pIoc2->RaidVolume[0].VolumeID ) {
++						if (maxWordsLeft <= 0) {
++							printk(KERN_ERR "mptctl_gettargetinfo - "
++			"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
++							goto data_space_full;
++						}
++						if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
++                        				devType = 0x80;
++                    				else
++                        				devType = 0xC0;
++						bus_id = pIoc2->RaidVolume[0].VolumeBus;
++	            				numDevices++;
++                    				*pdata = ( (devType << 24) | (bus_id << 8) | id );
+ 						dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+ 		"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+-						pdata++;
++                    				pdata++;
+ 						--maxWordsLeft;
+ 						goto next_id;
+-					}
+-				} else {
+-					pIoc3 = ioc->raid_data.pIocPg3;
+-					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
+-						if ((pIoc3->PhysDisk[jj].PhysDiskID == id) && (pIoc3->PhysDisk[jj].PhysDiskBus == bus))
+-							goto next_id;
++					} else {
++						pIoc3 = ioc->raid_data.pIocPg3;
++            					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
++                    					if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
++								goto next_id;
++						}
+ 					}
+ 				}
+-			}
+-			if ((pMptTarget = ioc->Target_List[bus])) {
+-				pTarget = pMptTarget->Target[id];
+-				if (pTarget) {
++				if ( (vdev = hd->Targets[id]) ) {
+ 					for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
+ 						lun_index = (jj >> 5);
+ 						indexed_lun = (jj % 32);
+ 						lun = (1 << indexed_lun);
+-						if (pTarget->luns[lun_index] & lun) {
++						if (vdev->luns[lun_index] & lun) {
+ 							if (maxWordsLeft <= 0) {
+ 								printk(KERN_ERR "mptctl_gettargetinfo - "
+-				"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
++			"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
+ 								goto data_space_full;
+ 							}
+-							bus = pTarget->bus;
++							bus_id = vdev->bus_id;
+ 							numDevices++;
+-							*pdata = ( (jj << 16) | (bus << 8) | id );
++                            				*pdata = ( (jj << 16) | (bus_id << 8) | id );
+ 							dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+-			"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
++		"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+ 							pdata++;
+ 							--maxWordsLeft;
+ 						}
+ 					}
+ 				}
+-			}
+ next_id:
+-			id++;
++				id++;
++			}
+ 		}
+ 	}
+ data_space_full:
+@@ -1729,7 +1690,7 @@ data_space_full:
+ 	 */
+ 	if (copy_to_user((char __user *)arg, &karg,
+ 				sizeof(struct mpt_ioctl_targetinfo))) {
+-		printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+ 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		kfree(pmem);
+@@ -1739,7 +1700,7 @@ data_space_full:
+ 	/* Copy the remaining data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
+-		printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+ 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+ 				__FILE__, __LINE__, pdata);
+ 		kfree(pmem);
+@@ -1751,70 +1712,6 @@ data_space_full:
+ 	return 0;
+ }
+ 
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*
+- *	mptctl_hba_pciinfo - Obtain all mpt HBAs pci (Config Space) information.
+- *	@arg: User space argument
+- *
+- * Outputs:	None.
+- * Return:	0 if successful
+- *		-EFAULT if data unavailable
+- */
+-static int
+-mptctl_hba_pciinfo (unsigned long arg)
+-{
+-	struct mpt_ioctl_hbapciinfo *uarg = (struct mpt_ioctl_hbapciinfo *) arg;
+-	struct mpt_ioctl_hbapciinfo karg;
+-
+-	MPT_ADAPTER	*ioc;
+-	int		ioc_num=0, data_size;
+-	u8			revision;
+-
+-	data_size = sizeof(mpt_ioctl_header)+4;
+-	/* Clear the struct before filling in data. */
+-	memset( &karg, 0, (uarg->hdr.maxDataSize + data_size) );
+-
+-	dctlprintk((KERN_INFO MYNAM ": Checking for MPT adapters...maxDataSize=%d data_size=%d\n", uarg->hdr.maxDataSize, data_size));
+-
+-	list_for_each_entry(ioc,&ioc_list,list) {
+-		data_size += sizeof (struct mpt_ioctl_mptpciinfo);
+-		if ( data_size >= uarg->hdr.maxDataSize ) {
+-			dctlprintk((KERN_INFO MYNAM ": data_size=%d >= maxDataSize=%d\n", data_size, uarg->hdr.maxDataSize));
+-			break;
+-		}
+-		karg.hbapciinfo[ioc_num].iocNumber = ioc_num;
+-		karg.hbapciinfo[ioc_num].deviceID = ioc->deviceID;
+-		karg.hbapciinfo[ioc_num].vendorID = ioc->vendorID;
+-
+-		pci_read_config_byte(ioc->pcidev, PCI_CLASS_REVISION, &revision);
+-
+-		karg.hbapciinfo[ioc_num].subSystemVendorID = ioc->pcidev->subsystem_vendor;
+-		karg.hbapciinfo[ioc_num].subSystemID = ioc->pcidev->subsystem_device;
+-
+-		karg.hbapciinfo[ioc_num].revisionID = revision;
+-		mpt_GetIocState(ioc, 1);
+-		karg.hbapciinfo[ioc_num++].iocState = (ioc->last_state >> MPI_IOC_STATE_SHIFT);
+-	}
+-
+-	karg.totalIOC = ioc_num;
+-
+-	dctlprintk((KERN_INFO MYNAM ": %d MPT adapters found, arg=%p karg=%p size=%d\n",
+-		 karg.totalIOC, (char *)arg, &karg, (int)sizeof(struct mpt_ioctl_hbapciinfo)));
+-
+-	/* Copy the data from kernel memory to user memory
+-	 */
+-	if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_hbapciinfo))) {
+-		printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+-			"Unable to write out mpt_ioctl_eventquery struct @ %p\n",
+-				__FILE__, __LINE__, (void*)uarg);
+-		return -EFAULT;
+-	}
+-	return 0;
+-}
+-#endif
+-
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /* MPT IOCTL Test function.
+  *
+@@ -1833,7 +1730,7 @@ mptctl_readtest (unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_readtest called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
+-		printk(KERN_ERR "%s@%d: mptctl_readtest - "
++		printk(KERN_ERR "%s@%d::mptctl_readtest - "
+ 			"Unable to read in mpt_ioctl_test struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1863,7 +1760,7 @@ mptctl_readtest (unsigned long arg)
+ 	/* Copy the data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
+-		printk(KERN_ERR "%s@%d: mptctl_readtest - "
++		printk(KERN_ERR "%s@%d::mptctl_readtest - "
+ 			"Unable to write out mpt_ioctl_test struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1893,7 +1790,7 @@ mptctl_eventquery (unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_eventquery called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
+-		printk(KERN_ERR "%s@%d: mptctl_eventquery - "
++		printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+ 			"Unable to read in mpt_ioctl_eventquery struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1912,7 +1809,7 @@ mptctl_eventquery (unsigned long arg)
+ 	/* Copy the data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
+-		printk(KERN_ERR "%s@%d: mptctl_eventquery - "
++		printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+ 			"Unable to write out mpt_ioctl_eventquery struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1931,7 +1828,7 @@ mptctl_eventenable (unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_eventenable called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
+-		printk(KERN_ERR "%s@%d: mptctl_eventenable - "
++		printk(KERN_ERR "%s@%d::mptctl_eventenable - "
+ 			"Unable to read in mpt_ioctl_eventenable struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -1978,7 +1875,7 @@ mptctl_eventreport (unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_eventreport called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
+-		printk(KERN_ERR "%s@%d: mptctl_eventreport - "
++		printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+ 			"Unable to read in mpt_ioctl_eventreport struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -2010,7 +1907,7 @@ mptctl_eventreport (unsigned long arg)
+ 	 */
+ 	numBytes = max * sizeof(MPT_IOCTL_EVENTS);
+ 	if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
+-		printk(KERN_ERR "%s@%d: mptctl_eventreport - "
++		printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+ 			"Unable to write out mpt_ioctl_eventreport struct @ %p\n",
+ 				__FILE__, __LINE__, ioc->events);
+ 		return -EFAULT;
+@@ -2031,7 +1928,7 @@ mptctl_replace_fw (unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_replace_fw called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
+-		printk(KERN_ERR "%s@%d: mptctl_replace_fw - "
++		printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+ 			"Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -2067,7 +1964,7 @@ mptctl_replace_fw (unsigned long arg)
+ 	/* Copy the data from user memory to kernel space
+ 	 */
+ 	if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
+-		printk(KERN_ERR "%s@%d: mptctl_replace_fw - "
++		printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+ 			"Unable to read in mpt_ioctl_replace_fw image @ %p\n",
+ 			__FILE__, __LINE__, uarg);
+ 		mpt_free_fw_memory(ioc);
+@@ -2104,7 +2001,7 @@ mptctl_mpt_command (unsigned long arg)
+ 	dctlprintk(("mptctl_command called.\n"));
+ 
+ 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
+-		printk(KERN_ERR "%s@%d: mptctl_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
+ 			"Unable to read in mpt_ioctl_command struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -2149,11 +2046,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 	int		iocnum, flagsLength;
+ 	int		sz, rc = 0;
+ 	int		msgContext;
+-	u16		req_idx=0;
++	u16		req_idx;
+ 	ulong 		timeout;
+-        MPT_FRAME_HDR   *SAS_handshake_mf=NULL;
+-        char            *SAS_handshake_reply=NULL;
+-        u16             msgSize=0;
++
++	dctlprintk(("mptctl_do_mpt_command called.\n"));
+ 	bufIn.kptr = bufOut.kptr = NULL;
+ 
+ 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+@@ -2162,14 +2058,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 				iocnum));
+ 		return -ENODEV;
+ 	}
+-	dctlprintk(("ioc%d: mptctl_do_mpt_command called.\n", iocnum));
+ 	if (!ioc->ioctl) {
+-		printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 			"No memory available during driver init.\n",
+ 				__FILE__, __LINE__);
+ 		return -ENOMEM;
+ 	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
+-		printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 			"Busy with IOC Reset \n", __FILE__, __LINE__);
+ 		return -EBUSY;
+ 	}
+@@ -2183,7 +2078,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 		sz += sizeof(dma_addr_t) + sizeof(u32);
+ 
+ 	if (sz > ioc->req_sz) {
+-		printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 			"Request frame too large (%d) maximum (%d)\n",
+ 				__FILE__, __LINE__, sz, ioc->req_sz);
+ 		return -EFAULT;
+@@ -2191,44 +2086,18 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 
+ 	/* Get a free request frame and save the message context.
+ 	 */
+-	if (((MPIHeader_t *)(mfPtr))->MsgContext == 0x02012020) {
+-		msgSize = karg.hdr.port >> 16;
+-		if ( (mf = (MPT_FRAME_HDR *)kmalloc(msgSize, GFP_KERNEL)) == NULL) {
+-			dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc msgSize=%d for SAS_handshake!!\n",
+-			ioc->name, msgSize));
+-			return -ENOMEM;
+-		}
+-		SAS_handshake_mf = mf;
+-		if (karg.maxReplyBytes) {
+-			if ( (SAS_handshake_reply = (char *)kmalloc(karg.maxReplyBytes, GFP_KERNEL)) == NULL) {
+-				kfree(SAS_handshake_mf);
+-				dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc maxReplyBytes=%d for SAS_handshake!!\n",
+-					ioc->name, karg.maxReplyBytes));
+-				return -ENOMEM;
+-			}
+-		}
+-		hdr = (MPIHeader_t *) mf;
+-		msgContext = le32_to_cpu(0x02012020);
+-		karg.hdr.port &= 0x0000ffff;
+-	} else {
+-		if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-			dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
+-			    ioc->name,__FUNCTION__));
+-			return -EAGAIN;
+-		} else {
+-			hdr = (MPIHeader_t *) mf;
+-			msgContext = le32_to_cpu(hdr->MsgContext);
+-			req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-		}
+-	}
++        if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
++                return -EAGAIN;
+ 
++	hdr = (MPIHeader_t *) mf;
++	msgContext = le32_to_cpu(hdr->MsgContext);
++	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+ 
+-//@@@@@
+ 	/* Copy the request frame
+ 	 * Reset the saved message context.
+ 	 */
+ 	if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
+-		printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 			"Unable to read MF from mpt_ioctl_command struct @ %p\n",
+ 			__FILE__, __LINE__, mfPtr);
+ 		rc = -EFAULT;
+@@ -2259,34 +2128,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 	case MPI_FUNCTION_SCSI_IO_REQUEST:
+ 		if (ioc->sh) {
+ 			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
+-			struct _MPT_DEVICE	*pMptTarget;
+ 			VirtDevice	*pTarget = NULL;
+ 			MPT_SCSI_HOST	*hd = NULL;
+ 			int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
+ 			int scsidir = 0;
+-			int id = (int) pScsiReq->TargetID;
+-			int bus = (int) pScsiReq->Bus;
++			int target = (int) pScsiReq->TargetID;
+ 			int dataSize;
+ 
+-			if ((id < 0) || (id > ioc->DevicesPerBus)) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-					"Target ID=%d out of bounds.  DevicesPerBus=%d\n",
+-					__FILE__, __LINE__, id, ioc->DevicesPerBus);
+-				rc = -ENODEV;
+-				goto done_free_mem;
+-			}
+-
+-			if ((bus < 0) || (bus >= ioc->NumberOfBuses)) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-					"Target Bus=%d out of bounds.  NumberOfBuses=%d\n",
+-					__FILE__, __LINE__, bus, ioc->NumberOfBuses);
+-				rc = -ENODEV;
+-				goto done_free_mem;
+-			}
+-			if ((pMptTarget = ioc->Target_List[bus]) == NULL) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-					"Target_List=NULL for %s bus=%d\n",
+-					__FILE__, __LINE__, ioc->name, bus);
++			if ((target < 0) || (target >= ioc->sh->max_id)) {
++				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
++					"Target ID out of bounds. \n",
++					__FILE__, __LINE__);
+ 				rc = -ENODEV;
+ 				goto done_free_mem;
+ 			}
+@@ -2310,7 +2162,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 				   + (req_idx * MPT_SENSE_BUFFER_ALLOC));
+ 
+ 			if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
+-				pTarget = pMptTarget->Target[id];
++				if (hd->Targets)
++					pTarget = hd->Targets[target];
+ 			}
+ 
+ 			if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+@@ -2331,10 +2184,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 			pScsiReq->DataLength = cpu_to_le32(dataSize);
+ 
+ 			ioc->ioctl->reset = MPTCTL_RESET_OK;
+-			ioc->ioctl->id = id;
++			ioc->ioctl->target = target;
+ 
+ 		} else {
+-			printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				"SCSI driver is not loaded. \n",
+ 					__FILE__, __LINE__);
+ 			rc = -EFAULT;
+@@ -2353,7 +2206,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 
+ 	case MPI_FUNCTION_SATA_PASSTHROUGH:
+ 		if (!ioc->sh) {
+-			printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				"SCSI driver is not loaded. \n",
+ 					__FILE__, __LINE__);
+ 			rc = -EFAULT;
+@@ -2409,10 +2262,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 			pScsiReq->DataLength = cpu_to_le32(dataSize);
+ 
+ 			ioc->ioctl->reset = MPTCTL_RESET_OK;
+-			ioc->ioctl->id = pScsiReq->TargetID;
+-			ioc->ioctl->bus = pScsiReq->Bus;
++			ioc->ioctl->target = pScsiReq->TargetID;
+ 		} else {
+-			printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				"SCSI driver is not loaded. \n",
+ 					__FILE__, __LINE__);
+ 			rc = -EFAULT;
+@@ -2424,7 +2276,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 		{
+ 			MPT_SCSI_HOST *hd = NULL;
+ 			if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 					"SCSI driver not loaded or SCSI host not found. \n",
+ 					__FILE__, __LINE__);
+ 				rc = -EFAULT;
+@@ -2457,7 +2309,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 				(pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
+ 				(pInit->HostMfaHighAddr != high_addr) ||
+ 				(pInit->SenseBufferHighAddr != sense_high)) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 					"IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
+ 					__FILE__, __LINE__);
+ 				rc = -EFAULT;
+@@ -2490,7 +2342,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 		 	MPI_FUNCTION_LAN_RESET
+ 		*/
+ 
+-		printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 			"Illegal request (function 0x%x) \n",
+ 			__FILE__, __LINE__, hdr->Function);
+ 		rc = -EFAULT;
+@@ -2550,7 +2402,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 						karg.dataOutBufPtr,
+ 						bufOut.len)) {
+ 					printk(KERN_ERR
+-						"%s@%d: mptctl_do_mpt_command - Unable "
++						"%s@%d::mptctl_do_mpt_command - Unable "
+ 						"to read user data "
+ 						"struct @ %p\n",
+ 						__FILE__, __LINE__,karg.dataOutBufPtr);
+@@ -2561,7 +2413,16 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 		}
+ 
+ 		if (karg.dataInSize > 0) {
+-			flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++			if ((karg.dataOutSize > 0) &&
++			    (hdr->Function == MPI_FUNCTION_SMP_PASSTHROUGH)){
++				flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++						MPI_SGE_FLAGS_END_OF_BUFFER |
++						MPI_SGE_FLAGS_DIRECTION |
++						mpt_addr_size() )
++						<< MPI_SGE_FLAGS_SHIFT;
++			} else {
++				flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++			}
+ 			flagsLength |= karg.dataInSize;
+ 
+ 			bufIn.len = karg.dataInSize;
+@@ -2585,14 +2446,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 	}
+ 
+ 	ioc->ioctl->wait_done = 0;
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+ 	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+ 
+ 		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
+ 
+ 		if (mpt_send_handshake_request(mptctl_id, ioc,
+-		    sizeof(SCSITaskMgmt_t), (u32*)mf,10, CAN_SLEEP) != 0) {
++			sizeof(SCSITaskMgmt_t), (u32*)mf,
++			CAN_SLEEP) != 0) {
+ 			dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+ 				" (ioc %p, mf %p) \n", ioc->name,
+ 				ioc, mf));
+@@ -2600,73 +2460,27 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ 			rc = -ENODATA;
+ 			goto done_free_mem;
+ 		}
+-timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+-timeout = wait_event_timeout(mptctl_wait,ioc->ioctl->wait_done == 1,HZ*timeout);
+ 
+- if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
+-               /* Now we need to reset the board */
+-                       mptctl_free_tm_flags(ioc);
+-                       mptctl_timeout_expired(ioc->ioctl);
+-                       rc = -ENODATA;
+-                       goto done_free_mem;
+-               }
+-} else {
+-               if ( SAS_handshake_mf ) {
+-                       dctlprintk(("SAS_handshake_message Function=%x\n",
+-                               hdr->Function));
+-
+-                       timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+-                       rc = mpt_handshake_req_reply_wait(ioc,
+-                               msgSize,
+-                               (u32*)SAS_handshake_mf,
+-                              karg.maxReplyBytes,
+-                              (u16*)SAS_handshake_reply, timeout /*seconds*/,
+-                               CAN_SLEEP);
+-                       kfree(SAS_handshake_mf);
+-                       SAS_handshake_mf = NULL;
+-              if (rc == 0) {
+-              dctlprintk(("SAS_handshake_message Function=%x completed successfully\n",
+-                               hdr->Function));
+-                               sz = karg.maxReplyBytes;
+-                               if (sz > 0) {
+-                    if (copy_to_user((char *)karg.replyFrameBufPtr,SAS_handshake_reply, sz)){
+-printk(KERN_ERR "%s@%d::mptctl_do_mpt_command -" "Unable to write out reply frame %p\n",__FILE__, __LINE__, (void*)karg.replyFrameBufPtr);
+-                               rc =  -ENODATA;
+-                              }
+-                       }else {
+-
+-                                rc =  -ENODATA;
+-                               dctlprintk(("SAS_handshake_message failed sz=%d\n", sz));
+-                                }
+-                               kfree(SAS_handshake_reply);
+-                               SAS_handshake_reply = NULL;
+-                               goto done_free_mem;
+-                             }
+-                            else
+-                            {
+-                               rc = -ENODATA;
+-                               kfree(SAS_handshake_reply);
+-                               SAS_handshake_reply = NULL;
+-                               goto done_free_mem;
+-                            }
+-                         }else {
+-                               mpt_put_msg_frame(mptctl_id, ioc, mf);
+-                       /* Now wait for the command to complete */
+-                       timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+-                       timeout = wait_event_timeout(mptctl_wait,
+-                        ioc->ioctl->wait_done == 1,
+-                            HZ*timeout);
++	} else
++		mpt_put_msg_frame(mptctl_id, ioc, mf);
+ 
+-                if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
++	/* Now wait for the command to complete */
++	timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
++	timeout = wait_event_timeout(mptctl_wait,
++	     ioc->ioctl->wait_done == 1,
++	     HZ*timeout);
+ 
++	if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
+ 	/* Now we need to reset the board */
+ 
++		if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
++			mptctl_free_tm_flags(ioc);
++
+ 		mptctl_timeout_expired(ioc->ioctl);
+ 		rc = -ENODATA;
+ 		goto done_free_mem;
+-	       }
+-       }
+-}
++	}
++
+ 
+ 	mf = NULL;
+ 
+@@ -2684,7 +2498,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+ 			if (copy_to_user(karg.replyFrameBufPtr,
+ 				 &ioc->ioctl->ReplyFrame, sz)){
+ 
+-				 printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++				 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				 "Unable to write out reply frame %p\n",
+ 				 __FILE__, __LINE__, karg.replyFrameBufPtr);
+ 				 rc =  -ENODATA;
+@@ -2699,7 +2513,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+ 		sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
+ 		if (sz > 0) {
+ 			if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
+-				printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				"Unable to write sense data to user %p\n",
+ 				__FILE__, __LINE__,
+ 				karg.senseDataPtr);
+@@ -2716,7 +2530,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+ 				(karg.dataInSize > 0) && (bufIn.kptr)) {
+ 		if (copy_to_user(karg.dataInBufPtr,
+ 			 bufIn.kptr, karg.dataInSize)) {
+-			printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ 				"Unable to write data to user %p\n",
+ 				__FILE__, __LINE__,
+ 				karg.dataInBufPtr);
+@@ -2726,6 +2540,10 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+ 
+ done_free_mem:
+ 
++	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
++		MPT_IOCTL_STATUS_SENSE_VALID |
++		MPT_IOCTL_STATUS_RF_VALID );
++
+ 	/* Free the allocated memory.
+ 	 */
+ 	 if (bufOut.kptr != NULL) {
+@@ -2738,14 +2556,6 @@ done_free_mem:
+ 			bufIn.len, (void *) bufIn.kptr, dma_addr_in);
+ 	}
+ 
+-if (SAS_handshake_mf) {
+-		kfree(SAS_handshake_mf);
+-		mf=NULL;
+-	}
+-if (SAS_handshake_reply)
+-		kfree(SAS_handshake_reply);
+-
+-
+ 	/* mf is null if command issued successfully
+ 	 * otherwise, failure occured after mf acquired.
+ 	 */
+@@ -2792,7 +2602,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
+ 		return -EFAULT;
+ 
+ 	if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
+-		printk(KERN_ERR "%s@%d: mptctl_hp_host_info - "
++		printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
+ 			"Unable to read in hp_host_info struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -2914,8 +2724,6 @@ mptctl_hp_hostinfo(unsigned long arg, un
+ 	    (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
+ 
+ 	ioc->ioctl->wait_done = 0;
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+ 	mpt_put_msg_frame(mptctl_id, ioc, mf);
+ 
+ 	rc = wait_event_timeout(mptctl_wait,
+@@ -2947,7 +2755,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
+ 	/* Copy the data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
+-		printk(KERN_ERR "%s@%d: mptctl_hpgethostinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
+ 			"Unable to write out hp_host_info @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -2986,7 +2794,7 @@ mptctl_hp_targetinfo(unsigned long arg)
+ 
+ 	dctlprintk(("mptctl_hp_targetinfo called.\n"));
+ 	if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
+-		printk(KERN_ERR "%s@%d: mptctl_hp_targetinfo - "
++		printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
+ 			"Unable to read in hp_host_targetinfo struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -3097,7 +2905,7 @@ mptctl_hp_targetinfo(unsigned long arg)
+ 	/* Copy the data from kernel memory to user memory
+ 	 */
+ 	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
+-		printk(KERN_ERR "%s@%d: mptctl_hp_target_info - "
++		printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
+ 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+ 				__FILE__, __LINE__, uarg);
+ 		return -EFAULT;
+@@ -3231,8 +3039,6 @@ allocDiagBuffer:
+ 	DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp);
+ 
+ 	ioc->ioctl->wait_done = 0;
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+ 	mpt_put_msg_frame(mptctl_id, ioc, mf);
+ 
+ 	/* Now wait for the command to complete */
+@@ -3275,6 +3081,10 @@ allocDiagBuffer:
+ 
+ mptctl_register_diag_buffer_out:
+ 
++	ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID );
++
+ 	if ( rc ) {
+ 		pci_free_consistent(ioc->pcidev, request_data_sz,
+ 			request_data,
+@@ -3371,8 +3181,6 @@ mptctl_release_diag_buffer (unsigned lon
+ 	DiagRelease->MsgFlags = 0;
+ 
+ 	ioc->ioctl->wait_done = 0;
+-	INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+ 	mpt_put_msg_frame(mptctl_id, ioc, mf);
+ 
+ 	/* Now wait for the command to complete */
+@@ -3410,6 +3218,10 @@ mptctl_release_diag_buffer (unsigned lon
+ 
+ mptctl_release_diag_buffer_out:
+ 
++	ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++	    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++	    MPT_IOCTL_STATUS_RF_VALID);
++
+ 	return rc;
+ }
+ 
+@@ -3706,8 +3518,6 @@ mptctl_read_diag_buffer (unsigned long a
+ 		DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp);
+ 
+ 		ioc->ioctl->wait_done = 0;
+-		INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+ 		mpt_put_msg_frame(mptctl_id, ioc, mf);
+ 
+ 		/* Now wait for the command to complete */
+@@ -3746,8 +3556,14 @@ mptctl_read_diag_buffer (unsigned long a
+ 				ioc->ioctl->status));
+ 			rc = -EFAULT;
+ 		}
+-	}
++
+ mptctl_read_diag_buffer_out:
++
++		ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++		    MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++		    MPT_IOCTL_STATUS_RF_VALID);
++
++	}
+ 	return rc;
+ }
+ 
+@@ -3796,7 +3612,7 @@ compat_mptctl_ioctl(unsigned int fd, uns
+ 	int ret;
+ 
+ 	lock_kernel();
+-	dctlprintk((KERN_INFO MYNAM ": compat_mptctl_ioctl() called\n"));
++	dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n"));
+ 	ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 	return ret;
+@@ -3820,7 +3636,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+ 	int nonblock = (filp->f_flags & O_NONBLOCK);
+ 	int ret;
+ 
+-	dctlprintk((KERN_INFO MYNAM ": compat_mptfwxfer_ioctl() called\n"));
++	dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
+ 
+ 	if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
+ 		return -EFAULT;
+@@ -3829,7 +3645,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+ 	iocnumX = kfw32.iocnum & 0xFF;
+ 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+ 	    (iocp == NULL)) {
+-		dctlprintk((KERN_ERR MYNAM ": compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
++		dctlprintk((KERN_ERR MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
+ 				__LINE__, iocnumX));
+ 		return -ENODEV;
+ 	}
+@@ -3866,7 +3682,7 @@ compat_mpt_command(struct file *filp, un
+ 	int nonblock = (filp->f_flags & O_NONBLOCK);
+ 	int ret;
+ 
+-	dctlprintk((KERN_INFO MYNAM ": compat_mpt_command() called\n"));
++	dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
+ 
+ 	if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
+ 		return -EFAULT;
+@@ -3875,7 +3691,7 @@ compat_mpt_command(struct file *filp, un
+ 	iocnumX = karg32.hdr.iocnum & 0xFF;
+ 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+ 	    (iocp == NULL)) {
+-		dctlprintk((KERN_ERR MYNAM ": compat_mpt_command @%d - ioc%d not found!\n",
++		dctlprintk((KERN_ERR MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
+ 				__LINE__, iocnumX));
+ 		return -ENODEV;
+ 	}
+@@ -4087,14 +3903,6 @@ static int __init mptctl_init(void)
+ 	if (++where && err) goto out_fail;
+ 	err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG, compat_mptctl_ioctl);
+ 	if (++where && err) goto out_fail;
+-	err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES, compat_mptctl_ioctl);
+-	if (++where && err) goto out_fail;
+-	err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL, compat_mptctl_ioctl);
+-	if (++where && err) goto out_fail;
+-	err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT, compat_mptctl_ioctl);
+-	if (++where && err) goto out_fail;
+-	err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION, compat_mptctl_ioctl);
+-	if (++where && err) goto out_fail;
+ 	err = register_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO, compat_mptctl_ioctl);
+ 	if (++where && err) goto out_fail;
+ 	err = register_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU, compat_mptctl_ioctl);
+@@ -4185,10 +3993,6 @@ out_fail:
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT);
+@@ -4260,10 +4064,6 @@ static void mptctl_exit(void)
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT);
+-	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU);
+ 	unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT);
+@@ -4277,7 +4077,7 @@ static void mptctl_exit(void)
+ }
+ 
+ #if defined(CPQ_CIM)
+-#include "csmi/csmisas.c"
++#include "csmisas.c"
+ #endif // CPQ_CIM
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h	2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptctl.h,v 1.14 2003/03/18 22:49:51 Exp $
+  */
+@@ -59,6 +59,7 @@
+  */
+ #define MPT_MISCDEV_BASENAME            "mptctl"
+ #define MPT_MISCDEV_PATHNAME            "/dev/" MPT_MISCDEV_BASENAME
++#define MPT_CSMI_DESCRIPTION	        "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
+ 
+ #define MPT_PRODUCT_LENGTH              12
+ 
+@@ -94,16 +95,6 @@
+ #define MPTDIAGQUERY		_IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t)
+ #define MPTDIAGREADBUFFER	_IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t)
+ 
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-#define MPTHBAPCIINFO		_IOWR(MPT_MAGIC_NUMBER,31,struct mpt_ioctl_hbapciinfo)
+-#endif
+-
+-
+-#define INITIALIZE_IOCTL_STATUS(status) \
+-	status &= ~( MPT_IOCTL_STATUS_COMMAND_GOOD \
+-	| MPT_IOCTL_STATUS_SENSE_VALID \
+-	| MPT_IOCTL_STATUS_RF_VALID);
+-
+ /*
+  * SPARC PLATFORM REMARKS:
+  * IOCTL data structures that contain pointers
+@@ -314,28 +305,6 @@ typedef struct mpt_ioctl_replace_fw {
+ 	u8		 newImage[1];
+ } mpt_ioctl_replace_fw_t;
+ 
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-struct mpt_ioctl_mptpciinfo {
+-    U8  iocNumber;
+-    U8  iocState;
+-    U8  revisionID;
+-    U8  reserved1;
+-    U16 vendorID;
+-    U16 deviceID;
+-    U16 subSystemVendorID;
+-    U16 subSystemID;
+-};
+-
+-
+-struct mpt_ioctl_hbapciinfo {
+-	mpt_ioctl_header     hdr;
+-    U8                   totalIOC;
+-    U8                   reserved[3];
+-    struct mpt_ioctl_mptpciinfo hbapciinfo[18];
+-};
+-#endif
+-
+-
+ /* General MPT Pass through data strucutre
+  *
+  * iocnum
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c	2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -74,7 +74,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /* Command line args */
+ static int mpt_pq_filter = 0;
+@@ -131,7 +130,7 @@ static struct scsi_host_template mptfc_d
+ 	.bios_param			= mptscsih_bios_param,
+ 	.can_queue			= MPT_FC_CAN_QUEUE,
+ 	.this_id			= -1,
+-	.sg_tablesize			= CONFIG_FUSION_MAX_SGE,
++	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
+ 	.max_sectors			= 8192,
+ 	.cmd_per_lun			= 7,
+ 	.use_clustering			= ENABLE_CLUSTERING,
+@@ -161,8 +160,6 @@ static struct pci_device_id mptfc_pci_ta
+ 		PCI_ANY_ID, PCI_ANY_ID },
+ 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
+ 		PCI_ANY_ID, PCI_ANY_ID },
+-        { 0x1657, MPI_MANUFACTPAGE_DEVICEID_FC949E,
+-                PCI_ANY_ID, PCI_ANY_ID },
+ 	{0}	/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
+@@ -184,6 +181,8 @@ mptfc_probe(struct pci_dev *pdev, const 
+ 	MPT_ADAPTER 		*ioc;
+ 	unsigned long		 flags;
+ 	int			 sz, ii;
++	int			 numSGE = 0;
++	int			 scale;
+ 	int			 ioc_cap;
+ 	u8			*mem;
+ 	int			error=0;
+@@ -262,16 +261,46 @@ mptfc_probe(struct pci_dev *pdev, const 
+ 		ioc->name, mpt_can_queue, ioc->req_depth,
+ 		sh->can_queue));
+ 
+-	sh->max_id = ioc->DevicesPerBus;
++	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+ 
+ 	sh->max_lun = MPT_LAST_LUN + 1;
+-	sh->max_channel = ioc->NumberOfBuses - 1;
++	sh->max_channel = 0;
+ 	sh->this_id = ioc->pfacts[0].PortSCSIID;
+ 
++
+ 	/* Required entry.
+ 	 */
+ 	sh->unique_id = ioc->id;
+-	sh->sg_tablesize = ioc->sg_tablesize;
++
++	/* Verify that we won't exceed the maximum
++	 * number of chain buffers
++	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
++	 * For 32bit SGE's:
++	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++	 *               + (req_sz - 64)/sizeof(SGE)
++	 * A slightly different algorithm is required for
++	 * 64bit SGEs.
++	 */
++	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++	if (sizeof(dma_addr_t) == sizeof(u64)) {
++		numSGE = (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	} else {
++		numSGE = 1 + (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	}
++
++	if (numSGE < sh->sg_tablesize) {
++		/* Reset this value */
++		dprintk((MYIOC_s_INFO_FMT
++		  "Resetting sg_tablesize to %d from %d\n",
++		  ioc->name, numSGE, sh->sg_tablesize));
++		sh->sg_tablesize = numSGE;
++	}
+ 
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	/* Set the pci device pointer in Scsi_Host structure.
+@@ -300,24 +329,23 @@ mptfc_probe(struct pci_dev *pdev, const 
+ 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ 		 ioc->name, hd->ScsiLookup, sz));
+ 
+-	for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-		/* Allocate memory for the device structures.
+-		 * A non-Null pointer at an offset
+-		 * indicates a device exists.
+-		 */
+-		sz = ioc->DevicesPerBus * sizeof(void *);
+-		mem = kmalloc(sz, GFP_ATOMIC);
+-		if (mem == NULL) {
+-			error = -ENOMEM;
+-			goto out_mptfc_probe;
+-		}
++	/* Allocate memory for the device structures.
++	 * A non-Null pointer at an offset
++	 * indicates a device exists.
++	 * max_id = 1 + maximum id (hosts.h)
++	 */
++	sz = sh->max_id * sizeof(void *);
++	mem = kmalloc(sz, GFP_ATOMIC);
++	if (mem == NULL) {
++		error = -ENOMEM;
++		goto out_mptfc_probe;
++	}
+ 
+-		memset(mem, 0, sz);
+-		ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++	memset(mem, 0, sz);
++	hd->Targets = (VirtDevice **) mem;
+ 
+-		dinitprintk((KERN_INFO
+-		  " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz));
+-	}
++	dprintk((KERN_INFO
++	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+ 
+ 	/* Clear the TM flags
+ 	 */
+@@ -333,17 +361,13 @@ mptfc_probe(struct pci_dev *pdev, const 
+ 	 */
+ 	hd->cmdPtr = NULL;
+ 
+-	/* Initialize this IOC's timers
++	/* Initialize this SCSI Hosts' timers
+ 	 * To use, set the timer expires field
+-	 * and add_timer. Used for internally
+-         * generated commands.
++	 * and add_timer
+ 	 */
+-        init_timer(&hd->InternalCmdTimer);
+-	hd->InternalCmdTimer.data = (unsigned long) hd;
+-	hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-        init_timer(&ioc->TMtimer);
+-	ioc->TMtimer.data = (unsigned long) ioc;
+-	ioc->TMtimer.function = mptscsih_TM_timeout;
++	init_timer(&hd->timer);
++	hd->timer.data = (unsigned long) hd;
++	hd->timer.function = mptscsih_timer_expired;
+ 
+ 	hd->mpt_pq_filter = mpt_pq_filter;
+ 
+@@ -356,9 +380,6 @@ mptfc_probe(struct pci_dev *pdev, const 
+ 	hd->scandv_wait_done = 0;
+ 	hd->last_queue_full = 0;
+ 
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+-
+ 	error = scsi_add_host (sh, &ioc->pcidev->dev);
+ 	if(error) {
+ 		dprintk((KERN_ERR MYNAM
+@@ -394,60 +415,6 @@ static struct pci_driver mptfc_driver = 
+ };
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-int
+-mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+-{
+-	MPT_SCSI_HOST *hd;
+-	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+-
+-	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to FC host driver!\n",
+-			ioc->name, event));
+-
+-	if (ioc->sh == NULL ||
+-		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+-		return 1;
+-
+-	switch (event) {
+-	case MPI_EVENT_UNIT_ATTENTION:			/* 03 */
+-		/* FIXME! */
+-		break;
+-	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
+-	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
+-		if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
+-			hd->soft_resets++;
+-		break;
+-	case MPI_EVENT_LOGOUT:				/* 09 */
+-		/* FIXME! */
+-		break;
+-
+-		/*
+-		 *  CHECKME! Don't think we need to do
+-		 *  anything for these, but...
+-		 */
+-	case MPI_EVENT_RESCAN:				/* 06 */
+-	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
+-	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
+-		/*
+-		 *  CHECKME!  Falling thru...
+-		 */
+-		break;
+-
+-	case MPI_EVENT_NONE:				/* 00 */
+-	case MPI_EVENT_LOG_DATA:			/* 01 */
+-	case MPI_EVENT_STATE_CHANGE:			/* 02 */
+-	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
+-	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
+-	default:
+-		devtprintk((KERN_INFO "%s:  Ignoring event (=%02Xh)\n",
+-			__FUNCTION__, event));
+-		break;
+-	}
+-
+-	return 1;		/* currently means nothing really */
+-}
+-
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
+  *	linux scsi mid-layer.
+@@ -464,9 +431,9 @@ mptfc_init(void)
+ 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
+ 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
+ 
+-        if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
++	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
+ 		devtprintk((KERN_INFO MYNAM
+-                  ": mptfc_event_process Registered for IOC event notifications\n"));
++		  ": Registered for IOC event notifications\n"));
+ 	}
+ 
+ 	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
+@@ -488,7 +455,6 @@ mptfc_exit(void)
+ {
+ 	pci_unregister_driver(&mptfc_driver);
+ 
+-
+ 	mpt_reset_deregister(mptfcDoneCtx);
+ 	dprintk((KERN_INFO MYNAM
+ 	  ": Deregistered for IOC reset notifications\n"));
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c	2007-11-02 09:10:23.000000000 +0100
+@@ -4,7 +4,7 @@
+  *      For use with LSI Logic Fibre Channel PCI chip/adapters
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 2000-2007 LSI Logic Corporation
++ *  Copyright (c) 2000-2005 LSI Logic Corporation
+  *
+  *  $Id: mptlan.c,v 1.55 2003/05/07 14:08:32 Exp $
+  */
+@@ -57,11 +57,9 @@
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ 
+-#define my_VERSION	MPT_LINUX_VERSION_COMMON
+ #define MYNAM		"mptlan"
+ 
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+@@ -185,16 +183,16 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+ 	struct net_device *dev = ioc->netdev;
+ 	int FreeReqFrame = 0;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
++	dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
+ 		  IOC_AND_NETDEV_NAMES_s_s(dev)));
+ 
+-//	dlioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n",
++//	dioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n",
+ //			mf, reply));
+ 
+ 	if (mf == NULL) {
+ 		u32 tmsg = CAST_PTR_TO_U32(reply);
+ 
+-		dlioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
++		dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
+ 				IOC_AND_NETDEV_NAMES_s_s(dev),
+ 				tmsg));
+ 
+@@ -204,14 +202,14 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+ 		//  mptbase.c::mpt_interrupt() routine and callcack here
+ #if 0
+ 		case LAN_REPLY_FORM_MESSAGE_CONTEXT:
+-//			dlioprintk((KERN_INFO MYNAM "/lan_reply: "
++//			dioprintk((KERN_INFO MYNAM "/lan_reply: "
+ //				  "MessageContext turbo reply received\n"));
+ 			FreeReqFrame = 1;
+ 			break;
+ #endif
+ 
+ 		case LAN_REPLY_FORM_SEND_SINGLE:
+-//			dlioprintk((MYNAM "/lan_reply: "
++//			dioprintk((MYNAM "/lan_reply: "
+ //				  "calling mpt_lan_send_reply (turbo)\n"));
+ 
+ 			//	FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
+@@ -230,7 +228,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+ 			break;
+ 
+ 		case LAN_REPLY_FORM_RECEIVE_SINGLE:
+-//			dlioprintk((KERN_INFO MYNAM "@lan_reply: "
++//			dioprintk((KERN_INFO MYNAM "@lan_reply: "
+ //				  "rcv-Turbo = %08x\n", tmsg));
+ 			mpt_lan_receive_post_turbo(dev, tmsg);
+ 			break;
+@@ -248,10 +246,10 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+ 	}
+ 
+ //	msg = (u32 *) reply;
+-//	dlioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n",
++//	dioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n",
+ //		  le32_to_cpu(msg[0]), le32_to_cpu(msg[1]),
+ //		  le32_to_cpu(msg[2]), le32_to_cpu(msg[3])));
+-//	dlioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n",
++//	dioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n",
+ //		  reply->u.hdr.Function));
+ 
+ 	switch (reply->u.hdr.Function) {
+@@ -275,7 +273,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+ 			if (!(pRecvRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY))
+ 				FreeReqFrame = 1;
+ 		} else
+-			dlioprintk((KERN_INFO MYNAM "@lan_reply: zero context "
++			dioprintk((KERN_INFO MYNAM "@lan_reply: zero context "
+ 				  "ReceivePostReply received.\n"));
+ 		break;
+ 	}
+@@ -617,7 +615,7 @@ mpt_lan_send_turbo(struct net_device *de
+ 	priv->stats.tx_packets++;
+ 	priv->stats.tx_bytes += sent->len;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
++	dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+ 			IOC_AND_NETDEV_NAMES_s_s(dev),
+ 			__FUNCTION__, sent));
+ 
+@@ -649,7 +647,7 @@ mpt_lan_send_reply(struct net_device *de
+ 
+ 	count = pSendRep->NumberOfContexts;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n",
++	dioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n",
+ 		 le16_to_cpu(pSendRep->IOCStatus)));
+ 
+ 	/* Add check for Loginfo Flag in IOCStatus */
+@@ -683,7 +681,7 @@ mpt_lan_send_reply(struct net_device *de
+ 		sent = priv->SendCtl[ctx].skb;
+ 		priv->stats.tx_bytes += sent->len;
+ 
+-		dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
++		dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+ 				IOC_AND_NETDEV_NAMES_s_s(dev),
+ 				__FUNCTION__, sent));
+ 
+@@ -722,7 +720,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+ 	int ctx;
+ 	u16 cur_naa = 0x1000;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
++	dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
+ 			__FUNCTION__, skb));
+ 
+ 	spin_lock_irqsave(&priv->txfidx_lock, flags);
+@@ -748,7 +746,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+ 	ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--];
+ 	spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+ 
+-//	dlioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n",
++//	dioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n",
+ //			IOC_AND_NETDEV_NAMES_s_s(dev)));
+ 
+ 	pSendReq = (LANSendRequest_t *) mf;
+@@ -783,7 +781,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+ 	pTrans->Flags         = 0;
+ 	pTrans->TransactionContext[0] = cpu_to_le32(ctx);
+ 
+-//	dlioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n",
++//	dioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n",
+ //			IOC_AND_NETDEV_NAMES_s_s(dev),
+ //			ctx, skb, skb->data));
+ 
+@@ -843,7 +841,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+ 	mpt_put_msg_frame (LanCtx, mpt_dev, mf);
+ 	dev->trans_start = jiffies;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n",
++	dioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n",
+ 			IOC_AND_NETDEV_NAMES_s_s(dev),
+ 			le32_to_cpu(pSimple->FlagsLength)));
+ 
+@@ -864,10 +862,10 @@ mpt_lan_wake_post_buckets_task(struct ne
+ 			schedule_work(&priv->post_buckets_task);
+ 		} else {
+ 			schedule_delayed_work(&priv->post_buckets_task, 1);
+-			dlioprintk((KERN_INFO MYNAM ": post_buckets queued on "
++			dioprintk((KERN_INFO MYNAM ": post_buckets queued on "
+ 				   "timer.\n"));
+ 		}
+-	        dlioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
++	        dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
+ 			   IOC_AND_NETDEV_NAMES_s_s(dev) ));
+ 	}
+ }
+@@ -880,7 +878,7 @@ mpt_lan_receive_skb(struct net_device *d
+ 
+ 	skb->protocol = mpt_lan_type_trans(skb, dev);
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) "
++	dioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) "
+ 		 "delivered to upper level.\n",
+ 			IOC_AND_NETDEV_NAMES_s_s(dev), skb->len));
+ 
+@@ -890,13 +888,13 @@ mpt_lan_receive_skb(struct net_device *d
+ 	skb->dev = dev;
+ 	netif_rx(skb);
+ 
+-	dlioprintk((MYNAM "/receive_skb: %d buckets remaining\n",
++	dioprintk((MYNAM "/receive_skb: %d buckets remaining\n",
+ 		 atomic_read(&priv->buckets_out)));
+ 
+ 	if (atomic_read(&priv->buckets_out) < priv->bucketthresh)
+ 		mpt_lan_wake_post_buckets_task(dev, 1);
+ 
+-	dlioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets "
++	dioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets "
+ 		  "remaining, %d received back since sod\n",
+ 		  atomic_read(&priv->buckets_out), priv->total_received));
+ 
+@@ -1027,8 +1025,8 @@ mpt_lan_receive_post_reply(struct net_de
+ 	int count;
+ 	int i, l;
+ 
+-	dlioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n"));
+-	dlioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n",
++	dioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n"));
++	dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n",
+ 		 le16_to_cpu(pRecvRep->IOCStatus)));
+ 
+ 	if ((le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_MASK) ==
+@@ -1057,14 +1055,14 @@ mpt_lan_receive_post_reply(struct net_de
+ //				offset);
+ //	}
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n",
++	dioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n",
+ 			IOC_AND_NETDEV_NAMES_s_s(dev),
+ 			offset, len));
+ 
+ 	if (count > 1) {
+ 		int szrem = len;
+ 
+-//		dlioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned "
++//		dioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned "
+ //			"for single packet, concatenating...\n",
+ //				IOC_AND_NETDEV_NAMES_s_s(dev)));
+ 
+@@ -1086,7 +1084,7 @@ mpt_lan_receive_post_reply(struct net_de
+ 			if (szrem < l)
+ 				l = szrem;
+ 
+-//			dlioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n",
++//			dioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n",
+ //					IOC_AND_NETDEV_NAMES_s_s(dev),
+ //					i, l));
+ 
+@@ -1214,7 +1212,7 @@ mpt_lan_post_receive_buckets(void *dev_i
+ 	curr = atomic_read(&priv->buckets_out);
+ 	buckets = (priv->max_buckets_out - curr);
+ 
+-	dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
++	dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
+ 			IOC_AND_NETDEV_NAMES_s_s(dev),
+ 			__FUNCTION__, buckets, curr));
+ 
+@@ -1226,7 +1224,7 @@ mpt_lan_post_receive_buckets(void *dev_i
+ 		if (mf == NULL) {
+ 			printk (KERN_ERR "%s: Unable to alloc request frame\n",
+ 				__FUNCTION__);
+-			dlioprintk((KERN_ERR "%s: %u buckets remaining\n",
++			dioprintk((KERN_ERR "%s: %u buckets remaining\n",
+ 				 __FUNCTION__, buckets));
+ 			goto out;
+ 		}
+@@ -1337,9 +1335,9 @@ mpt_lan_post_receive_buckets(void *dev_i
+ 	}
+ 
+ out:
+-	dlioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
++	dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
+ 		  __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
+-	dlioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
++	dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
+ 	__FUNCTION__, priv->total_posted, priv->total_received));
+ 
+ 	clear_bit(0, &priv->post_buckets_active);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h	2007-11-02 09:10:23.000000000 +0100
+@@ -65,9 +65,9 @@ MODULE_DESCRIPTION(LANAME);
+ 
+ /*****************************************************************************/
+ #ifdef MPT_LAN_IO_DEBUG
+-#define dlioprintk(x)  printk x
++#define dioprintk(x)  printk x
+ #else
+-#define dlioprintk(x)
++#define dioprintk(x)
+ #endif
+ 
+ #ifdef MPT_LAN_DEBUG
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c	2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -64,7 +64,6 @@
+ 
+ #include "mptbase.h"
+ #include "mptscsih.h"
+-#include "mptsas.h"
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #define my_NAME		"Fusion MPT SAS Host driver"
+@@ -74,10 +73,8 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /* Command line args */
+-
+ static int mpt_pq_filter = 0;
+ module_param(mpt_pq_filter, int, 0);
+ MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
+@@ -90,627 +87,40 @@ static int mpt_sas_hot_plug_enable = 1;
+ module_param(mpt_sas_hot_plug_enable, int, 0);
+ MODULE_PARM_DESC(mpt_sas_hot_plug_enable, " Enable SAS Hot Plug Support: enable=1 (default=1)");
+ 
+-static int mpt_cmd_retry_count = 144;
+-module_param(mpt_cmd_retry_count, int, 0);
+-MODULE_PARM_DESC(mpt_cmd_retry_count, " Device discovery TUR command retry count: default=144");
+-
+-extern int mpt_enable_deadioc_detect;
+-
+-extern int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout);
++extern int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+ static int	mptsasDoneCtx = -1;
+ static int	mptsasTaskCtx = -1;
+ static int	mptsasInternalCtx = -1; /* Used only for internal commands */
+ 
+-static void mptsas_hotplug_work(void *arg);
+-
+-#if defined(CPQ_CIM)
+-/**
+- * mptsas_sas_io_unit_pg0
+- *
+- * obtaining SAS_IO_UNIT page 0
+- *
+- * @ioc
+- * @port_info
+- *
+- **/
+-static int
+-mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+-{
+-	ConfigExtendedPageHeader_t hdr;
+-	CONFIGPARMS cfg;
+-	SasIOUnitPage0_t *buffer;
+-	dma_addr_t dma_handle;
+-	int error, i;
+-
+-	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.pageAddr = 0;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = 10;
+-
+-	error = mpt_config(ioc, &cfg);
+-	if (error)
+-		goto out;
+-	if (!hdr.ExtPageLength) {
+-		error = -ENXIO;
+-		goto out;
+-	}
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-					    &dma_handle);
+-	if (!buffer) {
+-		error = -ENOMEM;
+-		goto out;
+-	}
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	error = mpt_config(ioc, &cfg);
+-	if (error)
+-		goto out_free_consistent;
+-
+-	port_info->num_phys = buffer->NumPhys;
+-	port_info->phy_info = kmalloc(port_info->num_phys *
+-		sizeof(*port_info->phy_info),GFP_KERNEL);
+-	if (!port_info->phy_info) {
+-		error = -ENOMEM;
+-		goto out_free_consistent;
+-	}
+-
+-	if (port_info->num_phys)
+-		port_info->handle =
+-		    le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
+-	for (i = 0; i < port_info->num_phys; i++) {
+-		port_info->phy_info[i].phy_id = i;
+-		port_info->phy_info[i].port_id =
+-		    buffer->PhyData[i].Port;
+-		port_info->phy_info[i].negotiated_link_rate =
+-		    buffer->PhyData[i].NegotiatedLinkRate;
+-		port_info->phy_info[i].portinfo = port_info;
+-		port_info->phy_info[i].port_flags =
+-		    buffer->PhyData[i].PortFlags;
+-	}
+-
+- out_free_consistent:
+-	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-			    buffer, dma_handle);
+- out:
+-	return error;
+-}
+-
+-/**
+- * mptsas_sas_device_pg0
+- *
+- * obtaining SAS_DEVICE page 0
+- *
+- * @ioc
+- * device_info
+- *
+- **/
+-static int
+-mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+-		u32 form, u32 form_specific)
+-{
+-	ConfigExtendedPageHeader_t hdr;
+-	CONFIGPARMS cfg;
+-	SasDevicePage0_t *buffer;
+-	dma_addr_t dma_handle;
+-	u64 sas_address;
+-	int error=0;
+-
+-	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-	hdr.ExtPageLength = 0;
+-	hdr.PageNumber = 0;
+-	hdr.Reserved1 = 0;
+-	hdr.Reserved2 = 0;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-	cfg.cfghdr.ehdr = &hdr;
+-	cfg.pageAddr = form + form_specific;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.dir = 0;	/* read */
+-	cfg.timeout = 10;
+-
+-	memset(device_info, 0, sizeof(struct mptsas_devinfo));
+-	error = mpt_config(ioc, &cfg);
+-	if (error)
+-		goto out;
+-	if (!hdr.ExtPageLength) {
+-		error = -ENXIO;
+-		goto out;
+-	}
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-				      &dma_handle);
+-	if (!buffer) {
+-		error = -ENOMEM;
+-		goto out;
+-	}
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	error = mpt_config(ioc, &cfg);
+-	if (error)
+-		goto out_free_consistent;
+-
+-	device_info->handle = le16_to_cpu(buffer->DevHandle);
+-	device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
+-	device_info->handle_enclosure =
+-	    le16_to_cpu(buffer->EnclosureHandle);
+-	device_info->slot = le16_to_cpu(buffer->Slot);
+-	device_info->phy_id = buffer->PhyNum;
+-	device_info->port_id = buffer->PhysicalPort;
+-	device_info->id = buffer->TargetID;
+-	device_info->channel = buffer->Bus;
+-	memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
+-	device_info->sas_address = le64_to_cpu(sas_address);
+-	device_info->device_info =
+-	    le32_to_cpu(buffer->DeviceInfo);
+-
+- out_free_consistent:
+-	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-			    buffer, dma_handle);
+- out:
+-	return error;
+-}
+-
+-/**
+- *	mptsas_get_number_hotspares - returns num hot spares in this ioc
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *
+- *	Return: number of hotspares
+- *
+- **/
+-static int
+-mptsas_get_number_hotspares(MPT_ADAPTER *ioc)
+-{
+-	ConfigPageHeader_t	 hdr;
+-	CONFIGPARMS		 cfg;
+-	IOCPage5_t		 *buffer = NULL;
+-	dma_addr_t		 dma_handle;
+-	int			 data_sz=0;
+-	int			 rc;
+-
+-	memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-	memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-	rc = 0;
+-	hdr.PageNumber = 5;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.timeout = 10;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	if (hdr.PageLength == 0)
+-		goto get_ioc_pg5;
+-
+-	data_sz = hdr.PageLength * 4;
+-	buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-		data_sz, &dma_handle);
+-	if (!buffer)
+-		goto get_ioc_pg5;
+-
+-	memset((u8 *)buffer, 0, data_sz);
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	rc = buffer->NumHotSpares;
+-
+- get_ioc_pg5:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, data_sz,
+-		    (u8 *) buffer, dma_handle);
+-
+-	return rc;
+-}
+-
+-/**
+- *	mptsas_get_ioc_pg5 - ioc Page 5 hot spares
+- *	@ioc: Pointer to MPT_ADAPTER structure
+- *	@pIocPage5: ioc page 5
+- *
+- *	Return: 0 for success
+- *	-ENOMEM if no memory available
+- *		-EPERM if not allowed due to ISR context
+- *		-EAGAIN if no msg frames currently available
+- *		-EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-mptsas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5)
+-{
+-	ConfigPageHeader_t	 hdr;
+-	CONFIGPARMS		 cfg;
+-	IOCPage5_t		 *buffer = NULL;
+-	dma_addr_t		 dma_handle;
+-	int			 data_sz=0;
+-	int			 rc;
+-
+-	memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-	memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-	rc = 0;
+-	hdr.PageNumber = 5;
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.physAddr = -1;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-	cfg.timeout = 10;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	if (hdr.PageLength == 0) {
+-		rc = -EFAULT;
+-		goto get_ioc_pg5;
+-	}
+-
+-	data_sz = hdr.PageLength * 4;
+-	buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-		data_sz, &dma_handle);
+-	if (!buffer) {
+-		rc = -ENOMEM;
+-		goto get_ioc_pg5;
+-	}
+-
+-	memset((u8 *)buffer, 0, data_sz);
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if ((rc = mpt_config(ioc, &cfg)) != 0)
+-		goto get_ioc_pg5;
+-
+-	memcpy(iocPage5, buffer, sizeof(*iocPage5));
+-
+- get_ioc_pg5:
+-
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, data_sz,
+-		    (u8 *) buffer, dma_handle);
+-
+-	return rc;
+-}
+-
+-/**
+- * mptsas_add_device_component
+- *
+- * @ioc
+- * @channel - fw mapped id's
+- * @id
+- * @sas_address
+- * @device_info
+- *
+- **/
+-static void
+-mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
+-	u64 sas_address, u32 device_info)
+-{
+-	struct sas_device_info	*sas_info, *next;
+-
+-	down(&ioc->sas_device_info_mutex);
+-
+-	/*
+-	 * Delete all matching sas_address's out of tree
+-	 */
+-	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-		if (sas_info->sas_address != sas_address)
+-			continue;
+-		list_del(&sas_info->list);
+-		kfree(sas_info);
+-	}
+-
+-	/*
+-	 * If there is a matching channel/id, then swap out with new target info
+-	 */
+-	list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
+-		if (sas_info->fw.channel == channel && sas_info->fw.id == id)
+-			goto initialize_data;
+-	}
+-
+-	if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL)))
+-		goto out;
+-	memset(sas_info, 0, sizeof(*sas_info));
+-
+-	/*
+-	 * mapping - is for compatibility with drivers supporting sas transport layer
+-	 */
+-	sas_info->fw.id = id;
+-	sas_info->fw.channel = channel;
+-	sas_info->os.id = id;
+-	sas_info->os.channel = channel;
+-	list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+-
+- initialize_data:
+-
+-	sas_info->sas_address = sas_address;
+-	sas_info->device_info = device_info;
+-	sas_info->is_cached = 0;
+-	sas_info->is_logical_volume = 0;
+-	devtprintk((KERN_INFO "%s: adding channel=%d id=%d "
+-	    "sas_address=0x%llX\n", __FUNCTION__, channel, id, sas_address));
+-
+- out:
+-	up(&ioc->sas_device_info_mutex);
+-	return;
+-}
+-
+-/**
+- * mptsas_add_device_component_single
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static void
+-mptsas_add_device_component_single(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct mptsas_devinfo sas_device;
+-	int rc;
+-
+-	rc = mptsas_sas_device_pg0(ioc, &sas_device,
+-	    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+-	     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+-	    (channel << 8) + id);
+-	if (rc)
+-		return;
+-
+-	mptsas_add_device_component(ioc, sas_device.channel,
+-	    sas_device.id, sas_device.sas_address, sas_device.device_info);
+-}
+-
+-/**
+- * mptsas_add_device_component_hotspare
+- *
+- * Handle adding hotspares into the list
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_add_device_component_hotspare(MPT_ADAPTER *ioc)
+-{
+-	int		num_hotspares;
+-	IOCPage5_t 	*iocPage5;
+-	RaidPhysDiskPage0_t	phys_disk;
+-	int 		i;
+-
+-	iocPage5 = NULL;
+-	num_hotspares = mptsas_get_number_hotspares(ioc);
+-	if (!num_hotspares)
+-		goto out;
+-
+-	iocPage5 = kmalloc(offsetof(IOCPage5_t,HotSpare) +
+-	    num_hotspares * sizeof(IOC_5_HOT_SPARE), GFP_KERNEL);
+-	if (!iocPage5)
+-		goto out;
+-	memset(iocPage5, 0, sizeof(*iocPage5));
+-	if (mptsas_get_ioc_pg5(ioc, iocPage5) != 0)
+-		goto out;
+-	for(i = 0; i < num_hotspares; i++) {
+-		mpt_raid_phys_disk_pg0(ioc,
+-		    iocPage5->HotSpare[i].PhysDiskNum, &phys_disk );
+-		mptsas_add_device_component_single(ioc,
+-		    phys_disk.PhysDiskBus, phys_disk.PhysDiskID);
+-	}
+- out:
+-	kfree(iocPage5);
+-
+-}
+-
+-/**
+- * mptsas_add_device_component_ir
+- *
+- * Handle Integrated RAID, adding each individual device to list
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static void
+-mptsas_add_device_component_ir(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	CONFIGPARMS			cfg;
+-	ConfigPageHeader_t		hdr;
+-	dma_addr_t			dma_handle;
+-	pRaidVolumePage0_t		buffer = NULL;
+-	int				i;
+-	RaidPhysDiskPage0_t 		phys_disk;
+-	struct sas_device_info		*sas_info;
+-
+-	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-	cfg.pageAddr = (channel << 8) + id;
+-	cfg.cfghdr.hdr = &hdr;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto out;
+-
+-	if (!hdr.PageLength)
+-		goto out;
+-
+-	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-	    &dma_handle);
+-
+-	if (!buffer)
+-		goto out;
+-
+-	cfg.physAddr = dma_handle;
+-	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-	if (mpt_config(ioc, &cfg) != 0)
+-		goto out;
+-
+-	if (!buffer->NumPhysDisks)
+-		goto out;
+-
+-	/*
+-	 * Adding entry for hidden components
+-	 */
+-	for (i = 0; i < buffer->NumPhysDisks; i++) {
+-
+-		if(mpt_raid_phys_disk_pg0(ioc,
+-		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+-			continue;
+ 
+-		mptsas_add_device_component_single(ioc, phys_disk.PhysDiskBus,
+-		    phys_disk.PhysDiskID);
+-	}
+-
+-	/*
+-	 * Adding entry for logical volume in list
+-	 */
+-	list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
+-		if (sas_info->fw.channel == channel && sas_info->fw.id ==  id)
+-			goto initialize_data;
+-	}
+-
+-	if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL)))
+-		goto out;
+-	memset(sas_info, 0, sizeof(*sas_info));
+-
+-	sas_info->fw.id = id;
+-	sas_info->fw.channel = channel; /* channel zero */
+-	down(&ioc->sas_device_info_mutex);
+-	list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+-	up(&ioc->sas_device_info_mutex);
+-
+- initialize_data:
+-
+-	sas_info->os.id = id;
+-	sas_info->os.channel = channel;
+-	sas_info->sas_address = 0;
+-	sas_info->device_info = 0;
+-	sas_info->is_logical_volume = 1;
+-	sas_info->is_cached = 0;
+-
+-	devtprintk((KERN_INFO "%s: adding volume at channel=%d id=%d\n",
+-	    __FUNCTION__, channel, id));
+-
+-	mptsas_add_device_component_hotspare(ioc);
+- out:
+-	if (buffer)
+-		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-		    dma_handle);
+-}
+-
+-
+-/**
+- * mptsas_del_device_component
+- *
+- * Once a device has been removed, we mark the
+- * entry in the list as being cached
+- *
+- * @ioc
+- * @channel - os mapped id's
+- * @id
+- *
+- **/
+-static void
+-mptsas_del_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct sas_device_info	*sas_info, *next;
+-
+-	/*
+-	 * Set is_cached flag
+-	 */
+-	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-		if (sas_info->os.channel == channel && sas_info->os.id == id) {
+-			sas_info->is_cached = 1;
+-			devtprintk((KERN_INFO
+-			    "%s: deleting channel=%d id=%d "
+-			    "sas_address=0x%llX\n", __FUNCTION__, channel, id,
+-			    sas_info->sas_address));
+-		}
+-	}
+-}
+-
+-/**
+- * mptsas_del_device_components
+- *
+- * Cleaning the list
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_del_device_components(MPT_ADAPTER *ioc)
+-{
+-	struct sas_device_info	*sas_info, *next;
+-
+-	down(&ioc->sas_device_info_mutex);
+-	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-		list_del(&sas_info->list);
+-		kfree(sas_info);
+-	}
+-	up(&ioc->sas_device_info_mutex);
+-}
+-#endif
+-
+-/**
+- * mptsas_find_vdevice
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static VirtDevice *
+-mptsas_find_vdevice(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	struct _MPT_DEVICE *pMptTarget;
+-
+-	if (id >= ioc->DevicesPerBus || channel >= ioc->NumberOfBuses)
+-		return NULL;
++enum mptsas_hotplug_action {
++	MPTSAS_ADD_DEVICE,
++	MPTSAS_DEL_DEVICE,
++};
+ 
+-	pMptTarget = ioc->Target_List[channel];
+-	return pMptTarget->Target[id];
+-}
++struct mptsas_hotplug_event {
++	struct work_struct	work;
++	MPT_ADAPTER		*ioc;
++	enum mptsas_hotplug_action event_type;
++	u64			sas_address;
++	u32			channel;
++	u32			id;
++	u32			device_info;
++	u16			handle;
++	u16			parent_handle;
++	u8			phy_id;
++	u8			isRaid;
++};
+ 
+-/**
+- * mptsas_qcmd
+- *
+- * receiving a scsi_cmnd from upper layers
+- *
+- * @SCpnt
+- * @done
+- *
+- **/
+ static int
+ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+ {
+ 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+-	MPT_ADAPTER *ioc = hd->ioc;
+-	static VirtDevice *pTarget;
+-	int id = SCpnt->device->id;
+-	int channel = SCpnt->device->channel;
+-
+-	/* If Device has been removed, inhibit any more IO */
+-	pTarget = mptsas_find_vdevice(ioc, channel, id);
+-	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_DELETED)) {
++	int	 id = SCpnt->device->id;
++
++	/* Device has been removed, so inhibit any more IO */
++	if (hd->Targets[id] &&
++	    hd->Targets[id]->tflags & MPT_TARGET_FLAGS_DELETED) {
+ 		SCpnt->result = DID_NO_CONNECT << 16;
+ 		done(SCpnt);
+ 		return 0;
+@@ -719,32 +129,6 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, voi
+ 	return mptscsih_qcmd(SCpnt,done);
+ }
+ 
+-/**
+- * mptsas_slave_configure
+- *
+- *
+- * @sdev
+- *
+- **/
+-static int
+-mptsas_slave_configure(struct scsi_device *sdev)
+-{
+-#if defined(CPQ_CIM)
+-	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+-	MPT_ADAPTER *ioc = hd->ioc;
+-	int		channel;
+-	int		id;
+-
+-	channel = sdev->channel;
+-	id = sdev->id;
+-
+-	if ((ioc->raid_data.isRaid & (1 << id)) == 0)
+-		mptsas_add_device_component_single(ioc, channel, id);
+-#endif
+-	return mptscsih_slave_configure(sdev);
+-}
+-
+-
+ /* Show the ioc state for this card */
+ static ssize_t
+ mptsas_show_iocstate(struct class_device *class_dev, char *buf)
+@@ -778,300 +162,49 @@ static struct scsi_host_template mptsas_
+ 	.info				= mptscsih_info,
+ 	.queuecommand			= mptsas_qcmd,
+ 	.slave_alloc			= mptscsih_slave_alloc,
+-	.slave_configure		= mptsas_slave_configure,
+-	.slave_destroy			= mptscsih_slave_destroy,
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
+-	.change_queue_depth 		= mptscsih_change_queue_depth,
+-#endif
+-	.eh_abort_handler		= mptscsih_abort,
+-	.eh_device_reset_handler	= mptscsih_dev_reset,
+-	.eh_bus_reset_handler		= mptscsih_bus_reset,
+-	.eh_host_reset_handler		= mptscsih_host_reset,
+-	.bios_param			= mptscsih_bios_param,
+-	.can_queue			= MPT_FC_CAN_QUEUE,
+-	.this_id			= -1,
+-	.sg_tablesize			= CONFIG_FUSION_MAX_SGE,
+-	.max_sectors			= 8192,
+-	.cmd_per_lun			= 7,
+-	.use_clustering			= ENABLE_CLUSTERING,
+-	.shost_attrs			= mptsas_host_attrs,
+-	.dump_sanity_check		= mptscsih_sanity_check,
+-	.dump_poll			= mptscsih_poll,
+-};
+-
+-/**
+- * mptsas_remove
+- *
+- *
+- * @pdev
+- *
+- **/
+-static void __devexit mptsas_remove(struct pci_dev *pdev)
+-{
+-#if defined(CPQ_CIM)
+-	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+-  if(ioc->sh != NULL)
+-	mptsas_del_device_components(ioc);
+-#endif
+-
+-	flush_scheduled_work();
+-	mptscsih_remove(pdev);
+-}
+-
+-/**
+- * mptsas_target_reset
+- *
+- * Issues TARGET_RESET to end device using handshaking method
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- * Returns (1) success
+- *         (0) failure
+- *
+- **/
+-static int
+-mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-	MPT_FRAME_HDR	*mf;
+-	SCSITaskMgmt_t	*pScsiTm;
+-
+-	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+-		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
+-		    ioc->name,__FUNCTION__, __LINE__));
+-		return 0;
+-	}
+-
+-	/* Format the Request
+-	 */
+-	pScsiTm = (SCSITaskMgmt_t *) mf;
+-	memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+-	pScsiTm->TargetID = id;
+-	pScsiTm->Bus = channel;
+-	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+-	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+-	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+-
+-// EDM	printk("tm target reset : issue : channel=%d id=%d\n", channel, id);
+-	DBG_DUMP_TM_REQUEST_FRAME(mf);
+-
+-	if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
+-	    sizeof(SCSITaskMgmt_t), (u32 *)mf, 10,NO_SLEEP)) {
+-		mpt_free_msg_frame(ioc, mf);
+-		dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
+-		    ioc->name,__FUNCTION__, __LINE__));
+-		return 0;
+-	}
+-
+-	return 1;
+-}
+-
+-/**
+- * mptsas_target_reset_queue
+- *
+- * Receive request for TARGET_RESET after recieving an firmware
+- * event NOT_RESPONDING_EVENT, then put command in link list
+- * and queue if task_queue already in use.
+- *
+- * @ioc
+- * @sas_event_data
+- *
+- **/
+-static void
+-mptsas_target_reset_queue(MPT_ADAPTER *ioc,
+-    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+-{
+-	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-	VirtDevice *vdevice = NULL;
+-	struct mptscsih_target_reset	*target_reset_list;
+-	u8		id, channel;
+-
+-	id = sas_event_data->TargetID;
+-	channel = sas_event_data->Bus;
+-
+-	if (!(vdevice = mptsas_find_vdevice(ioc, channel, id)))
+-		return;
+-
+-	vdevice->tflags |= MPT_TARGET_FLAGS_DELETED;
+-
+-	target_reset_list = kmalloc(sizeof(*target_reset_list),
+-	    GFP_ATOMIC);
+-	if (!target_reset_list) {
+-		dfailprintk((MYIOC_s_WARN_FMT
+-			"%s, failed to allocate mem @%d..!!\n",
+-		    ioc->name,__FUNCTION__, __LINE__));
+-		return;
+-	}
+-
+-	memset(target_reset_list, 0, sizeof(*target_reset_list));
+-// EDM	printk("tm target reset : queue : channel=%d id=%d\n", channel, id);
+-
+-	memcpy(&target_reset_list->sas_event_data, sas_event_data,
+-		sizeof(*sas_event_data));
+-	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
+-
+-	if (hd->resetPending)
+-		return;
+-
+-	if (mptsas_target_reset(ioc, channel, id)) {
+-		target_reset_list->target_reset_issued = 1;
+-		hd->resetPending = 1;
+-	}
+-}
+-
+-/**
+- * mptsas_dev_reset_complete
+- *
+- * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
+- * enable work queue to finish off removing device from upper layers.
+- * then send next TARGET_RESET in the queue.
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+-{
+-	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-        struct list_head *head = &hd->target_reset_list;
+-	struct mptscsih_target_reset	*target_reset_list;
+-	struct mptsas_hotplug_event *ev;
+-	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+-	u8		id, channel;
+-	u64		sas_address;
+-
+-	if (list_empty(head))
+-		return;
+-
+-	target_reset_list = list_entry(head->next,
+-	    struct mptscsih_target_reset, list);
+-
+-	sas_event_data = &target_reset_list->sas_event_data;
+-	id = sas_event_data->TargetID;
+-	channel = sas_event_data->Bus;
+-	hd->resetPending = 0;
+-
+-	/*
+-	 * retry target reset
+-	 */
+-	if (!target_reset_list->target_reset_issued) {
+-		if (mptsas_target_reset(ioc, channel, id)) {
+-			target_reset_list->target_reset_issued = 1;
+-			hd->resetPending = 1;
+-		}
+-		return;
+-	}
+-
+-// EDM	printk("tm target reset : complete : channel=%d id=%d\n", channel, id);
+-
+-	/*
+-	 * enable work queue to remove device from upper layers
+-	 */
+-	list_del(&target_reset_list->list);
+-
+-	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+-	if (!ev) {
+-		dfailprintk((MYIOC_s_WARN_FMT
+-		    "%s, failed to allocate mem @%d..!!\n",
+-		    ioc->name,__FUNCTION__, __LINE__));
+-		return;
+-	}
+-
+-	memset(ev, 0, sizeof(*ev));
+-	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+-	ev->ioc = ioc;
+-	ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+-	ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+-	ev->channel = channel;
+-	ev->id = id;
+-	ev->phy_id = sas_event_data->PhyNum;
+-	memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(u64));
+-	ev->sas_address = le64_to_cpu(sas_address);
+-	ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+-	ev->event_type = MPTSAS_DEL_DEVICE;
+-	schedule_work(&ev->work);
+-	kfree(target_reset_list);
+-
+-	/*
+-	 * issue target reset to next device in the queue
+-	 */
+-
+-	head = &hd->target_reset_list;
+-	if (list_empty(head))
+-		return;
+-
+-	target_reset_list = list_entry(head->next, struct mptscsih_target_reset,
+-	    list);
+-
+-	sas_event_data = &target_reset_list->sas_event_data;
+-	id = sas_event_data->TargetID;
+-	channel = sas_event_data->Bus;
+-
+-	if (mptsas_target_reset(ioc, channel, id)) {
+-		target_reset_list->target_reset_issued = 1;
+-		hd->resetPending = 1;
+-	}
+-}
++	.slave_configure		= mptscsih_slave_configure,
++	.slave_destroy			= mptscsih_slave_destroy,
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
++	.change_queue_depth 		= mptscsih_change_queue_depth,
++#endif
++	.eh_abort_handler		= mptscsih_abort,
++	.eh_device_reset_handler	= mptscsih_dev_reset,
++	.eh_bus_reset_handler		= mptscsih_bus_reset,
++	.eh_host_reset_handler		= mptscsih_host_reset,
++	.bios_param			= mptscsih_bios_param,
++	.can_queue			= MPT_FC_CAN_QUEUE,
++	.this_id			= -1,
++	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
++	.max_sectors			= 8192,
++	.cmd_per_lun			= 7,
++	.use_clustering			= ENABLE_CLUSTERING,
++	.shost_attrs			= mptsas_host_attrs,
++	.dump_sanity_check		= mptscsih_sanity_check,
++	.dump_poll			= mptscsih_poll,
++};
+ 
+-/**
+- * mptsas_taskmgmt_complete
+- *
+- * @ioc
+- * @mf
+- * @mr
+- *
+- **/
+-static int
+-mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
++static void __devexit mptsas_remove(struct pci_dev *pdev)
+ {
+-	mptsas_dev_reset_complete(ioc);
+-	return mptscsih_taskmgmt_complete(ioc, mf, mr);
++	flush_scheduled_work();
++	mptscsih_remove(pdev);
+ }
+ 
+-/**
+- * mptscsih_ioc_reset
+- *
+- * @ioc
+- * @reset_phase
+- *
+- **/
+-static int
+-mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
++static void
++mptsas_target_reset(MPT_ADAPTER *ioc, VirtDevice * vdevice)
+ {
+-        MPT_SCSI_HOST   *hd =NULL;
+-	struct mptscsih_target_reset	*target_reset_list, *n;
+-	int rc;
+-
+-        if ((ioc->sh != NULL) && (ioc->sh->hostdata != NULL))
+-              hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-
+-	rc = mptscsih_ioc_reset(ioc, reset_phase);
++	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ 
+-	if (reset_phase != MPT_IOC_POST_RESET)
+-		goto out;
+-
+-	if (ioc->bus_type != SAS)
+-		goto out;
+-       if(hd == NULL)
+-               goto out;
+-
+-
+-	if (list_empty(&hd->target_reset_list))
+-		goto out;
+-
+-	/* flush the target_reset_list */
+-	list_for_each_entry_safe(target_reset_list, n,
+-	    &hd->target_reset_list, list) {
+-		list_del(&target_reset_list->list);
+-		kfree(target_reset_list);
++	if (mptscsih_TMHandler(hd,
++	     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
++	     vdevice->bus_id, vdevice->target_id, 0, 0, 5) < 0) {
++		hd->tmPending = 0;
++		hd->tmState = TM_STATE_NONE;
++		printk(MYIOC_s_WARN_FMT
++	       "Error processing TaskMgmt id=%d TARGET_RESET\n",
++			ioc->name, vdevice->target_id);
+ 	}
+-
+- out:
+-	return rc;
+ }
+ 
+-
+ /****************************************************************************
+  * Supported hardware
+  */
+@@ -1092,13 +225,6 @@ static struct pci_device_id mptsas_pci_t
+ MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
+ 
+ 
+-/**
+- * mptscsih_sas_persist_clear_table
+- *
+- *
+- * @ioc
+- *
+- **/
+ static void
+ mptscsih_sas_persist_clear_table(void * arg)
+ {
+@@ -1107,52 +233,76 @@ mptscsih_sas_persist_clear_table(void * 
+ 	mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+ }
+ 
+-/**
+- * mptsas_hotplug_print
+- *
+- *
+- * @ioc
+- * @hot_plug_info
+- * @msg_string
+- *
+- **/
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* mptbase_sas_update_device_list -
++ * This is called from the work queue.
++ * Purpose is to called when a logical volume has been created, deleted,
++ * or status change.
++ * Since in SAS the phydisk can be moved to different location, we will need
++ * to refresh the device list by recreating it.
++ */
++static void
++mptscsih_sas_update_device_list(MPT_ADAPTER *ioc )
++{
++	sas_device_info_t *sasDevice, *pNext;
++
++	/*
++	 * Kill everything in the device list, then rediscover
++	 */
++	list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) {
++		list_del(&sasDevice->list);
++		kfree(sasDevice);
++		ioc->alloc_total -= sizeof (sas_device_info_t);
++	}
++
++	if (ioc->sasPhyInfo != NULL) {
++		kfree(ioc->sasPhyInfo);
++		ioc->sasPhyInfo = NULL;
++		ioc->alloc_total -=
++		    ioc->numPhys * sizeof (sas_phy_info_t);
++	}
++	ioc->numPhys = 0;
++
++	/*
++	 *  Rescsan list
++	 */
++	mpt_sas_get_info(ioc);
++}
++
+ static void
+ mptsas_hotplug_print(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info,  u32 lun, u8 * msg_string)
+ {
+-	char *ds;
++	char *ds = NULL;
+ 	u32 	id = hot_plug_info->id;
+-	u32 	channel = hot_plug_info->channel;
+ 
+-	if ( id >= ioc->DevicesPerBus ) {
+-		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-		    ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
++	if ( id > ioc->pfacts->MaxDevices ) {
++		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++		    ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+ 		return;
+ 	}
+ 
+-	if ( channel >= ioc->NumberOfBuses ) {
+-		printk(MYIOC_s_WARN_FMT
+-		    "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-		    ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-		return;
++	if (hot_plug_info->isRaid) {
++		printk(MYIOC_s_INFO_FMT
++		    "%s device, channel %d, id %d, lun %d\n",
++			ioc->name, msg_string,
++			hot_plug_info->channel,
++			id, lun);
++	} else {
++		if (hot_plug_info->device_info &
++		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
++			ds = "sas";
++		if (hot_plug_info->device_info &
++		    MPI_SAS_DEVICE_INFO_STP_TARGET)
++			ds = "stp";
++		if (hot_plug_info->device_info &
++		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++			ds = "sata";
++		printk(MYIOC_s_INFO_FMT
++		    "%s %s device, channel %d, id %d, lun %d,"
++		    "  phy %d\n", ioc->name, msg_string, ds,
++		    hot_plug_info->channel, id, lun,
++		    hot_plug_info->phy_id);
+ 	}
+-
+-	if (hot_plug_info->device_info &
+-	    MPI_SAS_DEVICE_INFO_SSP_TARGET)
+-		ds = "sas ";
+-	else if (hot_plug_info->device_info &
+-	    MPI_SAS_DEVICE_INFO_STP_TARGET)
+-		ds = "stp ";
+-	else if (hot_plug_info->device_info &
+-	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+-		ds = "sata ";
+-	else
+-		ds = "";
+-
+-	printk(MYIOC_s_INFO_FMT
+-	    "%s %sdevice, channel %d, id %d, lun %d,"
+-	    "  phy %d\n", ioc->name, msg_string, ds,
+-	    channel, id, lun,
+-	    hot_plug_info->phy_id);
+ }
+ 
+ /*
+@@ -1167,32 +317,20 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s
+ 	struct Scsi_Host *shost = ioc->sh;
+ 	unsigned long flags;
+ 	struct scsi_device *sdev;
+-	static VirtDevice *pTarget;
+ 	u32 channel, id;
++	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ 
+ 	id = hot_plug_info->id;
+-	channel = hot_plug_info->channel;
+-
+-	if ( id >= ioc->DevicesPerBus ) {
+-		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-		    ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
+-		return;
+-	}
+ 
+-	if ( channel >= ioc->NumberOfBuses ) {
+-		printk(MYIOC_s_WARN_FMT
+-		    "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-		    ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
++	if ( id > ioc->pfacts->MaxDevices ) {
++		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++		    ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+ 		return;
+ 	}
+ 
+-	pTarget = mptsas_find_vdevice(ioc, channel, id);
+-	if (!pTarget)
+-		return;
+-
+-	pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE;
+-
++	mptsas_target_reset(ioc, hd->Targets[id]);
+ 
++	channel = hot_plug_info->channel;
+ 	spin_lock_irqsave(shost->host_lock, flags);
+  restart:
+ 	list_for_each_entry(sdev, &shost->__devices, siblings) {
+@@ -1208,46 +346,26 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+ 
+-/**
+- * mptsas_add_device
+- *
+- *
+- * @ioc
+- * @hot_plug_info
+- *
+- **/
+ static void
+ mptsas_add_device(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info,
+     u32 lun)
+ {
+ 	u32 	channel, id;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+ 	struct scsi_device *sdev;
++#else
++        int 	error;
++#endif
+ 
+ 	id = hot_plug_info->id;
+ 
+-	if ( id >= ioc->DevicesPerBus ) {
+-		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-		    ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
++	if ( id > ioc->pfacts->MaxDevices ) {
++		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++		    ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+ 		return;
+ 	}
+ 
+ 	channel = hot_plug_info->channel;
+-	if ( channel >= ioc->NumberOfBuses ) {
+-		printk(MYIOC_s_WARN_FMT
+-		    "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-		    ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-		return;
+-	}
+-
+-	/*
+-	 * avoid adding a device that is already present
+-	 */
+-	sdev = scsi_device_lookup(ioc->sh, channel, id, lun);
+-	if (sdev) {
+-		scsi_device_put(sdev);
+-		return;
+-	}
+-
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+ 	sdev = scsi_add_device(ioc->sh, channel, id, lun);
+ 	if (!IS_ERR(sdev))
+@@ -1261,13 +379,6 @@ mptsas_add_device(MPT_ADAPTER *ioc, stru
+ #endif
+ }
+ 
+-/**
+- * scsilun_to_int
+- *
+- *
+- * @scsilun
+- *
+- **/
+ static int scsilun_to_int(struct scsi_lun *scsilun)
+ {
+ 	int i;
+@@ -1298,170 +409,56 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+ 	u32 		length, channel, id, lun, num_luns;
+ 	u8 		*data;
+ 	u32		retries;
+-	int 		rc;
++	int 		completion_code;
+ 
+ 	id = hot_plug_info->id;
+-	channel = hot_plug_info->channel;
+ 
+-	if ( id > ioc->DevicesPerBus ) {
+-		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-		    ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
+-		return;
+-	}
+-
+-	if ( channel >= ioc->NumberOfBuses ) {
+-		printk(MYIOC_s_WARN_FMT
+-		    "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-		    ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-		return;
+-	}
+-
+-	/*
+-	 * Integrated RAID doesn't support REPORT_LUNS, it will timeout
+-	 */
+-	if (ioc->raid_data.isRaid & (1 << id)) {
+-		mptsas_add_device(ioc, hot_plug_info, 0);
++	if ( id > ioc->pfacts->MaxDevices ) {
++		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++		    ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+ 		return;
+ 	}
+ 
+-	/* initialize REPORT_LUN params */
++	channel = hot_plug_info->channel;
+ 	lun = 0;
+-	lun_data_len = 0;
+-	lun_data = NULL;
+-	lunp = NULL;
+ 
+ 	/*
+-	 * Test Unit Ready
++	 * Integrated RAID doesn't support luns greater than 0
+ 	 */
+-	iocmd.cmd = TEST_UNIT_READY;
+-	iocmd.bus = channel;
+-	iocmd.id = id;
+-	iocmd.lun = lun;
+-	iocmd.flags = 0;
+-	iocmd.data_dma = -1;
+-	iocmd.data = NULL;
+-	iocmd.size = 0;
+-	dinitprintk((MYIOC_s_INFO_FMT "Sending TURs to channel=%d id=%d \n",
+-		ioc->name, channel, id));
+-	for (retries = 0; retries < mpt_cmd_retry_count; retries++) {
+-		if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+-			dinitprintk((MYIOC_s_INFO_FMT
+-			    "TUR: mptscsih_do_cmd failed\n",
+-			    ioc->name));
+-			goto tur_done;
+-		}
+-
+-		if (hd->pLocal == NULL) {
+-			dinitprintk((MYIOC_s_INFO_FMT "TUR: no pLocal\n",
+-			    ioc->name));
+-			goto tur_done;
+-		}
+-
+-		rc = hd->pLocal->completion;
+-		if (rc == MPT_SCANDV_GOOD) {
+-			dinitprintk((MYIOC_s_INFO_FMT "TUR: succeeded\n",
+-			    ioc->name));
+-			goto tur_done;
+-		} else if (rc == MPT_SCANDV_BUSY) {
+-			dinitprintk((MYIOC_s_INFO_FMT "TUR: BUSY\n",
+-				ioc->name));
+-		         msleep(1000);  /* sleep 1 second */
+-			continue;
+-		} else if (rc == MPT_SCANDV_SENSE) {
+-			u8 skey = hd->pLocal->sense[2] & 0x0F;
+-			u8 asc = hd->pLocal->sense[12];
+-			u8 ascq = hd->pLocal->sense[13];
+-			dinitprintk((MYIOC_s_INFO_FMT
+-			    "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+-			    ioc->name, skey, asc, ascq));
+-
+-			if (skey == UNIT_ATTENTION) {
+-				dinitprintk((MYIOC_s_INFO_FMT
+-				    "TUR: UNIT ATTENTION\n",
+-				    ioc->name));
+-				continue;
+-			} else if ((skey == NOT_READY) &&
+-			    (asc == 0x04)&&(ascq == 0x01)) {
+-				dinitprintk((MYIOC_s_INFO_FMT
+-				    "TUR: Becoming Ready\n",
+-				    ioc->name));
+-                                    msleep(1000);  /* sleep 1 second */
+-				continue;
+-			}
+-		}
++	if (hot_plug_info->isRaid) {
++		mptsas_add_device(ioc, hot_plug_info, lun);
++		return;
+ 	}
+ 
+- tur_done:
+-
+ 	lun_data_len = (MPT_LAST_LUN + 1) * sizeof(struct scsi_lun);
+ 	lun_data = pci_alloc_consistent(ioc->pcidev, lun_data_len,
+ 	    &lun_data_dma);
+ 	if (!lun_data)
+-		goto report_luns_done;
++		goto out;
+ 
+-	/*
+-	 * Report Luns
+-	 */
+ 	iocmd.cmd = REPORT_LUNS;
+ 	iocmd.data_dma = lun_data_dma;
+ 	iocmd.data = (u8 *)lun_data;
+ 	iocmd.size = lun_data_len;
++	iocmd.bus = channel;
++	iocmd.id = id;
++	iocmd.lun = lun;
+ 	iocmd.flags = 0;
+ 
+ 	/*
+-	 * While loop for 10 sec retrying REPORT_LUNS, this is done
++	 * While loop for 3 sec retrying REPORT_LUNS, this is done
+ 	 * because some devices return MPI_SCSI_STATUS_BUSY for several
+ 	 * seconds.
+ 	 */
+-	dinitprintk((MYIOC_s_INFO_FMT
+-	   "Sending REPORT_LUNS to channel=%d id=%d \n",
+-	    ioc->name, channel, id));
++//	for (retries = 0; retries < 3; retries++) {  /* EDM - TRY 10 */
+ 	for (retries = 0; retries < 10; retries++) {
+ 		memset(lun_data, 0, lun_data_len);
+-		if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+-			dinitprintk((MYIOC_s_INFO_FMT
+-			    "RL: mptscsih_do_cmd failed\n", ioc->name));
+-			goto report_luns_done;
+-		}
+-
+-		if (hd->pLocal == NULL) {
+-			dinitprintk((MYIOC_s_INFO_FMT "RL: no pLocal\n",
+-			    ioc->name));
+-			goto report_luns_done;
+-		}
+-
+-		rc = hd->pLocal->completion;
+-		if (rc == MPT_SCANDV_GOOD) {
+-			dinitprintk((MYIOC_s_INFO_FMT "RL: succeeded\n",
+-			    ioc->name));
+-			goto report_luns_done;
+-		} else if (rc == MPT_SCANDV_BUSY) {
+-			dinitprintk((MYIOC_s_INFO_FMT "RL: BUSY\n", ioc->name));
+-		        msleep(1000);
+-			continue;
+-		} else if (rc == MPT_SCANDV_SENSE) {
+-			u8 skey = hd->pLocal->sense[2] & 0x0F;
+-			u8 asc = hd->pLocal->sense[12];
+-			u8 ascq = hd->pLocal->sense[13];
+-			dinitprintk((MYIOC_s_INFO_FMT
+-			    "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name,
+-			    skey, asc, ascq));
+-
+-			if (skey == UNIT_ATTENTION) {
+-				dinitprintk((MYIOC_s_INFO_FMT
+-				   "RL: UNIT ATTENTION\n", ioc->name));
+-				continue;
+-			} else if ((skey == NOT_READY) &&
+-			    (asc == 0x04)&&(ascq == 0x01)) {
+-				dinitprintk((MYIOC_s_INFO_FMT
+-				    "RL: Becoming Ready\n", ioc->name));
+-				     msleep(1000);
+-                                     continue;
+-			}
+-		}
++		completion_code = mptscsih_do_cmd(hd, &iocmd);
++		if (!completion_code)
++			break;
++		msleep(1000);
+ 	}
+ 
+- report_luns_done:
+ 	/*
+ 	 * Attaching lun=0
+ 	 */
+@@ -1470,8 +467,6 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+ 	/*
+ 	 * Get the length from the first four bytes of lun_data.
+ 	 */
+-	if (!lun_data)
+-		goto out;
+ 	data = (u8 *)lun_data;
+ 	length = ((data[0] << 24) | (data[1] << 16) |
+ 	    (data[2] << 8) | (data[3] << 0));
+@@ -1501,91 +496,93 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+ 		    lun_data_dma);
+ }
+ 
+-/**
+- * mptsas_hotplug_work
+- *
+- *
+- * @hot_plug_info
+- *
+- **/
+ static void
+ mptsas_hotplug_work(void *arg)
+ {
+ 	struct mptsas_hotplug_event *hot_plug_info = arg;
+ 	MPT_ADAPTER 		*ioc = hot_plug_info->ioc;
+-	u32 			id, channel;
++	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
++	VirtDevice		*pTarget;
++	u32 			id = hot_plug_info->id;
+ 
+-	id = hot_plug_info->id;
+-	channel = hot_plug_info->channel;
+ 
+ 	dhotpprintk((MYIOC_s_WARN_FMT "Entering %s for channel=%d id=%d\n",
+-		ioc->name,__FUNCTION__, channel, id));
++		ioc->name,__FUNCTION__, 
++		hot_plug_info->channel, id));
++
++
++	if ( id > ioc->pfacts->MaxDevices ) {
++		printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++		    ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
++		return;
++	}
+ 
+ 	down(&ioc->hot_plug_semaphore);
+ 
+-	/* If there has been a change to raid, then we need to
+-	 * refresh the config raid data
+-	 */
+-	if (hot_plug_info->refresh_raid_config_pages)
+-		mpt_findImVolumes(ioc);
++	pTarget = hd->Targets[id];
++	dhotpprintk((MYIOC_s_WARN_FMT "hot_plug_info=%p ioc=%p hd=%p pTarget=%p\n",
++		    ioc->name, hot_plug_info, ioc, hd, pTarget));
+ 
+ 	switch  (hot_plug_info->event_type) {
+ 	case MPTSAS_DEL_DEVICE:
+-#if defined(CPQ_CIM)
+-		mptsas_del_device_component(ioc, channel, id);
+-		if (hot_plug_info->refresh_raid_config_pages)
+-			mptsas_add_device_component_hotspare(ioc);
+-#endif
+ 		dhotpprintk((MYIOC_s_WARN_FMT
+ 		    "MPTSAS_DEL_DEVICE: channel=%d id=%d\n",
+-		    ioc->name, channel, id));
++			ioc->name,
++			hot_plug_info->channel,
++			id));
++		if (pTarget == NULL) {
++			dhotpprintk((MYIOC_s_WARN_FMT
++			    "hot_plug id=%d not found in Targets array",
++				ioc->name,
++				id));
++			goto out;
++		}
++		pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE;
++		pTarget->tflags |= MPT_TARGET_FLAGS_DELETED;
+ 		mptsas_remove_target(ioc, hot_plug_info);
+ 		break;
+ 
+ 	case MPTSAS_ADD_DEVICE:
+-#if defined(CPQ_CIM)
+-		if (ioc->raid_data.isRaid & (1 << id))
+-			mptsas_add_device_component_ir(ioc, channel, id);
+-#endif
+ 		dhotpprintk((MYIOC_s_WARN_FMT
+ 		    "MPTSAS_ADD_DEVICE: channel=%d id=%d\n",
+-		    ioc->name, channel, id));
++			ioc->name,
++			hot_plug_info->channel,
++			id));
++		if (pTarget) {
++			dhotpprintk((MYIOC_s_WARN_FMT
++			    "hot_plug id=%d already in Targets array",
++				ioc->name,
++				id));
++			goto out;
++		}
+ 		mptsas_scan_target(ioc, hot_plug_info);
+ 		break;
+-#if defined(CPQ_CIM)
+-	case MPTSAS_ADD_INACTIVE_VOLUME:
+-		dhotpprintk((MYIOC_s_WARN_FMT
+-		    "MPTSAS_ADD_INACTIVE_VOLUME: channel=%d id=%d\n",
+-		    ioc->name, channel, id));
+-		mptsas_add_device_component_ir(ioc, channel, id);
+-		break;
+-	case MPTSAS_PHYSDISK_ADD:
+-		mptsas_add_device_component_single(ioc, channel, id);
+-		break;
+-#endif
+ 	default:
+ 		dhotpprintk((MYIOC_s_WARN_FMT
+-		    "Unknown hot_plug event_type=%x: channel=%d id=%d "
+-		    " skipping\n", ioc->name, hot_plug_info->event_type,
+-		    channel, id));
+-		goto out;
++		    "Unknown hot_plug event_type=%x: channel=%d id=%d\n",
++			ioc->name,
++			hot_plug_info->event_type,
++			hot_plug_info->channel,
++			id));
++		break;
++	}
++
++	/* If there has been a change to raid, then we need to
++	 * refresh the config raid data, and sas device link list
++	 */
++	if (hot_plug_info->isRaid) {
++		mpt_findImVolumes(ioc);
++		mptscsih_sas_update_device_list(ioc);
+ 	}
+ 
+  out:
+ 	dhotpprintk((MYIOC_s_WARN_FMT "%s: kfree hot_plug_info=%p\n",
+-	    ioc->name,__FUNCTION__, hot_plug_info));
++		    ioc->name,__FUNCTION__, hot_plug_info));
+ 	kfree(hot_plug_info);
+ 	up(&ioc->hot_plug_semaphore);
+ }
+ 
+-/**
+- * mptsas_send_sas_event
+- *
+- *
+- * @ioc
+- * @sas_event_data
+- *
+- **/
++
+ static void
+ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+ 		EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+@@ -1610,11 +607,8 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+ 	}
+ 
+ 	switch (sas_event_data->ReasonCode) {
+-	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+-		mptsas_target_reset_queue(ioc, sas_event_data);
+-		break;
+-
+ 	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
++	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+ 		ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ 		if (!ev) {
+ 			printk(KERN_WARNING "mptsas: lost hotplug event\n");
+@@ -1642,7 +636,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+ 			ev->event_type = MPTSAS_DEL_DEVICE;
+ 		schedule_work(&ev->work);
+ 		break;
+-
+ 	case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+ 	/*
+ 	 * Persistent table is full.
+@@ -1652,7 +645,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+ 		    (void *)ioc);
+ 		schedule_work(&ioc->mptscsih_persistTask);
+ 		break;
+-
+ 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+ 	/* TODO */
+ 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+@@ -1662,21 +654,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+ 	}
+ }
+ 
+-/**
+- * mptsas_send_raid_event
+- *
+- *
+- * @ioc
+- * @raid_event_data
+- *
+- **/
+ static void
+ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+ 		EVENT_DATA_RAID *raid_event_data)
+ {
+ 	struct mptsas_hotplug_event *ev;
+-	int status = le32_to_cpu(raid_event_data->SettingsStatus);
+-	int state = (status >> 8) & 0xff;
++	RAID_VOL0_STATUS * volumeStatus;
+ 
+ 	if (ioc->bus_type != SAS)
+ 		return;
+@@ -1688,13 +671,11 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+ 	}
+ 
+ 	memset(ev,0,sizeof(struct mptsas_hotplug_event));
++	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ 	ev->ioc = ioc;
+ 	ev->id = raid_event_data->VolumeID;
+-	ev->channel = raid_event_data->VolumeBus;
+-	ev->refresh_raid_config_pages = 1;
++	ev->isRaid=1;
+ 
+-	devtprintk((KERN_INFO MYNAM ": VolumeID=%d Reason=%x received\n",
+-	    ev->id, raid_event_data->ReasonCode));
+ 	switch (raid_event_data->ReasonCode) {
+ 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+ 		ev->event_type = MPTSAS_ADD_DEVICE;
+@@ -1702,24 +683,6 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+ 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+ 		ev->event_type = MPTSAS_DEL_DEVICE;
+ 		break;
+-	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+-		switch (state) {
+-		case MPI_PD_STATE_ONLINE:
+-		case MPI_PD_STATE_NOT_COMPATIBLE:
+-			ev->event_type = MPTSAS_PHYSDISK_ADD;
+-			break;
+-		case MPI_PD_STATE_MISSING:
+-		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
+-		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
+-		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+-			ev->event_type = MPTSAS_DEL_DEVICE;
+-			break;
+-		default:
+-			devtprintk((KERN_INFO MYNAM
+-			    ": ignoring this event! %d\n", __LINE__));
+-			return;
+-		}
+-		break;
+ 	case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+ 		ev->event_type = MPTSAS_DEL_DEVICE;
+ 		break;
+@@ -1727,68 +690,18 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+ 		ev->event_type = MPTSAS_ADD_DEVICE;
+ 		break;
+ 	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+-		switch (state) {
+-		case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+-		case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+-			ev->event_type = MPTSAS_DEL_DEVICE;
+-			break;
+-		case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+-		case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+-			ev->event_type = MPTSAS_ADD_DEVICE;
+-			break;
+-		default:
+-			devtprintk((KERN_INFO MYNAM
+-			    ": ignoring this event! %d\n", __LINE__));
+-			return;
+-		}
++		volumeStatus = (RAID_VOL0_STATUS *) &
++		    raid_event_data->SettingsStatus;
++		ev->event_type = (volumeStatus->State ==
++		    MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
++		    MPTSAS_DEL_DEVICE : MPTSAS_ADD_DEVICE;
+ 		break;
+ 	default:
+-		devtprintk((KERN_INFO MYNAM
+-		    ": ignoring this event! %d\n", __LINE__));
+-		return;
++		break;
+ 	}
+-	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ 	schedule_work(&ev->work);
+ }
+ 
+-#if defined(CPQ_CIM)
+-/*
+- * mptsas_send_ir2_event
+- *
+- * This handle exposing hidden disk when an inactive raid volume is added
+- */
+-static void
+-mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+-{
+-	struct mptsas_hotplug_event *ev;
+-
+-	if (ir2_data->ReasonCode !=
+-	    MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
+-		return;
+-
+-	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+-	if (!ev)
+-		return;
+-	memset(ev, 0, sizeof(*ev));
+-	ev->ioc = ioc;
+-	ev->id = ir2_data->TargetID;
+-	ev->channel = ir2_data->Bus;
+-	ev->refresh_raid_config_pages = 1;
+-	ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+-
+-	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+-	schedule_work(&ev->work);
+-};
+-#endif
+-
+-/**
+- * mptsas_event_process
+- *
+- *
+- * @ioc
+- * @reply
+- *
+- **/
+ static int
+ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+ {
+@@ -1803,16 +716,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
+ 
+ 	switch (event) {
+ 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+-#if defined(CPQ_CIM)
+-		ioc->csmi_change_count++;
+-#endif
+ 		mptsas_send_sas_event(ioc,
+ 			(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+ 		break;
+ 	case MPI_EVENT_INTEGRATED_RAID:
+-#if defined(CPQ_CIM)
+-		ioc->csmi_change_count++;
+-#endif
+ 		mptsas_send_raid_event(ioc,
+ 			(EVENT_DATA_RAID *)reply->Data);
+ 		break;
+@@ -1822,13 +729,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
+ 		    (void *)ioc);
+ 		schedule_work(&ioc->mptscsih_persistTask);
+ 		break;
+-#if defined(CPQ_CIM)
+-	case MPI_EVENT_IR2:
+-		ioc->csmi_change_count++;
+-		mptsas_send_ir2_event(ioc,
+-		    (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+-		break;
+-#endif
+ 	default:
+ 		rc = mptscsih_event_process(ioc, reply);
+ 		break;
+@@ -1855,13 +755,12 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	MPT_ADAPTER 		*ioc;
+ 	unsigned long		 flags;
+ 	int			 sz, ii;
++	int			 numSGE = 0;
++	int			 scale;
+ 	int			 ioc_cap;
+ 	u8			*mem;
+ 	int			error=0;
+ 	int			r;
+-#if defined(CPQ_CIM)
+-	struct mptsas_portinfo	*port_info;
+-#endif
+ 
+ 	if ((r = mpt_attach(pdev,id)) != 0)
+ 		return r;
+@@ -1874,27 +773,19 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	/*  Added sanity check on readiness of the MPT adapter.
+ 	 */
+ 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+-                 if(mpt_enable_deadioc_detect)
+-	             return 0;
+-                 else {
+-                  printk(MYIOC_s_WARN_FMT
+-                         "Skipping because it's not operational!\n", ioc->name);
+-                      error = -ENODEV;
+-               goto out_mptsas_probe;
+-                 }
++		printk(MYIOC_s_WARN_FMT
++		  "Skipping because it's not operational!\n",
++		  ioc->name);
++		error = -ENODEV;
++		goto out_mptsas_probe;
+ 	}
+ 
+ 	if (!ioc->active) {
+-	      if(mpt_enable_deadioc_detect)
+-                      return 0;
+-               else {
+-
+-              printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
++		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+ 		  ioc->name);
+ 		error = -ENODEV;
+ 		goto out_mptsas_probe;
+ 	}
+-     }
+ 
+ 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
+ 	 */
+@@ -1906,8 +797,9 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	}
+ 
+ 	if (!ioc_cap) {
+-		printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI "
+-		    "Initiator mode is NOT enabled!\n", ioc->name, ioc);
++		printk(MYIOC_s_WARN_FMT
++			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
++			ioc->name, ioc);
+ 		return 0;
+ 	}
+ 
+@@ -1915,8 +807,8 @@ mptsas_probe(struct pci_dev *pdev, const
+ 
+ 	if (!sh) {
+ 		printk(MYIOC_s_WARN_FMT
+-		    "Unable to register controller with SCSI subsystem\n",
+-		    ioc->name);
++			"Unable to register controller with SCSI subsystem\n",
++			ioc->name);
+ 		error = -1;
+ 		goto out_mptsas_probe;
+         }
+@@ -1939,19 +831,49 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	else
+ 		sh->can_queue = ioc->req_depth;
+ 	dinitprintk((MYIOC_s_INFO_FMT
+-	    "mpt_can_queue=%d req_depth=%d can_queue=%d\n",
+-	    ioc->name, mpt_can_queue, ioc->req_depth, sh->can_queue));
++		"mpt_can_queue=%d req_depth=%d can_queue=%d\n",
++		ioc->name, mpt_can_queue, ioc->req_depth,
++		sh->can_queue));
+ 
+-	sh->max_id = ioc->DevicesPerBus;
++	sh->max_id = ioc->pfacts->MaxDevices + 1;
+ 
+ 	sh->max_lun = MPT_LAST_LUN + 1;
+-	sh->max_channel = ioc->NumberOfBuses - 1;
++	sh->max_channel = 0;
+ 	sh->this_id = ioc->pfacts[0].PortSCSIID;
+ 
+ 	/* Required entry.
+ 	 */
+ 	sh->unique_id = ioc->id;
+-	sh->sg_tablesize = ioc->sg_tablesize;
++
++	/* Verify that we won't exceed the maximum
++	 * number of chain buffers
++	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
++	 * For 32bit SGE's:
++	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++	 *               + (req_sz - 64)/sizeof(SGE)
++	 * A slightly different algorithm is required for
++	 * 64bit SGEs.
++	 */
++	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++	if (sizeof(dma_addr_t) == sizeof(u64)) {
++		numSGE = (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	} else {
++		numSGE = 1 + (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	}
++
++	if (numSGE < sh->sg_tablesize) {
++		/* Reset this value */
++		dprintk((MYIOC_s_INFO_FMT
++		  "Resetting sg_tablesize to %d from %d\n",
++		  ioc->name, numSGE, sh->sg_tablesize));
++		sh->sg_tablesize = numSGE;
++	}
+ 
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	/* Set the pci device pointer in Scsi_Host structure.
+@@ -1968,7 +890,7 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	 * (with size equal to req_depth*PtrSz!)
+ 	 */
+ 	sz = ioc->req_depth * sizeof(void *);
+-	mem = kmalloc(sz, GFP_KERNEL);
++	mem = kmalloc(sz, GFP_ATOMIC);
+ 	if (mem == NULL) {
+ 		error = -ENOMEM;
+ 		goto out_mptsas_probe;
+@@ -1978,26 +900,25 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	hd->ScsiLookup = (struct scsi_cmnd **) mem;
+ 
+ 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+-	    ioc->name, hd->ScsiLookup, sz));
++		 ioc->name, hd->ScsiLookup, sz));
+ 
+-	for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-		/* Allocate memory for the device structures.
+-		 * A non-Null pointer at an offset
+-		 * indicates a device exists.
+-		 */
+-		sz = ioc->DevicesPerBus * sizeof(void *);
+-		mem = kmalloc(sz, GFP_KERNEL);
+-		if (mem == NULL) {
+-			error = -ENOMEM;
+-			goto out_mptsas_probe;
+-		}
++	/* Allocate memory for the device structures.
++	 * A non-Null pointer at an offset
++	 * indicates a device exists.
++	 * max_id = 1 + maximum id (hosts.h)
++	 */
++	sz = sh->max_id * sizeof(void *);
++	mem = kmalloc(sz, GFP_ATOMIC);
++	if (mem == NULL) {
++		error = -ENOMEM;
++		goto out_mptsas_probe;
++	}
+ 
+-		memset(mem, 0, sz);
+-		ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++	memset(mem, 0, sz);
++	hd->Targets = (VirtDevice **) mem;
+ 
+-		dinitprintk((KERN_INFO " For Bus=%d, Target_List=%p sz=%d\n",
+-		    ii, mem, sz));
+-	}
++	dprintk((KERN_INFO
++	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+ 
+ 	/* Clear the TM flags
+ 	 */
+@@ -2013,18 +934,13 @@ mptsas_probe(struct pci_dev *pdev, const
+ 	 */
+ 	hd->cmdPtr = NULL;
+ 
+-	/* Initialize this IOC's  timers
++	/* Initialize this SCSI Hosts' timers
+ 	 * To use, set the timer expires field
+-	 * and add_timer. Used for internally
+-         * generated commands.
++	 * and add_timer
+ 	 */
+-       init_timer(&hd->InternalCmdTimer);
+-       hd->InternalCmdTimer.data = (unsigned long) hd;
+-       hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-
+-       init_timer(&ioc->TMtimer);
+-       ioc->TMtimer.data = (unsigned long) ioc;
+-       ioc->TMtimer.function = mptscsih_TM_timeout;
++	init_timer(&hd->timer);
++	hd->timer.data = (unsigned long) hd;
++	hd->timer.function = mptscsih_timer_expired;
+ 
+ 	init_MUTEX(&ioc->hot_plug_semaphore);
+ 
+@@ -2038,50 +954,24 @@ mptsas_probe(struct pci_dev *pdev, const
+ 		    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
+ 	}
+ 
+-	ddvprintk((MYIOC_s_INFO_FMT "mpt_pq_filter %x mpt_pq_filter %x\n",
+-	    ioc->name, mpt_pq_filter, mpt_pq_filter));
++	ddvprintk((MYIOC_s_INFO_FMT
++		"mpt_pq_filter %x mpt_pq_filter %x\n",
++		ioc->name,
++		mpt_pq_filter,
++		mpt_pq_filter));
+ 
+ 	init_waitqueue_head(&hd->scandv_waitq);
+ 	hd->scandv_wait_done = 0;
+ 	hd->last_queue_full = 0;
+ 
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+-
+-	INIT_LIST_HEAD(&hd->target_reset_list);
+-
+-#if defined(CPQ_CIM)
+-	INIT_LIST_HEAD(&ioc->sas_device_info_list);
+-	init_MUTEX(&ioc->sas_device_info_mutex);
+-	port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+-	if (port_info && !mptsas_sas_io_unit_pg0(ioc, port_info))
+-		ioc->num_ports = port_info->num_phys;
+-	kfree(port_info);
+-#endif
+-
+ 	error = scsi_add_host (sh, &ioc->pcidev->dev);
+ 	if(error) {
+-		dprintk((KERN_ERR MYNAM "scsi_add_host failed\n"));
++		dprintk((KERN_ERR MYNAM
++		  "scsi_add_host failed\n"));
+ 		goto out_mptsas_probe;
+ 	}
+ 
+ 	scsi_scan_host(sh);
+-
+-#if defined(CPQ_CIM)
+-	/*
+-	 * Handling Inactive Volumes
+-	 */
+-	if (!ioc->ir_firmware ||
+-	    !ioc->raid_data.pIocPg2 ||
+-	    !ioc->raid_data.pIocPg2->NumActiveVolumes)
+-	return 0;
+-
+-	for (ii = 0; ii < ioc->raid_data.pIocPg2->NumActiveVolumes; ii++)
+-		mptsas_add_device_component_ir(ioc,
+-		    ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeBus,
+-		    ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID);
+-#endif
+-
+ 	return 0;
+ 
+ out_mptsas_probe:
+@@ -2122,17 +1012,17 @@ mptsas_init(void)
+ 	show_mptmod_ver(my_NAME, my_VERSION);
+ 
+ 	mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
+-	mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
++	mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+ 	mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
+ 
+ 	if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
+ 		devtprintk((KERN_INFO MYNAM
+-		    ": Registered for sas IOC event notifications\n"));
++		  ": Registered for sas IOC event notifications\n"));
+ 	}
+ 
+-	if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
++	if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+ 		dprintk((KERN_INFO MYNAM
+-		    ": Registered for IOC reset notifications\n"));
++		  ": Registered for IOC reset notifications\n"));
+ 	}
+ 
+ 	return pci_register_driver(&mptsas_driver);
+@@ -2151,11 +1041,11 @@ mptsas_exit(void)
+ 
+ 	mpt_reset_deregister(mptsasDoneCtx);
+ 	dprintk((KERN_INFO MYNAM
+-	    ": Deregistered for IOC reset notifications\n"));
++	  ": Deregistered for IOC reset notifications\n"));
+ 
+ 	mpt_event_deregister(mptsasDoneCtx);
+ 	dprintk((KERN_INFO MYNAM
+-	    ": Deregistered for IOC event notifications\n"));
++	  ": Deregistered for IOC event notifications\n"));
+ 
+ 	mpt_deregister(mptsasInternalCtx);
+ 	mpt_deregister(mptsasTaskCtx);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,166 +0,0 @@
+-/*
+- *  linux/drivers/message/fusion/mptsas.h
+- *      High performance SCSI + LAN / Fibre Channel device drivers.
+- *      For use with PCI chip/adapter(s):
+- *          LSIFC9xx/LSI409xx Fibre Channel
+- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+- *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
+- *
+- */
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*
+-    This program is free software; you can redistribute it and/or modify
+-    it under the terms of the GNU General Public License as published by
+-    the Free Software Foundation; version 2 of the License.
+-
+-    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.
+-
+-    NO WARRANTY
+-    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+-    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+-    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+-    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+-    solely responsible for determining the appropriateness of using and
+-    distributing the Program and assumes all risks associated with its
+-    exercise of rights under this Agreement, including but not limited to
+-    the risks and costs of program errors, damage to or loss of data,
+-    programs or equipment, and unavailability or interruption of operations.
+-
+-    DISCLAIMER OF LIABILITY
+-    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+-    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+-    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+-
+-    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-*/
+-
+-#ifndef MPTSAS_H_INCLUDED
+-#define MPTSAS_H_INCLUDED
+-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-
+-struct mptscsih_target_reset {
+-	struct list_head 	list;
+-	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+-	u8	target_reset_issued;
+-};
+-
+-enum mptsas_hotplug_action {
+-	MPTSAS_ADD_DEVICE,
+-	MPTSAS_DEL_DEVICE,
+-	MPTSAS_ADD_INACTIVE_VOLUME,
+-	MPTSAS_PHYSDISK_ADD,
+-};
+-
+-struct mptsas_hotplug_event {
+-	struct work_struct	work;
+-	MPT_ADAPTER		*ioc;
+-	enum mptsas_hotplug_action event_type;
+-	u64			sas_address;
+-	u32			channel;
+-	u32			id;
+-	u32			device_info;
+-	u16			handle;
+-	u16			parent_handle;
+-	u8			phy_id;
+-	u8			refresh_raid_config_pages;
+-};
+-
+-/*
+- * SAS topology structures
+- *
+- * The MPT Fusion firmware interface spreads information about the
+- * SAS topology over many manufacture pages, thus we need some data
+- * structure to collect it and process it for the SAS transport class.
+- */
+-
+-struct mptsas_devinfo {
+-	u16	handle;		/* unique id to address this device */
+-	u16	handle_parent;	/* unique id to address parent device */
+-	u16	handle_enclosure; /* enclosure identifier of the enclosure */
+-	u16	slot;		/* physical slot in enclosure */
+-	u8	phy_id;		/* phy number of parent device */
+-	u8	port_id;	/* sas physical port this device
+-				   is assoc'd with */
+-	u8	id;		/* logical target id of this device */
+-	u32	phys_disk_num;	/* phys disk id, for csmi-ioctls */
+-	u8	channel;	/* logical bus number of this device */
+-	u64	sas_address;    /* WWN of this device,
+-				   SATA is assigned by HBA,expander */
+-	u32	device_info;	/* bitfield detailed info about this device */
+-#if !defined(MPT_WIDE_PORT_API)
+-	u8	wide_port_enable;	/* when set, this is part of wide port*/
+-#endif
+-};
+-
+-/*
+- * Specific details on ports, wide/narrow
+- */
+-struct mptsas_portinfo_details{
+-#if !defined(MPT_WIDE_PORT_API)
+-	u8	port_id; 	/* port number provided to transport */
+-	u8	rphy_id; 	/* phy index used for reporting end device*/
+-	u32	device_info;	/* bitfield detailed info about this device */
+-#endif
+-	u16	num_phys;	/* number of phys beloing to this port */
+-	u64	phy_bitmask; 	/* this needs extending to support 128 phys */
+-	struct sas_rphy *rphy; /* rphy for end devices */
+-#if defined(MPT_WIDE_PORT_API)
+-	struct sas_port *port;	/* transport layer port object */
+-#endif
+-	struct scsi_target *starget;
+-	struct mptsas_portinfo *port_info;
+-};
+-
+-struct mptsas_phyinfo {
+-	u8	phy_id; 		/* phy index */
+-	u8	port_id; 		/* port number this phy is part of */
+-	u8	negotiated_link_rate;	/* nego'd link rate for this phy */
+-	u8	hw_link_rate; 		/* hardware max/min phys link rate */
+-	u8	programmed_link_rate;	/* programmed max/min phy link rate */
+-#if defined(MPT_WIDE_PORT_API)
+-	u8	sas_port_add_phy;	/* flag to request sas_port_add_phy*/
+-#endif
+-#if defined(CPQ_CIM)
+-	u8	change_count;		/* change count of the phy */
+-	u8	port_flags;		/* info wrt host sas ports */
+-#endif
+-	u32	phy_info;		/* various info wrt the phy */
+-	struct mptsas_devinfo identify;	/* point to phy device info */
+-	struct mptsas_devinfo attached;	/* point to attached device info */
+-	struct sas_phy *phy;
+-	struct mptsas_portinfo *portinfo;
+-	struct mptsas_portinfo_details * port_details;
+-};
+-
+-struct mptsas_portinfo {
+-	struct list_head list;
+-	u16		handle;		/* unique id to address this */
+-	u16		num_phys;	/* number of phys */
+-	struct mptsas_phyinfo *phy_info;
+-};
+-
+-struct mptsas_enclosure {
+-	u64	enclosure_logical_id;	/* The WWN for the enclosure */
+-	u16	enclosure_handle;	/* unique id to address this */
+-	u16	flags;			/* details enclosure management */
+-	u16	num_slot;		/* num slots */
+-	u16	start_slot;		/* first slot */
+-	u8	start_id;		/* starting logical target id */
+-	u8	start_channel;		/* starting logical channel id */
+-	u8	sep_id;			/* SEP device logical target id */
+-	u8	sep_channel;		/* SEP channel logical channel id */
+-};
+-
+-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-#endif
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c	2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 Exp $
+  */
+@@ -74,7 +74,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ 
+@@ -83,6 +82,13 @@ typedef struct _BIG_SENSE_BUF {
+ } BIG_SENSE_BUF;
+ 
+ #define OEM_TLR_COMMAND			0xC2
++#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
++#define MPT_SCANDV_DID_RESET		(0x00000001)
++#define MPT_SCANDV_SENSE		(0x00000002)
++#define MPT_SCANDV_SOME_ERROR		(0x00000004)
++#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
++#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
++#define MPT_SCANDV_FALLBACK		(0x00000020)
+ 
+ #define MPT_SCANDV_MAX_RETRIES		(10)
+ 
+@@ -116,37 +122,44 @@ typedef struct _dv_parameters {
+ int		mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+ static void	mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
+ int		mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
++
+ static int	mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
+ 				 SCSIIORequest_t *pReq, int req_idx);
+ static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
+ static void	mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+ static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
+-static int	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
+-int		mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout);
+-static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout);
++static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
++static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
++
++int		mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
++static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+ 
+ int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+ int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+-static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen);
+-static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56);
+-static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id);
+-static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus);
++
++static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
++static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
++static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
++static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
++static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
++static int	mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
++static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
+ int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+-void           mptscsih_InternalCmdTimer_expired(unsigned long data);
++void		mptscsih_timer_expired(unsigned long data);
+ static int	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
+ 
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
+ static void	mptscsih_domainValidation(void *hd);
+-static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id);
++static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
+ static void	mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
+-static int	mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int id);
+-static void    mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc);
++static int	mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
+ static void	mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
+-static MPT_FRAME_HDR * mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc);
+ static void	mptscsih_fillbuf(char *buffer, int size, int index, int width);
++static void	mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
+ #endif
+-static void	mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget);
++static void
++mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget);
+ 
+ void		mptscsih_remove(struct pci_dev *);
+ // This was changed in the 2.6.13 kernel
+@@ -169,6 +182,8 @@ int mptscsih_resume(struct pci_dev *pdev
+  */
+ static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
+ static int dvtaskQ_active = 0;
++static int dvtaskQ_release = 0;
++static struct work_struct	dvTaskQ_task;
+ #endif
+ 
+ 
+@@ -560,7 +575,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 	}
+ 
+ 	sc = hd->ScsiLookup[req_idx];
+-	hd->ScsiLookup[req_idx] = NULL;
+ 	if (sc == NULL) {
+ 		MPIHeader_t *hdr = (MPIHeader_t *)mf;
+ 
+@@ -575,10 +589,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 		mptscsih_freeChainBuffers(ioc, req_idx);
+ 		return 1;
+ 	}
+-	if ((unsigned char *)mf != sc->host_scribble) {
+-		mptscsih_freeChainBuffers(ioc, req_idx);
+-		return 1;
+-	}
+ 
+ 	sc->result = DID_OK << 16;		/* Set default reply as OK */
+ 	pScsiReq = (SCSIIORequest_t *) mf;
+@@ -601,12 +611,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 		u32	 xfer_cnt;
+ 		u16	 ioc_status;
+ 		u8	 scsi_state, scsi_status;
+-#ifdef MPT_DEBUG_ERROR
+-               u8       ii, skey, asc, ascq;
+-#endif
+-	        struct _MPT_DEVICE	*pMptTarget;
+-		VirtDevice	*pTarget;
+-		int	 bus, id;
++		VirtDevice		*pTarget;
++		int	 target;
+ 
+ 		ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+ 		scsi_state = pScsiReply->SCSIState;
+@@ -627,35 +633,18 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 			ioc_status = MPI_IOCSTATUS_SUCCESS;
+ 		}
+ 
+-#ifdef MPT_DEBUG_ERR
+-		if (ioc_status != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) {	/* 0x0043 */
+-			derrprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
+-				"IOCStatus=%04x SCSIState=%02x SCSIStatus=%02x\n"
+-				"resid=%d bufflen=%d xfer_cnt=%d\n",
+-				ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+-				ioc_status, scsi_state, scsi_status, sc->resid,
+-				sc->request_bufflen, xfer_cnt));
+-		}
+-#endif
++		dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
++			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
++			"resid=%d bufflen=%d xfer_cnt=%d\n",
++			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++			ioc_status, scsi_state, scsi_status, sc->resid,
++			sc->request_bufflen, xfer_cnt));
+ 
+-		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID){
++		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
+ 			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
+ 
+-#ifdef MPT_DEBUG_ERROR
+-                       skey = sc->sense_buffer[2];
+-                       asc  = sc->sense_buffer[12];
+-                       ascq = sc->sense_buffer[13];
+-                       derrprintk((MYIOC_s_WARN_FMT
+-                               "id=%d SenseKey:ASC:ASCQ = (%x:%02x:%02x) CDB:\n",
+-                               ioc->name, pScsiReq->TargetID,
+-                               skey, asc, ascq));
+-
+-                       for (ii=0; ii<pScsiReq->CDBLength; ii++) {
+-                               printk("%02x ", pScsiReq->CDB[ii]);
+-                       }
+-                       printk("\n");
+-#endif
+-  } else if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) {
++		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
++		    pScsiReply->ResponseInfo) {
+ 			printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+ 			"FCP_ResponseInfo=%08xh\n",
+ 			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+@@ -670,13 +659,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 			 * killing interrupt handler:-(
+ 			 */
+ 			sc->result = SAM_STAT_BUSY;
+-#ifdef MPT_DEBUG_FAIL
+-                       derrprintk((MYIOC_s_ERR_FMT
+-                               "id=%d MPI_IOCSTATUS_BUSY\n",
+-                               ioc->name, pScsiReq->TargetID));
+-//                     panic ("IOCSTATUS_BUSY!!!!!\n");
+-#endif
+-
+ 			break;
+ 
+ 		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */
+@@ -688,15 +670,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 			/* Spoof to SCSI Selection Timeout! */
+ 			sc->result = DID_NO_CONNECT << 16;
+ 
+-			bus = pScsiReq->Bus;
+-			id = pScsiReq->TargetID;
+-			if ( ioc->bus_type == SPI ) {
+-				if (hd->sel_timeout[id] < 0xFFFF)
+-					hd->sel_timeout[pScsiReq->TargetID]++;
+-			}
++			target = pScsiReq->TargetID;
++			if (hd->sel_timeout[target] < 0xFFFF)
++				hd->sel_timeout[pScsiReq->TargetID]++;
+ 
+-			pMptTarget = ioc->Target_List[bus];
+-			pTarget = (VirtDevice *)pMptTarget->Target[id];
++			pTarget = hd->Targets[target];
+ 
+ 			if ( pTarget ) {
+ 				if (pTarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
+@@ -710,8 +688,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 					} else {
+ 						SEPMsg = (SEPRequest_t *)mf;
+ 						SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+-						SEPMsg->Bus = pTarget->bus;
+-						SEPMsg->TargetID = pTarget->id;
++						SEPMsg->Bus = pTarget->bus_id;
++						SEPMsg->TargetID = pTarget->target_id;
+ 						SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
+ 						SEPMsg->SlotStatus = MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED;
+ 						pTarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
+@@ -726,24 +704,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
+ 			if ( ioc->bus_type == SAS ) {
+ 				u16	 status = le16_to_cpu(pScsiReply->IOCStatus);
+-				u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+-// 				sc->result = DID_RESET << 16;
+-				sc->result = DID_SOFT_ERROR << 16;
+ 				if (status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+-					if ((log_info & 0xFFFF0000) ==
+-						SAS_LOGINFO_NEXUS_LOSS) {
++					u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
++					log_info &= 0xFFFF0000;  /* mask subcodes */
++					dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n"
++			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh "
++			"loginfo=%08x\n"
++			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++			status, scsi_state, scsi_status, log_info));
++					if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+ 						sc->result = (DID_BUS_BUSY << 16);
++						break;
+ 					}
++				} else {
++					dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n"
++			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n",
++			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++			status, scsi_state, scsi_status));
+ 				}
+-				derrprintk((KERN_NOTICE "IOC_TERMINATED: "
+-					"ha=%d id=%d lun=%d "
+-					"IOCStatus=%04x SCSIState=%02x\n"
+-					"SCSIStatus=%02x LogInfo=%08x "
+-					"sc->result=%08x sc=%p\n",
+-					ioc->id, pScsiReq->TargetID,
+-					pScsiReq->LUN[1], status, scsi_state,
+-					scsi_status, log_info, sc->result, sc));
+-				break;
+ 			}  /* allow non-SAS & non-NEXUS_LOSS to drop into below code */
+ 
+ 		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
+@@ -775,7 +753,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 			} else {
+ 				sc->result = DID_SOFT_ERROR << 16;
+ 			}
+-//			derrprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
++//			dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+ 			printk("RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id);
+ 			break;
+ #else
+@@ -784,7 +762,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 				sc->result=DID_SOFT_ERROR << 16;
+ 			else /* Sufficient data transfer occurred */
+ 				sc->result = (DID_OK << 16) | scsi_status;
+-			derrprintk((KERN_NOTICE
++			dreplyprintk((KERN_NOTICE 
+ 			    "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+ 			break;
+ #endif
+@@ -804,9 +782,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 						sc->result = SAM_STAT_BUSY;
+ 					else
+ 						sc->result = DID_SOFT_ERROR << 16;
+- derrprintk((KERN_NOTICE " xfer_cnt=%d < sc->underflow=%d result=%08x\n",xfer_cnt, sc->underflow, sc->result));
+-
+-                                 }
++				}
+ 				if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
+ 					/* What to do?
+ 				 	*/
+@@ -818,6 +794,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 				}
+ 			}
+ 
++			dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
++					sc->underflow));
++			dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
+ 			/* Report Queue Full
+ 			 */
+ 			if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
+@@ -896,18 +875,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 			break;
+ 
+ 		}	/* switch(ioc_status) */
+-               if (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
+-                       derrprintk((KERN_NOTICE "ha=%d id=%d lun=%d "
+-                               "IOCStatus=%04x SCSIState=%02x\n"
+-                               "SCSIStatus=%02x "
+-                               "sc->result=%08x sc=%p\n",
+-                               ioc->id, pScsiReq->TargetID,
+-                               pScsiReq->LUN[1], ioc_status,
+-                               scsi_state, scsi_status, sc->result,
+-                               sc));
+-               }
+ 
+-              } /* end of address reply case */
++		dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
++	} /* end of address reply case */
+ 
+ 	/* Unmap the DMA buffers, if any. */
+ 	if (sc->use_sg) {
+@@ -918,7 +888,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+ 				sc->request_bufflen, sc->sc_data_direction);
+ 	}
+ 
+-	sc->host_scribble = NULL;
++	hd->ScsiLookup[req_idx] = NULL;
++
+ 	sc->scsi_done(sc);		/* Issue the command callback */
+ 
+ 	/* Free Chain buffers */
+@@ -945,9 +916,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS
+ 	int		 ii;
+ 	int		 max = ioc->req_depth;
+ 
+-
+-drsprintk((MYIOC_s_WARN_FMT ": %s entered\n",ioc->name, __FUNCTION__));
+-
++	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
+ 	for (ii= 0; ii < max; ii++) {
+ 		if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
+ 
+@@ -959,24 +928,8 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere
+ 			hd->ScsiLookup[ii] = NULL;
+ 
+ 			mf = MPT_INDEX_2_MFPTR(ioc, ii);
+-
+-/*                     drsprintk((MYIOC_s_WARN_FMT "flush mf=%p sc=%p\n",
+-                               ioc->name, mf, SCpnt));
+-                       DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf) */
+-
+-
+-			/* Free Chain buffers */
+-			mptscsih_freeChainBuffers(ioc, ii);
+-
+-			/* Free Message frames */
+-			mpt_free_msg_frame(ioc, mf);
+-
+-			if ((unsigned char *)mf != SCpnt->host_scribble) {
+-                     drsprintk(( "%s Skipping scsi_done mf=%p host_scribble=%p\n",
+-                         __FUNCTION__, mf, SCpnt->host_scribble));
+-
+-				continue;
+-			}
++			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
++					mf, SCpnt));
+ 
+ 			/* Set status, free OS resources (SG DMA buffers)
+ 			 * Do OS callback
+@@ -993,14 +946,20 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere
+ 					SCpnt->request_bufflen,
+ 					SCpnt->sc_data_direction);
+ 			}
+-                        SCpnt->result = (DID_BUS_BUSY << 16);
++			SCpnt->result = DID_RESET << 16;
+ 			SCpnt->host_scribble = NULL;
++
++			/* Free Chain buffers */
++			mptscsih_freeChainBuffers(ioc, ii);
++
++			/* Free Message frames */
++			mpt_free_msg_frame(ioc, mf);
++
+ 			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */
+ 		}
+ 	}
+ 
+-drsprintk((MYIOC_s_WARN_FMT ": %s exiting\n", ioc->name, __FUNCTION__));
+-
++	return;
+ }
+ 
+ /*
+@@ -1010,7 +969,7 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin
+  *		Do NOT access the referenced scsi_cmnd structure or
+  *		members. Will cause either a paging or NULL ptr error.
+  *	@hd: Pointer to a SCSI HOST structure
+- *	@id: target id
++ *	@target: target id
+  *	@lun: lun
+  *
+  *	Returns: None.
+@@ -1018,47 +977,43 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin
+  *	Called from slave_destroy.
+  */
+ static void
+-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint id, uint lun)
++mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+ {
+-	MPT_ADAPTER		*ioc = hd->ioc;
+ 	SCSIIORequest_t	*mf = NULL;
+ 	int		 ii;
+-	int		 max = ioc->req_depth;
++	int		 max = hd->ioc->req_depth;
+ 	struct scsi_cmnd *sc;
+ 
+-	dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d max %d\n",
+-			id, lun, max));
++	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
++			target, lun, max));
+ 
+ 	for (ii=0; ii < max; ii++) {
+ 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
+ 
+-			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
++			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
+ 
+ 			dsprintk(( "search_running: found (sc=%p, mf = %p)\n",
+ 					hd->ScsiLookup[ii], mf));
+ 			if (mf == NULL)
+ 				continue;
+-			dsprintk(( "search_running: found (sc=%p, mf = %p) id %d, lun %d \n",
++			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
+ 					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
+ 
+-			if ((mf->TargetID != ((u8)id)) || (mf->LUN[1] != ((u8) lun)))
++			if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
+ 				continue;
+ 
+ 			/* Cleanup
+ 			 */
+ 			hd->ScsiLookup[ii] = NULL;
+-			mptscsih_freeChainBuffers(ioc, ii);
+-			mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
+-			if ((unsigned char *)mf != sc->host_scribble) {
+-				continue;
+-			}
++			mptscsih_freeChainBuffers(hd->ioc, ii);
++			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+ 			if (sc->use_sg) {
+-				pci_unmap_sg(ioc->pcidev,
++				pci_unmap_sg(hd->ioc->pcidev,
+ 				(struct scatterlist *) sc->request_buffer,
+ 					sc->use_sg,
+ 					sc->sc_data_direction);
+ 			} else if (sc->request_bufflen) {
+-				pci_unmap_single(ioc->pcidev,
++				pci_unmap_single(hd->ioc->pcidev,
+ 					sc->SCp.dma_handle,
+ 					sc->request_bufflen,
+ 					sc->sc_data_direction);
+@@ -1068,8 +1023,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
+ 			sc->scsi_done(sc);
+ 		}
+ 	}
+-	dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d completed\n",
+-			id, lun));
++	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d completed\n",
++			target, lun));
+ 	return;
+ }
+ 
+@@ -1169,66 +1124,9 @@ mptscsih_sendIOCInit(MPT_SCSI_HOST *hd)
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*	mptscsih_TM_timeout - Call back for timeout on a
+- *	task management request.
+- *	@data: Pointer to MPT_ADAPTER recast as an unsigned long
+- *
+- */
+-void mptscsih_TM_timeout(unsigned long data)
+-{
+-	MPT_ADAPTER	*ioc=(MPT_ADAPTER *)data;
+-	MPT_SCSI_HOST	*hd =(MPT_SCSI_HOST *)ioc->sh->hostdata;
+-	int		 retval;
+-	u32              ioc_state;
+-
+-	dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_TM_timeout: "
+-		   "TM request timed out!\n", ioc->name));
+-
+-	/* Delete the timer that triggered this callback.
+-	 * Remark: DEL_TIMER checks to make sure timer is active
+-	 * before deleting.
+-	 */
+-	del_timer(&ioc->TMtimer);
+-
+-	mpt_free_msg_frame(ioc, ioc->tmPtr);
+-
+-	ioc->tmPtr = NULL;
+-
+-	dtmprintk((MYIOC_s_WARN_FMT "%s: Calling mpt_SendIocReset MUR!\n",
+-		ioc->name, __FUNCTION__));
+-	if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP)) != 0) {
+-		ioc_state = mpt_GetIocState(ioc, 0);
+-		dfailprintk((MYIOC_s_WARN_FMT "%s: IOC MUR failed! ioc_state=%08x\n",
+-			ioc->name, __FUNCTION__, ioc_state));
+-//		panic ("IOC MUR Failed");
+-		ioc->IOCResetInProgress = 0;
+-
+-		if ((retval = mpt_HardResetHandler(ioc, NO_SLEEP)) < 0){
+-			printk(KERN_WARNING "%s: %s: HardResetHandler FAILED!!\n",
+-				ioc->name, __FUNCTION__);
+-		} else {
+-			dtmprintk((MYIOC_s_WARN_FMT "%s: HardResetHandler succeeded!!\n",
+-				ioc->name, __FUNCTION__));
+-		}
+-	} else {
+-		dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name));
+-		mptscsih_flush_running_cmds(hd);
+-		dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name));
+-		if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, NO_SLEEP)) != 0) {
+-			dfailprintk((MYIOC_s_ERR_FMT "%s: (%d) ioc_recovery failed\n", ioc->name, __FUNCTION__, retval));
+-		} else {
+-			dtmprintk((MYIOC_s_WARN_FMT "%s:Successful do_ioc_recovery! \n", ioc->name, __FUNCTION__));
+-		}
+-	}
+-	hd->TM_wait_done = 1;
+-	wake_up(&hd->TM_waitq);
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*	mptscsih_writeFCPortPage3  - write FC Port Page 3
+  *	@hd: Pointer to a SCSI Host Structure
+- *	@bus: write FC Port Page 3 for this bus
+- *	@id: write FC Port Page 3 for this target ID
++ *	@target_id: write FC Port Page 3 for this target ID
+  *
+  *	Return: -EAGAIN if unable to obtain a Message Frame
+  *		or 0 if success.
+@@ -1236,7 +1134,7 @@ void mptscsih_TM_timeout(unsigned long d
+  *	Remark: We do not wait for a return, write pages sequentially.
+  */
+ static int
+-mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int bus, int id)
++mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int target_id)
+ {
+ 	MPT_ADAPTER		*ioc = hd->ioc;
+ 	Config_t		*pReq;
+@@ -1247,7 +1145,6 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+ 	u32			 frameOffset;
+ 	u32			 flagsLength;
+ 	int			 ii;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+ 
+ 	/* Get a MF for this command.
+@@ -1287,10 +1184,9 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+        	pReq->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT |
+ 				MPI_CONFIG_PAGEATTR_PERSISTENT;
+ 	pReq->PageAddress = cpu_to_le32(MPI_FC_PORT_PGAD_FORM_INDEX |
+-					id);
++					target_id);
+ 
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
++	pTarget = hd->Targets[target_id];
+ 
+ 	FCPort3->Header.PageVersion = MPI_FCPORTPAGE3_PAGEVERSION;
+ 	FCPort3->Header.PageLength = sizeof(FCPortPage3_t) / 4;
+@@ -1299,8 +1195,8 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+ 				   MPI_CONFIG_PAGEATTR_PERSISTENT;
+        	FCPort3->Entry[0].PhysicalIdentifier.WWN.WWPN = pTarget->WWPN;
+        	FCPort3->Entry[0].PhysicalIdentifier.WWN.WWNN = pTarget->WWNN;
+-	FCPort3->Entry[0].TargetID = id;
+-	FCPort3->Entry[0].Bus = bus;
++       	FCPort3->Entry[0].TargetID = pTarget->target_id;
++       	FCPort3->Entry[0].Bus = pTarget->bus_id;
+ 	FCPort3->Entry[0].Flags = cpu_to_le16(MPI_PERSISTENT_FLAGS_ENTRY_VALID);
+ 
+ 	/* Add a SGE to the config request.
+@@ -1308,7 +1204,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+ 	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sizeof(FCPortPage3_t);
+ 	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+ 
+-	drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: bus=%d id=%d\n", ioc->name, , bus, id));
++	drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: target=%d\n", ioc->name, target_id));
+ 
+ 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+ 
+@@ -1320,7 +1216,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+  *	mptscsih_readFCDevicePage0 - returns FC Device Page 0 data
+  *	@ioc: Pointer to MPT_ADAPTER structure
+  *	@bus: bus id
+- *	@id: target id
++ *	@targetId: target id
+  *	@fcDevicePage: FC Device Page 0 data
+  *
+  *	Returns count of number bytes copied into @fcDevicePage
+@@ -1328,7 +1224,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+  */
+ 
+ int
+-mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 id, pFCDevicePage0_t fcDevicePage)
++mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage)
+ {
+ 	ConfigPageHeader_t	 hdr;
+ 	CONFIGPARMS		 cfg;
+@@ -1348,7 +1244,7 @@ mptscsih_readFCDevicePage0(MPT_ADAPTER *
+ 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ 	cfg.dir = 0;
+ 
+-	cfg.pageAddr = (bus << 8) + id + MPI_FC_DEVICE_PGAD_FORM_BUS_TID;
++	cfg.pageAddr = (bus << 8) + targetId + MPI_FC_DEVICE_PGAD_FORM_BUS_TID;
+ 	cfg.timeout = 0;
+ 
+ 	if ((rc = mpt_config(ioc, &cfg)) != 0)
+@@ -1436,16 +1332,15 @@ mptscsih_remove(struct pci_dev *pdev)
+ 		spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+ 	}
+ 	if (!count)
+-   printk(KERN_ERR MYNAM ": %s: ERROR - DV thread still active!\n",
+-            ioc->name);
+-#ifdef MPT_DEBUG_DV
++		printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
+ 	else
+-		printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", ioc->name,10 * HZ, count);
++		printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
+ #endif
+ #endif
+ 
+-	dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p MaxDevices=%d\n",
+-		ioc->name, ioc, hd, ioc->facts.MaxDevices));
++	dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p Targets=%p MaxDevices=%d\n", 
++		ioc->name, ioc, hd, hd->Targets, ioc->facts.MaxDevices));
+ // This was changed in the 2.6.13 kernel
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	mptscsih_shutdown(&pdev->dev);
+@@ -1453,19 +1348,19 @@ mptscsih_remove(struct pci_dev *pdev)
+ 	mptscsih_shutdown(pdev);
+ #endif
+ 
+-	dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n",
++	dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n", 
+ 		ioc->name, ioc, host));
+ 
+ 	scsi_remove_host(host);
+ 	dexitprintk((KERN_INFO MYNAM ": %s: scsi_remove_host completed\n", ioc->name));
+ 
+ 	if (hd->ScsiLookup != NULL) {
+-		sz1 = ioc->req_depth * sizeof(void *);
++		sz1 = hd->ioc->req_depth * sizeof(void *);
+ 		kfree(hd->ScsiLookup);
+ 		hd->ScsiLookup = NULL;
+ 		dprintk((MYIOC_s_INFO_FMT
+ 			"Free'd ScsiLookup (%d) memory\n",
+-			ioc->name, sz1));
++			hd->ioc->name, sz1));
+ 	}
+ 
+ 	if (hd->info_kbuf != NULL)
+@@ -1473,7 +1368,7 @@ mptscsih_remove(struct pci_dev *pdev)
+ 
+ 	/* NULL the Scsi_Host pointer
+ 	 */
+-	ioc->sh = NULL;
++	hd->ioc->sh = NULL;
+ 
+ 	scsi_host_put(host);
+ 
+@@ -1498,36 +1393,25 @@ mptscsih_shutdown(struct pci_dev *pdev)
+ {
+        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
+ #endif
+-	struct Scsi_Host 	*host;
++	struct Scsi_Host 	*host = ioc->sh;
+ 	MPT_SCSI_HOST		*hd;
+ 
+-	host = ioc->sh;
+-
+ 	if(!host)
+ 		return;
+ 
+ 	hd = (MPT_SCSI_HOST *)host->hostdata;
+ 
+-	dexitprintk((KERN_INFO MYNAM ": %s: ioc=%p hd=%p\n",
+-		__FUNCTION__, ioc, hd));
+-
+ 	/* Flush the cache of this adapter
+ 	 */
+-	if(hd != NULL) {
+-		dexitprintk((KERN_INFO MYNAM ": Calling mptscsih_synchronize_cache for %s\n",
+-			ioc->name));
++	if(hd != NULL)
+ 		mptscsih_synchronize_cache(hd, 0);
+-		dexitprintk((KERN_INFO MYNAM ": mptscsih_synchronize_cache for %s completed\n",
+-			ioc->name));
+-	}
+-	dexitprintk((KERN_INFO MYNAM ": %s done: ioc=%p hd=%p\n",
+-		__FUNCTION__, ioc, hd));
++
+ }
+ 
+ #ifdef CONFIG_PM
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+- *	mptscsih_suspend - Fusion MPT scsi driver suspend routine.
++ *	mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+  *
+  *
+  */
+@@ -1566,7 +1450,7 @@ mptscsih_resume(struct pci_dev *pdev)
+ 		return 0;
+ 
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-/*	{
++	{
+ 	unsigned long lflags;
+ 	spin_lock_irqsave(&dvtaskQ_lock, lflags);
+ 	if (!dvtaskQ_active) {
+@@ -1578,7 +1462,7 @@ mptscsih_resume(struct pci_dev *pdev)
+ 	} else {
+ 		spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
+ 	}
+-	} */
++	}
+ #endif
+ 	return 0;
+ }
+@@ -1732,13 +1616,10 @@ int
+ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+ {
+ 	MPT_SCSI_HOST		*hd;
+-	MPT_ADAPTER		*ioc;
+ 	MPT_FRAME_HDR		*mf;
+ 	SCSIIORequest_t		*pScsiReq;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+-        unsigned long 	         flags;
+-        int	 bus, id;
++	int	 target;
+ 	int	 lun;
+ 	u32	 datalen;
+ 	u32	 scsictl;
+@@ -1746,34 +1627,18 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
+ 	int	 my_idx;
+ 	int	 ii;
+ 
+-	/* EDM Debug */
+-//	mptscsih_scsi_print_command(SCpnt);
+-
+ 	hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+-	ioc = hd->ioc;
+-	bus = SCpnt->device->channel;
+-	id = SCpnt->device->id;
++	target = SCpnt->device->id;
+ 	lun = SCpnt->device->lun;
+ 	SCpnt->scsi_done = done;
+ 
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dfailprintk((MYIOC_s_WARN_FMT "qcmd, SCpnt=%p IOCResetInProgress!!\n",
+-                            ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-               goto fail;
+-       }
+-       spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
++	pTarget = hd->Targets[target];
+ 
+ 	if ( pTarget ) {
+ 		if ( lun > pTarget->last_lun ) {
+ 			dsprintk((MYIOC_s_INFO_FMT
+ 				"qcmd: lun=%d > last_lun=%d on id=%d\n",
+-				ioc->name, lun, pTarget->last_lun, id));
++				hd->ioc->name, lun, pTarget->last_lun, target));
+ 			SCpnt->result = DID_BAD_TARGET << 16;
+ 			SCpnt->scsi_done(SCpnt);
+ 			return 0;
+@@ -1782,31 +1647,32 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
+ 		 * allocated, use the Inquiry data to determine if device 
+ 		 * supports tagged.
+ 	 	*/
+-		if ( pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
++		if ( (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
++		    && (SCpnt->device->tagged_supported)) {
+ 			scsictl = MPI_SCSIIO_CONTROL_SIMPLEQ;
+-		 else
++		} else {
+ 			scsictl = MPI_SCSIIO_CONTROL_UNTAGGED;
++		}
+ 
+-	} else {
++	} else
+ 		scsictl = MPI_SCSIIO_CONTROL_UNTAGGED;
+-dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%02x id=%d lun=%d Null pTarget, sending Untagged\n",
+-                       ioc->name, SCpnt->cmnd[0], id, lun));
+-               if (ioc->bus_type == SPI) {
+-                       dnegoprintk(("writeSDP1: id=%d Async/Narrow\n",
+-                               id));
+-                       mpt_writeSDP1(ioc, 0, id, 0);
+-               }
++	dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
++			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
+ 
+- }
++	if (hd->resetPending) {
++		dfailprintk((MYIOC_s_INFO_FMT "QueueCmd, SCpnt=%p resetPending!!\n",
++				hd->ioc->name, SCpnt));
++		return SCSI_MLQUEUE_HOST_BUSY;
++	}
+ 
+ 	/*
+ 	 *  Put together a MPT SCSI request...
+ 	 */
+-	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
++	if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
+ 		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-		    ioc->name,__FUNCTION__));
+-	            goto fail;
+-               }
++		    hd->ioc->name,__FUNCTION__));
++		return SCSI_MLQUEUE_HOST_BUSY;
++	}
+ 
+ 	pScsiReq = (SCSIIORequest_t *) mf;
+ 
+@@ -1831,8 +1697,8 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+ 
+ 	/* Use the above information to set up the message frame
+ 	 */
+-	pScsiReq->TargetID = (u8) id;
+-	pScsiReq->Bus = (u8) bus;
++	pScsiReq->TargetID = (u8) target;
++	pScsiReq->Bus = (u8) SCpnt->device->channel;
+ 	pScsiReq->ChainOffset = 0;
+ 	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+ 	pScsiReq->CDBLength = SCpnt->cmd_len;
+@@ -1863,7 +1729,7 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+ 	pScsiReq->DataLength = cpu_to_le32(datalen);
+ 
+ 	/* SenseBuffer low address */
+-	pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
++	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+ 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
+ 
+ 	/* Now add the SG list
+@@ -1875,39 +1741,67 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+ 			(dma_addr_t) -1);
+ 	} else {
+ 		/* Add a 32 or 64 bit SGE */
+-		if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS){
+-                    mptscsih_freeChainBuffers(ioc, my_idx);
+-                    mpt_free_msg_frame(ioc, mf);
++		if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
+ 			goto fail;
+-                   }
+ 	}
+ 
+-       SCpnt->host_scribble = (unsigned char *)mf;
+-
+-       if (ioc->bus_type == SPI &&
+-               ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_IN_PROGRESS) {
+-               spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-               ioc->PendingMF = mf;
+-               ioc->PendingSCpnt = SCpnt;
+-               spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-               dpendprintk((KERN_INFO " qcmd: %s: DV In Progress id=%d mf=%p sc=%p into PendingMF\n",
+-                       ioc->name, id, mf, SCpnt));
+-               DBG_DUMP_REQUEST_FRAME(ioc, mf)
+-//             mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
+-               return 0;
+-}
+ 	hd->ScsiLookup[my_idx] = SCpnt;
++	SCpnt->host_scribble = NULL;
+ 
+-	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++	if (hd->ioc->bus_type == SPI) {
++		int dvStatus = hd->ioc->spi_data.dvStatus[target];
++		int issueCmd = 1;
++
++		if (dvStatus || hd->ioc->spi_data.forceDv) {
++
++			if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
++				(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
++				unsigned long lflags;
++				/* Schedule DV if necessary */
++				spin_lock_irqsave(&dvtaskQ_lock, lflags);
++				if (!dvtaskQ_active) {
++					dvtaskQ_active = 1;
++					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
++					INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
++
++					schedule_work(&dvTaskQ_task);
++				} else {
++					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
++				}
++				hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
++			}
++
++			/* Trying to do DV to this target, extend timeout.
++			 * Wait to issue until flag is clear
++			 */
++			if (dvStatus & MPT_SCSICFG_DV_PENDING) {
++				mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
++				issueCmd = 0;
++			}
++
++			/* Set the DV flags.
++			 */
++			if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
++				mptscsih_set_dvflags(hd, pScsiReq);
++
++			if (!issueCmd)
++				goto fail;
++		}
++	}
++#endif
++
++	mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
+ 	dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
+-			ioc->name, SCpnt, mf, my_idx));
+-	DBG_DUMP_REQUEST_FRAME(ioc,mf)
++			hd->ioc->name, SCpnt, mf, my_idx));
++	DBG_DUMP_REQUEST_FRAME(mf)
+ 	return 0;
+ 
+  fail:
+-       SCpnt->result = DID_BUS_BUSY << 16;
+-       SCpnt->scsi_done(SCpnt);
+-       return 0;
++	hd->ScsiLookup[my_idx] = NULL;
++	mptscsih_freeChainBuffers(hd->ioc, my_idx);
++	mpt_free_msg_frame(hd->ioc, mf);
++	return SCSI_MLQUEUE_HOST_BUSY;
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -1972,8 +1866,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
+  *
+  *	@ioc: Pointer to MPT_ADAPTER structure
+  *	@type: Task Management type
+- *	@bus: Logical Bus for reset (if appropriate)
+- *	@id: Logical Target ID for reset (if appropriate)
++ *	@target: Logical Target ID for reset (if appropriate)
+  *	@lun: Logical Unit for reset (if appropriate)
+  *	@ctx2abort: Context for the task to be aborted (if appropriate)
+  *
+@@ -1982,10 +1875,10 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
+  *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
+  *	will be active.
+  *
+- *	Returns 0 for SUCCESS.
++ *	Returns 0 for SUCCESS or -1 if FAILED.
+  */
+ int
+-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout)
++mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+ {
+ 	MPT_ADAPTER	*ioc;
+ 	int		 rc = -1;
+@@ -2000,15 +1893,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+ 		return 0;
+ 
+ 	ioc = hd->ioc;
+-
++	if (ioc == NULL) {
++		printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
++		return FAILED;
++	}
+ 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
+ 
+ 	// SJR - CHECKME - Can we avoid this here?
+ 	// (mpt_HardResetHandler has this check...)
+ 	spin_lock_irqsave(&ioc->diagLock, flags);
+- if (ioc->IOCResetInProgress) {
+-     dtmprintk((KERN_INFO MYNAM ": %s: TMHandler failing: "
+-                "IOCResetInProgress\n", ioc->name));
++	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
+ 		spin_unlock_irqrestore(&ioc->diagLock, flags);
+ 		return FAILED;
+ 	}
+@@ -2023,54 +1917,52 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+ 		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+ 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
+ 			   "Timed out waiting for last TM (%d) to complete! \n",
+-			   ioc->name, hd->tmPending));
++			   hd->ioc->name, hd->tmPending));
+ 			return FAILED;
+ 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
+ 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
+ 			   "Timed out waiting for last TM (%d) to complete! \n",
+-			   ioc->name, hd->tmPending));
++			   hd->ioc->name, hd->tmPending));
+ 			return FAILED;
+ 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
+ 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
+ 			   "Timed out waiting for last TM (%d) to complete! \n",
+-			   ioc->name, hd->tmPending));
++			   hd->ioc->name, hd->tmPending));
+ 			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
+ 				return FAILED;
+ 
+ 			doTask = 0;
+ 		}
+ 	} else {
+-		spin_lock_irqsave(&ioc->FreeQlock, flags);
++		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+ 		hd->tmPending |=  (1 << type);
+-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ 	}
+ 
+ 	/* Is operational?
+ 	 */
+-	ioc_raw_state = mpt_GetIocState(ioc, 0);
++	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
+ 
+ #ifdef MPT_DEBUG_RESET
+ 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
+ 		printk(MYIOC_s_WARN_FMT
+ 			"TM Handler: IOC Not operational(0x%x)!\n",
+-                ioc->name, ioc_raw_state);
+-               return FAILED;
+-//             panic ( "TMHandler: IOC Not operational!");
++			hd->ioc->name, ioc_raw_state);
+ 	}
+ #endif
+ 
+ 	if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
+ 				&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
+ 
+-		/* Issue the Task Mgmt request.
++		/* Isse the Task Mgmt request.
+ 		 */
+ 		if (hd->hard_resets < -1)
+ 			hd->hard_resets++;
+-		rc = mptscsih_IssueTaskMgmt(hd, type, bus, id, lun, ctx2abort, timeout);
++		rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
+ 		if (rc) {
+-			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", ioc->name);
++			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
+ 		} else {
+-			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", ioc->name));
++			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
+ 		}
+ 	}
+ 
+@@ -2079,21 +1971,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+ 	if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
+ 		ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
+ 		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+-			 ioc->name));
+-		rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
++			 hd->ioc->name));
++		rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+ 	}
+ 
+-    /*
+-     * Check IOCStatus from TM reply message
+-     */
+-	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
+-	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+-	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+-		rc = 0;
+-	else
+-		rc = FAILED;
+-
+-	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", ioc->name, rc));
++	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
+ 
+ 	return rc;
+ }
+@@ -2104,7 +1986,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+  *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
+  *	@hd: Pointer to MPT_SCSI_HOST structure
+  *	@type: Task Management type
+- *	@id: Logical Target ID for reset (if appropriate)
++ *	@target: Logical Target ID for reset (if appropriate)
+  *	@lun: Logical Unit for reset (if appropriate)
+  *	@ctx2abort: Context for the task to be aborted (if appropriate)
+  *
+@@ -2117,31 +1999,28 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+  *	else other non-zero value returned.
+  */
+ static int
+-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout)
++mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+ {
+-	MPT_ADAPTER		*ioc = hd->ioc;
+ 	MPT_FRAME_HDR	*mf;
+ 	SCSITaskMgmt_t	*pScsiTm;
+ 	int		 ii;
+ 	int		 retval;
+-	u32              ioc_state;
+-	unsigned long	 flags;
+ 
+ 	/* Return Fail to calling function if no message frames available.
+ 	 */
+-	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
++	if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
+ 		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-		    ioc->name,__FUNCTION__));
++		    hd->ioc->name,__FUNCTION__));
+ 		return FAILED;
+ 	}
+-	dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt request @ %p\n",
+-			ioc->name, mf));
++	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
++			hd->ioc->name, mf));
+ 
+ 	/* Format the Request
+ 	 */
+ 	pScsiTm = (SCSITaskMgmt_t *) mf;
+-	pScsiTm->TargetID = id;
+-	pScsiTm->Bus = bus;
++	pScsiTm->TargetID = target;
++	pScsiTm->Bus = channel;
+ 	pScsiTm->ChainOffset = 0;
+ 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+ 
+@@ -2161,52 +2040,31 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
+ 
+ 	pScsiTm->TaskMsgContext = ctx2abort;
+ 
+-	dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+-			ioc->name, ctx2abort, type));
++	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
++			hd->ioc->name, ctx2abort, type));
+ 
+ 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
+ 
+-	hd->TM_wait_done = 0;
+-	if ((retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
+-		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, timeout, CAN_SLEEP)) != 0) {
+-		dfailprintk((MYIOC_s_WARN_FMT "%s: send_handshake FAILED!\n",
+-			ioc->name, __FUNCTION__));
+-		mpt_free_msg_frame(ioc, mf);
+-
+-		dtmprintk((MYIOC_s_WARN_FMT "Calling mpt_SendIocReset MUR!\n",
+-			ioc->name));
+-		if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) != 0) {
+-			ioc_state = mpt_GetIocState(ioc, 0);
+-			dfailprintk((MYIOC_s_WARN_FMT "IOC MUR failed! ioc_state=%08x\n", ioc->name, ioc_state));
+-//			panic ("IOC MUR Failed");
+-			ioc->IOCResetInProgress = 0;
++	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
++		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
++		CAN_SLEEP)) != 0) {
++		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
++			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
++			hd->ioc, mf));
++		mpt_free_msg_frame(hd->ioc, mf);
++		return retval;
++	}
+ 
+-			if ((retval = mpt_HardResetHandler(ioc, CAN_SLEEP)) < 0){
+-				printk((KERN_WARNING " HardResetHandler FAILED!!\n"));			}
+-			else {
+-				dtmprintk((MYIOC_s_WARN_FMT " HardResetHandler succeeded!!\n", ioc->name));
+-			}
+-		} else {
+-			dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name));
+-			mptscsih_flush_running_cmds(hd);
+-			dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name));
+-			if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
+-				dfailprintk((MYIOC_s_ERR_FMT "- (%d) ioc_recovery failed\n", ioc->name, retval));
+-			} else {
+-				dtmprintk((MYIOC_s_WARN_FMT "Successful do_ioc_recovery! \n", ioc->name));
+-			}
+-		}
+-	} else {
+-		dtmprintk((MYIOC_s_WARN_FMT "%s: send_handshake SUCCESS!\n",
+-			ioc->name, __FUNCTION__));
+-		if (hd->TM_wait_done == 0) {
+-			wait_event(hd->TM_waitq, hd->TM_wait_done);
+-		}
++	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
++		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
++			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
++			hd->ioc, mf));
++		mpt_free_msg_frame(hd->ioc, mf);
++		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
++			 hd->ioc->name));
++		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+ 	}
+-	spin_lock_irqsave(&ioc->FreeQlock, flags);
+-	hd->tmPending = 0;
+-	hd->tmState = TM_STATE_NONE;
+-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++
+ 	return retval;
+ }
+ 
+@@ -2229,8 +2087,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
+ 	int		 scpnt_idx;
+ 	int		 retval;
+ 	int		 tm_timeout;
+-        unsigned long    flags;
+-	unsigned long	 sn = SCpnt->serial_number;
+ 
+ /* From the 2.6.13 kernels, they have removed calling
+  *	eh_threads with the host_lock in locked state
+@@ -2251,57 +2107,30 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
+ 	}
+ 
+ 	ioc = hd->ioc;
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dtmprintk((KERN_INFO ": %s: abort: "
+-                          "IOCResetInProgress (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-
++	if (hd->resetPending) {
+ 		return FAILED;
+ 	}
+ 
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+ 	if (hd->timeouts < -1)
+-
+ 		hd->timeouts++;
+ 
+-       printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
+-              ioc->name, SCpnt);
+-             scsi_print_command(SCpnt);
+-
+-//     printk(KERN_WARNING MYNAM ": %s: Delaying 30 seconds\n", ioc->name);
+-//     mdelay (30000);
+-       /* If this command is pended, then timeout/hang occurred
+-        * during DV. Post command and flush pending Q
+-        * and then following up with the reset request.
+-        */
+-       if ( (mf = mptscsih_search_PendingMF(ioc, SCpnt)) != NULL) {
+-               /* Cmd was in PendingMF.
+-                */
+-               dpendprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+-                          "Command was in PendingMF! (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               return SUCCESS;
+-       }
+-
+-
+-
+ 	/* Find this command
+ 	 */
+ 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
+ 		/* Cmd not found in ScsiLookup.
+ 		 * Do OS callback.
+ 		 */
+-//		SCpnt->result = DID_RESET << 16;
++		SCpnt->result = DID_RESET << 16;
+ 		dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+ 			   "Command not in the active list! (sc=%p)\n",
+-			   ioc->name, SCpnt));
++			   hd->ioc->name, SCpnt));
+ 		return SUCCESS;
+ 	}
+ 
++	printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
++	       hd->ioc->name, SCpnt);
++	scsi_print_command(SCpnt);
++
+ 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
+ 	 * (the IO to be ABORT'd)
+ 	 *
+@@ -2309,7 +2138,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 	 *	 swap it here either.  It is an opaque cookie to
+ 	 *	 the controller, so it does not matter. -DaveM
+ 	 */
+-	mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
++	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
+ 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
+ 
+ 	hd->abortSCpnt = SCpnt;
+@@ -2318,7 +2147,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 	spin_unlock_irq(host_lock);
+ #endif
+ 	/* set timeout in seconds */
+-	switch (ioc->bus_type) {
++	switch (hd->ioc->bus_type) {
+ 	case FC:
+ 		tm_timeout=40;
+ 		break;
+@@ -2327,7 +2156,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 		break;
+ 	case SPI:
+ 	default:
+-		tm_timeout=10;
++		tm_timeout=2;
+ 		break;
+ 	}
+ 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+@@ -2337,30 +2166,17 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 	spin_lock_irq(host_lock);
+ #endif
+ 
+-if (ioc->bus_type == FC) {
+-	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+-	    SCpnt->serial_number == sn) {
+-		dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+-			   "scpnt_idx=%08x sn=%lx (sc=%p)\n",
+-			   ioc->name, scpnt_idx, sn, SCpnt));
+-		retval = FAILED;
+-	}
+-}
+-
+ 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
+-		ioc->name,
++		hd->ioc->name,
+ 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+-       hd->ScsiLookup[scpnt_idx] = NULL;
+-//panic ("Task Abort completed");
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+ 
+ 	if (retval == 0)
+ 		return SUCCESS;
+ 
++	if(retval != FAILED ) {
++		hd->tmPending = 0;
++		hd->tmState = TM_STATE_NONE;
++	}
+ 	return FAILED;
+ }
+ 
+@@ -2377,10 +2193,8 @@ int
+ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
+ {
+ 	MPT_SCSI_HOST	*hd;
+-	MPT_ADAPTER	*ioc;
+-	int		id,retval;
++	int		 retval;
+ 	int		 tm_timeout;
+-        unsigned long    flags;
+ 
+ /* From the 2.6.13 kernels, they have removed calling
+  *	eh_threads with the host_lock in locked state
+@@ -2398,27 +2212,17 @@ mptscsih_dev_reset(struct scsi_cmnd * SC
+ 		return FAILED;
+ 	}
+ 
+-       ioc = hd->ioc;
+-       id = SCpnt->device->id;
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dtmprintk((KERN_INFO ": %s: target reset: "
+-                          "IOCResetInProgress (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-            return FAILED;
+-}
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
++	if (hd->resetPending)
++		return FAILED;
+ 
+ 	printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
+-	       ioc->name, SCpnt);
++	       hd->ioc->name, SCpnt);
+ 	scsi_print_command(SCpnt);
+ 
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	spin_unlock_irq(host_lock);
+ #endif
+-	switch (ioc->bus_type) {
++	switch (hd->ioc->bus_type) {
+ 	case FC:
+ 		tm_timeout=40;
+ 		break;
+@@ -2427,29 +2231,25 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+ 		break;
+ 	case SPI:
+ 	default:
+-		tm_timeout=10;
++		tm_timeout=5;
+ 		break;
+ 	}
+ 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+-	SCpnt->device->channel, id, 0, 0, tm_timeout);
++		SCpnt->device->channel, SCpnt->device->id,
++		0, 0, tm_timeout);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	spin_lock_irq(host_lock);
+ #endif
+ 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
+-		ioc->name,
++		hd->ioc->name,
+ 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-       if (retval == 0) {
+-               if (ioc->bus_type == SPI) {
+-                       dnegoprintk(("writeSDP1: id=%d USE_NVRAM\n",
+-                               id));
+-                       mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_USE_NVRAM);
+-               }
+-              return SUCCESS;
++
++	if (retval == 0)
++		return SUCCESS;
++
++	if(retval != FAILED ) {
++		hd->tmPending = 0;
++		hd->tmState = TM_STATE_NONE;
+ 	}
+ 	return FAILED;
+ }
+@@ -2467,10 +2267,8 @@ int
+ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
+ {
+ 	MPT_SCSI_HOST	*hd;
+-	MPT_ADAPTER	*ioc;
+ 	int		 retval;
+ 	int		 tm_timeout;
+-        unsigned long    flags;
+ 
+ /* From the 2.6.13 kernels, they have removed calling
+  *	eh_threads with the host_lock in locked state
+@@ -2488,9 +2286,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ 		return FAILED;
+ 	}
+ 
+-	ioc = hd->ioc;
+ 	printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
+-	       ioc->name, SCpnt);
++	       hd->ioc->name, SCpnt);
+ 	scsi_print_command(SCpnt);
+ 
+ 	if (hd->timeouts < -1)
+@@ -2500,7 +2297,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	spin_unlock_irq(host_lock);
+ #endif
+-	switch (ioc->bus_type) {
++	switch (hd->ioc->bus_type) {
+ 	case FC:
+ 		tm_timeout=40;
+ 		break;
+@@ -2509,7 +2306,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ 		break;
+ 	case SPI:
+ 	default:
+-		tm_timeout=10;
++		tm_timeout=5;
+ 		break;
+ 	}
+ 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+@@ -2519,20 +2316,17 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ #endif
+ 
+ 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
+-		ioc->name,
++		hd->ioc->name,
+ 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+ 
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-
+-
+ 	if (retval == 0)
+ 		return SUCCESS;
+ 
+-        return FAILED;
++	if(retval != FAILED ) {
++		hd->tmPending = 0;
++		hd->tmState = TM_STATE_NONE;
++	}
++	return FAILED;
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -2549,10 +2343,8 @@ int
+ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
+ {
+ 	MPT_SCSI_HOST *  hd;
+-	MPT_ADAPTER	*ioc;
+ 	int              status = SUCCESS;
+-        unsigned long    flags;
+-
++	int		 can_sleep;
+ /* From the 2.6.13 kernels, they have removed calling
+  *	eh_threads with the host_lock in locked state
+  */
+@@ -2560,6 +2352,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+ 	spinlock_t	*host_lock = SCpnt->device->host->host_lock;
+ #endif
+ 
++	can_sleep = crashdump_mode() ? NO_SLEEP : CAN_SLEEP;
++
+ 	/*  If we can't locate the host to reset, then we failed. */
+ 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
+ 		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
+@@ -2568,9 +2362,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+ 		return FAILED;
+ 	}
+ 
+-	ioc = hd->ioc;
+ 	printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
+-	       ioc->name, SCpnt);
++	       hd->ioc->name, SCpnt);
+ 
+ 	/*  If our attempts to reset the host failed, then return a failed
+ 	 *  status.  The host will be taken off line by the SCSI mid-layer.
+@@ -2578,78 +2371,26 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	MPT_HOST_UNLOCK(host_lock);
+ #endif
+-	if (mpt_HardResetHandler(ioc,
+-	    crashdump_mode() ? NO_SLEEP : CAN_SLEEP) < 0) {
+-dfailprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler failed\n", ioc->name));
+-
++	if (mpt_HardResetHandler(hd->ioc, can_sleep) < 0){
+ 		status = FAILED;
+ 	} else {
+-
+-dtmprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler succeeded\n", ioc->name));
+-        status = SUCCESS;
+-
++		/*  Make sure TM pending is cleared and TM state is set to
++		 *  NONE.
++		 */
++		hd->tmPending = 0;
++		hd->tmState = TM_STATE_NONE;
+ 	}
+-
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	MPT_HOST_LOCK(host_lock);
+ #endif
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-	return status;
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/* Search the pendingMF for a command with specific index.
+- * If found, delete and return mf pointer
+- * If not found, return NULL
+- */
+-static MPT_FRAME_HDR *
+-mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc)
+-{
+-	MPT_SCSI_HOST	*hd=(MPT_SCSI_HOST *) ioc->sh->hostdata;
+-	MPT_FRAME_HDR	*mf;
+-	unsigned long	 flags;
+-	u16		 req_idx;
+ 
+-	dpendprintk((MYIOC_s_WARN_FMT "%s entered\n",
+-		ioc->name, __FUNCTION__));
+-
+-	spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-	if ((mf=ioc->PendingMF) == NULL) {
+-		spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-		return NULL;
+-	}
++	dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
++		     "Status = %s\n",
++		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
+ 
+-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-	if (sc == hd->ScsiLookup[req_idx]) {
+-		ioc->PendingMF = NULL;
+-		spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-
+-		dpendprintk((MYIOC_s_WARN_FMT "%s: found mf=%p\n",
+-			ioc->name, __FUNCTION__, mf));
+-		DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf)
+-		/* Free Chain buffers */
+-		mptscsih_freeChainBuffers(ioc, req_idx);
+-		/* Free Message frames */
+-		mpt_free_msg_frame(ioc, mf);
+-		hd->ScsiLookup[req_idx] = NULL;
+-		sc->result = (DID_RESET << 16);
+-		sc->host_scribble = NULL;
+-		sc->scsi_done(sc);	/* Issue the command callback */
+-		dpendprintk(( "%s Executed scsi_done mf=%p sc=%p\n",
+-			__FUNCTION__, mf, sc));
+-		return mf;
+-	}
+-	spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-	dpendprintk((MYIOC_s_WARN_FMT "%s exiting mf=%p not in ScsiLookup\n",
+-		ioc->name, __FUNCTION__, mf));
+-	return NULL;
++	return status;
+ }
+ 
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *	mptscsih_tm_pending_wait - wait for pending task management request to
+@@ -2661,21 +2402,20 @@ mptscsih_search_PendingMF(MPT_ADAPTER *i
+ static int
+ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+ 	unsigned long  flags;
+ 	int            loop_count = 4 * 10;  /* Wait 10 seconds */
+ 	int            status = FAILED;
+ 
+ 	do {
+-		spin_lock_irqsave(&ioc->FreeQlock, flags);
++		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+ 		if (hd->tmState == TM_STATE_NONE) {
+ 			hd->tmState = TM_STATE_IN_PROGRESS;
+ 			hd->tmPending = 1;
+-			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ 			status = SUCCESS;
+ 			break;
+ 		}
+-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ 		msleep(250);
+ 	} while (--loop_count);
+ 
+@@ -2683,6 +2423,34 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST *
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/**
++ *	mptscsih_tm_wait_for_completion - wait for completion of TM task
++ *	@hd: Pointer to MPT host structure.
++ *
++ *	Returns {SUCCESS,FAILED}.
++ */
++static int
++mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
++{
++	unsigned long  flags;
++	int            loop_count = 4 * timeout;
++	int            status = FAILED;
++
++	do {
++		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
++		if(hd->tmPending == 0) {
++			status = SUCCESS;
++ 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
++			break;
++		}
++		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
++		msleep_interruptible(250);
++	} while (--loop_count);
++
++	return status;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static void
+ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
+ {
+@@ -2720,17 +2488,17 @@ mptscsih_taskmgmt_response_code(MPT_ADAP
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+- *      mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
+- *      @ioc: Pointer to MPT_ADAPTER structure
+- *      @mf: Pointer to SCSI task mgmt request frame
+- *      @mr: Pointer to SCSI task mgmt reply frame
+- *
+- *      This routine is called from mptbase.c::mpt_interrupt() at the completion
+- *      of any SCSI task management request.
+- *      This routine is registered with the MPT (base) driver at driver
+- *      load/init time via the mpt_register() API call.
++ *	mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
++ *	@ioc: Pointer to MPT_ADAPTER structure
++ *	@mf: Pointer to SCSI task mgmt request frame
++ *	@mr: Pointer to SCSI task mgmt reply frame
+  *
+- *      Returns 1 indicating alloc'd request frame ptr should be freed.
++ *	This routine is called from mptbase.c::mpt_interrupt() at the completion
++ *	of any SCSI task management request.
++ *	This routine is registered with the MPT (base) driver at driver
++ *	load/init time via the mpt_register() API call.
++ *
++ *	Returns 1 indicating alloc'd request frame ptr should be freed.
+  */
+ int
+ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+@@ -2739,26 +2507,27 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+ 	SCSITaskMgmt_t		*pScsiTmReq;
+ 	MPT_SCSI_HOST		*hd;
+ 	unsigned long		 flags;
+-	u16			 iocstatus = MPI_IOCSTATUS_SUCCESS;
++	u16			 iocstatus;
+ 	u8			 tmType;
+-	u32			 termination_count;
+ 
+ 	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
+ 			ioc->name, mf, mr));
++	if (ioc->sh) {
+ 		/* Depending on the thread, a timer is activated for
+ 		 * the TM request.  Delete this timer on completion of TM.
+ 		 * Decrement count of outstanding TM requests.
+ 		 */
+-	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-	if (ioc->tmPtr) {
+-		del_timer(&ioc->TMtimer);
+-		mpt_free_msg_frame(ioc, ioc->tmPtr);
+-		ioc->tmPtr = NULL;
++		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
++	} else {
++		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
++			ioc->name));
++		return 1;
+ 	}
+ 
+ 	if (mr == NULL) {
+-		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Turbo Reply: Request %p\n",
++		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
+ 			ioc->name, mf));
++		return 1;
+ 	} else {
+ 		pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
+ 		pScsiTmReq = (SCSITaskMgmt_t*)mf;
+@@ -2771,40 +2540,31 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+ 			mptscsih_taskmgmt_response_code(ioc,
+ 			    pScsiTmReply->ResponseCode);
+ 
+-		termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+-
+-		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x TerminationCount=%d\n",
+-			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo), termination_count));
++		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
++				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+ 		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+ 
++		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
++			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+ 		/* Error?  (anything non-zero?) */
+ 		if (iocstatus) {
+ 
+ 			/* clear flags and continue.
+ 			 */
+-			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+-				if (termination_count == 1) {
+-					iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
+-					dtmprintk((MYIOC_s_WARN_FMT "  SCSI Abort Task IOCStatus is now %04x\n",
+-						ioc->name, iocstatus));
+-				}
++			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+ 				hd->abortSCpnt = NULL;
+-			}
+ 
+ 			/* If an internal command is present
+ 			 * or the TM failed - reload the FW.
+ 			 * FC FW may respond FAILED to an ABORT
+ 			 */
+-			else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
++			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
+ 				if ((hd->cmdPtr) ||
+ 				    (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
+ 					if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
+ 						printk((KERN_WARNING
+ 							" Firmware Reload FAILED!!\n"));
+-						dfailprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset failed\n", ioc->name));
+-					} else {
+-						dtmprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset succeeded\n", ioc->name));
+ 					}
+ 				}
+ 			}
+@@ -2818,16 +2578,12 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+ 
+ 	spin_lock_irqsave(&ioc->FreeQlock, flags);
+ 	hd->tmPending = 0;
+-	hd->tm_iocstatus = iocstatus;
+-	hd->tmState = TM_STATE_NONE;
+ 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++	hd->tmState = TM_STATE_NONE;
+ 
+-	hd->TM_wait_done = 1;
+-	wake_up(&hd->TM_waitq);
+ 	return 1;
+ }
+ 
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  *	This is anyones guess quite frankly.
+@@ -2884,48 +2640,38 @@ mptscsih_slave_alloc(struct scsi_device 
+ {
+ 	struct Scsi_Host	*host = device->host;
+ 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+-	MPT_ADAPTER		*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+-	SpiCfgData             *pSpi;
+-        uint			bus=device->channel, id=device->id, lun=device->lun;
++	uint			target = device->id, lun = device->lun;
+ 	int			indexed_lun, lun_index;
+ 
++	if (hd == NULL)
++		return -ENODEV;
+ 
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
+-	dinitprintk((MYIOC_s_INFO_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d hd=%p pMptTarget=%p pTarget=%p\n",
+-		ioc->name, bus, id, lun, hd, pMptTarget, pTarget));
+-
+-	if (pTarget) {
+-		dinitprintk((MYIOC_s_ERR_FMT "slave_alloc: pTarget=%p already allocated!\n",
+-			ioc->name, pTarget));
++	if ((pTarget = hd->Targets[target]))
+ 		goto out;
+-	}
+ 
+ 	pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ 	if (!pTarget) {
+ 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+-			ioc->name, sizeof(VirtDevice));
++				hd->ioc->name, sizeof(VirtDevice));
+ 		return -ENOMEM;
+ 	}
+ 
++	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p\n",
++			hd->ioc->name, target, lun, pTarget));
+ 	memset(pTarget, 0, sizeof(VirtDevice));
+-if (ioc->bus_type != SPI)
+-        pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+-        pTarget->ioc = ioc;
+-        pTarget->id = id;
+-	pTarget->bus = bus;
++	pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
++	pTarget->ioc_id = hd->ioc->id;
++	pTarget->target_id = device->id;
++	pTarget->bus_id = device->channel;
+ 	pTarget->last_lun = MPT_LAST_LUN;
+-	pMptTarget->Target[id] = pTarget;
+-	if (ioc->bus_type == SPI) {
+-	         pSpi = &ioc->spi_data;
+-                 pSpi->dvStatus[id] |= (MPT_SCSICFG_NEED_DV |
+-                                         MPT_SCSICFG_DV_NOT_DONE);
+-
+-		if (ioc->raid_data.isRaid & (1 << device->id)) {
++	pTarget->raidVolume = 0;
++	pTarget->device = device;
++	hd->Targets[target] = pTarget;
++	if (hd->ioc->bus_type == SPI) {
++		if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
+ 			pTarget->raidVolume = 1;
+-			ddvprintk((KERN_INFO
++			ddvtprintk((KERN_INFO
+ 			    "RAID Volume @ id %d\n", device->id));
+ 		}
+ 	}
+@@ -2937,8 +2683,8 @@ out:
+ 	indexed_lun = (lun % 32);
+ 	pTarget->luns[lun_index] |= (1 << indexed_lun);
+ 
+-	dinitprintk((MYIOC_s_WARN_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d pTarget=%p num_luns=%d\n",
+-			ioc->name, bus, id, lun, pTarget, pTarget->num_luns));
++	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p num_luns=%d\n",
++			hd->ioc->name, target, lun, pTarget, pTarget->num_luns));
+ 	return 0;
+ }
+ 
+@@ -2951,24 +2697,20 @@ mptscsih_slave_destroy(struct scsi_devic
+ {
+ 	struct Scsi_Host	*host = device->host;
+ 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+-	MPT_ADAPTER		*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+-	uint			bus=device->channel, id=device->id, lun=device->lun;
++	uint			target = device->id, lun = device->lun;
+ 	int			indexed_lun, lun_index;
+ 
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
+-	if (pTarget == NULL) {
+-		printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p is NULL\n",
+-			ioc->name, bus, id, lun, pTarget);
++	if ((pTarget = hd->Targets[target]) == NULL) {
++		printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p is NULL\n",
++			hd->ioc->name, target, lun, pTarget);
+ 		return;
+ 	}
+-	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d type=%x pTarget=%p\n",
+-			ioc->name, bus, id, lun, pTarget->inq_data[0], pTarget));
++	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d type=%x pTarget=%p\n",
++			hd->ioc->name, target, lun, pTarget->inq_data[0], pTarget));
+ 
+-	if((ioc->bus_type == SPI) &&
+-		mptscsih_is_phys_disk(ioc, bus, id)) {
++	if((hd->ioc->bus_type == SPI) &&
++		mptscsih_is_phys_disk(hd->ioc, target)) {
+ 	; /* this target reset shouldn't be issued to hidden
+ 	   * phys disk in a raid volume.  The result would
+ 	   * kill domain validation on that disk; e.g. disk
+@@ -2984,41 +2726,38 @@ mptscsih_slave_destroy(struct scsi_devic
+ 	     */
+ 	}
+ 
+-	mptscsih_search_running_cmds(hd, id, lun);
++	mptscsih_search_running_cmds(hd, target, lun);
+ 
+ 	lun_index = (lun >> 5);  /* 32 luns per lun_index */
+ 	indexed_lun = (lun % 32);
+ 	pTarget->luns[lun_index] &= ~(1 << indexed_lun);
+ 
+ 	if (--pTarget->num_luns) {
+-		dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n",
+-			ioc->name, bus, id, lun, pTarget, pTarget->num_luns, pTarget->luns[0]));
++		dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n",
++			hd->ioc->name, target, lun, pTarget, pTarget->num_luns, pTarget->luns[0]));
+ 		return;
+ 	}
+ 
+-	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d freeing pTarget=%p\n",
+-			ioc->name, bus, id, lun, pTarget));
+-
+-	if (ioc->bus_type == SPI) {
+-		if (mptscsih_is_phys_disk(ioc, bus, id)) {
+-			ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+-    dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy PhysDisk bus=%d id=% d lun=%d pTarget=%p retained\n",ioc->name, bus, id, lun, pTarget));
+-
+-
++	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d freeing pTarget=%p\n",
++			hd->ioc->name, target, lun, pTarget));
++	kfree(pTarget);
++	hd->Targets[target] = NULL;
++
++	if (hd->ioc->bus_type == SPI) {
++		if (mptscsih_is_phys_disk(hd->ioc, target)) {
++			hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+ 		} else {
+-			ioc->spi_data.dvStatus[id] =
+-                (MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE);
+-                kfree(pTarget);
+-                pMptTarget->Target[id] = NULL;
+-                dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n",ioc->name, bus, id, lun, pTarget));
++			hd->ioc->spi_data.dvStatus[target] =
++				MPT_SCSICFG_NEGOTIATE;
+ 
++			if (!hd->negoNvram) {
++				hd->ioc->spi_data.dvStatus[target] |=
++					MPT_SCSICFG_DV_NOT_DONE;
++			}
+ 		}
+-}else {
+-kfree(pTarget);
+-pMptTarget->Target[id] = NULL;
+-dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n",
+-ioc->name, bus, id, lun, pTarget));
+-      }
++	}
++	dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p completed\n",
++			hd->ioc->name, target, lun, pTarget));
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -3033,34 +2772,29 @@ int
+ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ {
+ 	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+-	MPT_ADAPTER	*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice *pTarget;
+ 	int	max_depth;
+ 	int	tagged;
+ 
+-	pMptTarget = ioc->Target_List[sdev->channel];
+-	pTarget = pMptTarget->Target[sdev->id];
+-	if (pTarget == NULL)
++	if (!(pTarget = hd->Targets[sdev->id]))
+ 		return 0;
+ 
+-
+-       if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+-               if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+-                       max_depth = 1;
+-               else if (ioc->bus_type == SPI) {
+-                       if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
+-                                (pTarget->minSyncFactor <= MPT_ULTRA160 ))
++	if (hd->ioc->bus_type == SPI) {
++		if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
++			if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
++				max_depth = 1;
++			else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
++			         (pTarget->minSyncFactor <= MPT_ULTRA160 ))
+ 				max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+ 			else
+-			max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
++				max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
++		} else {
++			/* error case - No Inq. Data */
++			max_depth = 1;
++		}
++	} else
++		max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+ 
+-               } else
+-                       max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+-       } else {
+-               /* error case - No Inq. Data */
+-               max_depth = 1;
+-       }
+ 	if (qdepth > max_depth)
+ 		qdepth = max_depth;
+ 	if (qdepth == 1)
+@@ -3082,29 +2816,25 @@ int
+ mptscsih_slave_configure(struct scsi_device *device)
+ {
+ 	struct Scsi_Host	*sh = device->host;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+ 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
+-	MPT_ADAPTER		*ioc = hd->ioc;
+ 	int			rc;
+ 
+-       dinitprintk((MYIOC_s_INFO_FMT
+-               "%s: device @ %p, id=%d, LUN=%d, channel=%d\n",
+-               ioc->name, __FUNCTION__, device, device->id, device->lun,
+-               device->channel));
+-       dinitprintk((MYIOC_s_INFO_FMT
+-                "sdtr %d wdtr %d ppr %d inq length=%d\n",
+-		ioc->name, device->sdtr, device->wdtr,
++	dsprintk((MYIOC_s_INFO_FMT
++		"device @ %p, id=%d, LUN=%d, channel=%d\n",
++		hd->ioc->name, device, device->id, device->lun, device->channel));
++	dsprintk((MYIOC_s_INFO_FMT
++		"sdtr %d wdtr %d ppr %d inq length=%d\n",
++		hd->ioc->name, device->sdtr, device->wdtr,
+ 		device->ppr, device->inquiry_len));
+ 
+-	if (device->id >= ioc->DevicesPerBus) {
++	if (device->id > sh->max_id) {
+ 		/* error case, should never happen */
+ 		scsi_adjust_queue_depth(device, 0, 1);
+ 		goto slave_configure_exit;
+ 	}
+ 
+-	pMptTarget = ioc->Target_List[device->channel];
+-	pTarget = pMptTarget->Target[device->id];
++	pTarget = hd->Targets[device->id];
+ 
+ 	if (pTarget == NULL) {
+ 		/* Driver doesn't know about this device.
+@@ -3122,19 +2852,19 @@ mptscsih_slave_configure(struct scsi_dev
+ 		pTarget->configured_lun=1;
+ 
+ 	/* LUN persistancy support */
+-	if (ioc->bus_type == FC) {
++	if (hd->ioc->bus_type == FC) {
+ 		FCDevicePage0_t fcDevicePage;
+ 
+-		rc = mptscsih_readFCDevicePage0(ioc,
+-		    pTarget->bus, pTarget->id, &fcDevicePage);
++		rc = mptscsih_readFCDevicePage0(hd->ioc,
++		    pTarget->bus_id, pTarget->target_id, &fcDevicePage);
+ 
+ 		if (rc > offsetof(FCDevicePage0_t,PortIdentifier)) {
+ 			pTarget->WWPN = fcDevicePage.WWPN;
+ 			pTarget->WWNN = fcDevicePage.WWNN;
+ 
+ 			dsprintk((MYIOC_s_INFO_FMT
+-			"  bus=%d id=%d is WWPN = %08x%08x, WWNN = %08x%08x\n",
+-				ioc->name, pTarget->bus, pTarget->id,
++			"  target %d is WWPN = %08x%08x, WWNN = %08x%08x\n",
++				hd->ioc->name, pTarget->target_id,
+ 				le32_to_cpu(fcDevicePage.WWPN.High),
+ 				le32_to_cpu(fcDevicePage.WWPN.Low),
+ 				le32_to_cpu(fcDevicePage.WWNN.High),
+@@ -3147,19 +2877,19 @@ mptscsih_slave_configure(struct scsi_dev
+ 		device->inquiry, device->inquiry_len );
+ 	mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
+ 
+-	dinitprintk((MYIOC_s_INFO_FMT
++	dsprintk((MYIOC_s_INFO_FMT
+ 		"Queue depth=%d, tflags=%x\n",
+-		ioc->name, device->queue_depth, pTarget->tflags));
++		hd->ioc->name, device->queue_depth, pTarget->tflags));
+ 
+-	dinitprintk((MYIOC_s_INFO_FMT
++	dsprintk((MYIOC_s_INFO_FMT
+ 		"negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+-		ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
++		hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+ 
+ slave_configure_exit:
+ 
+-	dinitprintk((MYIOC_s_INFO_FMT
++	dsprintk((MYIOC_s_INFO_FMT
+ 		"tagged %d, simple %d, ordered %d\n",
+-		ioc->name,device->tagged_supported, device->simple_tags,
++		hd->ioc->name,device->tagged_supported, device->simple_tags,
+ 		device->ordered_tags));
+ 
+ 	return 0;
+@@ -3220,20 +2950,16 @@ mptscsih_poll(struct scsi_device *sdev)
+ static void
+ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice	*pTarget;
+ 	SCSIIORequest_t	*pReq;
+ 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
+-	int		 bus, id;
++	int		 target;
+ 
+ 	/* Get target structure
+ 	 */
+ 	pReq = (SCSIIORequest_t *) mf;
+-	bus = (int) pReq->Bus;
+-	id = (int) pReq->TargetID;
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
++	target = (int) pReq->TargetID;
++	pTarget = hd->Targets[target];
+ 
+ 	if (sense_count) {
+ 		u8 *sense_data;
+@@ -3241,15 +2967,15 @@ mptscsih_copy_sense_data(struct scsi_cmn
+ 
+ 		/* Copy the sense received into the scsi command block. */
+ 		req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-		sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
++		sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
+ 		memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
+-		DBG_DUMP_SENSE_DATA(sense_data);
+ 
+ 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
+ 		 */
+-		if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
++		if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
+ 			if ((sense_data[12] == 0x5D) && (pTarget->raidVolume == 0)) {
+ 				int idx;
++				MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 				idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
+ 				ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
+@@ -3287,21 +3013,19 @@ mptscsih_copy_sense_data(struct scsi_cmn
+ 		}
+ 	} else {
+ 		dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
+-				ioc->name));
++				hd->ioc->name));
+ 	}
+ }
+ 
+-static int
++static u32
+ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
+ {
+ 	MPT_SCSI_HOST *hd;
+-	MPT_ADAPTER	*ioc;
+ 	int i;
+ 
+ 	hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
+ 
+-	ioc = hd->ioc;
+-	for (i = 0; i < ioc->req_depth; i++) {
++	for (i = 0; i < hd->ioc->req_depth; i++) {
+ 		if (hd->ScsiLookup[i] == sc) {
+ 			return i;
+ 		}
+@@ -3315,10 +3039,8 @@ int
+ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+ {
+ 	MPT_SCSI_HOST	*hd;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice	*pTarget;
+ 	unsigned long	 flags;
+-	int 		bus, id, ii;
++	int 		ii;
+ 	int		n;
+ 
+ 	dtmprintk((KERN_INFO MYNAM
+@@ -3338,8 +3060,11 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+ 	if (reset_phase == MPT_IOC_SETUP_RESET) {
+ 		dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
+ 
+-                mptscsih_flush_running_cmds(hd);
+-                dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Complete\n", ioc->name));
++		/* Clean Up:
++		 * 1. Set Hard Reset Pending Flag
++		 * All new commands go to doneQ
++		 */
++		hd->resetPending = 1;
+ 
+ 	} else if (reset_phase == MPT_IOC_PRE_RESET) {
+ 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
+@@ -3358,41 +3083,28 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+ 		 * free these resources.
+ 		 */
+ 		if (hd->cmdPtr) {
+-			del_timer(&hd->InternalCmdTimer);
++			del_timer(&hd->timer);
+ 			mpt_free_msg_frame(ioc, hd->cmdPtr);
+-                        hd->cmdPtr = NULL;
+ 		}
+-               /* 2d. If a task management has not completed,
+-                * free resources associated with this request.
+-                */
+-               if (ioc->tmPtr) {
+-                       del_timer(&ioc->TMtimer);
+-                       mpt_free_msg_frame(ioc, ioc->tmPtr);
+-                       ioc->tmPtr = NULL;
+-               }
+ 
+-               dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
++		dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
+ 
+ 	} else {
+ 		dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
+ 
+ 		if (ioc->bus_type == FC) {
+ 			n = 0;
+-			for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-				pMptTarget = ioc->Target_List[bus];
+-				for (id=0; id < ioc->DevicesPerBus; id++) {
+-					pTarget = pMptTarget->Target[id];
+-					if (pTarget) {
+-						dsprintk((MYIOC_s_INFO_FMT
+-							"bus=%d id=%d is known to be WWPN %08x%08x, WWNN %08x%08x\n",
+-							ioc->name, bus, id,
+-							le32_to_cpu(pTarget->WWPN.High),
+-							le32_to_cpu(pTarget->WWPN.Low),
+-							le32_to_cpu(pTarget->WWNN.High),
+-							le32_to_cpu(pTarget->WWNN.Low)));
+-						mptscsih_writeFCPortPage3(hd, bus, id);
+-						n++;
+-					}
++			for (ii=0; ii < ioc->sh->max_id; ii++) {
++				if (hd->Targets && hd->Targets[ii]) {
++					dsprintk((MYIOC_s_INFO_FMT
++						"target %d is known to be WWPN %08x%08x, WWNN %08x%08x\n",
++						ioc->name, ii,
++						le32_to_cpu(hd->Targets[ii]->WWPN.High),
++						le32_to_cpu(hd->Targets[ii]->WWPN.Low),
++						le32_to_cpu(hd->Targets[ii]->WWNN.High),
++						le32_to_cpu(hd->Targets[ii]->WWNN.Low)));
++					mptscsih_writeFCPortPage3(hd, ii);
++					n++;
+ 				}
+ 			}
+ 
+@@ -3408,7 +3120,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+ 
+ 		/* ScsiLookup initialization
+ 		 */
+-		for (ii=0; ii < ioc->req_depth; ii++)
++		for (ii=0; ii < hd->ioc->req_depth; ii++)
+ 			hd->ScsiLookup[ii] = NULL;
+ 
+ 		/* 2. Chain Buffer initialization
+@@ -3417,19 +3129,17 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+ 		/* 4. Renegotiate to all devices, if SPI
+ 		 */
+ 		if (ioc->bus_type == SPI) {
+-                       dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS USE_NVRAM\n",
+-                               ioc->name, __FUNCTION__));
+-                       mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM));
+-
++			dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
++			mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
+ 		}
+ 
+ 		/* 5. Enable new commands to be posted
+ 		 */
+ 		spin_lock_irqsave(&ioc->FreeQlock, flags);
+ 		hd->tmPending = 0;
++		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++		hd->resetPending = 0;
+ 		hd->tmState = TM_STATE_NONE;
+-                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-
+ 
+ 		/* 6. If there was an internal command,
+ 		 * wake this process up.
+@@ -3448,9 +3158,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+ 		/* 7. Set flag to force DV and re-read IOC Page 3
+ 		 */
+ 		if (ioc->bus_type == SPI) {
+-ioc->spi_data.forceDv = MPT_SCSICFG_RELOAD_IOC_PG3;
+-ddvprintk(("Set reload IOC Pg3 Flag\n"));
+-
++			ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
++			ddvtprintk(("Set reload IOC Pg3 Flag\n"));
+ 		}
+ 
+ 		dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
+@@ -3468,13 +3177,9 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ {
+ 	MPT_SCSI_HOST *hd;
+ 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+-       struct _MPT_DEVICE      *pMptTarget;
+-       VirtDevice              *pTarget;
+-       int      physDiskNum, bus, id;
+-
+-       devtprintk((MYIOC_s_WARN_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+-                       ioc->name, event));
+ 
++	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
++			ioc->name, event));
+ 
+ 	if (ioc->sh == NULL ||
+ 		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+@@ -3508,53 +3213,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ 	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
+ 	{
++		pMpiEventDataRaid_t pRaidEventData =
++		    (pMpiEventDataRaid_t) pEvReply->Data;
+ 
+-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-                pMpiEventDataRaid_t pRaidEventData =
+-                (pMpiEventDataRaid_t) &pEvReply->Data;
+-
+-/* Domain Validation Needed */
++		/* Domain Validation Needed */
+ 		if (ioc->bus_type == SPI &&
+ 			pRaidEventData->ReasonCode ==
+ 			MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+-                         SpiCfgData      *pSpi;
+-                       physDiskNum = pRaidEventData->PhysDiskNum;
+-                       if (ioc->raid_data.pIocPg3) {
+-                               id = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskID;
+-                               bus = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskBus;
+-                               pMptTarget = ioc->Target_List[bus];
+-                               pTarget = (VirtDevice *)pMptTarget->Target[id];
+-                               ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                                       ioc->name, physDiskNum, bus, id, pTarget));
+-                       } else {
+-                               ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d but raid_data.pIocPg3 is NULL\n",
+-                                       ioc->name, physDiskNum));
+-                               break;
+-                       }
+-                       pSpi = &ioc->spi_data;
+-                       pSpi->dvStatus[id] |= (MPT_SCSICFG_PHYSDISK_DV_ONLY |
+-                                             MPT_SCSICFG_NEED_DV |
+-                                             MPT_SCSICFG_DV_NOT_DONE);
+-
+-                       if (pTarget == NULL) {
+- ddvprintk((KERN_WARNING " Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d but pTarget is NULL\n",
+-                                       physDiskNum, bus, id));
+-                               mptscsih_initTarget(hd, bus, id, 0,
+-                                       NULL, 0 );
+-                               pTarget = (VirtDevice *)pMptTarget->Target[id];
+- ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget%p now\n",
+-                                       ioc->name, physDiskNum, bus, id, pTarget));
+-                       }
+-                       pSpi->forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+- ddvprintk((KERN_WARNING "%s: Raid Event: Scheduling DV for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                               ioc->name, physDiskNum, bus, id, pTarget));
+- INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget);
+-                       schedule_work(&pTarget->dvTask);
+- ddvprintk((KERN_WARNING "%s: Raid Event: DV Scheduled for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                               ioc->name, physDiskNum, bus, id, pTarget));
+-#endif
+ 
+-	}
++			mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
++		}
+ 		break;
+ 	}
+ #endif
+@@ -3575,8 +3243,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ /*
+  *	mptscsih_initTarget - Target, LUN alloc/free functionality.
+  *	@hd: Pointer to MPT_SCSI_HOST structure
+- *	@bus: Bus number (?)
+- *	@id: SCSI target id
++ *	@bus_id: Bus number (?)
++ *	@target_id: SCSI target id
+  *	@lun: SCSI LUN id
+  *	@data: Pointer to data
+  *	@dlen: Number of INQUIRY bytes
+@@ -3589,17 +3257,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+  *
+  */
+ static void
+-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen)
++mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
+ {
+ 	int		indexed_lun, lun_index;
+ 	MPT_ADAPTER	*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice	*pTarget;
+ 	SpiCfgData	*pSpi;
+ 	char		data_56;
+ 
+-	dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
+-			ioc->name, bus, id, lun, hd));
++	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
++			ioc->name, bus_id, target_id, lun, hd));
+ 
+ 	/*
+ 	 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
+@@ -3610,71 +3277,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
+ 	 * around a bug in th emid-layer in some distributions in which the mid-layer will
+ 	 * continue to try to communicate to the LUN and evntually create a dummy LUN.
+ 	*/
+-	if (hd->mpt_pq_filter && dlen && (data[0] & 0x20))
++	if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
+ 		data[0] |= 0x40;
+ 
+ 	/* Is LUN supported? If so, upper 2 bits will be 0
+ 	* in first byte of inquiry data.
+ 	*/
++	if (data[0] & 0xe0)
++		return;
+ 
+-        if (dlen && (data[0] & 0xe0))
+-	return;
+-
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
+-       if (pTarget == NULL) {
+-               dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d pTarget is NULL\n"
+-,
+-                       ioc->name, bus, id, lun));
+-               pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+-               if (!pTarget) {
+-                       printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%zd) FAILED!\n",
+-                               ioc->name, sizeof(VirtDevice));
+-                       return;
+-               }
+-
+-               memset(pTarget, 0, sizeof(VirtDevice));
+-               if (ioc->bus_type != SPI)
+-                       pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+-               pTarget->ioc = ioc;
+-               pTarget->id = id;
+-               pTarget->bus = bus;
+-               pTarget->last_lun = MPT_LAST_LUN;
+-               pTarget->raidVolume = 0;
+-               pMptTarget->Target[id] = pTarget;
+-               if (ioc->bus_type == SPI) {
+-                       if (ioc->raid_data.isRaid & (1 << id)) {
+-                               pTarget->raidVolume = 1;
+-                               ddvprintk((KERN_INFO
+-                                   "RAID Volume @ id %d\n", id));
+-                       }
+-               }
+-
++	if ((pTarget = hd->Targets[target_id]) == NULL) {
+ 		return;
+-}
+-	dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d pTarget=%p\n",
+-			ioc->name, bus, id, lun, pTarget));
+-       pSpi = &ioc->spi_data;
+-       pTarget->ioc = ioc;
+-       pTarget->tflags &= ~MPT_TARGET_FLAGS_DELETED;
++	}
+ 
+ 	lun_index = (lun >> 5);  /* 32 luns per lun_index */
+ 	indexed_lun = (lun % 32);
+ 	pTarget->luns[lun_index] |= (1 << indexed_lun);
+ 
+-	if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+-		if ( dlen > 8 ) {
+-			memcpy (pTarget->inq_data, data, 8);
+-		} else {
+-			memcpy (pTarget->inq_data, data, dlen);
+-		}
+-	}
+ 	if (ioc->bus_type == SPI) {
+ 		if ((data[0] == TYPE_PROCESSOR) && (ioc->spi_data.Saf_Te)) {
+ 			/* Treat all Processors as SAF-TE if
+ 			 * command line option is set */
+ 			pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+-			mptscsih_writeIOCPage4(hd, id, bus);
++			mptscsih_writeIOCPage4(hd, target_id, bus_id);
+ 		}else if ((data[0] == TYPE_PROCESSOR) &&
+ 			!(pTarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+ 			if ( dlen > 49 ) {
+@@ -3686,17 +3311,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
+ 				     data[48] == 'T' &&
+ 				     data[49] == 'E' ) {
+ 					pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+-					mptscsih_writeIOCPage4(hd, id, bus);
++					mptscsih_writeIOCPage4(hd, target_id, bus_id);
+ 				}
+ 			}
+ 		}
+-data_56 = 0x00;  /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */
+-
+-
+ 		if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
++			if ( dlen > 8 ) {
++				memcpy (pTarget->inq_data, data, 8);
++			} else {
++				memcpy (pTarget->inq_data, data, dlen);
++			}
++
++			/* If have not done DV, set the DV flag.
++			 */
++			pSpi = &ioc->spi_data;
++			if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
++				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
++					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
++			}
+ 
+ 			pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+ 
++
++			data_56 = 0x00;  /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */
+ 			if (dlen > 56) {
+ 				if ( (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+ 				/* Update the target capabilities
+@@ -3705,6 +3342,7 @@ data_56 = 0x00;  /* Default to no Ultra 
+ 					pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
+ 				}
+ 			}
++			mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+ 		} else {
+ 			/* Initial Inquiry may not request enough data bytes to
+ 			 * obtain byte 57.  DV will; if target doesn't return
+@@ -3715,40 +3353,25 @@ data_56 = 0x00;  /* Default to no Ultra 
+ 				 */
+ 					data_56 = data[56];
+ 					pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
++					mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+ 				}
+ 			}
+ 		}
+-
+-mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+-if (pSpi->dvStatus[id] & MPT_SCSICFG_NEED_DV) {
+-       ddvprintk((MYIOC_s_WARN_FMT "%s: DV Scheduled for non-PhysDisk id %d\n",
+-                 ioc->name, __FUNCTION__, id));
+-INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget);
+-schedule_work(&pTarget->dvTask);
+-       }
+-       } else {
+-         pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+-         if (ioc->bus_type == SAS) {
+-            if ( (pTarget->inq_data[7] & 0x02) == 0) {
+-                 pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+-                     }
+-            if ((data[0] == TYPE_TAPE)) {
+-                      if (ioc->facts.IOCCapabilities &
+-                               MPI_IOCFACTS_CAPABILITY_TLR ) {
+-                      if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0){
+-                                               if ( data[8]  == 'H' &&
+-                                                    data[9]  == 'P' &&
+-                                                    data[10] == ' ' &&
+-                                                    data[11] == ' ' &&
+-                                                    data[12] == ' ' &&
+-                                                    data[13] == ' ' &&
+-                                                    data[14] == ' ' &&
+-                                                    data[15] == ' ' ) {
+-                                                       mpt_IssueTLR(hd, pTarget);
+-                                                  pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE;
+-
+-                                                }
+-
++	} else if (ioc->bus_type == SAS) {
++		if ((data[0] == TYPE_TAPE)) {
++			if (ioc->facts.IOCCapabilities & 
++				MPI_IOCFACTS_CAPABILITY_TLR ) {
++				if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0) {
++					if ( data[8]  == 'H' &&
++					     data[9]  == 'P' &&
++					     data[10] == ' ' &&
++					     data[11] == ' ' &&
++					     data[12] == ' ' &&
++					     data[13] == ' ' &&
++					     data[14] == ' ' &&
++					     data[15] == ' ' ) {
++						mpt_IssueTLR(hd, pTarget);
++						pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE;
+ 					}
+ 				}
+ 			}
+@@ -3760,12 +3383,11 @@ schedule_work(&pTarget->dvTask);
+ static void
+ mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget)
+ {
+-	MPT_ADAPTER		*ioc = hd->ioc;
+ 	INTERNAL_CMD		 iocmd;
+ 	int			 lun, indexed_lun, lun_index;
+ 
+-	iocmd.id = pTarget->id;
+-	iocmd.bus = pTarget->bus;
++	iocmd.id = pTarget->target_id;
++	iocmd.bus = pTarget->bus_id;
+ 	for (lun=0; lun <= MPT_LAST_LUN; lun++) {
+ 		/* If LUN present, issue the command
+ 		 */
+@@ -3777,7 +3399,7 @@ mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevi
+ 		}
+ 	}
+ 	printk(MYIOC_s_INFO_FMT "mpt_IssueTLR: Unable find a lun on id=%d\n",
+-		ioc->name, iocmd.id);
++		hd->ioc->name, iocmd.id);
+ 	return;
+ issueTLR:
+ 	iocmd.flags = 0;
+@@ -3790,7 +3412,7 @@ issueTLR:
+ 	if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+ 		if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+ 			printk(MYIOC_s_INFO_FMT "Unable to set TLR on id=%d\n",
+-				ioc->name, iocmd.id);
++				hd->ioc->name, iocmd.id);
+ 		}
+ 	}
+ }
+@@ -3802,14 +3424,12 @@ issueTLR:
+  *
+  */
+ static void
+-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56)
++mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+-	SpiCfgData *pspi_data = &ioc->spi_data;
+-	int  id = (int) pTarget->id;
++	SpiCfgData *pspi_data = &hd->ioc->spi_data;
++	int  id = (int) target->target_id;
+ 	int  nvram;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice	*loop_pTarget;
++	VirtDevice	*pTarget;
+ 	int ii;
+ 	u8 width = MPT_NARROW;
+ 	u8 factor = MPT_ASYNC;
+@@ -3817,36 +3437,31 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOS
+ 	u8 version, nfactor;
+ 	u8 noQas = 1;
+ 
+-	pTarget->negoFlags = pspi_data->noQas;
+-ddvprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n",
+-               pspi_data->noQas, id));
++	target->negoFlags = pspi_data->noQas;
+ 
+-/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
++	ddvtprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n", 
++		pspi_data->noQas, id));
++	/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
+ 	 * support. If available, default QAS to off and allow enabling.
+ 	 * If not available, default QAS to on, turn off for non-disks.
+ 	 */
+ 
+ 	/* Set flags based on Inquiry data
+ 	 */
+-	version = pTarget->inq_data[2] & 0x07;
++	version = target->inq_data[2] & 0x07;
+ 	if (version < 2) {
+ 		width = 0;
+ 		factor = MPT_ULTRA2;
+ 		offset = pspi_data->maxSyncOffset;
+-		pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
++		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+ 	} else {
+-		if (pTarget->inq_data[7] & 0x20) {
++		if (target->inq_data[7] & 0x20) {
+ 			width = 1;
+ 		}
+ 
+-               if (pTarget->inq_data[7] & 0x02)
+-                       pTarget->tflags |= MPT_TARGET_FLAGS_Q_YES;
+-               else
+-                       pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+-
+-		if (pTarget->inq_data[7] & 0x10) {
++		if (target->inq_data[7] & 0x10) {
+ 			factor = pspi_data->minSyncFactor;
+-			if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_56) {
++			if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
+ 				/* bits 2 & 3 show Clocking support */
+ 				if ((byte56 & 0x0C) == 0)
+ 					factor = MPT_ULTRA2;
+@@ -3857,17 +3472,17 @@ ddvprintk((KERN_INFO "Command-line QAS s
+ 						factor = MPT_ULTRA320;
+ 						if (byte56 & 0x02)
+ 						{
+-                                                   ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
++							ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+ 							noQas = 0;
+ 						}
+-						if (pTarget->inq_data[0] == TYPE_TAPE) {
++						if (target->inq_data[0] == TYPE_TAPE) {
+ 							if (byte56 & 0x01)
+-								pTarget->negoFlags |= MPT_TAPE_NEGO_IDP;
++								target->negoFlags |= MPT_TAPE_NEGO_IDP;
+ 						}
+ 					}
+ 				}
+ 			} else {
+-				ddvprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
++				ddvtprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
+ 				factor = MPT_ULTRA2;
+ 			}
+ 
+@@ -3879,7 +3494,7 @@ ddvprintk((KERN_INFO "Command-line QAS s
+ 			 * bit 1 QAS support, non-raid only
+ 			 * bit 0 IU support
+ 			 */
+-			if (pTarget->raidVolume == 1) {
++			if (target->raidVolume == 1) {
+ 				noQas = 0;
+ 			}
+ 		} else {
+@@ -3888,6 +3503,9 @@ ddvprintk((KERN_INFO "Command-line QAS s
+ 		}
+ 	}
+ 
++	if ( (target->inq_data[7] & 0x02) == 0) {
++		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
++	}
+ 
+ 	/* Update tflags based on NVRAM settings. (SCSI only)
+ 	 */
+@@ -3926,43 +3544,41 @@ ddvprintk((KERN_INFO "Command-line QAS s
+ 
+ 	/* Save the data to the target structure.
+ 	 */
+-	pTarget->minSyncFactor = factor;
+-	pTarget->maxOffset = offset;
+-	pTarget->maxWidth = width;
++	target->minSyncFactor = factor;
++	target->maxOffset = offset;
++	target->maxWidth = width;
+ 
+-	pTarget->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
++	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+ 
+ 	/* Disable unused features.
+ 	 */
+ 	if (!width)
+-		pTarget->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+ 
+ 	if (!offset)
+-		pTarget->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+ 
+ 	if ( factor > MPT_ULTRA320 )
+ 		noQas = 0;
+ 
+ 	/* GEM, processor WORKAROUND
+ 	 */
+-	if ((pTarget->inq_data[0] == TYPE_PROCESSOR) || (pTarget->inq_data[0] > 0x08)) {
+-		pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
++	if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
++		target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+ 		pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
+ 	} else {
+ 		if (noQas && (pspi_data->noQas == 0)) {
+ 			pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+-			pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
++			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+ 
+ 			/* Disable QAS in a mixed configuration case
+ 	 		*/
+-ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+ 
+-                pMptTarget = ioc->Target_List[0];
++			ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+ 			for (ii = 0; ii < id; ii++) {
+-				loop_pTarget = pMptTarget->Target[id];
+-				if ((loop_pTarget)) {
+-					loop_pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+-                                        mpt_writeSDP1(ioc, 0, ii, loop_pTarget->negoFlags);
++				if ( (pTarget = hd->Targets[ii]) ) {
++					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
++					mptscsih_writeSDP1(hd, 0, ii, pTarget->negoFlags);
+ 				}
+ 			}
+ 		}
+@@ -3970,33 +3586,115 @@ ddvprintk((KERN_INFO "Disabling QAS due 
+ 
+ 	/* Write SDP1 on this I/O to this target */
+ 	if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+-		dnegoprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
+-                /* First IO to this device; NEED_DV will cause async/narrow */
+-                mpt_writeSDP1(ioc, 0, id, 0);
++		ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
++		mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+ 		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+ 	} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+-		dnegoprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
+-		mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_BLK_NEGO);
++		ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
++		mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+ 		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+ 	}
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
++ * Else set the NEED_DV flag after Read Capacity Issued (disks)
++ * or Mode Sense (cdroms).
++ *
++ * Tapes, initTarget will set this flag on completion of Inquiry command.
++ * Called only if DV_NOT_DONE flag is set
++ */
++static void
++mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
++{
++	MPT_ADAPTER	*ioc = hd->ioc;
++	u8 cmd;
++	SpiCfgData	*pSpi;
++
++	ddvtprintk((MYIOC_s_NOTE_FMT
++		" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
++		hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
++
++	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
++		return;
++
++	cmd = pReq->CDB[0];
++
++	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
++		pSpi = &ioc->spi_data;
++		if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
++			/* Set NEED_DV for all hidden disks
++			 */
++			Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
++			int		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++
++			while (numPDisk) {
++				pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++				ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
++				pPDisk++;
++				numPDisk--;
++			}
++		}
++		pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
++		ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
++	}
++}
++
++/* mptscsih_raid_set_dv_flags()
++ *
++ * New or replaced disk. Set DV flag and schedule DV.
++ */
++static void
++mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
++{
++	MPT_ADAPTER	*ioc = hd->ioc;
++	SpiCfgData	*pSpi = &ioc->spi_data;
++	Ioc3PhysDisk_t	*pPDisk;
++	int		 numPDisk;
++
++	if (hd->negoNvram != 0)
++		return;
++
++	ddvtprintk(("DV requested for phys disk id %d\n", id));
++	if (ioc->raid_data.pIocPg3) {
++		pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
++		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++		while (numPDisk) {
++			if (id == pPDisk->PhysDiskNum) {
++				pSpi->dvStatus[pPDisk->PhysDiskID] =
++				    (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
++				pSpi->forceDv = MPT_SCSICFG_NEED_DV;
++				ddvtprintk(("NEED_DV set for phys disk id %d\n",
++				    pPDisk->PhysDiskID));
++				break;
++			}
++			pPDisk++;
++			numPDisk--;
++		}
++
++		if (numPDisk == 0) {
++			/* The physical disk that needs DV was not found
++			 * in the stored IOC Page 3. The driver must reload
++			 * this page. DV routine will set the NEED_DV flag for
++			 * all phys disks that have DV_NOT_DONE set.
++			 */
++			pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
++			ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
++		}
++	}
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  * If no Target, bus reset on 1st I/O. Set the flag to
+  * prevent any future negotiations to this device.
+  */
+ static void
+-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id)
++mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+-	VirtDevice	*pTarget;
+ 
+-	pMptTarget = ioc->Target_List[0];
+-	pTarget = pMptTarget->Target[id];
+-	if (pTarget == NULL)
+-		ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
++	if (hd->Targets[target_id] == NULL)
++		hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
+ 
+ 	return;
+ }
+@@ -4006,9 +3704,266 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd,
+  *  SCSI Config Page functionality ...
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*	mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
++ *	based on width, factor and offset parameters.
++ *	@width: bus width
++ *	@factor: sync factor
++ *	@offset: sync offset
++ *	@requestedPtr: pointer to requested values (updated)
++ *	@configurationPtr: pointer to configuration values (updated)
++ *	@flags: flags to block WDTR or SDTR negotiation
++ *
++ *	Return: None.
++ *
++ *	Remark: Called by writeSDP1 and _dv_params
++ */
++static void
++mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
++{
++	u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
++	u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
++
++	*configurationPtr = 0;
++	*requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
++	*requestedPtr |= (offset << 16) | (factor << 8);
++
++	if (width && offset && !nowide && !nosync) {
++		if (factor < MPT_ULTRA160) {
++			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
++			if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
++				*requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
++			if (flags & MPT_TAPE_NEGO_IDP)
++				*requestedPtr |= 0x08000000;
++		} else if (factor < MPT_ULTRA2) {
++			*requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
++		}
++	}
++
++	if (nowide)
++		*configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
++
++	if (nosync)
++		*configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
++
++	return;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*	mptscsih_writeSDP1  - write SCSI Device Page 1
++ *	@hd: Pointer to a SCSI Host Strucutre
++ *	@portnum: IOC port number
++ *	@target_id: writeSDP1 for single ID
++ *	@flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
++ *
++ *	Return: -EFAULT if read of config page header fails
++ *		or 0 if success.
++ *
++ *	Remark: If a target has been found, the settings from the
++ *		target structure are used, else the device is set
++ *		to async/narrow.
++ *
++ *	Remark: Called during init and after a FW reload.
++ *	Remark: We do not wait for a return, write pages sequentially.
++ */
++static int
++mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
++{
++	MPT_ADAPTER		*ioc = hd->ioc;
++	Config_t		*pReq;
++	SCSIDevicePage1_t	*pData;
++	VirtDevice		*pTarget;
++	MPT_FRAME_HDR		*mf;
++	dma_addr_t		 dataDma;
++	u16			 req_idx;
++	u32			 frameOffset;
++	u32			 requested, configuration, flagsLength;
++	int			 ii, nvram;
++	int			 id = 0, maxid = 0;
++	u8			 width;
++	u8			 factor;
++	u8			 offset;
++	u8			 bus = 0;
++	u8			 negoFlags;
++	u8			 maxwidth, maxoffset, maxfactor;
++
++	if (ioc->spi_data.sdp1length == 0)
++		return 0;
++
++	if (flags & MPT_SCSICFG_ALL_IDS) {
++		id = 0;
++		maxid = ioc->sh->max_id - 1;
++	} else if (ioc->sh) {
++		id = target_id;
++		maxid = min_t(int, id, ioc->sh->max_id - 1);
++	}
++
++	for (; id <= maxid; id++) {
++
++		if (id == ioc->pfacts[portnum].PortSCSIID)
++			continue;
++
++		/* Use NVRAM to get adapter and target maximums
++		 * Data over-riden by target structure information, if present
++		 */
++		maxwidth = ioc->spi_data.maxBusWidth;
++		maxoffset = ioc->spi_data.maxSyncOffset;
++		maxfactor = ioc->spi_data.minSyncFactor;
++		if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++			nvram = ioc->spi_data.nvram[id];
++
++			if (maxwidth)
++				maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
++
++			if (maxoffset > 0) {
++				maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
++				if (maxfactor == 0) {
++					/* Key for async */
++					maxfactor = MPT_ASYNC;
++					maxoffset = 0;
++				} else if (maxfactor < ioc->spi_data.minSyncFactor) {
++					maxfactor = ioc->spi_data.minSyncFactor;
++				}
++			} else
++				maxfactor = MPT_ASYNC;
++		}
++
++		/* Set the negotiation flags.
++		 */
++		negoFlags = ioc->spi_data.noQas;
++		if (!maxwidth)
++			negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++
++		if (!maxoffset)
++			negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++
++		if (flags & MPT_SCSICFG_USE_NVRAM) {
++			width = maxwidth;
++			factor = maxfactor;
++			offset = maxoffset;
++		} else {
++			width = 0;
++			factor = MPT_ASYNC;
++			offset = 0;
++			//negoFlags = 0;
++			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
++		}
++
++		/* If id is not a raid volume, get the updated
++		 * transmission settings from the target structure.
++		 */
++		if ( (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
++			width = pTarget->maxWidth;
++			factor = pTarget->minSyncFactor;
++			offset = pTarget->maxOffset;
++			negoFlags |= pTarget->negoFlags;
++		}
++
++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++		/* Force to async and narrow if DV has not been executed
++		 * for this ID
++		 */
++		if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
++			width = 0;
++			factor = MPT_ASYNC;
++			offset = 0;
++		}
++#endif
++
++		if (flags & MPT_SCSICFG_BLK_NEGO)
++			negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
++
++		mptscsih_setDevicePage1Flags(width, factor, offset,
++					&requested, &configuration, negoFlags);
++		dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++			target_id, width, factor, offset, negoFlags, requested, configuration));
++
++		/* Get a MF for this command.
++		 */
++		if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
++			dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
++			    ioc->name,__FUNCTION__));
++			return -EAGAIN;
++		}
++
++		ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
++			hd->ioc->name, mf, id, requested, configuration));
++
++
++		/* Set the request and the data pointers.
++		 * Request takes: 36 bytes (32 bit SGE)
++		 * SCSI Device Page 1 requires 16 bytes
++		 * 40 + 16 <= size of SCSI IO Request = 56 bytes
++		 * and MF size >= 64 bytes.
++		 * Place data at end of MF.
++		 */
++		pReq = (Config_t *)mf;
++
++		req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++		frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
++
++		pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
++		dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
++
++		/* Complete the request frame (same for all requests).
++		 */
++		pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++		pReq->Reserved = 0;
++		pReq->ChainOffset = 0;
++		pReq->Function = MPI_FUNCTION_CONFIG;
++		pReq->ExtPageLength = 0;
++		pReq->ExtPageType = 0;
++		pReq->MsgFlags = 0;
++		for (ii=0; ii < 8; ii++) {
++			pReq->Reserved2[ii] = 0;
++		}
++		pReq->Header.PageVersion = ioc->spi_data.sdp1version;
++		pReq->Header.PageLength = ioc->spi_data.sdp1length;
++		pReq->Header.PageNumber = 1;
++		pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
++		pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
++
++		/* Add a SGE to the config request.
++		 */
++		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
++
++		mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
++
++		/* Set up the common data portion
++		 */
++		pData->Header.PageVersion = pReq->Header.PageVersion;
++		pData->Header.PageLength = pReq->Header.PageLength;
++		pData->Header.PageNumber = pReq->Header.PageNumber;
++		pData->Header.PageType = pReq->Header.PageType;
++		pData->RequestedParameters = cpu_to_le32(requested);
++		pData->Reserved = 0;
++		pData->Configuration = cpu_to_le32(configuration);
++
++		if ( pTarget ) {
++			if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) {
++				pTarget->last_lun = MPT_LAST_LUN;
++			} else {
++				pTarget->last_lun = MPT_NON_IU_LAST_LUN;
++			}
++			dsprintk((MYIOC_s_INFO_FMT
++				"writeSDP1: last_lun=%d on id=%d\n",
++				ioc->name, pTarget->last_lun, id));
++		}
++
++		dprintk((MYIOC_s_INFO_FMT
++			"write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
++				ioc->name, id, (id | (bus<<8)),
++				requested, configuration));
++
++		mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++	}
++
++	return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*	mptscsih_writeIOCPage4  - write IOC Page 4
+  *	@hd: Pointer to a SCSI Host Structure
+- *	@id: write IOC Page4 for this ID & Bus
++ *	@target_id: write IOC Page4 for this ID & Bus
+  *
+  *	Return: -EAGAIN if unable to obtain a Message Frame
+  *		or 0 if success.
+@@ -4016,7 +3971,7 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd,
+  *	Remark: We do not wait for a return, write pages sequentially.
+  */
+ static int
+-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus)
++mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
+ {
+ 	MPT_ADAPTER		*ioc = hd->ioc;
+ 	Config_t		*pReq;
+@@ -4060,10 +4015,10 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
+        	IOCPage4Ptr = ioc->spi_data.pIocPg4;
+        	dataDma = ioc->spi_data.IocPg4_dma;
+        	ii = IOCPage4Ptr->ActiveSEP++;
+-	IOCPage4Ptr->SEP[ii].SEPTargetID = id;
++       	IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
+        	IOCPage4Ptr->SEP[ii].SEPBus = bus;
+        	pReq->Header = IOCPage4Ptr->Header;
+-	pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
++	pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
+ 
+ 	/* Add a SGE to the config request.
+ 	 */
+@@ -4074,7 +4029,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
+ 
+ 	dinitprintk((MYIOC_s_INFO_FMT
+ 		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+-			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, bus));
++			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
+ 
+ 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+ 
+@@ -4116,9 +4071,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 
+ 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+ 
+-        del_timer(&hd->InternalCmdTimer);
+-
+-
+ 	if ((mf == NULL) ||
+ 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
+ 		printk(MYIOC_s_ERR_FMT
+@@ -4127,18 +4079,19 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 		goto wakeup;
+ 	}
+ 
++	del_timer(&hd->timer);
+ 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+ 	hd->ScsiLookup[req_idx] = NULL;
+ 	pReq = (SCSIIORequest_t *) mf;
+ 
+ 	if (mf != hd->cmdPtr) {
+-		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p,!= cmdPtr=%p, idx=%d)\n",
+-				ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
++		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
++				hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
+ 	}
+ 	hd->cmdPtr = NULL;
+ 
+-	ddvprintk((MYIOC_s_WARN_FMT "ScanDvComplete mf=%p,mr=%p,idx=%d\n",
+-			ioc->name, mf, mr, req_idx));
++	ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
++			hd->ioc->name, mf, mr, req_idx));
+ 
+ 	hd->pLocal = &hd->localReply;
+ 	hd->pLocal->scsiStatus = 0;
+@@ -4156,9 +4109,10 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 
+ 		status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+ 		scsi_status = pReply->SCSIStatus;
+- ddvprintk((MYIOC_s_WARN_FMT "%s: IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh IOCLogInfo=%08xh\n",
+-                     ioc->name, __FUNCTION__, status, pReply->SCSIState, scsi_status,
+-                     le32_to_cpu(pReply->IOCLogInfo)));
++
++		ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
++			     status, pReply->SCSIState, scsi_status,
++			     le32_to_cpu(pReply->IOCLogInfo)));
+ 
+ 		switch(status) {
+ 
+@@ -4203,14 +4157,13 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 				 */
+ 				completionCode = MPT_SCANDV_SENSE;
+ 				hd->pLocal->scsiStatus = scsi_status;
+-				sense_data = ((u8 *)ioc->sense_buf_pool +
++				sense_data = ((u8 *)hd->ioc->sense_buf_pool +
+ 					(req_idx * MPT_SENSE_BUFFER_ALLOC));
+ 
+ 				sz = min_t(int, pReq->SenseBufferLength,
+ 							SCSI_STD_SENSE_BYTES);
+ 				memcpy(hd->pLocal->sense, sense_data, sz);
+ 
+-				DBG_DUMP_SENSE_DATA(sense_data);
+ 				ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
+ 						sense_data));
+ 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
+@@ -4224,7 +4177,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 			else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
+ 				completionCode = MPT_SCANDV_DID_RESET;
+ 			else if (scsi_status == MPI_SCSI_STATUS_BUSY)
+-				completionCode = MPT_SCANDV_BUSY;
++				completionCode = MPT_SCANDV_SOME_ERROR;
+ 			else {
+ 				completionCode = MPT_SCANDV_GOOD;
+ 				hd->pLocal->scsiStatus = scsi_status;
+@@ -4243,9 +4196,9 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+ 			break;
+ 
+ 		}	/* switch(status) */
+-               ddvprintk((MYIOC_s_WARN_FMT ": completionCode=%08xh\n",
+-                       ioc->name, completionCode));
+ 
++		ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
++				completionCode));
+ 	} /* end of address reply case */
+ 
+ 	hd->pLocal->completion = completionCode;
+@@ -4266,53 +4219,48 @@ wakeup:
+ }
+ 
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*	mptscsih_InternalCmdTimer_expired - Call back for DV timer process.
++/*	mptscsih_timer_expired - Call back for timer process.
+  *	Used only for dv functionality.
+  *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
+  *
+  */
+-void mptscsih_InternalCmdTimer_expired(unsigned long data)
++void
++mptscsih_timer_expired(unsigned long data)
+ {
+ 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
+-	MPT_ADAPTER	*ioc=hd->ioc;
+-	MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
+ 
+-	ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired! cmdPtr=%p\n",
+-		ioc->name, cmd));
++	ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
+ 
+-	hd->cmdPtr = NULL;
+-	if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
+-#ifdef MPT_DEBUG_DV
+-		SCSIIORequest_t	*pScsiReq = (SCSIIORequest_t *) cmd;
+-		int	 id = pScsiReq->TargetID;
+-
+-		/* Desire to issue a task management request here.
+-		 * TM requests MUST be single threaded.
+-		 * If old eh code and no TM current, issue request.
+-		 * If new eh code, do nothing. Wait for OS cmd timeout
+-		 *	for bus reset.
+-		 */
+-		ddvprintk((MYIOC_s_WARN_FMT "DV Cmd Timeout: id=%d CDB=%02x\n",
+-			ioc->name, id, pScsiReq->CDB[0]));
+-#endif
++	if (hd->cmdPtr) {
++		MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
+ 
+-		/*
+-		 * Wake up the original calling thread
+-		 */
+-		hd->pLocal = &hd->localReply;
+-		hd->pLocal->completion = MPT_SCANDV_FALLBACK;
+-		hd->scandv_wait_done = 1;
+-		wake_up(&hd->scandv_waitq);
+-	} else {
+-		/* Perform a FW reload */
+-		if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
+-			printk(MYIOC_s_WARN_FMT "InternalCmdTimer_expired: HardReset FAILED!\n", ioc->name);
+-			dfailprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset failed\n", ioc->name));
++		if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
++			/* Desire to issue a task management request here.
++			 * TM requests MUST be single threaded.
++			 * If old eh code and no TM current, issue request.
++			 * If new eh code, do nothing. Wait for OS cmd timeout
++			 *	for bus reset.
++			 */
++			ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
+ 		} else {
+-			ddvprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset succeeded\n", ioc->name));
++			/* Perform a FW reload */
++			if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
++				printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
++			}
+ 		}
++	} else {
++		/* This should NEVER happen */
++		printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
+ 	}
+-	ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired Complete!\n", ioc->name));
++
++	/* No more processing.
++	 * TM call will generate an interrupt for SCSI TM Management.
++	 * The FW will reply to all outstanding commands, callback will finish cleanup.
++	 * Hard reset clean-up will free all resources.
++	 */
++	ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
++
++	return;
+ }
+ 
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+@@ -4331,23 +4279,22 @@ void mptscsih_InternalCmdTimer_expired(u
+ static int
+ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
+ {
+-	MPT_ADAPTER		*ioc = hd->ioc;
+ 	MpiRaidActionRequest_t	*pReq;
+ 	MPT_FRAME_HDR		*mf;
+ 	int			in_isr;
+ 
+ 	in_isr = in_interrupt();
+ 	if (in_isr) {
+-		dfailprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
+-				ioc->name));
++		dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
++       				hd->ioc->name));
+ 		return -EPERM;
+ 	}
+ 
+ 	/* Get and Populate a free Frame
+ 	 */
+-	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
++	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+ 		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-		    ioc->name,__FUNCTION__));
++		    hd->ioc->name,__FUNCTION__));
+ 		return -EAGAIN;
+ 	}
+ 	pReq = (MpiRaidActionRequest_t *)mf;
+@@ -4367,11 +4314,10 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+ 		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
+ 
+ 	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
+-			ioc->name, action, io->id));
++			hd->ioc->name, action, io->id));
+ 
+ 	hd->pLocal = NULL;
+-	hd->InternalCmdTimer.data = (unsigned long) hd;
+-        hd->InternalCmdTimer.expires = jiffies + HZ*10; /* 10 second timeout */
++	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
+ 	hd->scandv_wait_done = 0;
+ 
+ 	/* Save cmd pointer, for resource free if timeout or
+@@ -4379,8 +4325,8 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+ 	 */
+ 	hd->cmdPtr = mf;
+ 
+-	add_timer(&hd->InternalCmdTimer);
+-        mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
++	add_timer(&hd->timer);
++	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+ 	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+ 
+ 	if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
+@@ -4413,7 +4359,6 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+ int
+ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+ 	MPT_FRAME_HDR	*mf;
+ 	SCSIIORequest_t	*pScsiReq;
+ 	SCSIIORequest_t	 ReqCopy;
+@@ -4426,8 +4371,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 
+ 	in_isr = in_interrupt();
+ 	if (in_isr) {
+-		dfailprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
+-				ioc->name));
++		dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
++       				hd->ioc->name));
+ 		return -EPERM;
+ 	}
+ 
+@@ -4542,16 +4487,14 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 
+ 	default:
+ 		/* Error Case */
+-		dfailprintk((MYIOC_s_WARN_FMT "%s,Unknown cmd=%02x!!\n",
+-		    ioc->name,__FUNCTION__, cmd));
+ 		return -EFAULT;
+ 	}
+ 
+ 	/* Get and Populate a free Frame
+ 	 */
+-	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
++	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+ 		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-		    ioc->name,__FUNCTION__));
++		    hd->ioc->name,__FUNCTION__));
+ 		return -EBUSY;
+ 	}
+ 
+@@ -4593,18 +4536,18 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 	if (cmd == REQUEST_SENSE) {
+ 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
+ 		ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
+-			ioc->name, cmd));
++			hd->ioc->name, cmd));
+ 	}
+ 
+ 	for (ii=0; ii < 16; ii++)
+ 		pScsiReq->CDB[ii] = CDB[ii];
+ 
+ 	pScsiReq->DataLength = cpu_to_le32(io->size);
+-	pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
++	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+ 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
+ 
+-       ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d) mf=%p\n",
+-                       ioc->name, cmd, io->bus, io->id, io->lun, pScsiReq));
++	ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
++			hd->ioc->name, cmd, io->bus, io->id, io->lun));
+ 
+ 	if (dir == MPI_SCSIIO_CONTROL_READ) {
+ 		mpt_add_sge((char *) &pScsiReq->SGL,
+@@ -4630,8 +4573,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 	 *	set scandv_wait_done and call wake_up
+ 	 */
+ 	hd->pLocal = NULL;
+-        hd->InternalCmdTimer.data = (unsigned long) hd;
+-        hd->InternalCmdTimer.expires = jiffies + HZ*cmdTimeout;
++	hd->timer.expires = jiffies + HZ*cmdTimeout;
+ 	hd->scandv_wait_done = 0;
+ 
+ 	/* Save cmd pointer, for resource free if timeout or
+@@ -4639,8 +4581,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 	 */
+ 	hd->cmdPtr = mf;
+ 
+-        add_timer(&hd->InternalCmdTimer);
+-	mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
++	add_timer(&hd->timer);
++	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+ 	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+ 
+ 	if (hd->pLocal) {
+@@ -4657,7 +4599,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+ 		rc = -EFAULT;
+ 		/* This should never happen. */
+ 		ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
+-				ioc->name));
++				hd->ioc->name));
+ 	}
+ 
+ 	return rc;
+@@ -4678,7 +4620,6 @@ static int
+ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+ {
+ 	MPT_ADAPTER		*ioc= hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+ 	SCSIDevicePage1_t	*pcfg1Data = NULL;
+ 	INTERNAL_CMD		 iocmd;
+@@ -4690,6 +4631,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 	int			 lun;
+ 	int			 indexed_lun, lun_index;
+ 	int			 hostId = ioc->pfacts[portnum].PortSCSIID;
++	int			 max_id;
+ 	int			 requested, configuration, data;
+ 	int			 doConfig = 0;
+ 	u8			 flags, factor;
+@@ -4697,6 +4639,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 	dexitprintk((KERN_INFO MYNAM ": %s called\n",
+ 		__FUNCTION__));
+ 
++	max_id = ioc->sh->max_id - 1;
++
+ 	/* Following parameters will not change
+ 	 * in this routine.
+ 	 */
+@@ -4733,11 +4677,10 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 
+ 	/* loop through all devices on this port
+ 	 */
+-	while (bus < ioc->NumberOfBuses) {
++	while (bus < MPT_MAX_BUS) {
+ 		iocmd.bus = bus;
+ 		iocmd.id = id;
+-		pMptTarget = ioc->Target_List[bus];
+-		pTarget = pMptTarget->Target[id];
++		pTarget = hd->Targets[(int)id];
+ 
+ 		if (doConfig) {
+ 
+@@ -4745,9 +4688,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 			if (pTarget && !pTarget->raidVolume) {
+ 				flags = pTarget->negoFlags;
+ 			} else {
+-				flags = ioc->spi_data.noQas;
+-				if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+-					data = ioc->spi_data.nvram[id];
++				flags = hd->ioc->spi_data.noQas;
++				if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++					data = hd->ioc->spi_data.nvram[id];
+ 
+ 					if (data & MPT_NVRAM_WIDE_DISABLE)
+ 						flags |= MPT_TARGET_NO_NEGO_WIDE;
+@@ -4759,16 +4702,16 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 			}
+ 
+ 			/* Force to async, narrow */
+-                       mpt_setSDP1parameters(0, MPT_ASYNC, 0, flags,
+-                               &requested, &configuration);
+-                       dnegoprintk(("%s: syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+-                                "offset=0 negoFlags=%x requested=%x configuration=%x\n",
+-                                ioc->name, id, flags, requested, configuration));
++			mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
++					&configuration, flags);
++			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
++				"offset=0 negoFlags=%x request=%x config=%x\n",
++				id, flags, requested, configuration));
+ 			pcfg1Data->RequestedParameters = cpu_to_le32(requested);
+ 			pcfg1Data->Reserved = 0;
+ 			pcfg1Data->Configuration = cpu_to_le32(configuration);
+ 			cfg.pageAddr = (bus<<8) | id;
+-			mpt_config(ioc, &cfg);
++			mpt_config(hd->ioc, &cfg);
+ 		}
+ 
+ 		/* If target Ptr NULL or if this target is NOT a disk, skip.
+@@ -4780,9 +4723,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 				lun_index = (lun >> 5);  /* 32 luns per lun_index */
+ 				indexed_lun = (lun % 32);
+ 				if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
+-					dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache for bus=%d id=%d lun=%d\n",
+-						ioc->name, bus, id, lun));
+-
+ 					iocmd.lun = lun;
+ 					(void) mptscsih_do_cmd(hd, &iocmd);
+ 				}
+@@ -4795,27 +4735,21 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ 		if (id == hostId)
+ 			id++;
+ 
+-		if (id >= ioc->DevicesPerBus) {
++		if (id > max_id) {
+ 			id = 0;
+ 			bus++;
+ 		}
+ 	}
+ 
+-	dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache commands done\n",
+-		ioc->name));
+-
+ 	if (pcfg1Data) {
+-		dexitprintk((KERN_INFO MYNAM ": %s: free pcfg1Data=%p\n",
+-			ioc->name, pcfg1Data));
+ 		pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+ 	}
+ 
+-	dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache done\n",
+-		ioc->name));
+ 	return 0;
+ }
+ 
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *	mptscsih_domainValidation - Top level handler for domain validation.
+  *	@hd: Pointer to MPT_SCSI_HOST structure.
+@@ -4829,209 +4763,163 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ static void
+ mptscsih_domainValidation(void *arg)
+ {
+-	VirtDevice	*pTarget=(VirtDevice *)arg;
+-	MPT_SCSI_HOST	*hd;
+-	MPT_ADAPTER	*ioc;
+-	unsigned long	 flags;
+-	int 		 id, dvStatus;
+-	int		 ii;
++	MPT_SCSI_HOST		*hd;
++	MPT_ADAPTER		*ioc;
++	unsigned long		 flags;
++	int 			 id, maxid, dvStatus, did;
++	int			 ii, isPhysDisk;
+ 
+ 	spin_lock_irqsave(&dvtaskQ_lock, flags);
+ 	dvtaskQ_active = 1;
++	if (dvtaskQ_release) {
++		dvtaskQ_active = 0;
++		spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++		return;
++	}
+ 	spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+ 
+-	if (pTarget == NULL) {
+-		ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget\n"));
+-		goto mptscsih_domainValidation_exit;
+-	}
+-	id = pTarget->id;
+-	ioc = pTarget->ioc;
+-	if (ioc == NULL) {
+-		ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget->ioc id=%d\n", id));
+-		goto mptscsih_domainValidation_exit;
+-	}
+-//	set_current_state(TASK_INTERRUPTIBLE);
+-//	schedule_timeout(MPT_HZ/4);
++	if (crashdump_mode())
++		return;
+ 
+-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++	/* For this ioc, loop through all devices and do dv to each device.
++	 * When complete with this ioc, search through the ioc list, and
++	 * for each scsi ioc found, do dv for all devices. Exit when no
++	 * device needs dv.
++	 */
++	did = 1;
++	while (did) {
++		did = 0;
++		list_for_each_entry(ioc, &ioc_list, list) {
++			spin_lock_irqsave(&dvtaskQ_lock, flags);
++			if (dvtaskQ_release) {
++				dvtaskQ_active = 0;
++				spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++				return;
++			}
++			spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+ 
+-	ddvprintk((KERN_WARNING "domainValidation pTarget=%p ioc=%p hd=%p id=%d\n",
+-		pTarget, ioc, hd, id));
+-	if (hd == NULL) {
+-		ddvprintk((KERN_WARNING "domainValidation called with NULL hd id=%d\n", id));
+-		goto mptscsih_domainValidation_exit;
+-	}
++			msleep(250);
+ 
+-	if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
+-		mpt_read_ioc_pg_3(ioc);
+-		if (ioc->spi_data.dvStatus[id] & MPT_SCSICFG_PHYSDISK_DV_ONLY) {
+-			ddvprintk((KERN_WARNING "PHYSDISK_DV_ONLY id=%d\n", id));
+-			ioc->spi_data.dvStatus[id] &=
+-				~MPT_SCSICFG_PHYSDISK_DV_ONLY;
+-			if (mptscsih_doDv(hd, 0, id) == 1) {
+-				/* Untagged device was busy, try again
+-				 */
+-				ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
+-			} else {
+-				/* DV is complete. Clear flags.
+-				 */
+-				ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+-			}
+-			goto mptscsih_domainValidation_exit;
+-		}
++			/* DV only to SPI adapters */
++			if (ioc->bus_type != SPI)
++				continue;
+ 
+-		if (ioc->raid_data.pIocPg3) {
+-			Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+-			int	numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++			/* Make sure everything looks ok */
++			if (ioc->sh == NULL)
++				continue;
+ 
+-			while (numPDisk) {
+-				if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
+-					ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++			hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++			if (hd == NULL)
++				continue;
+ 
+-				pPDisk++;
+-				numPDisk--;
++			if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
++				mpt_read_ioc_pg_3(ioc);
++				if (ioc->raid_data.pIocPg3) {
++					Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
++					int		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++
++					while (numPDisk) {
++						if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
++							ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++
++						pPDisk++;
++						numPDisk--;
++					}
++				}
++				ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
+ 			}
+-		}
+-		ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
+-	}
+ 
+-	dvStatus = ioc->spi_data.dvStatus[id];
++			maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
+ 
+-	if (dvStatus & MPT_SCSICFG_NEED_DV) {
+-		ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS;
+-		ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
++			for (id = 0; id < maxid; id++) {
++				spin_lock_irqsave(&dvtaskQ_lock, flags);
++				if (dvtaskQ_release) {
++					dvtaskQ_active = 0;
++					spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++					return;
++				}
++				spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++				dvStatus = hd->ioc->spi_data.dvStatus[id];
+ 
+-//		set_current_state(TASK_INTERRUPTIBLE);
+-//		schedule_timeout(MPT_HZ/4);
++				if (dvStatus & MPT_SCSICFG_NEED_DV) {
++					did++;
++					hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
++					hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
++
++					msleep(250);
++
++					/* If hidden phys disk, block IO's to all
++					 *	raid volumes
++					 * else, process normally
++					 */
++					isPhysDisk = mptscsih_is_phys_disk(hd->ioc, id);
++					if (isPhysDisk) {
++						for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
++							if (hd->ioc->raid_data.isRaid & (1 << ii)) {
++								hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
++							}
++						}
++					}
+ 
+-		/* If hidden phys disk, block IO's to all
+-		 *	raid volumes
+-		 * else, process normally
+-		 */
+-		if (ioc->raid_data.isRaid & (1 << id)) {
+-			Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+-			int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+-			while (numPDisk) {
+-				ii = pPDisk->PhysDiskID;
+-				if ( ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) {
+-					ddvprintk((KERN_WARNING "doDv for PhysDiskNum=%d PhysDiskID=%d numPDisk=%d\n",
+-						pPDisk->PhysDiskNum, ii, numPDisk));
+-					if (mptscsih_doDv(hd, 0, ii) == 1) {
++					if(mpt_alt_ioc_wait(hd->ioc)!=0) {
++						ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
++						    hd->ioc->name));
++						continue;
++					}
++
++					if (mptscsih_doDv(hd, 0, id) == 1) {
+ 						/* Untagged device was busy, try again
+ 						 */
+-						ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
++						hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
++						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
+ 					} else {
+-						ddvprintk((KERN_WARNING "doDv successful for PhysDiskNum=%d PhysDiskID=%d\n",
+-							pPDisk->PhysDiskNum, ii));
+ 						/* DV is complete. Clear flags.
+ 						 */
+-						ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_NOT_DONE;
++						hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
++					}
++
++					spin_lock(&hd->ioc->initializing_hba_lock);
++					hd->ioc->initializing_hba_lock_flag=0;
++					spin_unlock(&hd->ioc->initializing_hba_lock);
++
++					if (isPhysDisk) {
++						for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
++							if (hd->ioc->raid_data.isRaid & (1 << ii)) {
++								hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
++							}
++						}
+ 					}
++
++					if (hd->ioc->spi_data.noQas)
++						mptscsih_qas_check(hd, id);
+ 				}
+-				pPDisk++;
+-				numPDisk--;
+-			}
+-		} else {
+-			ddvprintk((KERN_WARNING "doDv for id=%d\n",
+-				id));
+-			if (mptscsih_doDv(hd, 0, id) == 1) {
+-				/* Untagged device was busy, try again
+-				 */
+-				ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
+-			} else {
+-				ddvprintk((KERN_WARNING "doDv successful for id=%d\n",
+-					id));
+-				/* DV is complete. Clear flags.
+-				 */
+-				ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+ 			}
+ 		}
+-
+-		if (ioc->spi_data.noQas)
+-			mptscsih_qas_check(hd, id);
+-	} else {
+-		ddvprintk((KERN_INFO "~NEED_DV dvStatus=%x for id %d\n",
+-			dvStatus, id));
+-//		panic( "~NEED_DV");
+ 	}
+-mptscsih_domainValidation_exit:
++
+ 	spin_lock_irqsave(&dvtaskQ_lock, flags);
+ 	dvtaskQ_active = 0;
+ 	spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+-}
+-
+ 
+-/* Post command on the PendingMF to the FW.
+- */
+-void
+-mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc)
+-{
+-	MPT_SCSI_HOST	*hd;
+-	MPT_FRAME_HDR	*mf;
+-	struct scsi_cmnd *SCpnt;
+-	unsigned long	 flags;
+-	u16		 req_idx;
+-
+-	spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-	if ((mf=ioc->PendingMF) == NULL) {
+-		spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-		dpendprintk((MYIOC_s_INFO_FMT "%s: PendingMF is empty\n",
+-			ioc->name, __FUNCTION__));
+-		return;
+-	}
+-
+-	mf = ioc->PendingMF;
+-	SCpnt = ioc->PendingSCpnt;
+-	ioc->PendingMF = NULL;
+-	spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-
+-	dpendprintk((MYIOC_s_INFO_FMT "mptscsih_post_PendingMF_command: mf=%p\n",
+-		ioc->name, mf));
+-	DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf)
+-
+-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-	hd->ScsiLookup[req_idx] = SCpnt;
+-	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++	return;
+ }
+ 
+-
+ /* Search IOC page 3 to determine if this is hidden physical disk
+  */
+ static int
+-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
++mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+ {
+-	struct inactive_raid_component_info *component_info;
+ 	int i;
+-	int rc = 0;
+-
+-	if (!ioc->raid_data.pIocPg3)
+-		goto out;
+-	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-			rc = 1;
+-			goto out;
+-		}
+-	}
+ 
+-	/*
+-	 * Check inactive list for matching phys disks
+-	 */
+-	if (list_empty(&ioc->raid_data.inactive_list))
+-		goto out;
++	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
++		return 0;
+ 
+-	down(&ioc->raid_data.inactive_list_mutex);
+-	list_for_each_entry(component_info,
+-	    &ioc->raid_data.inactive_list, list) {
+-		if ((component_info->d.PhysDiskID == id) &&
+-		    (component_info->d.PhysDiskBus == channel))
+-			rc = 1;
++	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
++		if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
++			return 1;
+ 	}
+-	up(&ioc->raid_data.inactive_list_mutex);
+ 
+- out:
+-	return rc;
++	return 0;
+ }
+ 
+ /* Write SDP1 if no QAS has been enabled
+@@ -5039,37 +4927,32 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, 
+ static void
+ mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
+ {
+-	MPT_ADAPTER	*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice *pTarget;
+ 	int ii;
+ 
+-	pMptTarget = ioc->Target_List[0];
+ 	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+ 		if (ii == id)
+ 			continue;
+ 
+-		if ((ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
++		if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
+ 			continue;
+ 
+-		pTarget = pMptTarget->Target[ii];
+-
+-		if (pTarget) {
+-			if (!pTarget->raidVolume) {
+-				if ((pTarget->negoFlags & ioc->spi_data.noQas) == 0) {
+-					pTarget->negoFlags |= ioc->spi_data.noQas;
+-					dnegoprintk(("mptscsih_qas_check: writeSDP1: id=%d negoFlags=%d\n", ii, pTarget->negoFlags));
+-		      mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM);
+-						}
+-			} else {
+-				if (mptscsih_is_phys_disk(ioc, 0, ii) == 1) {
+-					dnegoprintk(("mptscsih_qas_check: is_phys_disk writeSDP1: id=%d SCSICFG_USE_NVRAM\n", ii));
+-				      mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM);
++		pTarget = hd->Targets[ii];
+ 
+-				}
++		if (pTarget && (!pTarget->raidVolume)) {
++			if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
++				pTarget->negoFlags |= hd->ioc->spi_data.noQas;
++				dnegoprintk(("writeSDP1: id=%d negoFlags=%d\n", id, pTarget->negoFlags));
++				mptscsih_writeSDP1(hd, 0, ii, 0);
++			}
++		} else {
++			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
++				dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
++				mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
+ 			}
+ 		}
+ 	}
++	return;
+ }
+ 
+ 
+@@ -5094,16 +4977,15 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, in
+  *	Return: None.
+  */
+ static int
+-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus, int id)
++mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
+ {
+ 	MPT_ADAPTER		*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+ 	SCSIDevicePage1_t	*pcfg1Data;
+ 	SCSIDevicePage0_t	*pcfg0Data;
+ 	u8			*pbuf1;
+ 	u8			*pbuf2;
+-	u8			*pDvBuf=NULL;
++	u8			*pDvBuf;
+ 	dma_addr_t		 dvbuf_dma = -1;
+ 	dma_addr_t		 buf1_dma = -1;
+ 	dma_addr_t		 buf2_dma = -1;
+@@ -5127,7 +5009,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
+ 	char			 firstPass = 1;
+ 	char			 doFallback = 0;
+ 	char			 readPage0;
+-	char			 lun;
++	char			 bus, lun;
+ 	char			 inq0 = 0;
+ 
+ 	if (ioc->spi_data.sdp1length == 0)
+@@ -5141,10 +5023,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
+ 	 */
+ 	if (id == ioc->pfacts[0].PortSCSIID)
+ 		return 0;
+-ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS;
+ 
+ 	lun = 0;
+-	ddvprintk((MYIOC_s_INFO_FMT "DV Started: bus=%d id=%d dv @ %p\n",ioc->name, bus, id, &dv));
++	bus = (u8) bus_number;
++	ddvtprintk((MYIOC_s_NOTE_FMT
++			"DV Started: bus=%d id=%d dv @ %p\n",
++			ioc->name, bus, id, &dv));
+ 
+ 	/* Prep DV structure
+ 	 */
+@@ -5167,8 +5051,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 	iocmd.physDiskNum = -1;
+ 	iocmd.rsvd = iocmd.rsvd2 = 0;
+ 
+-	pMptTarget = ioc->Target_List[bus];
+-	pTarget = pMptTarget->Target[id];
++	pTarget = hd->Targets[id];
+ 
+ 	/* Use tagged commands if possible.
+ 	 */
+@@ -5176,12 +5059,12 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 		if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+ 			iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
+ 		else {
+-			if (ioc->facts.FWVersion.Word < 0x01000600)
+-				  goto doDv_done;
++			if (hd->ioc->facts.FWVersion.Word < 0x01000600)
++				return 0;
+ 
+-			if ((ioc->facts.FWVersion.Word >= 0x01010000) &&
+-				(ioc->facts.FWVersion.Word < 0x01010B00))
+-			         goto doDv_done;
++			if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
++				(hd->ioc->facts.FWVersion.Word < 0x01010B00))
++				return 0;
+ 		}
+ 	}
+ 
+@@ -5211,7 +5094,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 
+ 	pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
+ 	if (pDvBuf == NULL)
+-                goto doDv_done;
++		return 0;
+ 
+ 	sz = 0;
+ 	pbuf1 = (u8 *)pDvBuf;
+@@ -5237,7 +5120,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 	/* Skip this ID? Set cfg.cfghdr.hdr to force config page write
+ 	 */
+ 	{
+-		SpiCfgData *pspi_data = &ioc->spi_data;
++		SpiCfgData *pspi_data = &hd->ioc->spi_data;
+ 		if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+ 			/* Set the factor from nvram */
+ 			nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
+@@ -5247,7 +5130,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 			if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
+ 				(pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
+ 
+-				ddvprintk((MYIOC_s_INFO_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
++				ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
+ 					ioc->name, bus, id, lun));
+ 
+ 				dv.cmd = MPT_SET_MAX;
+@@ -5260,7 +5143,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 				cfg.physAddr = cfg1_dma_addr;
+ 				cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ 				cfg.dir = 1;
+-				mpt_config(ioc, &cfg);
++				mpt_config(hd->ioc, &cfg);
+ 				goto target_done;
+ 			}
+ 		}
+@@ -5295,7 +5178,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 	/* RAID Volume ID's may double for a physical device. If RAID but
+ 	 * not a physical ID as well, skip DV.
+ 	 */
+-	if ((ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
++	if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
+ 		goto target_done;
+ 
+ 
+@@ -5312,10 +5195,8 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+ 	readPage0 = 0;
+ 	sz = SCSI_MAX_INQUIRY_BYTES;
+ 	rc = MPT_SCANDV_GOOD;
+-
+-start_DV:
+ 	while (1) {
+-		ddvprintk((MYIOC_s_INFO_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
++		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
+ 		retcode = 0;
+ 		dv.cmd = MPT_SET_MIN;
+ 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+@@ -5324,7 +5205,7 @@ start_DV:
+ 		cfg.physAddr = cfg1_dma_addr;
+ 		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ 		cfg.dir = 1;
+-		if (mpt_config(ioc, &cfg) != 0)
++		if (mpt_config(hd->ioc, &cfg) != 0)
+ 			goto target_done;
+ 
+ 		/* Wide - narrow - wide workaround case
+@@ -5333,9 +5214,9 @@ start_DV:
+ 			/* Send an untagged command to reset disk Qs corrupted
+ 			 * when a parity error occurs on a Request Sense.
+ 			 */
+-			if ((ioc->facts.FWVersion.Word >= 0x01000600) ||
+-				((ioc->facts.FWVersion.Word >= 0x01010000) &&
+-				(ioc->facts.FWVersion.Word < 0x01010B00)) ) {
++			if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
++				((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
++				(hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
+ 
+ 				iocmd.cmd = REQUEST_SENSE;
+ 				iocmd.data_dma = buf1_dma;
+@@ -5400,6 +5281,12 @@ start_DV:
+ 		 * if PROCESSOR, quit DV.
+ 		 */
+ 		if (inq0 == TYPE_PROCESSOR) {
++			mptscsih_initTarget(hd,
++				bus,
++				id,
++				lun,
++				pbuf1,
++				sz);
+ 			goto target_done;
+ 		}
+ 
+@@ -5426,8 +5313,8 @@ start_DV:
+ 
+ 				if ((pbuf1[56] & 0x02) == 0) {
+ 					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+-					ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+-					ddvprintk((MYIOC_s_INFO_FMT
++					hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
++					ddvprintk((MYIOC_s_NOTE_FMT 
+ 					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
+ 					    ioc->name, id, pbuf1[56]));
+ 				}
+@@ -5440,7 +5327,7 @@ start_DV:
+ 			dv.cmd = MPT_SET_MAX;
+ 
+ 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+-		if (mpt_config(ioc, &cfg) != 0)
++		if (mpt_config(hd->ioc, &cfg) != 0)
+ 			goto target_done;
+ 
+ 		if ((!dv.now.width) && (!dv.now.offset))
+@@ -5473,7 +5360,7 @@ start_DV:
+ 					cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ 					cfg.dir = 0;
+ 
+-					if (mpt_config(ioc, &cfg) != 0)
++					if (mpt_config(hd->ioc, &cfg) != 0)
+ 						goto target_done;
+ 
+ 					sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
+@@ -5504,7 +5391,15 @@ start_DV:
+ 						if (!firstPass)
+ 							doFallback = 1;
+ 					} else {
+-
++						ddvprintk((MYIOC_s_NOTE_FMT
++						    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
++						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
++						mptscsih_initTarget(hd,
++							bus,
++							id,
++							lun,
++							pbuf1,
++							sz);
+ 						break;	/* test complete */
+ 					}
+ 				}
+@@ -5522,7 +5417,7 @@ start_DV:
+ 			firstPass = 0;
+ 		}
+ 	}
+-	ddvprintk((MYIOC_s_INFO_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
++	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
+ 
+ 	if (ioc->spi_data.mpt_dv == 0)
+ 		goto target_done;
+@@ -5534,10 +5429,10 @@ start_DV:
+ 	if (inq0 != 0)
+ 		goto target_done;
+ 
+-	ddvprintk((MYIOC_s_INFO_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
++	ddvprintk((MYIOC_s_NOTE_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
+ 			ioc->name, bus, id, lun, ioc->spi_data.PortFlags));
+ 	if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) {
+-		ddvprintk((MYIOC_s_INFO_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
++		ddvprintk((MYIOC_s_NOTE_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
+ 			ioc->name, bus, id, lun, ioc->spi_data.PortFlags));
+ 		goto target_done;
+ 	}
+@@ -5574,7 +5469,7 @@ start_DV:
+ 			u8 skey = hd->pLocal->sense[2] & 0x0F;
+ 			u8 asc = hd->pLocal->sense[12];
+ 			u8 ascq = hd->pLocal->sense[13];
+-			ddvprintk((MYIOC_s_WARN_FMT
++			ddvprintk((MYIOC_s_INFO_FMT
+ 				"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+ 				ioc->name, skey, asc, ascq));
+ 
+@@ -5646,7 +5541,7 @@ start_DV:
+ 					u8 skey = hd->pLocal->sense[2] & 0x0F;
+ 					u8 asc = hd->pLocal->sense[12];
+ 					u8 ascq = hd->pLocal->sense[13];
+-					ddvprintk((MYIOC_s_WARN_FMT
++					ddvprintk((MYIOC_s_INFO_FMT
+ 						"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+ 						ioc->name, skey, asc, ascq));
+ 					if (skey == ILLEGAL_REQUEST) {
+@@ -5665,11 +5560,6 @@ start_DV:
+ 							ioc->name));
+ 						goto target_done;
+ 					}
+-                               } else if (rc == MPT_SCANDV_FALLBACK) {
+-                                       doFallback = 1; /* set fallback flag */
+-                                       notDone++;
+-                                       goto start_DV;
+-
+ 				} else {
+ 					/* All other errors are fatal
+ 					 */
+@@ -5812,7 +5702,7 @@ skip_Reserve:
+ 					dv.cmd = MPT_FALLBACK;
+ 					mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+ 
+-					if (mpt_config(ioc, &cfg) != 0)
++					if (mpt_config(hd->ioc, &cfg) != 0)
+ 						goto target_done;
+ 
+ 					if ((!dv.now.width) && (!dv.now.offset))
+@@ -5826,7 +5716,7 @@ skip_Reserve:
+ 				/* Restart data test if UA, else quit.
+ 				 */
+ 				u8 skey = hd->pLocal->sense[2] & 0x0F;
+-				ddvprintk((MYIOC_s_WARN_FMT
++				ddvprintk((MYIOC_s_INFO_FMT
+ 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
+ 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
+ 				if (skey == UNIT_ATTENTION) {
+@@ -5891,7 +5781,7 @@ skip_Reserve:
+ 						dv.cmd = MPT_FALLBACK;
+ 						mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+ 
+-						if (mpt_config(ioc, &cfg) != 0)
++						if (mpt_config(hd->ioc, &cfg) != 0)
+ 							goto target_done;
+ 
+ 						if ((!dv.now.width) && (!dv.now.offset))
+@@ -5909,7 +5799,7 @@ skip_Reserve:
+ 				dv.cmd = MPT_FALLBACK;
+ 				mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+ 
+-				if (mpt_config(ioc, &cfg) != 0)
++				if (mpt_config(hd->ioc, &cfg) != 0)
+ 					 goto target_done;
+ 
+ 				if ((!dv.now.width) && (!dv.now.offset))
+@@ -5922,7 +5812,7 @@ skip_Reserve:
+ 				/* Restart data test if UA, else quit.
+ 				 */
+ 				u8 skey = hd->pLocal->sense[2] & 0x0F;
+-				ddvprintk((MYIOC_s_WARN_FMT
++				ddvprintk((MYIOC_s_INFO_FMT
+ 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
+ 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
+ 				if (skey == UNIT_ATTENTION) {
+@@ -5964,8 +5854,8 @@ target_done:
+ 		/* If disk, not U320, disable QAS
+ 		 */
+ 		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
+-			ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+-			ddvprintk((MYIOC_s_INFO_FMT
++			hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
++			ddvprintk((MYIOC_s_NOTE_FMT
+ 			    "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
+ 		}
+ 
+@@ -5980,7 +5870,7 @@ target_done:
+ 		cfg.physAddr = cfg1_dma_addr;
+ 		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ 		cfg.dir = 1;
+-		mpt_config(ioc, &cfg);
++		mpt_config(hd->ioc, &cfg);
+ 		 */
+ 	}
+ 
+@@ -5991,18 +5881,13 @@ target_done:
+ 			ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
+ 	}
+ 
+-doDv_done:
+ 	/* Done with the DV scan of the current target
+ 	 */
+ 	if (pDvBuf)
+ 		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
+ 
+-	ddvprintk((MYIOC_s_WARN_FMT "DV Done id=%d\n",ioc->name, id));
+-       ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_IN_PROGRESS);
+-       /* Post an IO that was pended while
+-        * DV was running.
+-        */
+-       mptscsih_post_PendingMF_command(ioc);
++	ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
++			ioc->name, id));
+ 
+ 	return retcode;
+ }
+@@ -6017,8 +5902,6 @@ doDv_done:
+ static void
+ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
+ {
+-	MPT_ADAPTER		*ioc = hd->ioc;
+-	struct _MPT_DEVICE	*pMptTarget;
+ 	VirtDevice		*pTarget;
+ 	SCSIDevicePage0_t	*pPage0;
+ 	SCSIDevicePage1_t	*pPage1;
+@@ -6032,48 +5915,49 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 
+ 	switch (cmd) {
+ 	case MPT_GET_NVRAM_VALS:
+-		ddvprintk((MYIOC_s_INFO_FMT "Getting NVRAM: ",
+-			ioc->name));
++		ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
++							 hd->ioc->name));
+ 		/* Get the NVRAM values and save in tmax
+ 		 * If not an LVD bus, the adapter minSyncFactor has been
+ 		 * already throttled back.
+ 		 */
+-		negoFlags = ioc->spi_data.noQas;
+-		pMptTarget = ioc->Target_List[0];
+-		pTarget = pMptTarget->Target[id];
+-		if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+-			data = ioc->spi_data.nvram[id];
+-			width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+-			if ((offset = ioc->spi_data.maxSyncOffset) == 0)
+-				factor = MPT_ASYNC;
+-			else {
+-				factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+-				if ((factor == 0) || (factor == MPT_ASYNC)){
++		negoFlags = hd->ioc->spi_data.noQas;
++		if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume) {
++			width = pTarget->maxWidth;
++			offset = pTarget->maxOffset;
++			factor = pTarget->minSyncFactor;
++			negoFlags |= pTarget->negoFlags;
++		} else {
++			if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++				data = hd->ioc->spi_data.nvram[id];
++				width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
++				if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
+ 					factor = MPT_ASYNC;
+-					offset = 0;
++				else {
++					factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
++					if ((factor == 0) || (factor == MPT_ASYNC)){
++						factor = MPT_ASYNC;
++						offset = 0;
++					}
+ 				}
+-			ddvprintk(("NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				id, width, factor, offset, negoFlags));
++			} else {
++				width = MPT_NARROW;
++				offset = 0;
++				factor = MPT_ASYNC;
+ 			}
+-		} else {
+-			width = MPT_NARROW;
+-			offset = 0;
+-			factor = MPT_ASYNC;
+-			ddvprintk(("NVRAM_INVALID id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-				id, width, factor, offset, negoFlags));
+-		}
+ 
+-		/* Set the negotiation flags */
+-		if (!width)
+-			negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++			/* Set the negotiation flags */
++			if (!width)
++				negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+ 
+-		if (!offset)
+-			negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++			if (!offset)
++				negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++		}
+ 
+ 		/* limit by adapter capabilities */
+-		width = min(width, ioc->spi_data.maxBusWidth);
+-		offset = min(offset, ioc->spi_data.maxSyncOffset);
+-		factor = max(factor, ioc->spi_data.minSyncFactor);
++		width = min(width, hd->ioc->spi_data.maxBusWidth);
++		offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
++		factor = max(factor, hd->ioc->spi_data.minSyncFactor);
+ 
+ 		/* Check Consistency */
+ 		if (offset && (factor < MPT_ULTRA2) && !width)
+@@ -6083,13 +5967,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 		dv->max.offset = offset;
+ 		dv->max.factor = factor;
+ 		dv->max.flags = negoFlags;
+-		ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
++		ddvprintk((" id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+ 				id, width, factor, offset, negoFlags));
+ 		break;
+ 
+ 	case MPT_UPDATE_MAX:
+-		ddvprintk((MYIOC_s_INFO_FMT
+-			"Updating with SDP0 Data: ", ioc->name));
++		ddvprintk((MYIOC_s_NOTE_FMT
++			"Updating with SDP0 Data: ", hd->ioc->name));
+ 		/* Update tmax values with those from Device Page 0.*/
+ 		pPage0 = (SCSIDevicePage0_t *) pPage;
+ 		if (pPage0) {
+@@ -6103,10 +5987,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 		dv->now.offset = dv->max.offset;
+ 		dv->now.factor = dv->max.factor;
+ 		ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-			id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
++				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+ 		break;
+ 
+ 	case MPT_SET_MAX:
++		ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
++								hd->ioc->name));
+ 		/* Set current to the max values. Update the config page.*/
+ 		dv->now.width = dv->max.width;
+ 		dv->now.offset = dv->max.offset;
+@@ -6115,18 +6001,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 
+ 		pPage1 = (SCSIDevicePage1_t *)pPage;
+ 		if (pPage1) {
+-			mpt_setSDP1parameters (dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags,
+-				&val, &configuration);
++			mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
++				dv->now.offset, &val, &configuration, dv->now.flags);
++			dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
+ 			pPage1->RequestedParameters = cpu_to_le32(val);
+ 			pPage1->Reserved = 0;
+ 			pPage1->Configuration = cpu_to_le32(configuration);
+ 		}
+ 
+-		dnegoprintk(("%s: Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-				ioc->name, id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
++		ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
++				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
+ 		break;
+ 
+ 	case MPT_SET_MIN:
++		ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
++								hd->ioc->name));
+ 		/* Set page to asynchronous and narrow
+ 		 * Do not update now, breaks fallback routine. */
+ 		width = MPT_NARROW;
+@@ -6136,20 +6026,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 
+ 		pPage1 = (SCSIDevicePage1_t *)pPage;
+ 		if (pPage1) {
+-			mpt_setSDP1parameters (width, factor, offset, negoFlags,
+-				&val, &configuration);
++			mptscsih_setDevicePage1Flags (width, factor,
++				offset, &val, &configuration, negoFlags);
++			dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++				id, width, factor, offset, negoFlags, val, configuration));
+ 			pPage1->RequestedParameters = cpu_to_le32(val);
+ 			pPage1->Reserved = 0;
+ 			pPage1->Configuration = cpu_to_le32(configuration);
+ 		}
+-		dnegoprintk(("%s: Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-				ioc->name, id, width, factor, offset, negoFlags, val, configuration));
++		ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
++				id, width, factor, offset, val, configuration, negoFlags));
+ 		break;
+ 
+ 	case MPT_FALLBACK:
+-		ddvprintk((MYIOC_s_INFO_FMT
++		ddvprintk((MYIOC_s_NOTE_FMT
+ 			"Fallback: Start: offset %d, factor %x, width %d \n",
+-				ioc->name, dv->now.offset,
++				hd->ioc->name, dv->now.offset,
+ 				dv->now.factor, dv->now.width));
+ 		width = dv->now.width;
+ 		offset = dv->now.offset;
+@@ -6212,32 +6104,31 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 
+ 		pPage1 = (SCSIDevicePage1_t *)pPage;
+ 		if (pPage1) {
+-			mpt_setSDP1parameters (width, factor, offset, dv->now.flags,
+-				&val, &configuration);
++			mptscsih_setDevicePage1Flags (width, factor, offset, &val,
++						&configuration, dv->now.flags);
++			dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
++			     id, width, offset, factor, dv->now.flags, val, configuration));
+ 
+ 			pPage1->RequestedParameters = cpu_to_le32(val);
+ 			pPage1->Reserved = 0;
+ 			pPage1->Configuration = cpu_to_le32(configuration);
+ 		}
+ 
+-		ddvprintk(("%s: Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-			     ioc->name, id, width, offset, factor, dv->now.flags, val, configuration));
++		ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
++			     id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
+ 		break;
+ 
+ 	case MPT_SAVE:
+-		ddvprintk((MYIOC_s_INFO_FMT
+-			"Saving to pTarget: "
+-			"id=%d width=%x factor=%x offset=%d negoFlags=%x\n",
+-				ioc->name, id, dv->now.width, dv->now.factor,
+-				dv->now.offset, dv->now.flags));
++		ddvprintk((MYIOC_s_NOTE_FMT
++			"Saving to Target structure: ", hd->ioc->name));
++		ddvprintk(("id=%d width=%x factor=%x offset=%d negoFlags=%x\n",
++			     id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+ 
+ 		/* Save these values to target structures
+ 		 * or overwrite nvram (phys disks only).
+ 		 */
+ 
+-		pMptTarget = ioc->Target_List[0];
+-		pTarget = pMptTarget->Target[id];
+-		if (pTarget && !pTarget->raidVolume ) {
++		if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume ) {
+ 			pTarget->maxWidth = dv->now.width;
+ 			pTarget->maxOffset = dv->now.offset;
+ 			pTarget->minSyncFactor = dv->now.factor;
+@@ -6246,8 +6137,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 			/* Preserv all flags, use
+ 			 * read-modify-write algorithm
+ 			 */
+-			if (ioc->spi_data.nvram) {
+-				data = ioc->spi_data.nvram[id];
++			if (hd->ioc->spi_data.nvram) {
++				data = hd->ioc->spi_data.nvram[id];
+ 
+ 				if (dv->now.width)
+ 					data &= ~MPT_NVRAM_WIDE_DISABLE;
+@@ -6260,14 +6151,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+ 				data &= ~MPT_NVRAM_SYNC_MASK;
+ 				data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
+ 
+-				ioc->spi_data.nvram[id] = data;
++				hd->ioc->spi_data.nvram[id] = data;
+ 			}
+ 		}
+ 		break;
+ 	}
+ }
+ 
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*	mptscsih_fillbuf - fill a buffer with a special data pattern
+  *		cleanup. For bus scan only.
+@@ -6422,11 +6312,10 @@ EXPORT_SYMBOL(mptscsih_taskmgmt_complete
+ EXPORT_SYMBOL(mptscsih_scandv_complete);
+ EXPORT_SYMBOL(mptscsih_event_process);
+ EXPORT_SYMBOL(mptscsih_ioc_reset);
+-EXPORT_SYMBOL(mptscsih_InternalCmdTimer_expired);
++EXPORT_SYMBOL(mptscsih_timer_expired);
+ EXPORT_SYMBOL(mptscsih_readFCDevicePage0);
+ EXPORT_SYMBOL(mptscsih_change_queue_depth);
+ EXPORT_SYMBOL(mptscsih_TMHandler);
+-EXPORT_SYMBOL(mptscsih_TM_timeout);
+ EXPORT_SYMBOL(mptscsih_sanity_check);
+ EXPORT_SYMBOL(mptscsih_poll);
+ EXPORT_SYMBOL(mptscsih_do_cmd);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h	2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptscsih.h,v 1.1.2.2 2003/05/07 14:08:35 Exp $
+  */
+@@ -54,17 +54,7 @@
+  *	SCSI Public stuff...
+  */
+ 
+-#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
+-#define MPT_SCANDV_DID_RESET		(0x00000001)
+-#define MPT_SCANDV_SENSE		(0x00000002)
+-#define MPT_SCANDV_SOME_ERROR		(0x00000004)
+-#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
+-#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
+-#define MPT_SCANDV_FALLBACK		(0x00000020)
+-#define MPT_SCANDV_BUSY			(0x00000040)
+-
+-//#define MPT_SCSI_CMD_PER_DEV_HIGH	64
+-#define MPT_SCSI_CMD_PER_DEV_HIGH      48
++#define MPT_SCSI_CMD_PER_DEV_HIGH	64
+ #define MPT_SCSI_CMD_PER_DEV_LOW	32
+ 
+ #define MPT_SCSI_CMD_PER_LUN		7
+@@ -133,7 +123,7 @@ extern int mptscsih_taskmgmt_complete(MP
+ extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+-extern void mptscsih_InternalCmdTimer_expired(unsigned long data);
++extern void mptscsih_timer_expired(unsigned long data);
+ extern int mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage);
+ extern void mptscsih_hot_plug_worker_thread(void * arg);
+ extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+@@ -141,4 +131,4 @@ extern int mptscsih_change_queue_depth(s
+ extern int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
+ extern int mptscsih_sanity_check(struct scsi_device *sdev);
+ extern void mptscsih_poll(struct scsi_device *sdev);
+-extern void scsi_print_command(struct scsi_cmnd *cmd);
++extern void scsi_print_command(struct scsi_cmnd *cmd);
+\ Pas de fin de ligne à la fin du fichier.
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c	2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c	2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -73,7 +73,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ 
+ /* Command line args */
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+@@ -146,13 +145,12 @@ static struct scsi_host_template mptspi_
+ 	.change_queue_depth 		= mptscsih_change_queue_depth,
+ #endif
+ 	.eh_abort_handler		= mptscsih_abort,
+-        .eh_device_reset_handler        = mptscsih_dev_reset,
+ 	.eh_bus_reset_handler		= mptscsih_bus_reset,
+ 	.eh_host_reset_handler		= mptscsih_host_reset,
+ 	.bios_param			= mptscsih_bios_param,
+ 	.can_queue			= MPT_SCSI_CAN_QUEUE,
+ 	.this_id			= -1,
+-	.sg_tablesize			= CONFIG_FUSION_MAX_SGE,
++	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
+ 	.max_sectors			= 8192,
+ 	.cmd_per_lun			= 7,
+ 	.use_clustering			= ENABLE_CLUSTERING,
+@@ -191,6 +189,8 @@ mptspi_probe(struct pci_dev *pdev, const
+ 	MPT_ADAPTER 		*ioc;
+ 	unsigned long		 flags;
+ 	int			 sz, ii;
++	int			 numSGE = 0;
++	int			 scale;
+ 	int			 ioc_cap;
+ 	u8			*mem;
+ 	int			error=0;
+@@ -269,7 +269,7 @@ mptspi_probe(struct pci_dev *pdev, const
+ 		ioc->name, mpt_can_queue, ioc->req_depth,
+ 		sh->can_queue));
+ 
+-	sh->max_id = ioc->DevicesPerBus;
++	sh->max_id = MPT_MAX_SCSI_DEVICES;
+ 
+ 	sh->max_lun = MPT_LAST_LUN + 1;
+ 	sh->max_channel = 0;
+@@ -278,7 +278,36 @@ mptspi_probe(struct pci_dev *pdev, const
+ 	/* Required entry.
+ 	 */
+ 	sh->unique_id = ioc->id;
+-	sh->sg_tablesize = ioc->sg_tablesize;
++
++	/* Verify that we won't exceed the maximum
++	 * number of chain buffers
++	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
++	 * For 32bit SGE's:
++	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++	 *               + (req_sz - 64)/sizeof(SGE)
++	 * A slightly different algorithm is required for
++	 * 64bit SGEs.
++	 */
++	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++	if (sizeof(dma_addr_t) == sizeof(u64)) {
++		numSGE = (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	} else {
++		numSGE = 1 + (scale - 1) *
++		  (ioc->facts.MaxChainDepth-1) + scale +
++		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++		  sizeof(u32));
++	}
++
++	if (numSGE < sh->sg_tablesize) {
++		/* Reset this value */
++		dprintk((MYIOC_s_INFO_FMT
++		  "Resetting sg_tablesize to %d from %d\n",
++		  ioc->name, numSGE, sh->sg_tablesize));
++		sh->sg_tablesize = numSGE;
++	}
+ 
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+ 	/* Set the pci device pointer in Scsi_Host structure.
+@@ -307,29 +336,29 @@ mptspi_probe(struct pci_dev *pdev, const
+ 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ 		 ioc->name, hd->ScsiLookup, sz));
+ 
+-	for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-		/* Allocate memory for the device structures.
+-		 * A non-Null pointer at an offset
+-		 * indicates a device exists.
+-		 */
+-		sz = ioc->DevicesPerBus * sizeof(void *);
+-		mem = kmalloc(sz, GFP_ATOMIC);
+-		if (mem == NULL) {
+-			error = -ENOMEM;
+-			goto out_mptspi_probe;
+-		}
++	/* Allocate memory for the device structures.
++	 * A non-Null pointer at an offset
++	 * indicates a device exists.
++	 * max_id = 1 + maximum id (hosts.h)
++	 */
++	sz = sh->max_id * sizeof(void *);
++	mem = kmalloc(sz, GFP_ATOMIC);
++	if (mem == NULL) {
++		error = -ENOMEM;
++		goto out_mptspi_probe;
++	}
+ 
+-		memset(mem, 0, sz);
+-		ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++	memset(mem, 0, sz);
++	hd->Targets = (VirtDevice **) mem;
+ 
+-		dinitprintk((KERN_INFO
+-		  " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz));
+-	}
++	dprintk((KERN_INFO
++	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+ 
+ 	/* Clear the TM flags
+ 	 */
+ 	hd->tmPending = 0;
+ 	hd->tmState = TM_STATE_NONE;
++	hd->resetPending = 0;
+ 	hd->abortSCpnt = NULL;
+ 
+ 	/* Clear the pointer used to store
+@@ -339,21 +368,16 @@ mptspi_probe(struct pci_dev *pdev, const
+ 	 */
+ 	hd->cmdPtr = NULL;
+ 
+-	/* Initialize this IOC's  timers
++	/* Initialize this SCSI Hosts' timers
+ 	 * To use, set the timer expires field
+-	 * and add_timer.Used for internally
+-         * generated commands.
++	 * and add_timer
+ 	 */
+-       init_timer(&hd->InternalCmdTimer);
+-       hd->InternalCmdTimer.data = (unsigned long) hd;
+-       hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-
+-       init_timer(&ioc->TMtimer);
+-       ioc->TMtimer.data = (unsigned long) ioc;
+-       ioc->TMtimer.function = mptscsih_TM_timeout;
++	init_timer(&hd->timer);
++	hd->timer.data = (unsigned long) hd;
++	hd->timer.function = mptscsih_timer_expired;
+ 
+-       ioc->spi_data.Saf_Te = mpt_saf_te;
+-       hd->mpt_pq_filter = mpt_pq_filter;
++	ioc->spi_data.Saf_Te = mpt_saf_te;
++	hd->mpt_pq_filter = mpt_pq_filter;
+ 
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ 	if (ioc->spi_data.maxBusWidth > mpt_width)
+@@ -364,6 +388,7 @@ mptspi_probe(struct pci_dev *pdev, const
+ 		ioc->spi_data.maxSyncOffset = 0;
+ 	}
+ 	ioc->spi_data.mpt_dv = mpt_dv;
++	hd->negoNvram = 0;
+ 
+ 	ddvprintk((MYIOC_s_INFO_FMT
+ 		"dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
+@@ -374,7 +399,7 @@ mptspi_probe(struct pci_dev *pdev, const
+ 		mpt_saf_te,
+ 		mpt_pq_filter));
+ #else
+-
++	hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+ 	ddvprintk((MYIOC_s_INFO_FMT
+ 		"saf_te %x mpt_pq_filter %x\n",
+ 		ioc->name,
+@@ -387,18 +412,18 @@ mptspi_probe(struct pci_dev *pdev, const
+ 		ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
+ 	else
+ 		ioc->spi_data.noQas = 0;
+-/* enable domain validation flags */
+ 
+ 	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+-ioc->spi_data.dvStatus[ii] =
++		ioc->spi_data.dvStatus[ii] =
++		  MPT_SCSICFG_NEGOTIATE;
+ 
+-(MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE);
++	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
++		ioc->spi_data.dvStatus[ii] |=
++		  MPT_SCSICFG_DV_NOT_DONE;
+ 
+ 	init_waitqueue_head(&hd->scandv_waitq);
+ 	hd->scandv_wait_done = 0;
+ 	hd->last_queue_full = 0;
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+ 
+ 	error = scsi_add_host (sh, &ioc->pcidev->dev);
+ 	if(error) {
+@@ -414,10 +439,6 @@ ioc->spi_data.dvStatus[ii] =
+ 		    0, 0, 0, 0, 5 /* 5 second timeout */);
+ 	}
+ 
+-       dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS\n",
+-               ioc->name, __FUNCTION__));
+-       mpt_writeSDP1(ioc, 0, 0, MPT_SCSICFG_ALL_IDS);
+-
+ 	scsi_scan_host(sh);
+ 	return 0;
+ 
+@@ -464,7 +485,7 @@ mptspi_init(void)
+ 
+ 	if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
+ 		devtprintk((KERN_INFO MYNAM
+-        ": Registered for IOC event notifications mptspiDoneCtx=%08x\n", mptspiDoneCtx));
++		  ": Registered for IOC event notifications\n"));
+ 	}
+ 
+ 	if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
diff --git a/lustre/kernel_patches/series/2.6-rhel4.series b/lustre/kernel_patches/series/2.6-rhel4.series
index 072df44c0c6678cad95586f907eb9e204f8c5094..8cdcacb5fb24aa8d62fdfd2d9ce8793f519c8575 100644
--- a/lustre/kernel_patches/series/2.6-rhel4.series
+++ b/lustre/kernel_patches/series/2.6-rhel4.series
@@ -38,3 +38,4 @@ quota-umount-race-fix.patch
 quota-deadlock-on-pagelock-ext3.patch
 vfs-keep-inode-hashed-for-clear-inode.patch
 modpost_external_module_updates_rhel4.patch
+mpt-fusion-downgrade-to-3_02_73-rhel4.patch