patch-2.4.20 linux-2.4.20/drivers/message/fusion/mptscsih.c

Next file: linux-2.4.20/drivers/message/fusion/mptscsih.h
Previous file: linux-2.4.20/drivers/message/fusion/mptlan.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/message/fusion/mptscsih.c linux-2.4.20/drivers/message/fusion/mptscsih.c
@@ -26,7 +26,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptscsih.c,v 1.80 2002/02/27 18:44:27 sralston Exp $
+ *  $Id: mptscsih.c,v 1.101 2002/09/05 22:30:11 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -158,9 +158,8 @@
 static int	mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_io_direction(Scsi_Cmnd *cmd);
 
-static int	mptscsih_Add32BitSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+static int	mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
 				 SCSIIORequest_t *pReq, int req_idx);
-static void	mptscsih_AddNullSGE(SCSIIORequest_t *pReq);
 static int	mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex);
 static void	mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
 static int	mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
@@ -168,6 +167,8 @@
 static void	copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 #ifndef MPT_SCSI_USE_NEW_EH
 static void	search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd);
+#else
+static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 #endif
 static u32	SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
 static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
@@ -180,10 +181,11 @@
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 static VirtDevice	*mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-void		mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target);
+void		mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
 static void	clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
-static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq, char *data);
+static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
 static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
+static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
 static int	mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
 static int	mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static void	mptscsih_timer_expired(unsigned long data);
@@ -194,6 +196,8 @@
 #ifndef MPTSCSIH_DISABLE_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);
 static void	mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, 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);
@@ -222,11 +226,11 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
 static struct proc_dir_entry proc_mpt_scsihost =
 {
-	low_ino:	PROC_SCSI_MPT,
-	namelen:	8,
-	name:		"mptscsih",
-	mode:		S_IFDIR | S_IRUGO | S_IXUGO,
-	nlink:		2,
+	.low_ino =	PROC_SCSI_MPT,
+	.namelen =	8,
+	.name =		"mptscsih",
+	.mode =		S_IFDIR | S_IRUGO | S_IXUGO,
+	.nlink =	2,
 };
 #endif
 
@@ -286,7 +290,9 @@
 	MPT_SCSI_HOST	*hd;
 	SCSIIORequest_t	*pScsiReq;
 	SCSIIOReply_t	*pScsiReply;
+#ifndef MPT_SCSI_USE_NEW_EH
 	unsigned long	 flags;
+#endif
 	u16		 req_idx;
 
 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
@@ -294,7 +300,7 @@
 	if ((mf == NULL) ||
 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
 		printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n",
-				ioc->name, mf?"BAD":"NULL", mf);
+				ioc->name, mf?"BAD":"NULL", (void *) mf);
 		/* return 1; CHECKME SteveR. Don't free. */
 		return 0;
 	}
@@ -317,8 +323,8 @@
 		return 1;
 	}
 
-	dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p)\n",
-			ioc->name, mf, mr, sc));
+	dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
+			ioc->name, mf, mr, sc, req_idx));
 
 	atomic_dec(&queue_depth);
 
@@ -326,6 +332,14 @@
 	pScsiReq = (SCSIIORequest_t *) mf;
 	pScsiReply = (SCSIIOReply_t *) mr;
 
+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+	if (hd->is_spi) {
+		u32 qtag = le32_to_cpu(pScsiReq->Control);
+		if (qtag & MPI_SCSIIO_CONTROL_UNTAGGED)
+			hd->ioc->spi_data.iocntr[sc->target]--;
+	}
+#endif
+
 	if (pScsiReply == NULL) {
 		/* special context reply handling */
 
@@ -345,9 +359,6 @@
 			}
 		}
 		clear_sense_flag(hd, pScsiReq);
-
-		if (hd->is_spi)
-			mptscsih_set_dvflags(hd, pScsiReq, sc->buffer);
 	} else {
 		u32	 xfer_cnt;
 		u16	 status;
@@ -403,6 +414,10 @@
 			 * than an unsolicited DID_ABORT.
 			 */
 			sc->result = DID_RESET << 16;
+
+			/* GEM Workaround. */ 
+			if (hd->is_spi)
+				mptscsih_no_negotiate(hd, sc->target);
 			break;
 
 		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
@@ -411,6 +426,10 @@
 			search_taskQ_for_cmd(sc, hd);
 #endif
 			sc->result = DID_RESET << 16;
+
+			/* GEM Workaround. */ 
+			if (hd->is_spi)
+				mptscsih_no_negotiate(hd, sc->target);
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
@@ -470,9 +489,6 @@
 						sc->buffer,
 						xfer_cnt);
 			}
-
-			if (hd->is_spi)
-				mptscsih_set_dvflags(hd, pScsiReq, sc->buffer);
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
@@ -554,9 +570,6 @@
 						sc->buffer,
 						xfer_cnt);
 			}
-
-			if (hd->is_spi)
-				mptscsih_set_dvflags(hd, pScsiReq, sc->buffer);
 			break;
 
 		case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
@@ -606,9 +619,9 @@
 
 	sc->host_scribble = NULL;	/* CHECKME! - Do we need to clear this??? */
 
-	spin_lock_irqsave(&io_request_lock, flags);
+        MPT_HOST_LOCK(flags);
 	sc->scsi_done(sc);		/* Issue the command callback */
-	spin_unlock_irqrestore(&io_request_lock, flags);
+        MPT_HOST_UNLOCK(flags);
 
 	/* Free Chain buffers */
 	mptscsih_freeChainBuffers(hd, req_idx);
@@ -700,6 +713,7 @@
 	unsigned long flags;
 
 	dprintk((KERN_INFO MYNAM ": clean_taskQ called\n"));
+
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	if (! Q_IS_EMPTY(&hd->taskQ)) {
 		mf = hd->taskQ.head;
@@ -812,9 +826,9 @@
 
 		/* Do the OS callback.
 		 */
-		spin_lock_irqsave(&io_request_lock, flags);
+                MPT_HOST_LOCK(flags);
 		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+                MPT_HOST_UNLOCK(flags);
 	}
 
 	return;
@@ -871,7 +885,10 @@
 	MPT_FRAME_HDR	*mf = NULL;
 	int		 ii;
 	int		 max = hd->ioc->req_depth;
+
+#ifndef MPT_SCSI_USE_NEW_EH
 	unsigned long	 flags;
+#endif
 
 	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
 	for (ii= 0; ii < max; ii++) {
@@ -901,16 +918,26 @@
 			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
 					mf, SCpnt));
 
-			/* Set status
+			/* Set status, free OS resources (SG DMA buffers)
 			 * Do OS callback
-			 * Free chain buffers
-			 * Free message frame
+			 * Free driver resources (chain, msg buffers)
 			 */
+			if (SCpnt->use_sg) {
+				pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
+					    SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+			} else if (SCpnt->request_bufflen) {
+				scPrivate	*my_priv;
+		
+				my_priv = (scPrivate *) &SCpnt->SCp;
+				pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
+					   SCpnt->request_bufflen,
+					   scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+			}
 			SCpnt->result = DID_RESET << 16;
 			SCpnt->host_scribble = NULL;
-			spin_lock_irqsave(&io_request_lock, flags);
+                        MPT_HOST_LOCK(flags);
 			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */
-			spin_unlock_irqrestore(&io_request_lock, flags);
+                        MPT_HOST_UNLOCK(flags);
 
 			/* Free Chain buffers */
 			mptscsih_freeChainBuffers(hd, ii);
@@ -919,9 +946,82 @@
 			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 		}
 	}
+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+	/* Clear untagged counting array */
+	for (ii= 0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+		hd->ioc->spi_data.iocntr[ii] = 0;
+#endif
+
 	return;
 }
 
