[RFC] raid class support for mptfusion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds both raid class support and SPI transport class support (the
raid classes are built on top of the SPI transport class support, so it
just seemed easier to combine the two patches).  The raid class features
are quite primitive, but it can now show the state of the raid array and
the resync completion fraction.  The next project will be to add a piece
state model allowing the individual raid pieces to be taken on and
offline.

James
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -9,6 +9,8 @@ config FUSION_SPI
 	tristate "Fusion MPT ScsiHost drivers for SPI"
 	depends on PCI && SCSI
 	select FUSION
+	select SCSI_SPI_ATTRS
+	select RAID_ATTRS
 	---help---
 	  SCSI HOST support for a parallel SCSI host adapters.
 
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -333,6 +333,8 @@ typedef struct _SYSIF_REGS
  */
 typedef struct _VirtDevice {
 	struct scsi_device	*device;
+	RaidVolumePage0_t	*raidVolume;	/* set, if RAID Volume */
+	int			 raidpg0size;
 	u8			 tflags;
 	u8			 ioc_id;
 	u8			 target_id;
@@ -341,7 +343,6 @@ typedef struct _VirtDevice {
 	u8			 maxOffset;	/* 0 if async */
 	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
 	u8			 negoFlags;	/* bit field, see above */
-	u8			 raidVolume;	/* set, if RAID Volume */
 	u8			 type;		/* byte 0 of Inquiry data */
 	u8			 cflags;	/* controller flags */
 	u8			 rsvd1raid;
@@ -861,10 +862,15 @@ typedef struct _mpt_sge {
 typedef struct _MPT_LOCAL_REPLY {
 	ConfigPageHeader_t header;
 	int	completion;
-	u8	sense[SCSI_STD_SENSE_BYTES];
-	u8	scsiStatus;
-	u8	skip;
-	u32	pad;
+	union {
+		struct {
+			u8	sense[SCSI_STD_SENSE_BYTES];
+			u8	scsiStatus;
+			u8	skip;
+			u32	pad;
+		} s;
+		u64	r[6];
+	} u;
 } MPT_LOCAL_REPLY;
 
 #define MPT_HOST_BUS_UNKNOWN		(0xFF)
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -151,8 +151,6 @@ int		mptscsih_ioc_reset(MPT_ADAPTER *ioc
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 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);
@@ -163,19 +161,10 @@ static int	mptscsih_synchronize_cache(MP
 
 static struct work_struct   mptscsih_persistTask;
 
-#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 id);
-static void	mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
-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 void	mptscsih_fillbuf(char *buffer, int size, int index, int width);
-static void	mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
-#endif
-
 void 		mptscsih_remove(struct pci_dev *);
 void 		mptscsih_shutdown(struct pci_dev *);
+static int	mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id);
 #ifdef CONFIG_PM
 int 		mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 int 		mptscsih_resume(struct pci_dev *pdev);
@@ -183,16 +172,6 @@ int 		mptscsih_resume(struct pci_dev *pd
 
 #define SNS_LEN(scp)	sizeof((scp)->sense_buffer)
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*
- * Domain Validation task structure
- */
-static DEFINE_SPINLOCK(dvtaskQ_lock);
-static int dvtaskQ_active = 0;
-static int dvtaskQ_release = 0;
-static struct work_struct	dvTaskQ_task;
-#endif
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_add_sge - Place a simple SGE at address pAddr.
@@ -993,8 +972,6 @@ mptscsih_remove(struct pci_dev *pdev)
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
 	struct Scsi_Host 	*host = ioc->sh;
 	MPT_SCSI_HOST		*hd;
-	int 		 	count;
-	unsigned long	 	flags;
 	int sz1;
 
 	if(!host) {
@@ -1007,27 +984,6 @@ mptscsih_remove(struct pci_dev *pdev)
 	if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
 		return;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-	/* Check DV thread active */
-	count = 10 * HZ;
-	spin_lock_irqsave(&dvtaskQ_lock, flags);
-	if (dvtaskQ_active) {
-		spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-		while(dvtaskQ_active && --count) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
-		}
-	} else {
-		spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-	}
-	if (!count)
-		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", 10 * HZ, count);
-#endif
-#endif
-
 	mptscsih_shutdown(pdev);
 
 	sz1=0;
@@ -1120,21 +1076,6 @@ mptscsih_resume(struct pci_dev *pdev)
 	if(!hd)
 		return 0;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-	{
-	unsigned long lflags;
-	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);
-	}
-	}
-#endif
 	return 0;
 }
 
@@ -1289,6 +1230,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	VirtDevice		*pTarget = SCpnt->device->hostdata;
+	int	 target;
 	int	 lun;
 	u32	 datalen;
 	u32	 scsictl;
@@ -1298,9 +1240,12 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
 	int	 ii;
 
 	hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+	target = SCpnt->device->id;
 	lun = SCpnt->device->lun;
 	SCpnt->scsi_done = done;
 
+	pTarget = mpt_target(hd, SCpnt->device->channel, target);
+
 	dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
 
@@ -1310,6 +1255,12 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	if (SCpnt->device->channel && !mptscsih_is_raid_volume(hd, target)) {
+		SCpnt->result = DID_NO_CONNECT << 16;
+		done(SCpnt);
+		return 0;
+	}
+
 	/*
 	 *  Put together a MPT SCSI request...
 	 */
@@ -1353,10 +1304,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
 
 	/* Use the above information to set up the message frame
 	 */
-	pScsiReq->TargetID = (u8) pTarget->target_id;
-	pScsiReq->Bus = pTarget->bus_id;
+	pScsiReq->TargetID = (u8) target;
+	pScsiReq->Bus = 0;
 	pScsiReq->ChainOffset = 0;
-	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+	if (SCpnt->device->channel)
+		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+	else
+		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 	pScsiReq->CDBLength = SCpnt->cmd_len;
 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
 	pScsiReq->Reserved = 0;
@@ -1404,49 +1358,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
 	hd->ScsiLookup[my_idx] = SCpnt;
 	SCpnt->host_scribble = NULL;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-	if (hd->ioc->bus_type == SCSI) {
-		int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
-		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",
 			hd->ioc->name, SCpnt, mf, my_idx));
@@ -2150,6 +2061,22 @@ mptscsih_bios_param(struct scsi_device *
 	return 0;
 }
 