+#ifdef DROP_TEST
+/* 	mptscsih_flush_drop_test - Free resources and do callback if
+ *		DROP_TEST enabled.
+ *
+ *	@hd: Pointer to a SCSI HOST structure
+ *
+ *	Returns: None.
+ *
+ *	Must be called while new I/Os are being queued.
+ */
+static void
+mptscsih_flush_drop_test (MPT_SCSI_HOST *hd)
+{
+	Scsi_Cmnd	*sc;
+	unsigned long	 flags;
+	u16		 req_idx;
+
+	/* Free resources for the drop test MF
+	 * and chain buffers.
+	 */
+	if (dropMfPtr) {
+		req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx);
+		sc = hd->ScsiLookup[req_idx];
+		if (sc == NULL) {
+			printk(MYIOC_s_ERR_FMT "Drop Test: NULL ScsiCmd ptr!\n",
+					ioc->name);
+		} else {
+			/* unmap OS resources, set status, do callback
+			 * free driver resources
+			 */
+			if (sc->use_sg) {
+				pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
+					    sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
+			} else if (sc->request_bufflen) {
+				scPrivate	*my_priv;
+
+				my_priv = (scPrivate *) &sc->SCp;
+				pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
+					   sc->request_bufflen,
+					   scsi_to_pci_dma_dir(sc->sc_data_direction));
+			}
+
+			sc->host_scribble = NULL;
+			sc->result = DID_RESET << 16;
+			hd->ScsiLookup[req_idx] = NULL;
+			atomic_dec(&queue_depth);
+			MPT_HOST_LOCK(flags);
+			sc->scsi_done(sc);	/* Issue callback */
+			MPT_HOST_UNLOCK(flags);
+		}
+
+		mptscsih_freeChainBuffers(hd, req_idx);
+		mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr);
+		printk(MYIOC_s_INFO_FMT "Free'd Dropped cmd (%p)\n",
+					hd->ioc->name, sc);
+		printk(MYIOC_s_INFO_FMT "mf (%p) reqidx (%4x)\n",
+					hd->ioc->name, dropMfPtr, req_idx);
+		printk(MYIOC_s_INFO_FMT "Num Tot (%d) Good (%d) Bad (%d) \n",
+				hd->ioc->name, dropTestNum,
+				dropTestOK, dropTestBad);
+	}
+	dropMfPtr = NULL;
+
+	return;
+}
+#endif
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_initChainBuffers - Allocate memory for and initialize
@@ -951,7 +1051,7 @@
 	sz = numChain * sizeof(int);
 
 	if (hd->ReqToChain == NULL) {
-		mem = kmalloc(sz, GFP_KERNEL);
+		mem = kmalloc(sz, GFP_ATOMIC);
 		if (mem == NULL)
 			return -1;
 
@@ -962,7 +1062,7 @@
 	memset(mem, 0xFF, sz);
 
 	if (hd->ChainToChain == NULL) {
-		mem = kmalloc(sz, GFP_KERNEL);
+		mem = kmalloc(sz, GFP_ATOMIC);
 		if (mem == NULL)
 			return -1;
 
@@ -1038,7 +1138,7 @@
 	if (time - last_queue_full > 10 * HZ) {
 		char *ioc_str = "ioc?";
 
-		if (sc->host && sc->host->hostdata)
+		if (sc->host != NULL && sc->host->hostdata != NULL)
 			ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name;
 		printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
 				ioc_str, 0, sc->target, sc->lun);
@@ -1175,21 +1275,21 @@
 
 				/* Verify that we won't exceed the maximum
 				 * number of chain buffers
-				 * We can optimize:  ZZ = req_sz/sizeof(MptSge_t)
+				 * We can optimize:  ZZ = req_sz/sizeof(SGE)
 				 * For 32bit SGE's:
 				 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
-				 *               + (req_sz - 64)/sizeof(MptSge_t)
+				 *               + (req_sz - 64)/sizeof(SGE)
 				 * A slightly different algorithm is required for
 				 * 64bit SGEs.
 				 */
-				scale = this->req_sz/sizeof(MptSge_t);
-				if (sizeof(MptSge_t) == sizeof(SGESimple32_t)) {
-					numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
-						(this->req_sz - 64) / (sizeof(MptSge_t));
-				} else if (sizeof(MptSge_t) == sizeof(SGESimple64_t)) {
+				scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+				if (sizeof(dma_addr_t) == sizeof(u64)) {
 					numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
-						(this->req_sz - 60) / (sizeof(MptSge_t));
-				}
+						(this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+				} else {
+					numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
+						(this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+				} 
 
 				if (numSGE < sh->sg_tablesize) {
 					/* Reset this value */
@@ -1199,6 +1299,10 @@
 					sh->sg_tablesize = numSGE;
 				}
 
+				/* Set the pci device pointer in Scsi_Host structure.
+				 */
+				scsi_set_pci_device(sh, this->pcidev);
+
 				restore_flags(flags);
 
 				hd = (MPT_SCSI_HOST *) sh->hostdata;
@@ -1217,7 +1321,7 @@
 				 * (with size equal to req_depth*PtrSz!)
 				 */
 				sz = hd->ioc->req_depth * sizeof(void *);
-				mem = kmalloc(sz, GFP_KERNEL);
+				mem = kmalloc(sz, GFP_ATOMIC);
 				if (mem == NULL)
 					goto done;
 
@@ -1233,7 +1337,7 @@
 				/* Allocate memory for free and doneQ's
 				 */
 				sz = sh->can_queue * sizeof(MPT_DONE_Q);
-				mem = kmalloc(sz, GFP_KERNEL);
+				mem = kmalloc(sz, GFP_ATOMIC);
 				if (mem == NULL)
 					goto done;
 
@@ -1266,7 +1370,7 @@
 				 * max_id = 1 + maximum id (hosts.h)
 				 */
 				sz = sh->max_id * sizeof(void *);
-				mem = kmalloc(sz, GFP_KERNEL);
+				mem = kmalloc(sz, GFP_ATOMIC);
 				if (mem == NULL)
 					goto done;
 
@@ -1279,6 +1383,9 @@
 				/* Clear the TM flags
 				 */
 				hd->tmPending = 0;
+#ifdef MPT_SCSI_USE_NEW_EH
+				hd->tmState = TM_STATE_NONE;
+#endif
 				hd->resetPending = 0;
 				hd->abortSCpnt = NULL;
 				hd->tmPtr = NULL;
@@ -1333,7 +1440,11 @@
 					hd->ioc->spi_data.forceDv = 0;
 					for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
 						hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE;
-
+	
+					if (hd->negoNvram == 0) {
+						for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+							hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_NOT_DONE;
+					}
 
 					ddvprintk((MYIOC_s_INFO_FMT
 						"dv %x width %x factor %x \n",
@@ -1387,10 +1498,9 @@
 	spin_unlock_irqrestore(&dvtaskQ_lock, flags);
 #endif
 
+	count = 10 * HZ;
 	spin_lock_irqsave(&mytaskQ_lock, flags);
 	if (mytaskQ_bh_active) {
-		count = 10 * HZ;
-
 		spin_unlock_irqrestore(&mytaskQ_lock, flags);
 		dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));
 		clean_taskQ(hd);
@@ -1399,23 +1509,27 @@
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(1);
 		}
-		if (!count)
-			printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n");
+	} else {
+		spin_unlock_irqrestore(&mytaskQ_lock, flags);
 	}
-	spin_unlock_irqrestore(&mytaskQ_lock, flags);
+	if (!count)
+		printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n");
+
 #endif
 
 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
 	/* Check DV thread active */
 	count = 10 * HZ;
 	spin_lock_irqsave(&dvtaskQ_lock, flags);
-	while(dvtaskQ_active && --count) {
+	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);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(1);
-		spin_lock_irqsave(&dvtaskQ_lock, flags);
 	}
-	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)
@@ -1428,6 +1542,8 @@
 
 	if (hd != NULL) {
 		int sz1, sz2, sz3, sztarget=0;
+		int szr2chain = 0;
+		int szc2chain = 0;
 		int szchain = 0;
 		int szQ = 0;
 		int scale;
@@ -1452,20 +1568,20 @@
 		}
 
 		if (hd->ReqToChain != NULL) {
-			szchain += scale * hd->ioc->req_depth * sizeof(int);
+			szr2chain = scale * hd->ioc->req_depth * sizeof(int);
 			kfree(hd->ReqToChain);
 			hd->ReqToChain = NULL;
 		}
 
 		if (hd->ChainToChain != NULL) {
-			szchain += scale * hd->ioc->req_depth * sizeof(int);
+			szc2chain = scale * hd->ioc->req_depth * sizeof(int);
 			kfree(hd->ChainToChain);
 			hd->ChainToChain = NULL;
 		}
 
 		if (hd->ChainBuffer != NULL) {
 			sz2 = scale * hd->ioc->req_depth * hd->ioc->req_sz;
-			szchain += sz2;
+			szchain = szr2chain + szc2chain + sz2;
 
 			pci_free_consistent(hd->ioc->pcidev, sz2,
 				    hd->ChainBuffer, hd->ChainBufferDMA);
@@ -1772,10 +1888,10 @@
 	 *    will be no data transfer!  GRRRRR...
 	 */
 	datadir = mptscsih_io_direction(SCpnt);
-	if (datadir < 0) {
+	if (datadir == SCSI_DATA_READ) {
 		datalen = SCpnt->request_bufflen;
 		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */
-	} else if (datadir > 0) {
+	} else if (datadir == SCSI_DATA_WRITE) {
 		datalen = SCpnt->request_bufflen;
 		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */
 	} else {
@@ -1812,7 +1928,7 @@
 	pScsiReq->CDBLength = SCpnt->cmd_len;
 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
 	pScsiReq->Reserved = 0;
-	pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS;
+	pScsiReq->MsgFlags = mpt_msg_flags();
 	pScsiReq->LUN[0] = 0;
 	pScsiReq->LUN[1] = lun;
 	pScsiReq->LUN[2] = 0;
@@ -1845,10 +1961,11 @@
 	rc = SUCCESS;
 	if (datalen == 0) {
 		/* Add a NULL SGE */
-		mptscsih_AddNullSGE(pScsiReq);
+		mpt_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
+			(dma_addr_t) -1);
 	} else {
 		/* Add a 32 or 64 bit SGE */
-		rc = mptscsih_Add32BitSGE(hd, SCpnt, pScsiReq, my_idx);
+		rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
 	}
 
 
@@ -1896,11 +2013,15 @@
 
 			if (dvStatus || hd->ioc->spi_data.forceDv) {
 
-				/* Write SDP1 on 1st I/O to this target */
+				/* Write SDP1 on this I/O to this target */
 				if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
 					mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
 					dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
 					hd->ioc->spi_data.dvStatus[target] =  dvStatus;
+				} else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
+					mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
+					dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
+					hd->ioc->spi_data.dvStatus[target] =  dvStatus;
 				}
 
 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
@@ -1910,14 +2031,16 @@
 					spin_lock_irqsave(&dvtaskQ_lock, lflags);
 					if (!dvtaskQ_active) {
 						dvtaskQ_active = 1;
+						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 						mptscsih_dvTask.sync = 0;
 						mptscsih_dvTask.routine = mptscsih_domainValidation;
 						mptscsih_dvTask.data = (void *) hd;
 
 						SCHEDULE_TASK(&mptscsih_dvTask);
+					} else {
+						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 					}
 					hd->ioc->spi_data.forceDv = 0;
-					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 				}
 
 				/* Trying to do DV to this target, extend timeout.
@@ -1927,17 +2050,25 @@
 					mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
 					issueCmd = 0;
 				}
+
+				if (qtag == MPI_SCSIIO_CONTROL_UNTAGGED)
+					hd->ioc->spi_data.iocntr[target]++;
+
+				/* Set the DV flags.
+				 */
+				if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
+					mptscsih_set_dvflags(hd, pScsiReq);
 #endif
 			}
 		}
 
 		if (issueCmd) {
 			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
-			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p)\n",
-					hd->ioc->name, SCpnt));
+			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
+					hd->ioc->name, SCpnt, mf, my_idx));
 		} else {
-			ddvtprintk((MYIOC_s_INFO_FMT "Pending SCSI cmd (%p)\n",
-					hd->ioc->name, SCpnt));
+			ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
+					hd->ioc->name, SCpnt, my_idx));
 			/* Place this command on the pendingQ if possible */
 			spin_lock_irqsave(&hd->freedoneQlock, flags);
 			if (!Q_IS_EMPTY(&hd->freeQ)) {
@@ -1995,7 +2126,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_Add32BitSGE - Add a 32Bit SGE (plus chain buffers) to the
+ *	mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
  *	SCSIIORequest_t Message Frame.
  *	@hd: Pointer to MPT_SCSI_HOST structure
  *	@SCpnt: Pointer to Scsi_Cmnd structure
@@ -2004,19 +2135,19 @@
  *	Returns ...
  */
 static int
-mptscsih_Add32BitSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
 				 SCSIIORequest_t *pReq, int req_idx)
 {
-	MptSge_t *psge;
-	MptChain_t  *chainSge;
+	char 	*psge;
+	char	*chainSge;
 	struct scatterlist *sg;
 	int	 frm_sz;
 	int	 sges_left, sg_done;
 	int	 chain_idx = MPT_HOST_NO_CHAIN;
 	int	 sgeOffset;
 	int	 numSgeSlots, numSgeThisFrame;
-	u32	 sgflags, sgdir, len, thisxfer = 0;
-	int	 offset;
+	u32	 sgflags, sgdir, thisxfer = 0;
+	int	 chain_dma_off = 0;
 	int	 newIndex;
 	int	 ii;
 	dma_addr_t v2;
@@ -2028,7 +2159,7 @@
 		sgdir = MPT_TRANSFER_IOC_TO_HOST;
 	}
 
-	psge = (MptSge_t *) &pReq->SGL;
+	psge = (char *) &pReq->SGL;
 	frm_sz = hd->ioc->req_sz;
 
 	/* Map the data portion, if any.
@@ -2056,10 +2187,9 @@
 		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
 				hd->ioc->name, SCpnt, SCpnt->request_bufflen));
 
-		/* 0xD1000000 = LAST | EOB | SIMPLE | EOL */
-		psge->FlagsLength = cpu_to_le32(
-				0xD1000000|sgdir|SCpnt->request_bufflen);
-		cpu_to_leXX(buf_dma_addr, psge->Address);
+		mpt_add_sge((char *) &pReq->SGL,
+			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
+			buf_dma_addr);
 
 		return SUCCESS;
 	}
@@ -2078,7 +2208,7 @@
 	 */
 
 nextSGEset:
-	numSgeSlots = ((frm_sz - sgeOffset) / sizeof(MptSge_t));
+	numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
 	numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
 
 	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
@@ -2095,14 +2225,12 @@
 			continue;
 		}
 
-		len += thisxfer;
-		psge->FlagsLength = cpu_to_le32( sgflags | thisxfer );
 		v2 = sg_dma_address(sg);
-		cpu_to_leXX(v2, psge->Address);
+		mpt_add_sge(psge, sgflags | thisxfer, v2);
 
 		sg++;		/* Get next SG element from the OS */
-		psge++;		/* Point to next SG location in this MF */
-		sgeOffset += sizeof(MptSge_t);
+		psge += (sizeof(u32) + sizeof(dma_addr_t));
+		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
 		sg_done++;
 	}
 
@@ -2111,19 +2239,20 @@
 		 */
 		sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
 				MPT_SGE_FLAGS_END_OF_BUFFER |
-				MPT_SGE_FLAGS_ADDRESSING |
 				MPT_SGE_FLAGS_END_OF_LIST;
 
 		/* Add last SGE and set termination flags.
 		 * Note: Last SGE may have a length of 0 - which should be ok.
 		 */
 		thisxfer = sg_dma_len(sg);
-		len += thisxfer;
 
-		psge->FlagsLength = cpu_to_le32( sgflags | thisxfer );
 		v2 = sg_dma_address(sg);
-		cpu_to_leXX(v2, psge->Address);
-
+		mpt_add_sge(psge, sgflags | thisxfer, v2);
+		/*
+		sg++;
+		psge += (sizeof(u32) + sizeof(dma_addr_t));
+		*/
+		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
 		sg_done++;
 
 		if (chainSge) {
@@ -2132,9 +2261,7 @@
 			 * Update the chain element
 			 * Offset and Length fields.
 			 */
-			chainSge->NextChainOffset = 0;
-			sgeOffset += sizeof(MptSge_t);
-			chainSge->Length = cpu_to_le16(sgeOffset);
+			mpt_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The current buffer is the original MF
 			 * and there is no Chain buffer.
@@ -2163,11 +2290,10 @@
 		 * set properly).
 		 */
 		if (sg_done) {
-			psge--;
-			sgflags = le32_to_cpu (psge->FlagsLength);
+			u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
+			sgflags = le32_to_cpu(*ptmp);
 			sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
-			psge->FlagsLength = cpu_to_le32( sgflags );
-			psge++;
+			*ptmp = cpu_to_le32(sgflags);
 		}
 
 		if (chainSge) {
@@ -2177,9 +2303,9 @@
 			 * include chain element size) fields.
 			 * Old chain element is now complete.
 			 */
-			chainSge->NextChainOffset = (u8) (sgeOffset >> 2);
-			sgeOffset += sizeof(MptSge_t);
-			chainSge->Length = cpu_to_le16(sgeOffset);
+			u8 nextChain = (u8) (sgeOffset >> 2);
+			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+			mpt_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The original MF buffer requires a chain buffer -
 			 * set the offset.
@@ -2206,22 +2332,19 @@
 			hd->ReqToChain[req_idx] = newIndex;
 		}
 		chain_idx = newIndex;
-		offset = hd->ioc->req_sz * chain_idx;
+		chain_dma_off = hd->ioc->req_sz * chain_idx;
 
 		/* Populate the chainSGE for the current buffer.
 		 * - Set chain buffer pointer to psge and fill
 		 *   out the Address and Flags fields.
 		 */
-		chainSge = (MptChain_t *) psge;
-		chainSge->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
-		cpu_to_leXX ((hd->ChainBufferDMA + offset), chainSge->Address);
-
+		chainSge = (char *) psge;
 		dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",
 				psge, req_idx));
 
 		/* Start the SGE for the next buffer
 		 */
-		psge = (MptSge_t *) (hd->ChainBuffer + offset);
+		psge = (char *) (hd->ChainBuffer + chain_dma_off);
 		sgeOffset = 0;
 		sg_done = 0;
 
@@ -2239,25 +2362,6 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_AddNullSGE - Add a NULL SGE to the SCSIIORequest_t
- *	Message Frame.
- *	@pReq: Pointer to SCSIIORequest_t structure
- */
-static void
-mptscsih_AddNullSGE(SCSIIORequest_t *pReq)
-{
-	MptSge_t *psge;
-
-	psge = (MptSge_t *) &pReq->SGL;
-	psge->FlagsLength = cpu_to_le32(MPT_SGE_FLAGS_SSIMPLE_READ | 0);
-
-	cpu_to_leXX( (dma_addr_t) -1, psge->Address);
-
-	return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *	mptscsih_getFreeChainBuffes - Function to get a free chain
  *	from the MPT_SCSI_HOST FreeChainQ.
  *	@hd: Pointer to the MPT_SCSI_HOST instance
@@ -2333,11 +2437,9 @@
 
 		chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
 					+ (chain_idx * hd->ioc->req_sz));
-		//spin_lock_irqsave(&hd->FreeChainQlock, flags);
 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
 		Q_ADD_TAIL(&hd->FreeChainQ.head,
 					&chain->u.frame.linkage, MPT_FRAME_HDR);
-		//spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 
 		dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
@@ -2386,7 +2488,7 @@
 	/* If FW is being reloaded currently, return success to
 	 * the calling function.
 	 */
-	if (!hd)
+	if (hd == NULL)
 		return 0;
 
 	ioc = hd->ioc;
@@ -2431,6 +2533,9 @@
 		 */
 		rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag);
 		if (rc) {
+#ifdef MPT_SCSI_USE_NEW_EH
+			hd->tmState = TM_STATE_ERROR;
+#endif
 			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
 		} else {
 			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name);
@@ -2484,7 +2589,7 @@
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
 	int		 ii;
-	int		 retval = 0;
+	int		 retval;
 
 	/* Return Fail to calling function if no message frames available.
 	 */
@@ -2508,7 +2613,8 @@
 	pScsiTm->Reserved = 0;
 	pScsiTm->TaskType = type;
 	pScsiTm->Reserved1 = 0;
-	pScsiTm->MsgFlags = 0;
+	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
+	                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
 
 	for (ii= 0; ii < 8; ii++) {
 		pScsiTm->LUN[ii] = 0;
@@ -2540,7 +2646,6 @@
 		hd->tmPtr = NULL;
 		del_timer(&hd->TMtimer);
 		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
-		return ii;
 	}
 
 	return retval;
@@ -2564,41 +2669,62 @@
 	unsigned long	 flags;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
-	u8		 type;
-
-	printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO (=%p)\n", SCpnt);
-	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
 
+	/* If we can't locate our host adapter structure, return FAILED status.
+	 */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
 		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
 		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
+		nehprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+			   "Can't locate host! (sc=%p)\n",
+			   SCpnt));
+		return FAILED;
 	}
 
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
+	       hd->ioc->name, SCpnt);
+	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
+	       hd->ioc->name, atomic_read(&queue_depth));
+
 	/* Find this command
 	 */
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-		/* Cmd not found in ScsiLookup. If found in 
+		/* Cmd not found in ScsiLookup. If found in
 		 * doneQ, delete from Q. Do OS callback.
 		 */
 		search_doneQ_for_cmd(hd, SCpnt);
 
 		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
 		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+			   "Command not in the active list! (sc=%p)\n",
+			   hd->ioc->name, SCpnt));
 		return SUCCESS;
 	}
 
+	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
+	 *  If we time out, then we return a FAILED status to the caller.  This
+	 *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
+	 *  successful.
+	 */
+	if (mptscsih_tm_pending_wait(hd) == FAILED){
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+			   "Timed out waiting for previous TM to complete! "
+			   "(sc = %p)\n",
+			   hd->ioc->name, SCpnt));
+		return FAILED;
+	}
+
 	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Post command and flush pending Q 
+	 * during DV. Post command and flush pending Q
 	 * and then following up with the reset request.
 	 */
 	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
 		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
 		post_pendingQ_commands(hd);
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+			   "Found command in pending queue! (sc=%p)\n",
+			   hd->ioc->name, SCpnt));
 	}
 
 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
@@ -2611,61 +2737,62 @@
 	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
 
-	/* This thread will not exit until tmPending is cleared
-	 * FIXME - must ensure single threaded....DV conflict possible
-	 */
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	hd->tmPending = 1;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-	if (hd->is_spi)
-		type = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
-	else {
-		type = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
-		hd->abortSCpnt = SCpnt;
-		printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (sc=%p)\n", SCpnt);
-	}
+	hd->abortSCpnt = SCpnt;
 
-	if (mptscsih_TMHandler(hd, type,
-			SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) < 0) {
+	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+	                       SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) 
+		< 0
+	    || hd->tmState == TM_STATE_ERROR) {
 
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
 		 */
-		printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
-				hd->ioc->name, SCpnt);
+		printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
+		       hd->ioc->name, SCpnt);
 
 		/* If command not found, do not do callback,
-		 *  just return failed.  CHECKME 
+		 *  just return failed.  CHECKME
 		 */
 		if (hd->ScsiLookup[scpnt_idx] != NULL) {
-			//atomic_dec(&queue_depth);
 			SCpnt->result = STS_BUSY;
-			spin_lock_irqsave(&io_request_lock, flags);
 			SCpnt->scsi_done(SCpnt);
-			spin_unlock_irqrestore(&io_request_lock, flags);
 		}
 
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		/* We must clear our pending flag before clearing our state.
+		 */
 		hd->tmPending = 0;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-	}