+static int 
+mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
+{
+	int i;
+
+	if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
+		return 0;
+
+	for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		if (id == hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+			return 1;
+	}
+
+	return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	OS entry point to allow host driver to alloc memory
@@ -2165,10 +2092,10 @@ mptscsih_slave_alloc(struct scsi_device 
 	VirtDevice		*vdev;
 	uint			target = device->id;
 
-	if (hd == NULL)
-		return -ENODEV;
+	if (device->channel)
+		device->no_uld_attach = 1;
 
-	if ((vdev = hd->Targets[target]) != NULL)
+	if ((vdev = mpt_target(hd, device->channel, target)) != NULL)
 		goto out;
 
 	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
@@ -2181,13 +2108,22 @@ mptscsih_slave_alloc(struct scsi_device 
 	memset(vdev, 0, sizeof(VirtDevice));
 	vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
 	vdev->ioc_id = hd->ioc->id;
-	vdev->target_id = device->id;
+	vdev->target_id = target;
 	vdev->bus_id = device->channel;
-	vdev->raidVolume = 0;
-	hd->Targets[device->id] = vdev;
-	if (hd->ioc->bus_type == SCSI) {
+	vdev->device = device;
+	vdev->raidVolume = NULL;
+	hd->Targets[target + (host->max_id * device->channel)] = vdev;
+	if (device->channel == 0 && hd->ioc->bus_type == SCSI) {
 		if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
-			vdev->raidVolume = 1;
+			struct _CONFIG_PAGE_HEADER hdr;
+			if (mptscsih_read_raid_page0(device, (struct _CONFIG_PAGE_RAID_VOL_0 *)&hdr, sizeof(hdr), 0) < 0)
+				goto out_free;
+			vdev->raidpg0size = hdr.PageLength * 4;
+			vdev->raidVolume = kmalloc(vdev->raidpg0size, GFP_KERNEL);
+			if (!vdev->raidVolume)
+				goto out_free;
+			if (mptscsih_read_raid_page0(device, vdev->raidVolume, vdev->raidpg0size, hdr.PageVersion) < 0)
+				goto out_free;
 			ddvtprintk((KERN_INFO
 			    "RAID Volume @ id %d\n", device->id));
 		}
@@ -2199,6 +2135,12 @@ mptscsih_slave_alloc(struct scsi_device 
 	vdev->num_luns++;
 	device->hostdata = vdev;
 	return 0;
+ out_free:
+	dev_printk(KERN_ERR, &device->sdev_gendev, "failed to allocate vdev\n");
+	if (vdev)
+		kfree(vdev->raidVolume);
+	kfree(vdev);
+	return -EINVAL;
 }
 
 /*
@@ -2219,13 +2161,15 @@ mptscsih_slave_destroy(struct scsi_devic
 
 	mptscsih_search_running_cmds(hd, target, lun);
 
-	vdev = hd->Targets[target];
+	vdev = mpt_target(hd, device->channel, target);
 	vdev->luns[0] &= ~(1 << lun);
 	if (--vdev->num_luns)
 		return;
 
-	kfree(hd->Targets[target]);
-	hd->Targets[target] = NULL;
+	kfree(vdev->raidVolume);
+
+	kfree(hd->Targets[target + (device->channel * host->max_id)]);
+	hd->Targets[target + (device->channel * host->max_id)] = NULL;
 
 	if (hd->ioc->bus_type == SCSI) {
 		if (mptscsih_is_phys_disk(hd->ioc, target)) {
@@ -2257,10 +2201,11 @@ mptscsih_change_queue_depth(struct scsi_
 	VirtDevice *pTarget;
 	int	max_depth;
 	int	tagged;
+	int	target = sdev->id;
 
 	if (hd == NULL)
 		return 0;
-	if (!(pTarget = hd->Targets[sdev->id]))
+	if (!(pTarget = mpt_target(hd, sdev->channel, target)))
 		return 0;
 
 	if (hd->ioc->bus_type == SCSI) {
@@ -2302,6 +2247,7 @@ mptscsih_slave_configure(struct scsi_dev
 	struct Scsi_Host	*sh = device->host;
 	VirtDevice		*pTarget;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
+	int			target = device->id;
 
 	if ((hd == NULL) || (hd->Targets == NULL)) {
 		return 0;
@@ -2315,13 +2261,13 @@ mptscsih_slave_configure(struct scsi_dev
 		hd->ioc->name, device->sdtr, device->wdtr,
 		device->ppr, device->inquiry_len));
 
-	if (device->id > sh->max_id) {
+	if (target > sh->max_id) {
 		/* error case, should never happen */
 		scsi_adjust_queue_depth(device, 0, 1);
 		goto slave_configure_exit;
 	}
 
-	pTarget = hd->Targets[device->id];
+	pTarget = mpt_target(hd, device->channel, target);
 
 	if (pTarget == NULL) {
 		/* Driver doesn't know about this device.
@@ -2337,7 +2283,7 @@ mptscsih_slave_configure(struct scsi_dev
 		goto slave_configure_exit;
 	}
 
-	mptscsih_initTarget(hd, device->channel, device->id, device->lun,
+	mptscsih_initTarget(hd, device->channel, target, device->lun,
 		device->inquiry, device->inquiry_len );
 	mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
 
@@ -2508,7 +2454,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
 		/* 4. Renegotiate to all devices, if SCSI
 		 */
 		if (ioc->bus_type == SCSI) {
-			dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
+			printk("writeSDP1: ALL_IDS USE_NVRAM\n");
 			mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
 		}
 
@@ -2598,24 +2544,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
 		break;
 
 	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
-	{
-		pMpiEventDataRaid_t pRaidEventData =
-		    (pMpiEventDataRaid_t) pEvReply->Data;
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-		/* Domain Validation Needed */
-		if (ioc->bus_type == SCSI &&
-		    pRaidEventData->ReasonCode ==
-		    MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
-			mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
-#endif
-		break;
-	}
-
-	/* Persistent table is full. */
-	case MPI_EVENT_PERSISTENT_TABLE_FULL:
-		INIT_WORK(&mptscsih_persistTask,
-		    mptscsih_sas_persist_clear_table,(void *)ioc);
-		schedule_work(&mptscsih_persistTask);
 		break;
 
 	case MPI_EVENT_NONE:				/* 00 */
@@ -2676,7 +2604,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 	if (data[0] & 0xe0)
 		return;
 
-	if ((vdev = hd->Targets[target_id]) == NULL) {
+	if ((vdev = mpt_target(hd, bus_id, target_id)) == NULL) {
 		return;
 	}
 
@@ -2732,7 +2660,6 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
 				}
 			}
-			mptscsih_setTargetNegoParms(hd, vdev, data_56);
 		} else {
 			/* Initial Inquiry may not request enough data bytes to
 			 * obtain byte 57.  DV will; if target doesn't return
@@ -2743,232 +2670,10 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 				 */
 					data_56 = data[56];
 					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-					mptscsih_setTargetNegoParms(hd, vdev, data_56);
-				}
-			}
-		}
-	}
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Update the target negotiation parameters based on the
- *  the Inquiry data, adapter capabilities, and NVRAM settings.
- *
- */
-static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
-{
-	SpiCfgData *pspi_data = &hd->ioc->spi_data;
-	int  id = (int) target->target_id;
-	int  nvram;
-	VirtDevice	*vdev;
-	int ii;
-	u8 width = MPT_NARROW;
-	u8 factor = MPT_ASYNC;
-	u8 offset = 0;
-	u8 version, nfactor;
-	u8 noQas = 1;
-
-	target->negoFlags = pspi_data->noQas;
-
-	/* 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 = target->inq_data[2] & 0x07;
-	if (version < 2) {
-		width = 0;
-		factor = MPT_ULTRA2;
-		offset = pspi_data->maxSyncOffset;
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	} else {
-		if (target->inq_data[7] & 0x20) {
-			width = 1;
-		}
-
-		if (target->inq_data[7] & 0x10) {
-			factor = pspi_data->minSyncFactor;
-			if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
-				/* bits 2 & 3 show Clocking support */
-				if ((byte56 & 0x0C) == 0)
-					factor = MPT_ULTRA2;
-				else {
-					if ((byte56 & 0x03) == 0)
-						factor = MPT_ULTRA160;
-					else {
-						factor = MPT_ULTRA320;
-						if (byte56 & 0x02)
-						{
-							ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
-							noQas = 0;
-						}
-						if (target->inq_data[0] == TYPE_TAPE) {
-							if (byte56 & 0x01)
-								target->negoFlags |= MPT_TAPE_NEGO_IDP;
-						}
-					}
-				}
-			} else {
-				ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
-				noQas = 0;
-			}
-
-			offset = pspi_data->maxSyncOffset;
-
-			/* If RAID, never disable QAS
-			 * else if non RAID, do not disable
-			 *   QAS if bit 1 is set
-			 * bit 1 QAS support, non-raid only
-			 * bit 0 IU support
-			 */
-			if (target->raidVolume == 1) {
-				noQas = 0;
-			}
-		} else {
-			factor = MPT_ASYNC;
-			offset = 0;
-		}
-	}
-
-	if ( (target->inq_data[7] & 0x02) == 0) {
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	}
-
-	/* Update tflags based on NVRAM settings. (SCSI only)
-	 */
-	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-		nvram = pspi_data->nvram[id];
-		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-
-		if (width)
-			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-		if (offset > 0) {
-			/* Ensure factor is set to the
-			 * maximum of: adapter, nvram, inquiry
-			 */
-			if (nfactor) {
-				if (nfactor < pspi_data->minSyncFactor )
-					nfactor = pspi_data->minSyncFactor;
-
-				factor = max(factor, nfactor);
-				if (factor == MPT_ASYNC)
-					offset = 0;
-			} else {
-				offset = 0;
-				factor = MPT_ASYNC;
-		}
-		} else {
-			factor = MPT_ASYNC;
-		}
-	}
-
-	/* Make sure data is consistent
-	 */
-	if ((!width) && (factor < MPT_ULTRA2)) {
-		factor = MPT_ULTRA2;
-	}
-
-	/* Save the data to the target structure.
-	 */
-	target->minSyncFactor = factor;
-	target->maxOffset = offset;
-	target->maxWidth = width;
-
-	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
-
-	/* Disable unused features.
-	 */
-	if (!width)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-	if (!offset)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
-	if ( factor > MPT_ULTRA320 )
-		noQas = 0;
-
-	/* GEM, processor WORKAROUND
-	 */
-	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;
-			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
-			/* Disable QAS in a mixed configuration case
-	 		*/
-
-			ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-			for (ii = 0; ii < id; ii++) {
-				if ( (vdev = hd->Targets[ii]) ) {
-					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-					mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
 				}
 			}
 		}
 	}
-
-	/* Write SDP1 on this I/O to this target */
-	if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
-		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) {
-		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()
@@ -3189,17 +2894,6 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
 			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;
 
@@ -3216,8 +2910,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
 			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));
+		printk(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.
@@ -3414,7 +3108,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 			hd->ioc->name, mf, mr, req_idx));
 
 	hd->pLocal = &hd->localReply;
-	hd->pLocal->scsiStatus = 0;
+	hd->pLocal->u.s.scsiStatus = 0;
 
 	/* If target struct exists, clear sense valid flag.
 	 */
@@ -3468,6 +3162,9 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 					completionCode = MPT_SCANDV_GOOD;
 				else
 					completionCode = MPT_SCANDV_SOME_ERROR;
+				memcpy(hd->pLocal->u.r, pr,
+				       min((size_t)pr->MsgLength*4,
+					   sizeof(hd->pLocal->u.r)));
 
 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
 				u8		*sense_data;
@@ -3476,13 +3173,13 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 				/* save sense data in global structure
 				 */
 				completionCode = MPT_SCANDV_SENSE;
-				hd->pLocal->scsiStatus = scsi_status;
+				hd->pLocal->u.s.scsiStatus = scsi_status;
 				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);
+				memcpy(hd->pLocal->u.s.sense, sense_data, sz);
 
 				ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
 						sense_data));
@@ -3498,7 +3195,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 				completionCode = MPT_SCANDV_DID_RESET;
 			else {
 				completionCode = MPT_SCANDV_GOOD;
-				hd->pLocal->scsiStatus = scsi_status;
+				hd->pLocal->u.s.scsiStatus = scsi_status;
 			}
 			break;
 
@@ -3581,78 +3278,6 @@ mptscsih_timer_expired(unsigned long dat
 	return;
 }
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_do_raid - Format and Issue a RAID volume request message.
- *	@hd: Pointer to scsi host structure
- *	@action: What do be done.
- *	@id: Logical target id.
- *	@bus: Target locations bus.
- *
- *	Returns: < 0 on a fatal error
- *		0 on success
- *
- *	Remark: Wait to return until reply processed by the ISR.
- */
-static int
-mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
-{
-	MpiRaidActionRequest_t	*pReq;
-	MPT_FRAME_HDR		*mf;
-	int			in_isr;
-
-	in_isr = in_interrupt();
-	if (in_isr) {
-		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(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
-		ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
-					hd->ioc->name));
-		return -EAGAIN;
-	}
-	pReq = (MpiRaidActionRequest_t *)mf;
-	pReq->Action = action;
-	pReq->Reserved1 = 0;
-	pReq->ChainOffset = 0;
-	pReq->Function = MPI_FUNCTION_RAID_ACTION;
-	pReq->VolumeID = io->id;
-	pReq->VolumeBus = io->bus;
-	pReq->PhysDiskNum = io->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);
-
-	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
-			hd->ioc->name, action, io->id));
-
-	hd->pLocal = NULL;
-	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
-	hd->scandv_wait_done = 0;
-
-	/* Save cmd pointer, for resource free if timeout or
-	 * FW reload occurs
-	 */
-	hd->cmdPtr = 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))
-		return -1;
-
-	return 0;
-}
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -3886,7 +3511,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
 
 	if (hd->pLocal) {
 		rc = hd->pLocal->completion;
-		hd->pLocal->skip = 0;
+		hd->pLocal->u.s.skip = 0;
 
 		/* Always set fatal error codes in some cases.
 		 */
@@ -4054,151 +3679,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
 	return 0;
 }
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_domainValidation - Top level handler for domain validation.
- *	@hd: Pointer to MPT_SCSI_HOST structure.
- *
- *	Uses the ISR, but with special processing.
- *	Called from schedule, should not be in interrupt mode.
- *	While thread alive, do dv for all devices needing dv
- *
- *	Return: None.
- */
-static void
-mptscsih_domainValidation(void *arg)
-{
-	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);
-
-	/* 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);
-
-			msleep(250);
-
-			/* DV only to SCSI adapters */
-			if (ioc->bus_type != SCSI)
-				continue;
-
-			/* Make sure everything looks ok */
-			if (ioc->sh == NULL)
-				continue;
-
-			hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-			if (hd == NULL)
-				continue;
-
-			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;
-			}
-
-			maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
-
-			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];
-
-				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(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 (mptscsih_doDv(hd, 0, id) == 1) {
-						/* Untagged device was busy, try again
-						 */
-						hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
-						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
-					} else {
-						/* DV is complete. Clear flags.
-						 */
-						hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
-					}
-
-					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);
-				}
-			}
-		}
-	}
-
-	spin_lock_irqsave(&dvtaskQ_lock, flags);
-	dvtaskQ_active = 0;
-	spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-	return;
-}
-
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
 /* Search IOC page 3 to determine if this is hidden physical disk
  */
 static int