+		hd->tmState = TM_STATE_NONE;
 
+		return FAILED;
+	}
 
-	/* Spin on tmPending until we get the interrupt for this TM request.
+	/* Our task management request will either complete or time out.  So we
+	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
+	 * we encountered an error executing the task management request.
 	 */
-	while (1) {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		if (!hd->tmPending) {
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+	while (hd->tmPending == 1){
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/4);
 	}
+	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+	if (hd->tmState == TM_STATE_ERROR){
+		hd->tmState = TM_STATE_NONE;
+		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+			   "TM timeout error! (sc=%p)\n",
+			   hd->ioc->name,
+			   SCpnt));
+		return FAILED;
+	}
+	hd->tmState = TM_STATE_NONE;
+	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+
+	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+		   "Abort was successful! (sc=%p)\n",
+		   hd->ioc->name,
+		   SCpnt));
 
-	return FAILED;
+	return SUCCESS;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2681,98 +2808,75 @@
 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	MPT_FRAME_HDR	*mf;
 	unsigned long	 flags;
-	int		 scpnt_idx;
-	u8		 type;
-
-	printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt);
-	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
-
-	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
-		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
-	}
-
-	/* Find this command
-	 */
-	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-		/* Cmd not found in ScsiLookup. If found in 
-		 * doneQ, delete from Q. Do OS callback.
-		 */
-		search_doneQ_for_cmd(hd, SCpnt);
-
-		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
-	}
 
-	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Force bus reset by posting command to F/W
-	 * and then following up with the reset request.
+	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
-	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
-		post_pendingQ_commands(hd);
+	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
+		nehprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
+			   "Can't locate host! (sc=%p)\n",
+			   SCpnt));
+		return FAILED;
 	}
 
-	/* This thread will not exit until tmPending is cleared
-	 */
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	hd->tmPending = 1;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-	if (hd->is_spi)
-		type = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
-	else {
-		type = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
-		printk(KERN_WARNING MYNAM ": Attempting Target Reset! (sc=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
+	       hd->ioc->name, SCpnt);
+	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
+	       hd->ioc->name, atomic_read(&queue_depth));
+
+	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
+	 *  If we time out, then we return a FAILED status to the caller.  This
+	 *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
+	 *  successful.
+	 */
+	if (mptscsih_tm_pending_wait(hd) == FAILED) {
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
+			   "Timed out waiting for previous TM to complete! "
+			   "(sc = %p)\n",
+			   hd->ioc->name, SCpnt));
+		return FAILED;
 	}
 
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-				SCpnt->target, 0, 0, CAN_SLEEP) < 0) {
+	                       SCpnt->target, 0, 0, CAN_SLEEP) 
+		< 0){
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
 		 */
 		printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
 		 		hd->ioc->name, SCpnt);
-
-		/* If command not found, do not do callback,
-		 * just returned failed. CHECKME.
-		 */
-		if (hd->ScsiLookup[scpnt_idx] != NULL) {
-			//atomic_dec(&queue_depth);
-			SCpnt->result = STS_BUSY;
-			spin_lock_irqsave(&io_request_lock, flags);
-			SCpnt->scsi_done(SCpnt);
-			spin_unlock_irqrestore(&io_request_lock, flags);
-		}
-
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
 		hd->tmPending = 0;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		hd->tmState = TM_STATE_NONE;
+		return FAILED;
 	}
 
-	/* Spin on tmPending until we get the interrupt for this TM request.
+	/* Our task management request will either complete or time out.  So we
+	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
+	 * we encountered an error executing the task management request.
 	 */
-	while (1) {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		if (!hd->tmPending) {
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+	while (hd->tmPending == 1){
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/4);
 	}
+	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+	if (hd->tmState == TM_STATE_ERROR){
+		hd->tmState = TM_STATE_NONE;
+		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
+			   "TM timeout error! (sc=%p)\n",
+			   hd->ioc->name,
+			   SCpnt));
+		return FAILED;
+	}
+	hd->tmState = TM_STATE_NONE;
+	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+
+	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
+		   "Device reset was successful! (sc=%p)\n",
+		   hd->ioc->name,
+		   SCpnt));
 
-	//return SUCCESS;
-	return FAILED;
+	return SUCCESS;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2788,95 +2892,80 @@
 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	MPT_FRAME_HDR	*mf;
 	unsigned long	 flags;
-	int		 scpnt_idx;
 
-	printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt);
-	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
-
-	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
-		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
-	}
-
-	/* Find this command
+	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
-	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-		/* Cmd not found in ScsiLookup. If found in 
-		 * doneQ, delete from Q. Do OS callback.
-		 */
-		search_doneQ_for_cmd(hd, SCpnt);
-
-		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
+	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
+		nehprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
+			   "Can't locate host! (sc=%p)\n",
+			   SCpnt ) );
+		return FAILED;
 	}
 
-	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Force bus reset by posting command to F/W
-	 * and then following up with the reset request.
-	 */
-	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
-		post_pendingQ_commands(hd);
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
+	       hd->ioc->name, SCpnt);
+	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
+	       hd->ioc->name, atomic_read(&queue_depth));
+
+	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
+	 *  If we time out, then we return a FAILED status to the caller.  This
+	 *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
+	 *  successful.
+	 */
+	if (mptscsih_tm_pending_wait(hd) == FAILED) {
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
+			   "Timed out waiting for previous TM to complete! "
+			   "(sc = %p)\n",
+			   hd->ioc->name, SCpnt ) );
+		return FAILED;
 	}
 
-	/* This thread will not exit until tmPending is cleared
-	 */
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	hd->tmPending = 1;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
+	/* We are now ready to execute the task management request. */
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-						0, 0, 0, CAN_SLEEP) < 0) {
+	                       0, 0, 0, CAN_SLEEP) 
+	    < 0){
 
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
 		 */
-		printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
-		 		hd->ioc->name, SCpnt);
-
-		/* If command not found, do not do callback,
-		 * just returned failed. CHECKME.
-		 */
-		if (hd->ScsiLookup[scpnt_idx] != NULL) {
-			//atomic_dec(&queue_depth);
-			SCpnt->result = STS_BUSY;
-			spin_lock_irqsave(&io_request_lock, flags);
-			SCpnt->scsi_done(SCpnt);
-			spin_unlock_irqrestore(&io_request_lock, flags);
-		}
-
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		printk(MYIOC_s_WARN_FMT 
+		       "Error processing TaskMgmt request (sc=%p)\n",
+		       hd->ioc->name, SCpnt);
 		hd->tmPending = 0;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
+		hd->tmState = TM_STATE_NONE;
 		return FAILED;
 	}
 
-	/* Spin on tmPending until we get the interrupt for this TM request.
+	/* Our task management request will either complete or time out.  So we
+	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
+	 * we encountered an error executing the task management request.
 	 */
-	while (1) {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		if (!hd->tmPending) {
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+	while (hd->tmPending == 1){
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/4);
 	}
+	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+	if (hd->tmState == TM_STATE_ERROR){
+		hd->tmState = TM_STATE_NONE;
+		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
+			   "TM timeout error! (sc=%p)\n",
+			   hd->ioc->name,
+			   SCpnt));
+		return FAILED;
+	}
+	hd->tmState = TM_STATE_NONE;
+	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+
+	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
+		   "Bus reset was successful! (sc=%p)\n",
+		   hd->ioc->name,
+		   SCpnt));
 
 	return SUCCESS;
 }
 
-#if 0
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_host_reset - Perform a SCSI host adapter RESET!
@@ -2890,59 +2979,75 @@
 int
 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
 {
-	MPT_SCSI_HOST	*hd;
-	MPT_FRAME_HDR	*mf;
-
-	printk(KERN_WARNING MYNAM ": Attempting HOST_RESET (%p)\n", SCpnt);
-	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+	MPT_SCSI_HOST *  hd;
+	int              status = SUCCESS;
 
-	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
-		SCpnt->result = DID_RESET << 16;
-		spin_lock_irqsave(&io_request_lock, flags);
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return SUCCESS;
+	/*  If we can't locate the host to reset, then we failed. */
+	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
+		nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+			     "Can't locate host! (sc=%p)\n",
+			     SCpnt ) );
+		return FAILED;
 	}
 
-	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Force bus reset by posting command to F/W
-	 * and then following up with the reset request.
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
+	       hd->ioc->name, SCpnt);
+	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
+	       hd->ioc->name, atomic_read(&queue_depth));
+
+	/*  If our attempts to reset the host failed, then return a failed
+	 *  status.  The host will be taken off line by the SCSI mid-layer.
 	 */
-	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
-		post_pendingQ_commands(hd);
+	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
+		status = FAILED;
+	} else {
+		/*  Make sure TM pending is cleared and TM state is set to 
+		 *  NONE. 
+		 */
+		hd->tmPending = 0;
+		hd->tmState = TM_STATE_NONE;
 	}
 
-	/* This thread will not exit until tmPending is cleared
-	 */
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	hd->tmPending = 1;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 
-	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
-		SCpnt->result = STS_BUSY;
-		spin_lock_irqsave(&io_request_lock, flags);		// sjr-added
-		SCpnt->scsi_done(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);	// sjr-added
-		return FAILED;
-	}
+	nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+		     "Status = %s\n",
+		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
 
-	/* Spin on tmPending until we get the interrupt for this TM request.
-	 */
-	while (1) {
+	return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_tm_pending_wait - wait for pending task management request to 
+ *		complete.
+ *	@hd: Pointer to MPT host structure.
+ *
+ *	Returns {SUCCESS,FAILED}.
+ */
+static int
+mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
+{
+	unsigned long  flags;
+	int            loop_count = 60 * 4;  /* Wait 60 seconds */
+	int            status = FAILED;
+
+	do {
 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		if (!hd->tmPending) {
+		if (hd->tmState == TM_STATE_NONE) {
+			hd->tmState = TM_STATE_IN_PROGRESS;
+			hd->tmPending = 1;
 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+			status = SUCCESS;
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/4);
-	}
 
-	return SUCCESS;
+	} while (--loop_count);
+
+	return status;
 }
-#endif
 
 #else		/* MPT_SCSI old EH stuff... */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2963,7 +3068,7 @@
 	unsigned long		 flags;
 	int			 scpnt_idx;
 
-	printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt);
 	printk(KERN_WARNING "  IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
@@ -3061,6 +3166,8 @@
 
 	if (! mytaskQ_bh_active) {
 		mytaskQ_bh_active = 1;
+		spin_unlock_irqrestore(&mytaskQ_lock, flags);
+
 		/*
 		 *  Oh how cute, no alloc/free/mgmt needed if we use
 		 *  (bottom/unused portion of) MPT request frame.
@@ -3071,8 +3178,9 @@
 		ptaskfoo->data = SCpnt;
 
 		SCHEDULE_TASK(ptaskfoo);
+	} else  {
+		spin_unlock_irqrestore(&mytaskQ_lock, flags);
 	}
-	spin_unlock_irqrestore(&mytaskQ_lock, flags);
 
 	return SCSI_ABORT_PENDING;
 }
@@ -3096,7 +3204,7 @@
 	unsigned long		 flags;
 	int			 scpnt_idx;
 
-	printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt);
 	printk(KERN_WARNING "  IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
@@ -3174,8 +3282,11 @@
 	atomic_inc(&mpt_taskQdepth);
 	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 
-	spin_lock_irqsave(&mytaskQ_lock, flags);
 
+	dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n",
+		hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
+
+	spin_lock_irqsave(&mytaskQ_lock, flags);
 	/* Save the original SCpnt mf pointer
 	 */
 	SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
@@ -3184,11 +3295,9 @@
 	mf->u.frame.linkage.argp1 = SCpnt;
 	mf->u.frame.linkage.argp2 = (void *) hd;
 
-	dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n",
-		hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
-
 	if (! mytaskQ_bh_active) {
 		mytaskQ_bh_active = 1;
+		spin_unlock_irqrestore(&mytaskQ_lock, flags);
 		/*
 		 *  Oh how cute, no alloc/free/mgmt needed if we use
 		 *  (bottom/unused portion of) MPT request frame.
@@ -3199,8 +3308,9 @@
 		ptaskfoo->data = SCpnt;
 
 		SCHEDULE_TASK(ptaskfoo);
+	} else  {
+		spin_unlock_irqrestore(&mytaskQ_lock, flags);
 	}
-	spin_unlock_irqrestore(&mytaskQ_lock, flags);
 	return SCSI_RESET_PENDING;
 }
 
@@ -3243,7 +3353,7 @@
 					printk(KERN_ERR MYNAM
 							": ERROR - TaskMgmt NULL SCSI Host!"
 							"(ioc=%p, sh=%p hd=%p)\n",
-							ioc, ioc->sh, hd);
+							(void *) ioc, (void *) ioc->sh, (void *) hd);
 					continue;
 				}
 
@@ -3276,7 +3386,7 @@
 				SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
 				if (SCpnt == NULL) {
 					printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)\n",
-							mf, SCpnt);
+							(void *) mf, (void *) SCpnt);
 					mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
 					spin_lock_irqsave(&ioc->FreeQlock, flags);
 					hd->tmPending = 0;
@@ -3330,7 +3440,7 @@
 
 					hd->abortSCpnt = SCpnt;
 					printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)\n",
-							mf, SCpnt);
+							(void *) mf, (void *) SCpnt);
 				}
 
 				/* The TM handler will allocate a new mf,
@@ -3345,14 +3455,14 @@
 					 * Fatal error case.
 					 */
 					printk(KERN_WARNING MYNAM
-						": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", SCpnt);
+						": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt);
 
 					if (hd->ScsiLookup[scpnt_idx] != NULL) {
 						atomic_dec(&queue_depth);
 						SCpnt->result = DID_SOFT_ERROR << 16;
-						spin_lock_irqsave(&io_request_lock, flags);
+                                                MPT_HOST_LOCK(flags);
 						SCpnt->scsi_done(SCpnt);
-						spin_unlock_irqrestore(&io_request_lock, flags);
+                                                MPT_HOST_UNLOCK(flags);
 						mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
 					}
 					spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -3462,6 +3572,9 @@
 					}
 				}
 			}
+#ifdef MPT_SCSI_USE_NEW_EH
+			hd->tmState = TM_STATE_ERROR;
+#endif
 		} else {
 			dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
 
@@ -3483,58 +3596,14 @@
 			flush_doneQ(hd);
 
 #ifdef	DROP_TEST
-			if (dropMfPtr)
-				dropTestOK++;
-#endif
-		}
-	}
-
-#ifdef	DROP_TEST
-	{
-		Scsi_Cmnd	*sc;
-		unsigned long	 flags;
-		u16		 req_idx;
-
-		/* Free resources for the drop test MF and chain buffers.
-		 */
-		if (dropMfPtr) {
-			req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx);
-			sc = hd->ScsiLookup[req_idx];
-			if (sc == NULL) {
-				printk(MYIOC_s_ERR_FMT
-					"Drop Test: NULL ScsiCmd ptr!\n",
-					ioc->name);
-			} else {
-				sc->host_scribble = NULL;
-				if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
-					sc->result = DID_RESET << 16;
-				else
-					sc->result = DID_ABORT << 16;
-
-				hd->ScsiLookup[req_idx] = NULL;
-				atomic_dec(&queue_depth);
-				spin_lock_irqsave(&io_request_lock, flags);
-				sc->scsi_done(sc);	/* Issue callback */
-				spin_unlock_irqrestore(&io_request_lock, flags);
-
-				mptscsih_freeChainBuffers(hd, req_idx);
-				mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr);
-
-				printk(MYIOC_s_INFO_FMT
-						"Free'd Dropped cmd (%p)\n",
-						hd->ioc->name, sc);
-				printk(MYIOC_s_INFO_FMT
-						"mf (%p) reqidx (%4x)\n",
-						hd->ioc->name, dropMfPtr,
-						req_idx);
-				printk(MYIOC_s_INFO_FMT
-					"Num Tot (%d) Good (%d) Bad (%d) \n",
-					hd->ioc->name, dropTestNum,
-					dropTestOK, dropTestBad);
-			}
-			dropMfPtr = NULL;
+			if (dropMfPtr)
+				dropTestOK++;
+#endif
 		}
 	}
+
+#ifdef	DROP_TEST
+	mptscsih_flush_drop_test(hd);
 #endif
 
 #ifndef MPT_SCSI_USE_NEW_EH
@@ -3588,16 +3657,16 @@
 	MPT_SCSI_HOST		*hd;
 	int			 ii, max;
 
-	for (device = sdList; device; device = device->next) {
+	for (device = sdList; device != NULL; device = device->next) {
 
 		if (device->host != sh)
 			continue;
 
 		hd = (MPT_SCSI_HOST *) sh->hostdata;
-		if (!hd)
+		if (hd == NULL)
 			continue;
 
-		if (hd->Targets) {
+		if (hd->Targets != NULL) {
 			if (hd->is_spi)
 				max = MPT_MAX_SCSI_DEVICES;
 			else
@@ -3623,11 +3692,38 @@
  *     1 = _DATA_OUT
  *     0 = _DIR_NONE
  *    -1 = _DATA_IN
+ *
+ * Changed: 3-20-2002 pdelaney to use the default data
+ * direction and the defines set up in the
+ * 2.4 kernel series
+ *     1 = _DATA_OUT	changed to SCSI_DATA_WRITE (1)
+ *     0 = _DIR_NONE	changed to SCSI_DATA_NONE (3)
+ *    -1 = _DATA_IN	changed to SCSI_DATA_READ (2)
+ * If the direction is unknown, fall through to original code.
+ *
+ * Mid-layer bug fix(): sg interface generates the wrong data 
+ * direction in some cases. Set the direction the hard way for 
+ * the most common commands.
  */
 static int
 mptscsih_io_direction(Scsi_Cmnd *cmd)
 {
 	switch (cmd->cmnd[0]) {
+	case WRITE_6:		
+	case WRITE_10:		
+		return SCSI_DATA_WRITE;
+		break;
+	case READ_6:		
+	case READ_10:		
+		return SCSI_DATA_READ;
+		break;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
+		return cmd->sc_data_direction;
+#endif
+	switch (cmd->cmnd[0]) {
 	/*  _DATA_OUT commands	*/
 	case WRITE_6:		case WRITE_10:		case WRITE_12:
 	case WRITE_LONG:	case WRITE_SAME:	case WRITE_BUFFER:
@@ -3642,7 +3738,7 @@
 	case PERSISTENT_RESERVE_OUT:
 	case 0xea:
 	case 0xa3:
-		return 1;
+		return SCSI_DATA_WRITE;
 
 	/*  No data transfer commands  */
 	case SEEK_6:		case SEEK_10:
@@ -3650,26 +3746,26 @@
 	case TEST_UNIT_READY:
 	case START_STOP:
 	case ALLOW_MEDIUM_REMOVAL:
-		return 0;
+		return SCSI_DATA_NONE;
 
 	/*  Conditional data transfer commands	*/
 	case FORMAT_UNIT:
 		if (cmd->cmnd[1] & 0x10)	/* FmtData (data out phase)? */
-			return 1;
+			return SCSI_DATA_WRITE;
 		else
-			return 0;
+			return SCSI_DATA_NONE;
 
 	case VERIFY:
 		if (cmd->cmnd[1] & 0x02)	/* VERIFY:BYTCHK (data out phase)? */
-			return 1;
+			return SCSI_DATA_WRITE;
 		else
-			return 0;
+			return SCSI_DATA_NONE;
 
 	case RESERVE_10:
 		if (cmd->cmnd[1] & 0x03)	/* RESERVE:{LongID|Extent} (data out phase)? */
-			return 1;
+			return SCSI_DATA_WRITE;
 		else
-			return 0;
+			return SCSI_DATA_NONE;
 
 #if 0
 	case REZERO_UNIT:	/* (or REWIND) */
@@ -3681,7 +3777,7 @@
 
 	/*  Must be data _IN!  */
 	default:
-		return -1;
+		return SCSI_DATA_READ;
 	}
 }
 
@@ -3727,6 +3823,20 @@
 				sz =  SCSI_STD_SENSE_BYTES;
 			memcpy(target->sense, sense_data, sz);
 			target->tflags |= MPT_TARGET_FLAGS_VALID_SENSE;
+
+#ifdef ABORT_FIX
+			if (sz >= SCSI_STD_SENSE_BYTES) {
+				if ((sense_data[02] == ABORTED_COMMAND) && 
+					(sense_data[12] == 0x47) && (sense_data[13] == 0x00)){
+					target->numAborts++;
+					if ((target->raidVolume == 0) && (target->numAborts > 5)) {
+						target->numAborts = 0;
+						target->minSyncFactor++;
+						hd->ioc->spi_data.dvStatus[index] |= MPT_SCSICFG_NEGOTIATE;
+					}
+				}
+			}
+#endif
 		}
 
 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
@@ -3820,7 +3930,7 @@
 	MPT_FRAME_HDR	*mf = NULL;
 	MPT_FRAME_HDR	*cmdMfPtr = NULL;
 
-	ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ called...", hd->ioc->name));
+	ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
 	cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
 	spin_lock_irqsave(&hd->freedoneQlock, flags);
 	if (!Q_IS_EMPTY(&hd->pendingQ)) {
@@ -3860,7 +3970,7 @@
 
 	/* Flush the pendingQ.
 	 */
-	ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands called\n", hd->ioc->name));
+	ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
 	while (1) {
 		spin_lock_irqsave(&hd->freedoneQlock, flags);
 		if (Q_IS_EMPTY(&hd->pendingQ)) {
@@ -3874,23 +3984,29 @@
 		Q_DEL_ITEM(buffer);
 
 		mf = (MPT_FRAME_HDR *) buffer->argp;
+		buffer->argp = NULL;
+
+		/* Add to the freeQ
+		 */
+		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
+		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
+
 		if (!mf) {
 			/* This should never happen */
-			printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, mf);
-			spin_unlock_irqrestore(&hd->freedoneQlock, flags);
+			printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
 			continue;
 		}
 
 		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
-		ddvtprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (mf=%p)\n",
-				hd->ioc->name, mf));
 
-		buffer->argp = NULL;
-
-		/* Add to the freeQ
-		 */
-		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
+#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
+		{
+			u16		 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+			Scsi_Cmnd	*sc = hd->ScsiLookup[req_idx];
+			printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
+					hd->ioc->name, sc, req_idx, mf);
+		}
+#endif
 	}
 
 	return;
@@ -3935,40 +4051,7 @@
 		/* 2a. Drop Test Command.
 		 */
 #ifdef	DROP_TEST
-		{
-			Scsi_Cmnd	*sc;
-			unsigned long	 flags;
-			u16		 req_idx;
-
-			/* Free resources for the drop test MF
-			 * and chain buffers.
-			 */
-			if (dropMfPtr) {
-				req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx);
-				sc = hd->ScsiLookup[req_idx];
-				if (sc == NULL) {
-					printk(MYIOC_s_ERR_FMT
-					"Drop Test: NULL ScsiCmd ptr!\n",
-					ioc->name);
-				} else {
-					sc->host_scribble = NULL;
-					sc->result = DID_RESET << 16;
-					hd->ScsiLookup[req_idx] = NULL;
-					atomic_dec(&queue_depth);
-					spin_lock_irqsave(&io_request_lock, flags);
-					sc->scsi_done(sc);	/* Issue callback */
-					spin_unlock_irqrestore(&io_request_lock, flags);
-				}
-
-				mptscsih_freeChainBuffers(hd, req_idx);
-				mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr);
-				printk(MYIOC_s_INFO_FMT
-						"Free'd: mf (%p) reqidx (%4x)\n",
-						hd->ioc->name, dropMfPtr,
-						req_idx);
-			}
-			dropMfPtr = NULL;
-		}
+		mptscsih_flush_drop_test(hd);
 #endif
 
 		/* 2b. Reply to OS all known outstanding I/O commands.
@@ -4102,14 +4185,18 @@
 		/*
 		 *  CHECKME!  Falling thru...
 		 */