@@ -4217,1370 +3697,153 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, 
 	return 0;
 }
 
-/* Write SDP1 if no QAS has been enabled
- */
-static void
-mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
+int
+mptscsih_raid_action(MPT_SCSI_HOST *hd, int action, int volume, int volbus,
+		     MpiRaidActionReply_t *pRep, int repLen)
 {
-	VirtDevice *pTarget;
-	int ii;
-
-	if (hd->Targets == NULL)
-		return;
-
-	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-		if (ii == id)
-			continue;
-
-		if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
-			continue;
+	MpiRaidActionRequest_t	*pReq;
+	MPT_FRAME_HDR		*mf;
 
-		pTarget = hd->Targets[ii];
-
-		if ((pTarget != NULL) && (!pTarget->raidVolume)) {
-			if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
-				pTarget->negoFlags |= hd->ioc->spi_data.noQas;
-				dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
-				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;
-}
-
-
-
-#define MPT_GET_NVRAM_VALS	0x01
-#define MPT_UPDATE_MAX		0x02
-#define MPT_SET_MAX		0x04
-#define MPT_SET_MIN		0x08
-#define MPT_FALLBACK		0x10
-#define MPT_SAVE		0x20
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_doDv - Perform domain validation to a target.
- *	@hd: Pointer to MPT_SCSI_HOST structure.
- *	@portnum: IOC port number.
- *	@target: Physical ID of this target
- *
- *	Uses the ISR, but with special processing.
- *	MUST be single-threaded.
- *	Test will exit if target is at async & narrow.
- *
- *	Return: None.
- */
-static int
-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
-{
-	MPT_ADAPTER		*ioc = hd->ioc;
-	VirtDevice		*pTarget;
-	SCSIDevicePage1_t	*pcfg1Data;
-	SCSIDevicePage0_t	*pcfg0Data;
-	u8			*pbuf1;
-	u8			*pbuf2;
-	u8			*pDvBuf;
-	dma_addr_t		 dvbuf_dma = -1;
-	dma_addr_t		 buf1_dma = -1;
-	dma_addr_t		 buf2_dma = -1;
-	dma_addr_t		 cfg1_dma_addr = -1;
-	dma_addr_t		 cfg0_dma_addr = -1;
-	ConfigPageHeader_t	 header1;
-	ConfigPageHeader_t	 header0;
-	DVPARAMETERS		 dv;
-	INTERNAL_CMD		 iocmd;
-	CONFIGPARMS		 cfg;
-	int			 dv_alloc = 0;
-	int			 rc, sz = 0;
-	int			 bufsize = 0;
-	int			 dataBufSize = 0;
-	int			 echoBufSize = 0;
-	int			 notDone;
-	int			 patt;
-	int			 repeat;
-	int			 retcode = 0;
-	int			 nfactor =  MPT_ULTRA320;
-	char			 firstPass = 1;
-	char			 doFallback = 0;
-	char			 readPage0;
-	char			 bus, lun;
-	char			 inq0 = 0;
-
-	if (ioc->spi_data.sdp1length == 0)
-		return 0;
-
-	if (ioc->spi_data.sdp0length == 0)
-		return 0;
-
-	/* If multiple buses are used, require that the initiator
-	 * id be the same on all buses.
-	 */
-	if (id == ioc->pfacts[0].PortSCSIID)
-		return 0;
-
-	lun = 0;
-	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
-	 */
-	memset (&dv, 0, sizeof(DVPARAMETERS));
-	dv.id = id;
-
-	/* Populate tmax with the current maximum
-	 * transfer parameters for this target.
-	 * Exit if narrow and async.
-	 */
-	dv.cmd = MPT_GET_NVRAM_VALS;
-	mptscsih_dv_parms(hd, &dv, NULL);
-
-	/* Prep SCSI IO structure
-	 */
-	iocmd.id = id;
-	iocmd.bus = bus;
-	iocmd.lun = lun;
-	iocmd.flags = 0;
-	iocmd.physDiskNum = -1;
-	iocmd.rsvd = iocmd.rsvd2 = 0;
-
-	pTarget = hd->Targets[id];
-
-	/* Use tagged commands if possible.
-	 */
-	if (pTarget) {
-		if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
-			iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
-		else {
-			if (hd->ioc->facts.FWVersion.Word < 0x01000600)
-				return 0;
-
-			if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
-				(hd->ioc->facts.FWVersion.Word < 0x01010B00))
-				return 0;
-		}
-	}
-
-	/* Prep cfg structure
-	 */
-	cfg.pageAddr = (bus<<8) | id;
-	cfg.cfghdr.hdr = NULL;
-
-	/* Prep SDP0 header
-	 */
-	header0.PageVersion = ioc->spi_data.sdp0version;
-	header0.PageLength = ioc->spi_data.sdp0length;
-	header0.PageNumber = 0;
-	header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-	/* Prep SDP1 header
-	 */
-	header1.PageVersion = ioc->spi_data.sdp1version;
-	header1.PageLength = ioc->spi_data.sdp1length;
-	header1.PageNumber = 1;
-	header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-	if (header0.PageLength & 1)
-		dv_alloc = (header0.PageLength * 4) + 4;
-
-	dv_alloc +=  (2048 + (header1.PageLength * 4));
-
-	pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
-	if (pDvBuf == NULL)
-		return 0;
-
-	sz = 0;
-	pbuf1 = (u8 *)pDvBuf;
-	buf1_dma = dvbuf_dma;
-	sz +=1024;
-
-	pbuf2 = (u8 *) (pDvBuf + sz);
-	buf2_dma = dvbuf_dma + sz;
-	sz +=1024;
-
-	pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
-	cfg0_dma_addr = dvbuf_dma + sz;
-	sz += header0.PageLength * 4;
-
-	/* 8-byte alignment
-	 */
-	if (header0.PageLength & 1)
-		sz += 4;
-
-	pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
-	cfg1_dma_addr = dvbuf_dma + sz;
-
-	/* Skip this ID? Set cfg.cfghdr.hdr to force config page write
+	/* Get and Populate a free Frame
 	 */
-	{
-		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;
-			if (nfactor < pspi_data->minSyncFactor )
-				nfactor = pspi_data->minSyncFactor;
-
-			if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
-				(pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
-
-				ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
-					ioc->name, bus, id, lun));
-
-				dv.cmd = MPT_SET_MAX;
-				mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-				cfg.cfghdr.hdr = &header1;
-
-				/* Save the final negotiated settings to
-				 * SCSI device page 1.
-				 */
-				cfg.physAddr = cfg1_dma_addr;
-				cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-				cfg.dir = 1;
-				mpt_config(hd->ioc, &cfg);
-				goto target_done;
-			}
-		}
-	}
-
-	/* Finish iocmd inititialization - hidden or visible disk? */
-	if (ioc->raid_data.pIocPg3) {
-		/* Search IOC page 3 for matching id
-		 */
-		Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-		int		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
-		while (numPDisk) {
-			if (pPDisk->PhysDiskID == id) {
-				/* match */
-				iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
-				iocmd.physDiskNum = pPDisk->PhysDiskNum;
-
-				/* Quiesce the IM
-				 */
-				if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
-					ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
-					goto target_done;
-				}
-				break;
-			}
-			pPDisk++;
-			numPDisk--;
-		}
+	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+		ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
+					hd->ioc->name));
+		return -EAGAIN;
 	}
+	pReq = (MpiRaidActionRequest_t *)mf;
+	pReq->Action = action;
+	pReq->Reserved1 = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_RAID_ACTION;
+	pReq->VolumeID = volume;
+	pReq->VolumeBus = volbus;
+	pReq->PhysDiskNum = 0;
+	pReq->MsgFlags = 0;
+	pReq->Reserved2 = 0;
+	pReq->ActionDataWord = 0; /* Reserved for this action */
 
-	/* RAID Volume ID's may double for a physical device. If RAID but
-	 * not a physical ID as well, skip DV.
-	 */
-	if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
-		goto target_done;
+	mpt_add_sge((char *)&pReq->ActionDataSGE,
+		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 
+	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
+			hd->ioc->name, action, io->id));
 
-	/* Basic Test.
-	 * Async & Narrow - Inquiry
-	 * Async & Narrow - Inquiry
-	 * Maximum transfer rate - Inquiry
-	 * Compare buffers:
-	 *	If compare, test complete.
-	 *	If miscompare and first pass, repeat
-	 *	If miscompare and not first pass, fall back and repeat
-	 */
 	hd->pLocal = NULL;