+		break;
 
 	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
 		/* negoNvram set to 0 if DV enabled and to USE_NVRAM if 
-		 * if DV disabled
+		 * if DV disabled. Need to check for target mode.
 		 */
-		hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-		if (hd->negoNvram == 0) {
+		hd = NULL;
+		if (ioc->sh)
+			hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+
+		if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
 			ScsiCfgData	*pSpi;
 			Ioc3PhysDisk_t	*pPDisk;
 			int		 numPDisk;
@@ -4129,7 +4216,7 @@
 
 					while (numPDisk) {
 						if (physDiskNum == pPDisk->PhysDiskNum) {
-							pSpi->dvStatus[pPDisk->PhysDiskID] = MPT_SCSICFG_NEED_DV;
+							pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
 							pSpi->forceDv = MPT_SCSICFG_NEED_DV;
 							ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
 							break;
@@ -4556,7 +4643,7 @@
 		return 0;
 	}
 	if (	(sk==SK_UNIT_ATTENTION	&& asc==0x29 && (ascq==0x00 || ascq==0x01))
-	     || (sk==SK_NOT_READY	&& asc==0x04 && ascq==0x01)
+	     || (sk==SK_NOT_READY	&& asc==0x04 && (ascq==0x01 || ascq==0x02))
 	     || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
 	   )
 	{
@@ -4564,6 +4651,26 @@
 		return 0;
 	}
 
+	/* Prevent the system from continually writing to the log
+	 * if a medium is not found: 02 3A 00
+	 * Changer issues: TUR, Read Capacity, Table of Contents continually
+	 */
+	if (sk==SK_NOT_READY && asc==0x3A) {
+		if (ioop->cdbPtr == NULL) {
+			return 0;
+		} else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
+			(ioop->cdbPtr[0] == CMD_ReadCapacity) || 
+			(ioop->cdbPtr[0] == 0x43)) {
+			return 0;
+		}
+	}
+	if (sk==SK_UNIT_ATTENTION) {
+		if (ioop->cdbPtr == NULL)
+			return 0;
+		else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
+			return 0;
+	}
+
 	/*
 	 *  Protect ourselves...
 	 */
@@ -4675,6 +4782,13 @@
 		}
 	}
 
+	if (vdev) {
+		if (hd->ioc->spi_data.isRaid & (1 << target_id))
+			vdev->raidVolume = 1;
+		else
+			vdev->raidVolume = 0;
+	}
+
 	if (vdev && data) {
 		if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
 
@@ -4687,7 +4801,18 @@
 
 			/* Update the target capabilities
 			 */
-			mptscsih_setTargetNegoParms(hd, vdev);
+			if (dlen > 56)
+				mptscsih_setTargetNegoParms(hd, vdev, data[56]);
+			else
+				mptscsih_setTargetNegoParms(hd, vdev, 0);
+
+			/* If LUN 0, tape and have not done DV, set the DV flag.
+			 */
+			if ((lun == 0) && ((data[0] & 0x1F) == 0x01)) {
+				ScsiCfgData *pSpi = &hd->ioc->spi_data;
+				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
+					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
+			}
 		}
 
 		/* Is LUN supported? If so, upper 3 bits will be 0
@@ -4697,12 +4822,6 @@
 			vdev->luns |= (1 << lun);
 	}
 
-	if (vdev) {
-		if (hd->ioc->spi_data.isRaid & (1 << target_id))
-			vdev->raidVolume = 1;
-		else
-			vdev->raidVolume = 0;
-	}
 
 	dprintk((KERN_INFO "  target = %p\n", vdev));
 	return vdev;
@@ -4714,8 +4833,9 @@
  *  the Inquiry data, adapter capabilities, and NVRAM settings.
  *
  */
-void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target)
+void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 {
+	ScsiCfgData *pspi_data = &hd->ioc->spi_data;
 	int  id = (int) target->target_id;
 	int  nvram;
 	char canQ = 0;
@@ -4723,12 +4843,12 @@
 	u8 factor = MPT_ASYNC;
 	u8 offset = 0;
 	u8 version, nfactor;
-	ScsiCfgData *pspi_data = &hd->ioc->spi_data;
+	u8 noQas = 1;
 
 	/* Set flags based on Inquiry data
 	 */
 	if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-		version = target->inq_data[2] & 0x03;
+		version = target->inq_data[2] & 0x07;
 		if (version < 2) {
 			width = 0;
 			factor = MPT_ULTRA2;
@@ -4739,11 +4859,18 @@
 			}
 
 			if (target->inq_data[7] & 0x10) {
-				if (version == 2)
+				/* bits 2 & 3 show DT support
+				 */
+				if ((byte56 & 0x04) == 0)
 					factor = MPT_ULTRA2;
 				else
 					factor = MPT_ULTRA320;
 
+				/* bit 1 QAS support, non-raid only
+				 */
+				if ((target->raidVolume == 0) && (byte56 & 0x02) != 0)
+					noQas = 0;
+
 				offset = pspi_data->maxSyncOffset;
 			} else {
 				factor = MPT_ASYNC;
@@ -4801,15 +4928,39 @@
 
 		target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
 
-		/* Disable all wide (sync) extended messages
-		 * if device is narrow (async).
+		/* Disable unused features.
 		 */
-		target->negoFlags = 0;
+		target->negoFlags = pspi_data->noQas;
 		if (!width)
 			target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
 		if (!offset)
 			target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+		if (noQas)
+			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+		/* GEM, processor WORKAROUND
+		 */
+		if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)){
+			target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+			pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
+		}
+
+		/* Disable QAS if mixed configuration case
+		 */
+		if ((noQas) && (!pspi_data->noQas) && ((target->inq_data[0] & 0x1F) == 0x00)){
+			VirtDevice	*vdev;
+			int ii;
+
+			pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS;
+			for (ii = 0; ii < id; ii++) {
+				vdev = hd->Targets[id];
+				if (vdev != NULL)
+					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+			}
+		}
+
 	}
 
 	return;
@@ -4831,48 +4982,58 @@
 	return;
 }
 
-/* 
- * If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
+/* 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, key off of Inquiry command.
+ * 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, char *data)
+static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
 {
-	u8 cmd = pReq->CDB[0];
+	u8 cmd;
 	
-	if (pReq->LUN[1] != 0)
+	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
 		return;
 
-	if (hd->negoNvram != 0)
-		return;
+	cmd = pReq->CDB[0];
+
+	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
+		ScsiCfgData *pSpi = &hd->ioc->spi_data;
+		if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
+			/* Set NEED_DV for all hidden disks
+			 */
+			Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
+			int		numPDisk = pSpi->pIocPg3->NumPhysDisks;
 
-	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE) || 
-		((cmd == INQUIRY) && ((data[0] & 0x1F) == 0x01))) {
-		u8 dvStatus = hd->ioc->spi_data.dvStatus[pReq->TargetID];
-		if (!(dvStatus & MPT_SCSICFG_DV_DONE)) {
-			ScsiCfgData *pSpi = &hd->ioc->spi_data;
-			if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
-				/* Set NEED_DV for all hidden disks
-				 */
-				Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
-				int		numPDisk = pSpi->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));
-		};
+			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));
 	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
+ * If no Target, bus reset on 1st I/O. Set the flag to 
+ * prevent any future negotiations to this device.
+ */
+static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+{
+
+	if ((hd->Targets) && (hd->Targets[target_id] == NULL))
+		hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
+
+	return;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
  *  SCSI Config Page functionality ...
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4901,8 +5062,9 @@
 
 	if (width && offset && !nowide && !nosync) {
 		if (factor < MPT_ULTRA160) {
-			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT +
-						MPI_SCSIDEVPAGE1_RP_QAS);
+			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
+			if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
+				*requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
 		} else if (factor < MPT_ULTRA2) {
 			*requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
 		}
@@ -4922,7 +5084,7 @@
  *	@hd: Pointer to a SCSI Host Strucutre
  *	@portnum: IOC port number
  *	@target_id: writeSDP1 for single ID
- *	@flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM
+ *	@flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
  *
  *	Return: -EFAULT if read of config page header fails
  *		or 0 if success.
@@ -4942,7 +5104,6 @@
 	SCSIDevicePage1_t	*pData = NULL;
 	VirtDevice		*pTarget = NULL;
 	MPT_FRAME_HDR		*mf;
-	MptSge_t		*psge;
 	dma_addr_t		 dataDma;
 	u16			 req_idx;
 	u32			 frameOffset;
@@ -4954,6 +5115,7 @@
 	u8			 offset;
 	u8			 bus = 0;
 	u8			 negoFlags;
+	u8			 maxwidth, maxoffset, maxfactor;
 
 	if (ioc->spi_data.sdp1length == 0)
 		return 0;
@@ -4967,48 +5129,54 @@
 	}
 
 	for (; id <= maxid; id++) {
+
 		if (id == ioc->pfacts[portnum].PortSCSIID)
 			continue;
 
-		if (flags & MPT_SCSICFG_USE_NVRAM) {
-			/* Use NVRAM, adapter maximums and target settings.
-			 * Data over-riden by target structure information, if present
-			 */
-			width = ioc->spi_data.maxBusWidth;
-			offset = ioc->spi_data.maxSyncOffset;
-			factor = ioc->spi_data.minSyncFactor;
-			if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-				nvram = ioc->spi_data.nvram[id];
-
-				if (width)
-					width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-				if (offset > 0) {
-					factor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-					if (factor == 0) {
-						/* Key for async */
-						factor = MPT_ASYNC;
-						offset = 0;
-					} else if (factor < ioc->spi_data.minSyncFactor) {
-						factor = ioc->spi_data.minSyncFactor;
-					}
-				} else
-					factor = MPT_ASYNC;
-			}
+		/* Use NVRAM to get adapter and target maximums
+		 * Data over-riden by target structure information, if present
+		 */
+		maxwidth = ioc->spi_data.maxBusWidth;
+		maxoffset = ioc->spi_data.maxSyncOffset;
+		maxfactor = ioc->spi_data.minSyncFactor;
+		if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+			nvram = ioc->spi_data.nvram[id];
+
+			if (maxwidth)
+				maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+
+			if (maxoffset > 0) {
+				maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+				if (maxfactor == 0) {
+					/* Key for async */
+					maxfactor = MPT_ASYNC;
+					maxoffset = 0;
+				} else if (maxfactor < ioc->spi_data.minSyncFactor) {
+					maxfactor = ioc->spi_data.minSyncFactor;
+				}
+			} else
+				maxfactor = MPT_ASYNC;
+		}
 
-			/* Set the negotiation flags.
-			 */
-			negoFlags = 0;
-			if (!width)
-				negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-	
-			if (!offset)
-				negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+		/* Set the negotiation flags.
+		 */
+		negoFlags = ioc->spi_data.noQas;
+		if (!maxwidth)
+			negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+
+		if (!maxoffset)
+			negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+		if (flags & MPT_SCSICFG_USE_NVRAM) {
+			width = maxwidth;
+			factor = maxfactor;
+			offset = maxoffset;
 		} else {
 			width = 0;
 			factor = MPT_ASYNC;
 			offset = 0;
-			negoFlags = MPT_TARGET_NO_NEGO_SYNC;
+			//negoFlags = 0;
+			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
 		}
 
 		/* If id is not a raid volume, get the updated
@@ -5021,12 +5189,12 @@
 			negoFlags = pTarget->negoFlags;
 			pTarget = NULL;
 		}
-		mptscsih_setDevicePage1Flags(width, factor, offset,
-					&requested, &configuration, negoFlags);
 
+		if (flags & MPT_SCSICFG_BLK_NEGO)
+			negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
 
-		if (negoFlags == (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC))
-			continue;
+		mptscsih_setDevicePage1Flags(width, factor, offset,
+					&requested, &configuration, negoFlags);
 
 		/* Get a MF for this command.
 		 */
@@ -5036,6 +5204,10 @@
 			return -EAGAIN;
 		}
 
+		ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
+			hd->ioc->name, mf, id, requested, configuration));
+
+
 		/* Set the request and the data pointers.
 		 * Request takes: 36 bytes (32 bit SGE)
 		 * SCSI Device Page 1 requires 16 bytes
@@ -5074,9 +5246,7 @@
 		 */
 		flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
 
-		psge = (MptSge_t *) &pReq->PageBufferSGE;
-		psge->FlagsLength = cpu_to_le32(flagsLength);
-		cpu_to_leXX(dataDma, psge->Address);
+		mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
 
 		/* Set up the common data portion
 		 */
@@ -5109,19 +5279,39 @@
 {
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
 
-	dprintk((MYIOC_s_WARN_FMT "TM request timed out!\n", hd->ioc->name));
+	dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
+		   "TM request timed out!\n", hd->ioc->name));
+
 	/* Delete the timer that triggered this callback.
 	 * Remark: del_timer checks to make sure timer is active
 	 * before deleting.
 	 */
 	del_timer(&hd->TMtimer);
 
+#ifdef MPT_SCSI_USE_NEW_EH
+	/* Set the error flag to 1 so that the function that started the
+	 * task management request knows it timed out.
+	 */
+	hd->tmState = TM_STATE_ERROR;
+#endif
+
 	/* Call the reset handler. Already had a TM request
 	 * timeout - so issue a diagnostic reset
 	 */
 	if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
 		printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
 	}
+#ifdef MPT_SCSI_USE_NEW_EH
+	else {
+		/* Because we have reset the IOC, no TM requests can be
+		 * pending.  So let's make sure the tmPending flag is reset.
+		 */
+		nehprintk((KERN_WARNING MYNAM 
+			   ": %s: mptscsih_taskmgmt_timeout\n", 
+			   hd->ioc->name));
+		hd->tmPending = 0;
+	}
+#endif
 
 	return;
 }
@@ -5163,7 +5353,7 @@
 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
 		printk(MYIOC_s_ERR_FMT
 			"ScanDvComplete, %s req frame ptr! (=%p)\n",
-				ioc->name, mf?"BAD":"NULL", mf);
+				ioc->name, mf?"BAD":"NULL", (void *) mf);
 		goto wakeup;
 	}
 
@@ -5174,13 +5364,13 @@
 	pReq = (SCSIIORequest_t *) mf;
 
 	if (mf != hd->cmdPtr) {
-		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p)\n",
-				hd->ioc->name, mf, hd->cmdPtr);
+		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
+				hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
 	}
 	hd->cmdPtr = NULL;
 
-	ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p)\n",
-			hd->ioc->name, mf, mr));
+	ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
+			hd->ioc->name, mf, mr, req_idx));
 
 	atomic_dec(&queue_depth);
 
@@ -5392,8 +5582,6 @@
 {
 	MpiRaidActionRequest_t	*pReq;
 	MPT_FRAME_HDR		*mf;
-	MptSge_t		*psge;
-	int			flagsLength;
 	int			in_isr;
 
 	in_isr = in_interrupt();
@@ -5423,14 +5611,8 @@
 	pReq->ActionDataWord = 0; /* Reserved for this action */
 	//pReq->ActionDataSGE = 0;
 
-	psge = (MptSge_t *) &pReq->ActionDataSGE;
-
-	/* Add a SGE to the config request.
-	 */
-	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 0;
-
-	psge->FlagsLength = cpu_to_le32(flagsLength);
-	cpu_to_leXX( (dma_addr_t) -1, psge->Address);
+	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));
@@ -5479,7 +5661,6 @@
 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 {
 	MPT_FRAME_HDR	*mf;
-	MptSge_t	*mpisge;
 	SCSIIORequest_t	*pScsiReq;
 	SCSIIORequest_t	 ReqCopy;
 	int		 my_idx, ii, dir;
@@ -5614,7 +5795,7 @@
 
 	pScsiReq->Reserved = 0;
 
-	pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS;
+	pScsiReq->MsgFlags = mpt_msg_flags();
 	/* MsgContext set in mpt_get_msg_fram call  */
 
 	for (ii=0; ii < 8; ii++)
@@ -5636,21 +5817,16 @@
 	ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
 			hd->ioc->name, cmd, io->bus, io->id, io->lun));
 
-	/* 32 bit SG only */
-	mpisge = (MptSge_t *) &pScsiReq->SGL;
-
 	if (dir == MPI_SCSIIO_CONTROL_READ) {
-		mpisge->FlagsLength = cpu_to_le32(
-			MPT_SGE_FLAGS_SSIMPLE_READ | io->size);
+		mpt_add_sge((char *) &pScsiReq->SGL,
+			MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
+			io->data_dma);
 	} else {
-		mpisge->FlagsLength = cpu_to_le32(
-			MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size);
+		mpt_add_sge((char *) &pScsiReq->SGL,
+			MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
+			io->data_dma);
 	}
 
-	/* data_dma defaults to -1
-	 */
-	cpu_to_leXX(io->data_dma, mpisge->Address);
-
 	/* The ISR will free the request frame, but we need
 	 * the information to initialize the target. Duplicate.
 	 */