-	readPage0 = 0;
-	sz = SCSI_MAX_INQUIRY_BYTES;
-	rc = MPT_SCANDV_GOOD;
-	while (1) {
-		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);
-
-		cfg.cfghdr.hdr = &header1;
-		cfg.physAddr = cfg1_dma_addr;
-		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-		cfg.dir = 1;
-		if (mpt_config(hd->ioc, &cfg) != 0)
-			goto target_done;
-
-		/* Wide - narrow - wide workaround case
-		 */
-		if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
-			/* Send an untagged command to reset disk Qs corrupted
-			 * when a parity error occurs on a Request Sense.
-			 */
-			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;
-				iocmd.data = pbuf1;
-				iocmd.size = 0x12;
-				if (mptscsih_do_cmd(hd, &iocmd) < 0)
-					goto target_done;
-				else {
-					if (hd->pLocal == NULL)
-						goto target_done;
-					rc = hd->pLocal->completion;
-					if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
-						dv.max.width = 0;
-						doFallback = 0;
-					} else
-						goto target_done;
-				}
-			} else
-				goto target_done;
-		}
-
-		iocmd.cmd = INQUIRY;
-		iocmd.data_dma = buf1_dma;
-		iocmd.data = pbuf1;
-		iocmd.size = sz;
-		memset(pbuf1, 0x00, sz);
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-		else {
-			if (hd->pLocal == NULL)
-				goto target_done;
-			rc = hd->pLocal->completion;
-			if (rc == MPT_SCANDV_GOOD) {
-				if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
-					if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
-						retcode = 1;
-					else
-						retcode = 0;
-
-					goto target_done;
-				}
-			} else if  (rc == MPT_SCANDV_SENSE) {
-				;
-			} else {
-				/* If first command doesn't complete
-				 * with a good status or with a check condition,
-				 * exit.
-				 */
-				goto target_done;
-			}
-		}
-
-		/* Reset the size for disks
-		 */
-		inq0 = (*pbuf1) & 0x1F;
-		if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
-			sz = 0x40;
-			iocmd.size = sz;
-		}
-
-		/* Another GEM workaround. Check peripheral device type,
-		 * if PROCESSOR, quit DV.
-		 */
-		if (inq0 == TYPE_PROCESSOR) {
-			mptscsih_initTarget(hd,
-				bus,
-				id,
-				lun,
-				pbuf1,
-				sz);
-			goto target_done;
-		}
-
-		if (inq0 > 0x08)
-			goto target_done;
-
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-
-		if (sz == 0x40) {
-			if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
-				&& (pTarget->minSyncFactor > 0x09)) {
-				if ((pbuf1[56] & 0x04) == 0)
-					;
-				else if ((pbuf1[56] & 0x01) == 1) {
-					pTarget->minSyncFactor =
-					    nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
-				} else {
-					pTarget->minSyncFactor =
-					    nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
-				}
-
-				dv.max.factor = pTarget->minSyncFactor;
-
-				if ((pbuf1[56] & 0x02) == 0) {
-					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-					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]));
-				}
-			}
-		}
-
-		if (doFallback)
-			dv.cmd = MPT_FALLBACK;
-		else
-			dv.cmd = MPT_SET_MAX;
-
-		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-		if (mpt_config(hd->ioc, &cfg) != 0)
-			goto target_done;
-
-		if ((!dv.now.width) && (!dv.now.offset))
-			goto target_done;
-
-		iocmd.cmd = INQUIRY;
-		iocmd.data_dma = buf2_dma;
-		iocmd.data = pbuf2;
-		iocmd.size = sz;
-		memset(pbuf2, 0x00, sz);
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-		else if (hd->pLocal == NULL)
-			goto target_done;
-		else {
-			/* Save the return code.
-			 * If this is the first pass,
-			 * read SCSI Device Page 0
-			 * and update the target max parameters.
-			 */
-			rc = hd->pLocal->completion;
-			doFallback = 0;
-			if (rc == MPT_SCANDV_GOOD) {
-				if (!readPage0) {
-					u32 sdp0_info;
-					u32 sdp0_nego;
-
-					cfg.cfghdr.hdr = &header0;
-					cfg.physAddr = cfg0_dma_addr;
-					cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-					cfg.dir = 0;
-
-					if (mpt_config(hd->ioc, &cfg) != 0)
-						goto target_done;
-
-					sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
-					sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
-
-					/* Quantum and Fujitsu workarounds.
-					 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
-					 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
-					 * Resetart with a request for U160.
-					 */
-					if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
-							doFallback = 1;
-					} else {
-						dv.cmd = MPT_UPDATE_MAX;
-						mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
-						/* Update the SCSI device page 1 area
-						 */
-						pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
-						readPage0 = 1;
-					}
-				}
-
-				/* Quantum workaround. Restart this test will the fallback
-				 * flag set.
-				 */
-				if (doFallback == 0) {
-					if (memcmp(pbuf1, pbuf2, sz) != 0) {
-						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 */
-					}
-				}
-
-
-			} else if (rc == MPT_SCANDV_ISSUE_SENSE)
-				doFallback = 1;	/* set fallback flag */
-			else if ((rc == MPT_SCANDV_DID_RESET) ||
-				 (rc == MPT_SCANDV_SENSE) ||
-				 (rc == MPT_SCANDV_FALLBACK))
-				doFallback = 1;	/* set fallback flag */
-			else
-				goto target_done;
-
-			firstPass = 0;
-		}
-	}
-	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;
-
-	inq0 = (*pbuf1) & 0x1F;
-
-	/* Continue only for disks
-	 */
-	if (inq0 != 0)
-		goto target_done;
-
-	if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
-		goto target_done;
-
-	/* Start the Enhanced Test.
-	 * 0) issue TUR to clear out check conditions
-	 * 1) read capacity of echo (regular) buffer
-	 * 2) reserve device
-	 * 3) do write-read-compare data pattern test
-	 * 4) release
-	 * 5) update nego parms to target struct
-	 */
-	cfg.cfghdr.hdr = &header1;
-	cfg.physAddr = cfg1_dma_addr;
-	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-	cfg.dir = 1;
-
-	iocmd.cmd = TEST_UNIT_READY;
-	iocmd.data_dma = -1;
-	iocmd.data = NULL;
-	iocmd.size = 0;
-	notDone = 1;
-	while (notDone) {
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-
-		if (hd->pLocal == NULL)
-			goto target_done;
-
-		rc = hd->pLocal->completion;
-		if (rc == MPT_SCANDV_GOOD)
-			notDone = 0;
-		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];
-			ddvprintk((MYIOC_s_INFO_FMT
-				"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-				ioc->name, skey, asc, ascq));
-
-			if (skey == UNIT_ATTENTION)
-				notDone++; /* repeat */
-			else if ((skey == NOT_READY) &&
-					(asc == 0x04)&&(ascq == 0x01)) {
-				/* wait then repeat */
-				mdelay (2000);
-				notDone++;
-			} else if ((skey == NOT_READY) && (asc == 0x3A)) {
-				/* no medium, try read test anyway */
-				notDone = 0;
-			} else {
-				/* All other errors are fatal.
-				 */
-				ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-						ioc->name));
-				goto target_done;
-			}
-		} else
-			goto target_done;
-	}
-
-	iocmd.cmd = READ_BUFFER;
-	iocmd.data_dma = buf1_dma;
-	iocmd.data = pbuf1;
-	iocmd.size = 4;
-	iocmd.flags |= MPT_ICFLAG_BUF_CAP;
-
-	dataBufSize = 0;
-	echoBufSize = 0;
-	for (patt = 0; patt < 2; patt++) {
-		if (patt == 0)
-			iocmd.flags |= MPT_ICFLAG_ECHO;
-		else
-			iocmd.flags &= ~MPT_ICFLAG_ECHO;
-
-		notDone = 1;
-		while (notDone) {
-			bufsize = 0;
-
-			/* If not ready after 8 trials,
-			 * give up on this device.
-			 */
-			if (notDone > 8)
-				goto target_done;
-
-			if (mptscsih_do_cmd(hd, &iocmd) < 0)
-				goto target_done;
-			else if (hd->pLocal == NULL)
-				goto target_done;
-			else {
-				rc = hd->pLocal->completion;
-				ddvprintk(("ReadBuffer Comp Code %d", rc));
-				ddvprintk(("  buff: %0x %0x %0x %0x\n",
-					pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
-
-				if (rc == MPT_SCANDV_GOOD) {
-					notDone = 0;
-					if (iocmd.flags & MPT_ICFLAG_ECHO) {
-						bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
-						if (pbuf1[0] & 0x01)
-							iocmd.flags |= MPT_ICFLAG_EBOS;
-					} else {
-						bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
-					}
-				} 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];
-					ddvprintk((MYIOC_s_INFO_FMT
-						"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-						ioc->name, skey, asc, ascq));
-					if (skey == ILLEGAL_REQUEST) {
-						notDone = 0;
-					} else if (skey == UNIT_ATTENTION) {
-						notDone++; /* repeat */
-					} else if ((skey == NOT_READY) &&
-						(asc == 0x04)&&(ascq == 0x01)) {
-						/* wait then repeat */
-						mdelay (2000);
-						notDone++;
-					} else {
-						/* All other errors are fatal.
-						 */
-						ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-							ioc->name));
-						goto target_done;
-					}
-				} else {
-					/* All other errors are fatal
-					 */
-					goto target_done;
-				}
-			}
-		}
-
-		if (iocmd.flags & MPT_ICFLAG_ECHO)
-			echoBufSize = bufsize;
-		else
-			dataBufSize = bufsize;
-	}
-	sz = 0;
-	iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
-
-	/* Use echo buffers if possible,
-	 * Exit if both buffers are 0.
-	 */
-	if (echoBufSize > 0) {
-		iocmd.flags |= MPT_ICFLAG_ECHO;
-		if (dataBufSize > 0)
-			bufsize = min(echoBufSize, dataBufSize);
-		else
-			bufsize = echoBufSize;
-	} else if (dataBufSize == 0)
-		goto target_done;
-
-	ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
-		(iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
-
-	/* Data buffers for write-read-compare test max 1K.
-	 */
-	sz = min(bufsize, 1024);
-
-	/* --- loop ----
-	 * On first pass, always issue a reserve.
-	 * On additional loops, only if a reset has occurred.
-	 * iocmd.flags indicates if echo or regular buffer
-	 */
-	for (patt = 0; patt < 4; patt++) {
-		ddvprintk(("Pattern %d\n", patt));
-		if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
-			iocmd.cmd = TEST_UNIT_READY;
-			iocmd.data_dma = -1;
-			iocmd.data = NULL;
-			iocmd.size = 0;
-			if (mptscsih_do_cmd(hd, &iocmd) < 0)
-				goto target_done;
-
-			iocmd.cmd = RELEASE;
-			iocmd.data_dma = -1;
-			iocmd.data = NULL;
-			iocmd.size = 0;
-			if (mptscsih_do_cmd(hd, &iocmd) < 0)
-				goto target_done;
-			else if (hd->pLocal == NULL)
-				goto target_done;
-			else {
-				rc = hd->pLocal->completion;
-				ddvprintk(("Release rc %d\n", rc));
-				if (rc == MPT_SCANDV_GOOD)
-					iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-				else
-					goto target_done;
-			}
-			iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-		}
-		iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
-
-		if (iocmd.flags & MPT_ICFLAG_EBOS)
-			goto skip_Reserve;
-
-		repeat = 5;
-		while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
-			iocmd.cmd = RESERVE;
-			iocmd.data_dma = -1;
-			iocmd.data = NULL;
-			iocmd.size = 0;
-			if (mptscsih_do_cmd(hd, &iocmd) < 0)
-				goto target_done;
-			else if (hd->pLocal == NULL)
-				goto target_done;
-			else {
-				rc = hd->pLocal->completion;
-				if (rc == MPT_SCANDV_GOOD) {
-					iocmd.flags |= MPT_ICFLAG_RESERVED;
-				} else if (rc == MPT_SCANDV_SENSE) {
-					/* Wait if coming ready
-					 */
-					u8 skey = hd->pLocal->sense[2] & 0x0F;
-					u8 asc = hd->pLocal->sense[12];
-					u8 ascq = hd->pLocal->sense[13];
-					ddvprintk((MYIOC_s_INFO_FMT
-						"DV: Reserve Failed: ", ioc->name));
-					ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-							skey, asc, ascq));
-
-					if ((skey == NOT_READY) && (asc == 0x04)&&
-									(ascq == 0x01)) {
-						/* wait then repeat */
-						mdelay (2000);
-						notDone++;
-					} else {
-						ddvprintk((MYIOC_s_INFO_FMT
-							"DV: Reserved Failed.", ioc->name));
-						goto target_done;
-					}
-				} else {
-					ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
-							 ioc->name));
-					goto target_done;
-				}
-			}
-		}
-
-skip_Reserve:
-		mptscsih_fillbuf(pbuf1, sz, patt, 1);
-		iocmd.cmd = WRITE_BUFFER;
-		iocmd.data_dma = buf1_dma;
-		iocmd.data = pbuf1;
-		iocmd.size = sz;
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-		else if (hd->pLocal == NULL)
-			goto target_done;
-		else {
-			rc = hd->pLocal->completion;
-			if (rc == MPT_SCANDV_GOOD)
-				;		/* Issue read buffer */
-			else if (rc == MPT_SCANDV_DID_RESET) {
-				/* If using echo buffers, reset to data buffers.
-				 * Else do Fallback and restart
-				 * this test (re-issue reserve
-				 * because of bus reset).
-				 */
-				if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
-					iocmd.flags &= ~MPT_ICFLAG_ECHO;
-				} else {
-					dv.cmd = MPT_FALLBACK;
-					mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-					if (mpt_config(hd->ioc, &cfg) != 0)
-						goto target_done;
-
-					if ((!dv.now.width) && (!dv.now.offset))
-						goto target_done;
-				}
-
-				iocmd.flags |= MPT_ICFLAG_DID_RESET;
-				patt = -1;
-				continue;
-			} else if (rc == MPT_SCANDV_SENSE) {
-				/* Restart data test if UA, else quit.
-				 */
-				u8 skey = hd->pLocal->sense[2] & 0x0F;
-				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) {
-					patt = -1;
-					continue;
-				} else if (skey == ILLEGAL_REQUEST) {
-					if (iocmd.flags & MPT_ICFLAG_ECHO) {
-						if (dataBufSize >= bufsize) {
-							iocmd.flags &= ~MPT_ICFLAG_ECHO;
-							patt = -1;
-							continue;
-						}
-					}
-					goto target_done;
-				}
-				else
-					goto target_done;
-			} else {
-				/* fatal error */
-				goto target_done;
-			}
-		}
-
-		iocmd.cmd = READ_BUFFER;
-		iocmd.data_dma = buf2_dma;
-		iocmd.data = pbuf2;
-		iocmd.size = sz;
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			goto target_done;
-		else if (hd->pLocal == NULL)
-			goto target_done;
-		else {
-			rc = hd->pLocal->completion;
-			if (rc == MPT_SCANDV_GOOD) {
-				 /* If buffers compare,
-				  * go to next pattern,
-				  * else, do a fallback and restart
-				  * data transfer test.
-				  */
-				if (memcmp (pbuf1, pbuf2, sz) == 0) {
-					; /* goto next pattern */
-				} else {
-					/* Miscompare with Echo buffer, go to data buffer,
-					 * if that buffer exists.
-					 * Miscompare with Data buffer, check first 4 bytes,
-					 * some devices return capacity. Exit in this case.
-					 */
-					if (iocmd.flags & MPT_ICFLAG_ECHO) {
-						if (dataBufSize >= bufsize)
-							iocmd.flags &= ~MPT_ICFLAG_ECHO;
-						else
-							goto target_done;
-					} else {
-						if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
-							/* Argh. Device returning wrong data.
-							 * Quit DV for this device.
-							 */
-							goto target_done;
-						}
-
-						/* Had an actual miscompare. Slow down.*/
-						dv.cmd = MPT_FALLBACK;
-						mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-						if (mpt_config(hd->ioc, &cfg) != 0)
-							goto target_done;
-
-						if ((!dv.now.width) && (!dv.now.offset))
-							goto target_done;
-					}
-
-					patt = -1;
-					continue;
-				}
-			} else if (rc == MPT_SCANDV_DID_RESET) {
-				/* Do Fallback and restart
-				 * this test (re-issue reserve
-				 * because of bus reset).
-				 */
-				dv.cmd = MPT_FALLBACK;
-				mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-				if (mpt_config(hd->ioc, &cfg) != 0)
-					 goto target_done;
-
-				if ((!dv.now.width) && (!dv.now.offset))
-					goto target_done;
-
-				iocmd.flags |= MPT_ICFLAG_DID_RESET;
-				patt = -1;
-				continue;
-			} else if (rc == MPT_SCANDV_SENSE) {
-				/* Restart data test if UA, else quit.
-				 */
-				u8 skey = hd->pLocal->sense[2] & 0x0F;
-				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) {
-					patt = -1;
-					continue;
-				}
-				else
-					goto target_done;
-			} else {
-				/* fatal error */
-				goto target_done;
-			}
-		}
-
-	} /* --- end of patt loop ---- */
-
-target_done:
-	if (iocmd.flags & MPT_ICFLAG_RESERVED) {
-		iocmd.cmd = RELEASE;
-		iocmd.data_dma = -1;
-		iocmd.data = NULL;
-		iocmd.size = 0;
-		if (mptscsih_do_cmd(hd, &iocmd) < 0)
-			printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-					ioc->name, id);
-		else if (hd->pLocal) {
-			if (hd->pLocal->completion == MPT_SCANDV_GOOD)
-				iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-		} else {
-			printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-						ioc->name, id);
-		}
-	}
-
+	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
+	hd->scandv_wait_done = 0;
 
-	/* Set if cfg1_dma_addr contents is valid
+	/* Save cmd pointer, for resource free if timeout or
+	 * FW reload occurs
 	 */
-	if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
-		/* If disk, not U320, disable QAS
-		 */
-		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
-			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));
-		}
-
-		dv.cmd = MPT_SAVE;
-		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+	hd->cmdPtr = mf;
 
-		/* Double writes to SDP1 can cause problems,
-		 * skip save of the final negotiated settings to
-		 * SCSI device page 1.
-		 *
-		cfg.cfghdr.hdr = &header1;
-		cfg.physAddr = cfg1_dma_addr;
-		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-		cfg.dir = 1;
-		mpt_config(hd->ioc, &cfg);
-		 */
-	}
+	add_timer(&hd->timer);
+	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
-	/* If this is a RAID Passthrough, enable internal IOs
-	 */
-	if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
-		if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
-			ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
-	}
+	if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
+		return -1;
 
-	/* Done with the DV scan of the current target
-	 */
-	if (pDvBuf)
-		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
+	if (pRep)
+		memcpy(pRep, hd->pLocal->u.r, repLen);
 
-	ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
-			ioc->name, id));
+	return 0;
+}
+EXPORT_SYMBOL(mptscsih_raid_action);
 
-	return retcode;
+int
+mptscsih_read_raid_page0(struct scsi_device *sdev,
+			 struct _CONFIG_PAGE_RAID_VOL_0 *pass_pg0,
+			 int pg0len, int version)
+{
+	struct Scsi_Host *shost = sdev->host;
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+	struct _MPT_ADAPTER *ioc = hd->ioc;
+	struct _CONFIG_PAGE_RAID_VOL_0 *pg0;
+	dma_addr_t pg0_dma;
+	struct _x_config_parms cfg;
+	struct _CONFIG_PAGE_HEADER hdr;
+	int err = -EBUSY;
+
+	pg0 = dma_alloc_coherent(&ioc->pcidev->dev, pg0len, &pg0_dma, GFP_KERNEL);
+	if (pg0 == NULL) {
+		dev_printk(KERN_ERR, &sdev->sdev_gendev,
+			   "dma_alloc_coherent for raid failed\n");
+		return -EINVAL;
+	}
+	memset(&hdr, 0, sizeof(hdr));
+
+	hdr.PageVersion = version;
+	hdr.PageLength = pg0len / 4;
+	hdr.PageNumber = 0;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = pg0_dma;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.dir = 0;
+	cfg.pageAddr = sdev->id;
+
+	if (mpt_config(ioc, &cfg)) {
+		dev_printk(KERN_ERR, &sdev->sdev_gendev, "mpt_config failed\n");
+		goto out_free;
+	}
+	err = 0;
+	memcpy(pass_pg0, pg0, pg0len);
+
+ out_free:
+	dma_free_coherent(&ioc->pcidev->dev, pg0len, pg0, pg0_dma);
+	return err;
 }