@@ -5786,7 +5962,7 @@
 			if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
 				flags = pTarget->negoFlags;
 			} else {
-				flags = 0;
+				flags = hd->ioc->spi_data.noQas;
 				if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
 					data = hd->ioc->spi_data.nvram[id];
 	
@@ -5917,8 +6093,25 @@
 				dvStatus = hd->ioc->spi_data.dvStatus[id];
 
 				if (dvStatus & MPT_SCSICFG_NEED_DV) {
+					VirtDevice *pTarget = hd->Targets[id];
+					did++;
+					if (pTarget && ((pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) == 0)){
+						if (hd->ioc->spi_data.iocntr[id] == 0) {
+							hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
+						} else {
+							/* Wait until not busy
+							 */
+							ddvtprintk((MYIOC_s_NOTE_FMT 
+							" DV Wait: %d untagged and busy. cntr %d\n",
+							ioc->name, id, 
+							hd->ioc->spi_data.iocntr[id]));
+							continue;
+						}
+					} else {
+						hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
+					}
+
 
-					hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
 					hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
 
 					set_current_state(TASK_INTERRUPTIBLE);
@@ -5928,24 +6121,7 @@
 					 *	raid volumes
 					 * else, process normally
 					 */
-					isPhysDisk = 0;
-					if (ioc->spi_data.pIocPg3) {
-						/* Search IOC page 3 to determine if
-						 * this is hidden physical disk
-						 */
-						Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
-						int		numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
-						
-						while (numPDisk) {
-							if (pPDisk->PhysDiskID == id) {
-								isPhysDisk = 1;
-								break;
-							}
-							pPDisk++;
-							numPDisk--;
-						}
-					}
-
+					isPhysDisk = mptscsih_is_phys_disk(ioc, id);
 					if (isPhysDisk) {
 						for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
 							if (hd->ioc->spi_data.isRaid & (1 << ii)) {
@@ -5955,9 +6131,8 @@
 					}
 
 					mptscsih_doDv(hd, 0, id);
-					did++;
-					hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_DONE;
-					hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
+
+					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++) {
@@ -5971,6 +6146,9 @@
 					 * DV running.
 					 */
 					post_pendingQ_commands(hd);
+
+					if (hd->ioc->spi_data.noQas)
+						mptscsih_qas_check(hd);
 				}
 			}
 		}
@@ -5983,6 +6161,55 @@
 	return;
 }
 
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+{
+	if (ioc->spi_data.pIocPg3) {
+		Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
+		int		numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+
+		while (numPDisk) {
+			if (pPDisk->PhysDiskID == id) {
+				return 1;
+			}
+			pPDisk++;
+			numPDisk--;
+		}
+	}
+	return 0;
+}
+
+/* Write SDP1 if no QAS has been enabled
+ */
+static void mptscsih_qas_check(MPT_SCSI_HOST *hd)
+{
+	VirtDevice *pTarget = NULL;
+	int ii;
+
+	if (hd->Targets == NULL)
+		return;
+
+	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+		if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
+			continue;
+
+		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;
+				mptscsih_writeSDP1(hd, 0, ii, 0);
+			}
+		} else {
+			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
+				mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
+		}
+	}
+	return;
+}
+
+
 
 #define MPT_GET_NVRAM_VALS	0x01
 #define MPT_UPDATE_MAX		0x02
@@ -6009,19 +6236,22 @@
 {
 	MPT_ADAPTER		*ioc = hd->ioc;
 	VirtDevice		*pTarget = NULL;
+	SCSIDevicePage1_t	*pcfg1Data = NULL;
+	SCSIDevicePage0_t	*pcfg0Data = NULL;
 	u8			*pbuf1 = NULL;
 	u8			*pbuf2 = NULL;
+	u8			*pDvBuf = NULL;
+	dma_addr_t		 dvbuf_dma = -1;
 	dma_addr_t		 buf1_dma = -1;
 	dma_addr_t		 buf2_dma = -1;
-	ConfigPageHeader_t	 header1;
-	SCSIDevicePage1_t	*pcfg1Data = NULL;
 	dma_addr_t		 cfg1_dma_addr = -1;
-	ConfigPageHeader_t	 header0;
-	SCSIDevicePage0_t	*pcfg0Data = NULL;
 	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;
@@ -6033,6 +6263,7 @@
 	char			 doFallback = 0;
 	char			 readPage0;
 	char			 bus, lun;
+	char			 inq0 = 0;
 
 	if (ioc->spi_data.sdp1length == 0)
 		return;
@@ -6078,6 +6309,16 @@
 	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 		iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
 
+	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+		/* Another GEM workaround. Check peripheral device type,
+		 * if PROCESSOR, quit DV.
+		 */
+		if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
+			pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+			return;
+		}
+	}
+
 	/* Prep cfg structure
 	 */
 	cfg.pageAddr = (bus<<8) | id;
@@ -6089,10 +6330,6 @@
 	header0.PageLength = ioc->spi_data.sdp0length;
 	header0.PageNumber = 0;
 	header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-	pcfg0Data = (SCSIDevicePage0_t *)pci_alloc_consistent(ioc->pcidev,
-				 header0.PageLength * 4, &cfg0_dma_addr);
-	if (!pcfg0Data)
-		return;
 
 	/* Prep SDP1 header
 	 */
@@ -6100,10 +6337,36 @@
 	header1.PageLength = ioc->spi_data.sdp1length;
 	header1.PageNumber = 1;
 	header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-	pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
-				 header1.PageLength * 4, &cfg1_dma_addr);
-	if (!pcfg1Data)
-		goto target_done;
+
+	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;
+
+	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.hdr to force config page write
 	 */
@@ -6164,11 +6427,6 @@
 	hd->pLocal = NULL;
 	readPage0 = 0;
 	sz = SCSI_STD_INQUIRY_BYTES;
-	pbuf1 = pci_alloc_consistent(ioc->pcidev, sz, &buf1_dma);
-	pbuf2 = pci_alloc_consistent(ioc->pcidev, sz, &buf2_dma);
-	if (!pbuf1 || !pbuf2)
-		goto target_done;
-
 	while (1) {
 		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test.\n", ioc->name));
 		dv.cmd = MPT_SET_MIN;
@@ -6234,6 +6492,7 @@
 					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;
 
@@ -6277,12 +6536,13 @@
 			firstPass = 0;
 		}
 	}
-	/* Free pbuf2, but use pbuf1 for
-	 * acquiring the (echo) buffer size.
-	 */
-	pci_free_consistent(ioc->pcidev, sz, pbuf2, buf2_dma);
-	pbuf2 = NULL;
 	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test completed OK.\n", ioc->name));
+	inq0 = (*pbuf1) & 0x1F;
+
+	/* Continue only for disks
+	 */
+	if (inq0 != 0)
+		goto target_done;
 
 	/* Start the Enhanced Test.
 	 * 0) issue TUR to clear out check conditions
@@ -6418,8 +6678,6 @@
 		else
 			dataBufSize = bufsize;
 	}
-	pci_free_consistent(ioc->pcidev, sz, pbuf1, buf1_dma);
-	pbuf1 = NULL;
 	sz = 0;
 	iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
 
@@ -6438,13 +6696,9 @@
 	ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
 		(iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
 
-	/* Allocate data buffers for write-read-compare test.
+	/* Data buffers for write-read-compare test max 1K.
 	 */
 	sz = MIN(bufsize, 1024);
-	pbuf1 = pci_alloc_consistent(ioc->pcidev, sz, &buf1_dma);
-	pbuf2 = pci_alloc_consistent(ioc->pcidev, sz, &buf2_dma);
-	if (!pbuf1 || !pbuf2)
-		goto target_done;
 
 	/* --- loop ----
 	 * On first pass, always issue a reserve.
@@ -6698,6 +6952,12 @@
 	/* Set if cfg1_dma_addr contents is valid
 	 */
 	if (cfg.hdr != NULL) {
+
+		/* If disk, not U320, disable QAS
+		 */
+		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
+			hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+
 		dv.cmd = MPT_SAVE;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
 
@@ -6720,25 +6980,8 @@
 
 	/* Done with the DV scan of the current target
 	 */
-	if (pcfg0Data) {
-		pci_free_consistent(ioc->pcidev, header0.PageLength * 4,
-						pcfg0Data, cfg0_dma_addr);
-	}
-
-	if (pcfg1Data) {
-		pci_free_consistent(ioc->pcidev, header1.PageLength * 4,
-						pcfg1Data, cfg1_dma_addr);
-	}
-
-	if (pbuf1) {
-		pci_free_consistent(ioc->pcidev, sz, pbuf1, buf1_dma);
-		pbuf1 = NULL;
-	}
-
-	if (pbuf2) {
-		pci_free_consistent(ioc->pcidev, sz, pbuf2, buf2_dma);
-		pbuf2 = NULL;
-	}
+	if (pDvBuf)
+		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
 
 	ddvtprintk((MYIOC_s_INFO_FMT "DV Done. IOs outstanding = %d\n",
 			ioc->name, atomic_read(&queue_depth)));
@@ -6800,7 +7043,7 @@
 			}
 
 			/* Set the negotiation flags */
-			negoFlags = 0;
+			negoFlags = hd->ioc->spi_data.noQas;
 			if (!width)
 				negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
@@ -6947,6 +7190,7 @@
 			width = MPT_NARROW;
 			factor = MPT_ASYNC;
 		}
+		dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
 
 		dv->now.width = width;
 		dv->now.offset = offset;
@@ -6981,24 +7225,27 @@
 			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
 			 */
-			data = hd->ioc->spi_data.nvram[id];
+			if (hd->ioc->spi_data.nvram) {
+				data = hd->ioc->spi_data.nvram[id];
 
-			if (dv->now.width)
-				data &= ~MPT_NVRAM_WIDE_DISABLE;
-			else
-				data |= MPT_NVRAM_WIDE_DISABLE;
+				if (dv->now.width)
+					data &= ~MPT_NVRAM_WIDE_DISABLE;
+				else
+					data |= MPT_NVRAM_WIDE_DISABLE;
 
-			if (!dv->now.offset)
-				factor = MPT_ASYNC;
+				if (!dv->now.offset)
+					factor = MPT_ASYNC;
 
-			data &= ~MPT_NVRAM_SYNC_MASK;
-			data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
+				data &= ~MPT_NVRAM_SYNC_MASK;
+				data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
 
-			hd->ioc->spi_data.nvram[id] = data;
+				hd->ioc->spi_data.nvram[id] = data;
+			}
 		}
 		break;
 	}
@@ -7186,8 +7433,6 @@
 	unsigned long val;
 	int  c;
 
-	printk("KERN_WARNING: mptscsih_setup arg %s\n", str);
-
 	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
 		char *pe;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)