+EXPORT_SYMBOL(mptscsih_read_raid_page0);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_dv_parms - perform a variety of operations on the
- *	parameters used for negotiation.
- *	@hd: Pointer to a SCSI host.
- *	@dv: Pointer to a structure that contains the maximum and current
- *		negotiated parameters.
- */
-static void
-mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
+static int
+mptscsih_find_physDiskNum(struct _MPT_SCSI_HOST *hd, int physDiskBus,
+			  int physDiskID)
 {
-	VirtDevice		*pTarget;
-	SCSIDevicePage0_t	*pPage0;
-	SCSIDevicePage1_t	*pPage1;
-	int			val = 0, data, configuration;
-	u8			width = 0;
-	u8			offset = 0;
-	u8			factor = 0;
-	u8			negoFlags = 0;
-	u8			cmd = dv->cmd;
-	u8			id = dv->id;
-
-	switch (cmd) {
-	case MPT_GET_NVRAM_VALS:
-		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 = hd->ioc->spi_data.noQas;
-		if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !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;
-				else {
-					factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-					if ((factor == 0) || (factor == MPT_ASYNC)){
-						factor = MPT_ASYNC;
-						offset = 0;
-					}
-				}
-			} else {
-				width = MPT_NARROW;
-				offset = 0;
-				factor = MPT_ASYNC;
-			}
-
-			/* Set the negotiation flags */
-			if (!width)
-				negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-			if (!offset)
-				negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-		}
-
-		/* limit by adapter capabilities */
-		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)
-			factor = MPT_ULTRA2;
-
-		dv->max.width = width;
-		dv->max.offset = offset;
-		dv->max.factor = factor;
-		dv->max.flags = negoFlags;
-		ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
-				id, width, factor, offset, negoFlags));
-		break;
-
-	case MPT_UPDATE_MAX:
-		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) {
-			val = le32_to_cpu(pPage0->NegotiatedParameters);
-			dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
-			dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
-			dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
-		}
-
-		dv->now.width = dv->max.width;
-		dv->now.offset = dv->max.offset;
-		dv->now.factor = dv->max.factor;
-		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
-				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;
-		dv->now.factor = dv->max.factor;
-		dv->now.flags = dv->max.flags;
-
-		pPage1 = (SCSIDevicePage1_t *)pPage;
-		if (pPage1) {
-			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);
-		}
-
-		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;
-		offset = 0;
-		factor = MPT_ASYNC;
-		negoFlags = dv->max.flags;
-
-		pPage1 = (SCSIDevicePage1_t *)pPage;
-		if (pPage1) {
-			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);
-		}
-		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_NOTE_FMT
-			"Fallback: Start: offset %d, factor %x, width %d \n",
-				hd->ioc->name, dv->now.offset,
-				dv->now.factor, dv->now.width));
-		width = dv->now.width;
-		offset = dv->now.offset;
-		factor = dv->now.factor;
-		if ((offset) && (dv->max.width)) {
-			if (factor < MPT_ULTRA160)
-				factor = MPT_ULTRA160;
-			else if (factor < MPT_ULTRA2) {
-				factor = MPT_ULTRA2;
-				width = MPT_WIDE;
-			} else if ((factor == MPT_ULTRA2) && width) {
-				factor = MPT_ULTRA2;
-				width = MPT_NARROW;
-			} else if (factor < MPT_ULTRA) {
-				factor = MPT_ULTRA;
-				width = MPT_WIDE;
-			} else if ((factor == MPT_ULTRA) && width) {
-				width = MPT_NARROW;
-			} else if (factor < MPT_FAST) {
-				factor = MPT_FAST;
-				width = MPT_WIDE;
-			} else if ((factor == MPT_FAST) && width) {
-				factor = MPT_FAST;
-				width = MPT_NARROW;
-			} else if (factor < MPT_SCSI) {
-				factor = MPT_SCSI;
-				width = MPT_WIDE;
-			} else if ((factor == MPT_SCSI) && width) {
-				factor = MPT_SCSI;
-				width = MPT_NARROW;
-			} else {
-				factor = MPT_ASYNC;
-				offset = 0;
-			}
-
-		} else if (offset) {
-			width = MPT_NARROW;
-			if (factor < MPT_ULTRA)
-				factor = MPT_ULTRA;
-			else if (factor < MPT_FAST)
-				factor = MPT_FAST;
-			else if (factor < MPT_SCSI)
-				factor = MPT_SCSI;
-			else {
-				factor = MPT_ASYNC;
-				offset = 0;
-			}
-
-		} else {
-			width = MPT_NARROW;
-			factor = MPT_ASYNC;
-		}
-		dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
-		dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
-
-		dv->now.width = width;
-		dv->now.offset = offset;
-		dv->now.factor = factor;
-		dv->now.flags = dv->max.flags;
-
-		pPage1 = (SCSIDevicePage1_t *)pPage;
-		if (pPage1) {
-			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(("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_NOTE_FMT
-			"Saving to Target structure: ", hd->ioc->name));
-		ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%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).
-		 */
-
-		if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
-			pTarget->maxWidth = dv->now.width;
-			pTarget->maxOffset = dv->now.offset;
-			pTarget->minSyncFactor = dv->now.factor;
-			pTarget->negoFlags = dv->now.flags;
-		} else {
-			/* Preserv all flags, use
-			 * read-modify-write algorithm
-			 */
-			if (hd->ioc->spi_data.nvram) {
-				data = hd->ioc->spi_data.nvram[id];
-
-				if (dv->now.width)
-					data &= ~MPT_NVRAM_WIDE_DISABLE;
-				else
-					data |= MPT_NVRAM_WIDE_DISABLE;
-
-				if (!dv->now.offset)
-					factor = MPT_ASYNC;
+	int i;
 
-				data &= ~MPT_NVRAM_SYNC_MASK;
-				data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
+	struct _CONFIG_PAGE_IOC_3 *pg3 = hd->ioc->raid_data.pIocPg3;
 
-				hd->ioc->spi_data.nvram[id] = data;
-			}
+	for (i = 0; i < pg3->NumPhysDisks; i++) {
+		if (physDiskID == pg3->PhysDisk[i].PhysDiskID &&
+		    physDiskBus == pg3->PhysDisk[i].PhysDiskBus) {
+			return pg3->PhysDisk[i].PhysDiskNum;
 		}
-		break;
 	}
+	return -1;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_fillbuf - fill a buffer with a special data pattern
- *		cleanup. For bus scan only.
- *
- *	@buffer: Pointer to data buffer to be filled.
- *	@size: Number of bytes to fill
- *	@index: Pattern index
- *	@width: bus width, 0 (8 bits) or 1 (16 bits)
- */
-static void
-mptscsih_fillbuf(char *buffer, int size, int index, int width)
+struct _VirtDevice *
+mptscsih_find_raid_device(struct _MPT_SCSI_HOST *hd, int physDiskBus,
+			  int physDiskID)
 {
-	char *ptr = buffer;
-	int ii;
-	char byte;
-	short val;
-
-	switch (index) {
-	case 0:
-
-		if (width) {
-			/* Pattern:  0000 FFFF 0000 FFFF
-			 */
-			for (ii=0; ii < size; ii++, ptr++) {
-				if (ii & 0x02)
-					*ptr = 0xFF;
-				else
-					*ptr = 0x00;
-			}
-		} else {
-			/* Pattern:  00 FF 00 FF
-			 */
-			for (ii=0; ii < size; ii++, ptr++) {
-				if (ii & 0x01)
-					*ptr = 0xFF;
-				else
-					*ptr = 0x00;
-			}
-		}
-		break;
-
-	case 1:
-		if (width) {
-			/* Pattern:  5555 AAAA 5555 AAAA 5555
-			 */
-			for (ii=0; ii < size; ii++, ptr++) {
-				if (ii & 0x02)
-					*ptr = 0xAA;
-				else
-					*ptr = 0x55;
-			}
-		} else {
-			/* Pattern:  55 AA 55 AA 55
-			 */
-			for (ii=0; ii < size; ii++, ptr++) {
-				if (ii & 0x01)
-					*ptr = 0xAA;
-				else
-					*ptr = 0x55;
-			}
-		}
-		break;
-
-	case 2:
-		/* Pattern:  00 01 02 03 04 05
-		 * ... FE FF 00 01..
-		 */
-		for (ii=0; ii < size; ii++, ptr++)
-			*ptr = (char) ii;
-		break;
-
-	case 3:
-		if (width) {
-			/* Wide Pattern:  FFFE 0001 FFFD 0002
-			 * ...  4000 DFFF 8000 EFFF
-			 */
-			byte = 0;
-			for (ii=0; ii < size/2; ii++) {
-				/* Create the base pattern
-				 */
-				val = (1 << byte);
-				/* every 64 (0x40) bytes flip the pattern
-				 * since we fill 2 bytes / iteration,
-				 * test for ii = 0x20
-				 */
-				if (ii & 0x20)
-					val = ~(val);
-
-				if (ii & 0x01) {
-					*ptr = (char)( (val & 0xFF00) >> 8);
-					ptr++;
-					*ptr = (char)(val & 0xFF);
-					byte++;
-					byte &= 0x0F;
-				} else {
-					val = ~val;
-					*ptr = (char)( (val & 0xFF00) >> 8);
-					ptr++;
-					*ptr = (char)(val & 0xFF);
-				}
+	int i;
+	struct _VirtDevice *vdev;
+	int physDiskNum = mptscsih_find_physDiskNum(hd, physDiskBus, physDiskID);
+	if (physDiskNum < 0)
+		return NULL;
 
-				ptr++;
-			}
-		} else {
-			/* Narrow Pattern:  FE 01 FD 02 FB 04
-			 * .. 7F 80 01 FE 02 FD ...  80 7F
-			 */
-			byte = 0;
-			for (ii=0; ii < size; ii++, ptr++) {
-				/* Base pattern - first 32 bytes
-				 */
-				if (ii & 0x01) {
-					*ptr = (1 << byte);
-					byte++;
-					byte &= 0x07;
-				} else {
-					*ptr = (char) (~(1 << byte));
-				}
+	for (i = 0; i < hd->ioc->sh->max_id; i++) {
+		int j;
 
-				/* Flip the pattern every 32 bytes
-				 */
-				if (ii & 0x20)
-					*ptr = ~(*ptr);
-			}
+		vdev = mpt_target(hd, 0, i);
+		if (!vdev || !vdev->raidVolume)
+			continue;
+		for (j = 0; j < vdev->raidVolume->NumPhysDisks; j++) {
+			if (vdev->raidVolume->PhysDisk[j].PhysDiskNum ==
+			    physDiskNum)
+				goto found;
 		}
-		break;
 	}
+	return NULL;
+ found:
+	return vdev;
 }
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
+EXPORT_SYMBOL(mptscsih_find_raid_device);
 
 EXPORT_SYMBOL(mptscsih_remove);
 EXPORT_SYMBOL(mptscsih_shutdown);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -60,16 +60,6 @@
 
 #define MPT_SCSI_MAX_SECTORS    8192
 
-/* To disable domain validation, uncomment the
- * following line. No effect for FC devices.
- * For SCSI devices, driver will negotiate to
- * NVRAM settings (if available) or to maximum adapter
- * capabilities.
- */
-
-#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-
-
 /* SCSI driver setup structure. Settings can be overridden
  * by command line options.
  */
@@ -106,3 +96,18 @@ extern int mptscsih_event_process(MPT_AD
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
+extern int mptscsih_raid_action(MPT_SCSI_HOST *hd, int action, int volume,
+				int volbus, MpiRaidActionReply_t *pRep,
+				int repLen);
+extern int mptscsih_read_raid_page0(struct scsi_device *sdev,
+				    struct _CONFIG_PAGE_RAID_VOL_0 *pass_pg0,
+				    int pg0len, int version);
+
+extern struct _VirtDevice *
+mptscsih_find_raid_device(struct _MPT_SCSI_HOST *hd, int physDiskBus,
+			  int physDiskID);
+
+static inline VirtDevice *mpt_target(MPT_SCSI_HOST *hd, int channel, int id)
+{
+	return hd->Targets[id + (channel * hd->ioc->sh->max_id)];
+}
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -56,12 +56,15 @@
 #include <linux/reboot.h>	/* notifier code */
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/raid_class.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
 
 /* Command line args */
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
-module_param(mpt_dv, int, 0);
-MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int mpt_width = MPTSCSIH_MAX_WIDTH;
-module_param(mpt_width, int, 0);
-MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
-module_param(mpt_factor, ushort, 0);
-MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
-#endif
-
 static int mpt_saf_te = MPTSCSIH_SAF_TE;
 module_param(mpt_saf_te, int, 0);
 MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1  (default=MPTSCSIH_SAF_TE=0)");
@@ -98,10 +87,200 @@ 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)");
 
+static void mptspi_write_offset(struct scsi_target *, int);
+static void mptspi_write_width(struct scsi_target *, int);
+
+static struct scsi_transport_template *mptspi_transport_template = NULL;
+static struct raid_template *mptspi_raid_template = NULL;
+
 static int	mptspiDoneCtx = -1;
 static int	mptspiTaskCtx = -1;
 static int	mptspiInternalCtx = -1; /* Used only for internal commands */
 
+static int mptspi_target_alloc(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+
+	if (hd == NULL)
+		return -ENODEV;
+
+	if (hd->ioc->spi_data.nvram &&
+	    hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
+		u32 nvram = hd->ioc->spi_data.nvram[starget->id];
+		spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+		spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+	} else {
+		spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
+		spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
+	}
+	spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
+
+	spi_offset(starget) = 0;
+	mptspi_write_width(starget, 0);
+
+	return 0;
+}
+
+static int mptspi_read_page0(struct scsi_target *starget,
+			     struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+	struct _MPT_ADAPTER *ioc = hd->ioc;
+	struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
+	dma_addr_t pg0_dma;
+	int size;
+	struct _x_config_parms cfg;
+	struct _CONFIG_PAGE_HEADER hdr;
+	int err = -EBUSY;
+
+	size = ioc->spi_data.sdp0length * 4;
+	/*
+	if (ioc->spi_data.sdp0length & 1)
+		size += size + 4;
+	size += 2048;
+	*/
+
+	pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
+	if (pg0 == NULL) {
+		dev_printk(KERN_ERR, &starget->dev, "dma_alloc_coherent for parameters failed\n");
+		return -EINVAL;
+	}
+
+	memset(&hdr, 0, sizeof(hdr));
+
+	hdr.PageVersion = ioc->spi_data.sdp0version;
+	hdr.PageLength = ioc->spi_data.sdp0length;
+	hdr.PageNumber = 0;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = pg0_dma;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.dir = 0;
+	cfg.pageAddr = starget->id;
+
+	if (mpt_config(ioc, &cfg)) {
+		dev_printk(KERN_ERR, &starget->dev, "mpt_config failed\n");
+		goto out_free;
+	}
+	err = 0;
+	memcpy(pass_pg0, pg0, size);
+
+ out_free:
+	dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
+	return err;
+}
+
+static u32 mptspi_getRP(struct scsi_target *starget)
+{
+	u32 nego = 0;
+
+	nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
+	nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
+	nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
+	//nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
+	nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
+	nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
+	nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
+	nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
+
+	nego |= (spi_period(starget) <<  MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
+	nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
+	nego |= spi_width(starget) ?  MPI_SCSIDEVPAGE1_RP_WIDE : 0;
+
+	return nego;
+}
+
+static void mptspi_read_parameters(struct scsi_target *starget)
+{
+	int nego;
+	struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
+
+	mptspi_read_page0(starget, &pg0);
+
+	nego = le32_to_cpu(pg0.NegotiatedParameters);
+
+	spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
+	spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
+	spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
+	//spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
+	spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
+	spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
+	spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
+	spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
+	spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
+	spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
+	spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
+	spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
+}
+
+static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
+			     struct scsi_device *sdev)
+{
+	if (sdev->channel &&
+	    mptscsih_raid_action(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO,
+				 sdev->id, 0, NULL, 0) < 0) {
+		dev_printk(KERN_ERR, &sdev->sdev_target->dev,
+			   "Integrated RAID quiesce failed\n");
+		return;
+	}
+
+	spi_dv_device(sdev);
+
+	if (sdev->channel &&
+	    mptscsih_raid_action(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO,
+				 sdev->id, 0, NULL, 0) < 0)
+		dev_printk(KERN_ERR, &sdev->sdev_target->dev,
+			   "Integrated RAID resume failed\n");
+
+	mptspi_read_parameters(sdev->sdev_target);
+	spi_display_xfer_agreement(sdev->sdev_target);
+	mptspi_read_parameters(sdev->sdev_target);
+}
+
+static int mptspi_slave_configure(struct scsi_device *sdev)
+{
+	int ret = mptscsih_slave_configure(sdev);
+	struct _MPT_SCSI_HOST *hd =
+		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+
+	if (ret)
+		return ret;
+
+	if (!sdev->channel && (hd->ioc->raid_data.isRaid & (1 << sdev->id))) {
+		enum raid_level level = RAID_LEVEL_UNKNOWN;
+
+		switch (hd->ioc->raid_data.pIocPg2->RaidVolume[sdev->id].VolumeType) {
+		case MPI_RAID_VOL_TYPE_IS:
+			level = RAID_LEVEL_0;
+			break;
+		case MPI_RAID_VOL_TYPE_IME:
+		case MPI_RAID_VOL_TYPE_IM:
+		case MPI_RAID_VOL_TYPE_RAID_10:
+			level = RAID_LEVEL_1;
+			break;
+		case MPI_RAID_VOL_TYPE_RAID_5:
+		case MPI_RAID_VOL_TYPE_RAID_50:
+			level = RAID_LEVEL_5;
+			break;
+		case MPI_RAID_VOL_TYPE_RAID_6:
+			level = RAID_LEVEL_6;
+			break;
+		}
+		raid_set_level(mptspi_raid_template, &sdev->sdev_gendev, level);
+	}
+
+	if ((sdev->channel || !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
+	    !spi_initial_dv(sdev->sdev_target))
+		mptspi_dv_device(hd, sdev);
+
+	return 0;
+}
+
 static struct scsi_host_template mptspi_driver_template = {
 	.proc_name			= "mptspi",
 	.proc_info			= mptscsih_proc_info,
@@ -109,8 +288,9 @@ static struct scsi_host_template mptspi_
 	.info				= mptscsih_info,
 	.queuecommand			= mptscsih_qcmd,
 	.slave_alloc			= mptscsih_slave_alloc,
-	.slave_configure		= mptscsih_slave_configure,
+	.slave_configure		= mptspi_slave_configure,
 	.slave_destroy			= mptscsih_slave_destroy,
+	.target_alloc			= mptspi_target_alloc,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
 	.eh_device_reset_handler	= mptscsih_dev_reset,
@@ -125,6 +305,421 @@ static struct scsi_host_template mptspi_
 	.use_clustering			= ENABLE_CLUSTERING,
 };
 
+static int mptspi_write_page1(struct scsi_target *starget,
+			       struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+	struct _MPT_ADAPTER *ioc = hd->ioc;
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
+	dma_addr_t pg1_dma;
+	int size;
+	struct _x_config_parms cfg;
+	struct _CONFIG_PAGE_HEADER hdr;
+	int err = -EBUSY;
+
+	size = ioc->spi_data.sdp1length * 4;
+
+	pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
+	if (pg1 == NULL) {
+		dev_printk(KERN_ERR, &starget->dev, "dma_alloc_coherent for parameters failed\n");
+		return -EINVAL;
+	}
+
+	memset(&hdr, 0, sizeof(hdr));
+
+	hdr.PageVersion = ioc->spi_data.sdp1version;
+	hdr.PageLength = ioc->spi_data.sdp1length;
+	hdr.PageNumber = 1;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = pg1_dma;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	cfg.dir = 1;
+	cfg.pageAddr = starget->id;
+
+	memcpy(pg1, pass_pg1, size);
+
+	pg1->Header.PageVersion = hdr.PageVersion;
+	pg1->Header.PageLength = hdr.PageLength;
+	pg1->Header.PageNumber = hdr.PageNumber;
+	pg1->Header.PageType = hdr.PageType;
+
+	if (mpt_config(ioc, &cfg)) {
+		dev_printk(KERN_ERR, &starget->dev, "mpt_config failed\n");
+		goto out_free;
+	}
+	err = 0;
+
+ out_free:
+	dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
+	return err;
+}
+
+static void mptspi_write_offset(struct scsi_target *starget, int offset)
+{
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
+
+	if (offset < 0)
+		offset = 0;
+
+	if (offset > 255)
+		offset = 255;
+
+	if (spi_offset(starget) == -1)
+		mptspi_read_parameters(starget);
+
+	spi_offset(starget) = offset;
+
+	nego = mptspi_getRP(starget);
+
+	pg1.RequestedParameters = cpu_to_le32(nego);
+	pg1.Reserved = 0;
+	pg1.Configuration = 0;
+
+	mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_period(struct scsi_target *starget, int period)
+{
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
+
+	if (period < 8)
+		period = 8;
+
+	if (period > 255)
+		period = 255;
+
+	if (spi_period(starget) == -1)
+		mptspi_read_parameters(starget);
+
+	if (period == 8) {
+		spi_iu(starget) = 1;
+		spi_dt(starget) = 1;
+	} else if (period == 9) {
+		spi_dt(starget) = 1;
+	}
+
+	spi_period(starget) = period;
+
+	nego = mptspi_getRP(starget);
+
+	pg1.RequestedParameters = cpu_to_le32(nego);
+	pg1.Reserved = 0;
+	pg1.Configuration = 0;
+
+	mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_dt(struct scsi_target *starget, int dt)
+{
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
+
+	if (spi_period(starget) == -1)
+		mptspi_read_parameters(starget);
+
+	if (!dt && spi_period(starget) < 10)
+		spi_period(starget) = 10;
+
+	spi_dt(starget) = dt;
+
+	nego = mptspi_getRP(starget);
+
+	
+	pg1.RequestedParameters = cpu_to_le32(nego);
+	pg1.Reserved = 0;
+	pg1.Configuration = 0;
+
+	mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_iu(struct scsi_target *starget, int iu)
+{
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
+
+	if (spi_period(starget) == -1)
+		mptspi_read_parameters(starget);
+
+	if (!iu && spi_period(starget) < 9)
+		spi_period(starget) = 9;
+
+	spi_iu(starget) = iu;
+
+	nego = mptspi_getRP(starget);
+
+	
+	pg1.RequestedParameters = cpu_to_le32(nego);
+	pg1.Reserved = 0;
+	pg1.Configuration = 0;
+
+	mptspi_write_page1(starget, &pg1);
+}
+
+#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) 				\
+static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
+{									\
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;				\
+	u32 nego;							\
+									\
+	spi_rd_strm(starget) = parm;					\
+									\
+	nego = mptspi_getRP(starget);					\
+									\
+	pg1.RequestedParameters = cpu_to_le32(nego);			\
+	pg1.Reserved = 0;						\
+	pg1.Configuration = 0;						\
+									\
+	mptspi_write_page1(starget, &pg1);				\
+}
+
+MPTSPI_SIMPLE_TRANSPORT_PARM(qas)
+MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
+MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
+MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
+MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
+MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
+
+static void mptspi_write_width(struct scsi_target *starget, int width)
+{
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
+
+	if (!width) {
+		spi_dt(starget) = 0;
+		if (spi_period(starget) < 10)
+			spi_period(starget) = 10;
+	}
+
+	spi_width(starget) = width;
+
+	nego = mptspi_getRP(starget);
+	
+	pg1.RequestedParameters = cpu_to_le32(nego);
+	pg1.Reserved = 0;
+	pg1.Configuration = 0;
+
+	mptspi_write_page1(starget, &pg1);
+}
+
+struct work_queue_wrapper {
+	struct work_struct	work;
+	struct _MPT_SCSI_HOST	*hd;
+	int			disk;
+};
+
+static void mpt_work_wrapper(void *data)
+{
+	struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+	struct _MPT_SCSI_HOST *hd = wqw->hd;
+	int i, disk = wqw->disk;
+	struct _CONFIG_PAGE_IOC_3 *pg3 = hd->ioc->raid_data.pIocPg3;
+
+	kfree(wqw);
+
+	for (i = 0; i < pg3->NumPhysDisks; i++) {
+		if (disk == pg3->PhysDisk[i].PhysDiskNum) {
+			/* hard code channel 1 for phys device of RAID */
+			VirtDevice *vdev = mpt_target(hd, 1, disk);
+			if (!vdev)
+				break;
+			dev_printk(KERN_INFO, &vdev->device->sdev_target->dev,
+				   "Integrated RAID requests DV of new device\n");
+			mptspi_dv_device(hd, vdev->device);
+			return;
+		}
+	}
+	mpt_read_ioc_pg_3(hd->ioc);
+	dev_printk(KERN_INFO, &hd->ioc->sh->shost_gendev,
+		   "Integrated RAID detects new device %d\n", disk);
+	scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
+}
+
+
+static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
+{
+	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+
+	if (!wqw) {
+		dev_printk(KERN_ERR, &hd->ioc->sh->shost_gendev,
+			   "Failed to act on RAID event for physical disk %d\n",
+			   disk);
+		return;
+	}
+	INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
+	wqw->hd = hd;
+	wqw->disk = disk;
+
+	schedule_work(&wqw->work);
+}
+
+static int
+mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+
+	if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {
+		int reason
+			= (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
+
+		if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+			int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
+			mpt_dv_raid(hd, disk);
+		}
+	}
+	return mptscsih_event_process(ioc, pEvReply);
+}
+
+static int
+mptspi_deny_binding(struct scsi_target *starget)
+{
+	struct _MPT_SCSI_HOST *hd =
+		(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
+	return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
+		starget->channel == 0) ? 1 : 0;
+}
+
+static struct spi_function_template mptspi_transport_functions = {
+	.get_offset	= mptspi_read_parameters,
+	.set_offset	= mptspi_write_offset,
+	.show_offset	= 1,
+	.get_period	= mptspi_read_parameters,
+	.set_period	= mptspi_write_period,
+	.show_period	= 1,
+	.get_width	= mptspi_read_parameters,
+	.set_width	= mptspi_write_width,
+	.show_width	= 1,
+	.get_iu		= mptspi_read_parameters,
+	.set_iu		= mptspi_write_iu,
+	.show_iu	= 1,
+	.get_dt		= mptspi_read_parameters,
+	.set_dt		= mptspi_write_dt,
+	.show_dt	= 1,
+	.get_qas	= mptspi_read_parameters,
+	.set_qas	= mptspi_write_qas,
+	.show_qas	= 1,
+	.get_wr_flow	= mptspi_read_parameters,
+	.set_wr_flow	= mptspi_write_wr_flow,
+	.show_wr_flow	= 1,
+	.get_rd_strm	= mptspi_read_parameters,
+	.set_rd_strm	= mptspi_write_rd_strm,
+	.show_rd_strm	= 1,
+	.get_rti	= mptspi_read_parameters,
+	.set_rti	= mptspi_write_rti,
+	.show_rti	= 1,
+	.get_pcomp_en	= mptspi_read_parameters,
+	.set_pcomp_en	= mptspi_write_pcomp_en,
+	.show_pcomp_en	= 1,
+	.get_hold_mcs	= mptspi_read_parameters,
+	.set_hold_mcs	= mptspi_write_hold_mcs,
+	.show_hold_mcs	= 1,
+	.deny_binding	= mptspi_deny_binding,
+};
+
+static int mptspi_is_raid(struct device *dev) {
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct _MPT_SCSI_HOST *hd =
+		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+
+	return ((hd->ioc->raid_data.isRaid & (1 << sdev->id)) &&
+		sdev->channel == 0) ? 1 : 0;
+}
+
+static void mptspi_get_resync(struct device *dev)
+{
+	struct {
+		MpiRaidActionReply_t r;
+		u32	pad[sizeof(MpiRaidVolIndicator_t)/sizeof(u32) - 1];
+	} buf;
+	u32 total, remain;
+	int shift;
+	MpiRaidVolIndicator_t *ri = (MpiRaidVolIndicator_t *)&buf.r.ActionData;
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct _MPT_SCSI_HOST *hd =
+		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+
+	if (mptscsih_raid_action(hd, MPI_RAID_ACTION_INDICATOR_STRUCT,
+				 sdev->id, 0, &buf.r, sizeof(buf)) < 0) {
+		dev_printk(KERN_ERR, &sdev->sdev_gendev,
+			   "Integrated RAID indicator failed\n");
+		return;
+	}
+	shift = fls(le32_to_cpu(ri->TotalBlocks.High));
+	if (shift > 0) {
+		total = le32_to_cpu(ri->TotalBlocks.Low) >> shift;
+		total |= le32_to_cpu(ri->TotalBlocks.High) << (32 - shift);
+		remain = le32_to_cpu(ri->BlocksRemaining.Low) >> shift;
+		remain |= le32_to_cpu(ri->BlocksRemaining.High) << (32 - shift);
+	} else {
+		total = le32_to_cpu(ri->TotalBlocks.Low);
+		remain = le32_to_cpu(ri->BlocksRemaining.Low);
+	}
+	total /= RAID_MAX_RESYNC;
+	remain /= RAID_MAX_RESYNC;
+	remain = total - remain;
+	remain *= RAID_MAX_RESYNC;
+	if (total)
+		raid_set_resync(mptspi_raid_template, dev, remain/total);
+	else
+		raid_set_resync(mptspi_raid_template, dev, 0);
+}
+
+static void mptspi_get_state(struct device *dev)
+{
+	MpiRaidActionReply_t r;
+	enum raid_state state = RAID_STATE_UNKNOWN;
+	u32 volstate;
+
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct _MPT_SCSI_HOST *hd =
+		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+
+	if (mptscsih_raid_action(hd, MPI_RAID_ACTION_STATUS,
+				 sdev->id, 0, &r, sizeof(r)) < 0) {
+		dev_printk(KERN_ERR, &sdev->sdev_gendev,
+			   "Integrated RAID status failed\n");
+		return;
+	}
+
+	volstate = le32_to_cpu(r.VolumeStatus);
+
+	if (volstate & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
+		state = RAID_STATE_RESYNCING;
+	else
+		switch((volstate >> 8) & 0xff) {
+		case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+			state = RAID_STATE_ACTIVE;
+			break;
+		case  MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+			state = RAID_STATE_DEGRADED;
+			break;
+		case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+		case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+			state = RAID_STATE_OFFLINE;
+			break;
+		default:
+			dev_printk(KERN_ERR, &sdev->sdev_gendev,
+				   "Integrated RAID status unknown value = 0x%x\n", r.VolumeStatus);
+			break;
+		}
+	
+	raid_set_state(mptspi_raid_template, dev, state);
+}
+
+static struct raid_function_template mptspi_raid_functions = {
+	.cookie		= &mptspi_driver_template,
+	.is_raid	= mptspi_is_raid,
+	.get_resync	= mptspi_get_resync,
+	.get_state	= mptspi_get_state,
+};
+
 
 /****************************************************************************
  * Supported hardware
@@ -161,7 +756,7 @@ mptspi_probe(struct pci_dev *pdev, const
 	int			 ioc_cap;
 	u8			*mem;
 	int			error=0;
-	int			r;
+	int			i,r;
 
 	if ((r = mpt_attach(pdev,id)) != 0)
 		return r;
@@ -237,7 +832,10 @@ mptspi_probe(struct pci_dev *pdev, const
 	sh->max_id = MPT_MAX_SCSI_DEVICES;
 
 	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
+	if (ioc->raid_data.isRaid)
+		sh->max_channel = 1;
+	else
+		sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 	/* Required entry.
@@ -300,7 +898,7 @@ mptspi_probe(struct pci_dev *pdev, const
 	 * indicates a device exists.
 	 * max_id = 1 + maximum id (hosts.h)
 	 */
-	sz = sh->max_id * sizeof(void *);
+	sz = sh->max_id * sizeof(void *) *(sh->max_channel + 1);
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
@@ -338,34 +936,12 @@ mptspi_probe(struct pci_dev *pdev, const
 	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)
-		ioc->spi_data.maxBusWidth = mpt_width;
-	if (ioc->spi_data.minSyncFactor < mpt_factor)
-		ioc->spi_data.minSyncFactor = mpt_factor;
-	if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-		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",
-		ioc->name,
-		mpt_dv,
-		mpt_width,
-		mpt_factor,
-		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,
 		mpt_saf_te,
 		mpt_pq_filter));
-#endif
-
 	ioc->spi_data.forceDv = 0;
 	ioc->spi_data.noQas = 0;
 
@@ -381,6 +957,11 @@ mptspi_probe(struct pci_dev *pdev, const
 	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 
+	/* Some versions of the firmware don't support page 0; without
+	 * that we can't get the parameters */
+	if (hd->ioc->spi_data.sdp0length != 0)
+		sh->transportt = mptspi_transport_template;
+
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	if(error) {
 		dprintk((KERN_ERR MYNAM
@@ -389,6 +970,20 @@ mptspi_probe(struct pci_dev *pdev, const
 	}
 
 	scsi_scan_host(sh);
+	if (hd->ioc->raid_data.isRaid) {
+		/* now assemble the raid devices */
+		for (i = 0; i < hd->ioc->sh->max_id; i++) {
+			VirtDevice *vdev = mpt_target(hd, 1, i);
+			VirtDevice *vdev_raid;
+			if (!vdev)
+				break;
+			vdev_raid = mptscsih_find_raid_device(hd, 0, i);
+			if(vdev_raid != NULL)
+				raid_component_add(mptspi_raid_template,
+						   &vdev_raid->device->sdev_gendev,
+						   &vdev->device->sdev_gendev);
+		}
+	}
 	return 0;
 
 mptspi_probe_failed:
@@ -419,14 +1014,22 @@ static struct pci_driver mptspi_driver =
 static int __init
 mptspi_init(void)
 {
-
 	show_mptmod_ver(my_NAME, my_VERSION);
 
+	mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
+	if (!mptspi_transport_template)
+		return -ENODEV;
+	mptspi_raid_template = raid_class_attach(&mptspi_raid_functions);
+	if (!mptspi_raid_template) {
+		spi_release_transport(mptspi_transport_template);
+		return -ENODEV;
+	}
+
 	mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
 	mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
 	mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
 
-	if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
+	if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
 		devtprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
@@ -461,6 +1064,8 @@ mptspi_exit(void)
 	mpt_deregister(mptspiInternalCtx);
 	mpt_deregister(mptspiTaskCtx);
 	mpt_deregister(mptspiDoneCtx);
+	spi_release_transport(mptspi_transport_template);
+	raid_class_release(mptspi_raid_template);
 }
 
 module_init(mptspi_init);


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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux