patch-2.4.19 linux-2.4.19/drivers/message/fusion/mptbase.c

Next file: linux-2.4.19/drivers/message/fusion/mptbase.h
Previous file: linux-2.4.19/drivers/message/fusion/lsi/mpi_type.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/drivers/message/fusion/mptbase.c linux-2.4.19/drivers/message/fusion/mptbase.c
@@ -20,6 +20,12 @@
  *      And to Roger Hickerson (LSI Logic) for tirelessly supporting
  *      this driver project.
  *
+ *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
+ *      and countless enhancements while adding support for the 1030
+ *      chip family.  Pam has been instrumental in the development of
+ *      of the 2.xx.xx series fusion drivers, and her contributions are
+ *      far too numerous to hope to list in one place.
+ *
  *      All manner of help from Stephen Shirron (LSI Logic):
  *      low-level FC analysis, debug + various fixes in FCxx firmware,
  *      initial port to alpha platform, various driver code optimizations,
@@ -38,11 +44,12 @@
  *      for gobs of hard work fixing and optimizing LAN code.
  *      THANK YOU!
  *
- *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Copyright (c) 1999-2002 LSI Logic Corporation
  *  Originally By: Steven J. Ralston
- *  (mailto:Steve.Ralston@lsil.com)
+ *  (mailto:sjralston1@netscape.net)
+ *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptbase.c,v 1.53.4.3 2001/09/18 03:54:54 sralston Exp $
+ *  $Id: mptbase.c,v 1.110 2002/02/27 18:44:20 sralston Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -93,11 +100,14 @@
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
-#include <linux/proc_fs.h>
+#include <linux/interrupt.h>		/* needed for in_interrupt() proto */
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
+#ifdef __sparc__
+#include <asm/irq.h>			/* needed for __irq_itoa() proto */
+#endif
 
 #include "mptbase.h"
 
@@ -110,27 +120,33 @@
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
 
-
 /*
  *  cmd line parameters
  */
 MODULE_PARM(PortIo, "0-1i");
 MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");
-MODULE_PARM(HardReset, "0-1i");
-MODULE_PARM_DESC(HardReset, "0=Disable HardReset, [1]=Enable HardReset");
 static int PortIo = 0;
-static int HardReset = 1;
+
+#ifdef MFCNT
+static int mfcounter = 0;
+#define PRINT_MF_COUNT 20000
+#endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Public data...
  */
-int mpt_lan_index = 0;
-int mpt_stm_index = 0;
+int mpt_lan_index = -1;
+int mpt_stm_index = -1;
+
+struct proc_dir_entry *mpt_proc_root_dir;
+
+DmpServices_t *DmpService;
+
+void *mpt_v_ASCQ_TablePtr;
+const char **mpt_ScsiOpcodesPtr;
+int mpt_ASCQ_TableSz;
 
-void *mpt_v_ASCQ_TablePtr = NULL;
-const char **mpt_ScsiOpcodesPtr = NULL;
-int mpt_ASCQ_TableSz = 0;
 
 #define WHOINIT_UNKNOWN		0xAA
 
@@ -139,12 +155,12 @@
  *  Private data...
  */
 					/* Adapter lookup table */
-static MPT_ADAPTER		*mpt_adapters[MPT_MAX_ADAPTERS] = {0};
+       MPT_ADAPTER		*mpt_adapters[MPT_MAX_ADAPTERS];
 static MPT_ADAPTER_TRACKER	 MptAdapters;
 					/* Callback lookup table */
 static MPT_CALLBACK		 MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
 					/* Protocol driver class lookup table */
-static int	 		 MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
+static int			 MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
 					/* Event handler lookup table */
 static MPT_EVHANDLER		 MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 					/* Reset handler lookup table */
@@ -152,6 +168,10 @@
 
 static int	FusionInitCalled = 0;
 static int	mpt_base_index = -1;
+static int	last_drv_idx = -1;
+static int	isense_idx = -1;
+
+static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -160,49 +180,84 @@
 static void	mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
 static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 
-static int 	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason);
-static int 	mpt_adapter_install(struct pci_dev *pdev);
-static void	mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
+static int	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+static int	mpt_adapter_install(struct pci_dev *pdev);
+static void	mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
 static void	mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
 static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
 
 static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
-static int	MakeIocReady(MPT_ADAPTER *ioc, int force);
-static u32	GetIocState(MPT_ADAPTER *ioc, int cooked);
-static int	GetIocFacts(MPT_ADAPTER *ioc);
-static int	GetPortFacts(MPT_ADAPTER *ioc, int portnum);
-static int	SendIocInit(MPT_ADAPTER *ioc);
-static int	SendPortEnable(MPT_ADAPTER *ioc, int portnum);
-static int	mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore);
-static int	KickStart(MPT_ADAPTER *ioc, int ignore);
-static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type);
+static int	MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
+//static u32	mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
+static int	GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
+static int	GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
+static int	SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
+static int	SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
+static int	mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
+static int	mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
+static int	mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+static int	KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
 static int	PrimeIocFifos(MPT_ADAPTER *ioc);
-static int	HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait);
-static int	WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong);
-static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong);
-static int	WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong);
+static int	WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+static int	WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int	GetLanConfigPages(MPT_ADAPTER *ioc);
+static int	GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
+static int	GetIoUnitPage2(MPT_ADAPTER *ioc);
+static int	mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
+static int	mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
+static int	mpt_findImVolumes(MPT_ADAPTER *ioc);
+static void	mpt_timer_expired(unsigned long data);
 static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
 static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
 
-static int	procmpt_create(void);
 #ifdef CONFIG_PROC_FS
+static int	procmpt_create(void);
 static int	procmpt_destroy(void);
+static int	procmpt_summary_read(char *buf, char **start, off_t offset,
+				int request, int *eof, void *data);
+static int	procmpt_version_read(char *buf, char **start, off_t offset,
+				int request, int *eof, void *data);
+static int	procmpt_iocinfo_read(char *buf, char **start, off_t offset,
+				int request, int *eof, void *data);
 #endif
-static int	procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int	procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data);
-/*static int	procmpt_info(char *buf, char **start, off_t offset, int len);*/
+static void	mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
 
+//int		mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
 
-static struct proc_dir_entry	*procmpt_root_dir = NULL;
-
 int		fusion_init(void);
 static void	fusion_exit(void);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  more Private data...
+ */
+#ifdef CONFIG_PROC_FS
+struct _mpt_proc_list {
+	const char	*name;
+	int		(*f)(char *, char **, off_t, int, int *, void *);
+} mpt_proc_list[] = {
+	{ "summary", procmpt_summary_read},
+	{ "version", procmpt_version_read},
+};
+#define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0]))
+
+struct _mpt_ioc_proc_list {
+	const char	*name;
+	int		(*f)(char *, char **, off_t, int, int *, void *);
+} mpt_ioc_proc_list[] = {
+	{ "info", procmpt_iocinfo_read},
+	{ "summary", procmpt_summary_read},
+};
+#define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0]))
+
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* 20000207 -sralston
  *  GRRRRR...  IOSpace (port i/o) register access (for the 909) is back!
  * 20000517 -sralston
@@ -225,9 +280,18 @@
 		writel(v, a);
 }
 
+static inline void CHIPREG_PIO_WRITE32(volatile u32 *a, u32 v)
+{
+	outl(v, (unsigned long)a);
+}
+
+static inline u32 CHIPREG_PIO_READ32(volatile u32 *a)
+{
+	return inl((unsigned long)a);
+}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
  *	@irq: irq number (not used)
  *	@bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
@@ -252,8 +316,7 @@
 	MPT_FRAME_HDR	*mf;
 	MPT_FRAME_HDR	*mr;
 	u32		 pa;
-	u32		*m;
-	int		 req_idx;
+	int		 req_idx = -1;
 	int		 cb_idx;
 	int		 type;
 	int		 freeme;
@@ -262,6 +325,21 @@
 	ioc = bus_id;
 
 	/*
+	 * Verify ioc pointer is ok
+	 */
+	{
+		MPT_ADAPTER	*iocCmp;
+		iocCmp = mpt_adapter_find_first();
+		while ((ioc != iocCmp)  && iocCmp)
+			iocCmp = mpt_adapter_find_next(iocCmp);
+
+		if (!iocCmp) {
+			printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n");
+			return;
+		}
+	}
+
+	/*
 	 *  Drain the reply FIFO!
 	 *
 	 * NOTES: I've seen up to 10 replies processed in this loop, so far...
@@ -281,25 +359,27 @@
 		 *  Check for non-TURBO reply!
 		 */
 		if (pa & MPI_ADDRESS_REPLY_A_BIT) {
-			dma_addr_t reply_dma_addr;
+			u32 reply_dma_low;
 			u16 ioc_stat;
 
 			/* non-TURBO reply!  Hmmm, something may be up...
 			 *  Newest turbo reply mechanism; get address
 			 *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
 			 */
-			reply_dma_addr = (pa = (pa << 1));
 
-			/* Map DMA address of reply header to cpu address. */
-			m = (u32 *) ((u8 *)ioc->reply_frames +
-					(reply_dma_addr - ioc->reply_frames_dma));
+			/* Map DMA address of reply header to cpu address.
+			 * pa is 32 bits - but the dma address may be 32 or 64 bits
+			 * get offset based only only the low addresses
+			 */
+			reply_dma_low = (pa = (pa << 1));
+			mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
+					 (reply_dma_low - ioc->reply_frames_low_dma));
 
-			mr = (MPT_FRAME_HDR *) m;
 			req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
 			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
 			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 
-			dprintk((KERN_INFO MYNAM ": %s: Got non-TURBO reply=%p\n",
+			dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
 					ioc->name, mr));
 			DBG_DUMP_REPLY_FRAME(mr)
 
@@ -307,7 +387,7 @@
 			 *  Check/log IOC log info
 			 */
 			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
-	 		if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+			if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
 				u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
 				if ((int)ioc->chip_type <= (int)FC929)
 					mpt_fc_log_info(ioc, log_info);
@@ -318,7 +398,7 @@
 			/*
 			 *  Process turbo (context) reply...
 			 */
-			dirqprintk((KERN_INFO MYNAM ": %s: Got TURBO reply(=%08x)\n", ioc->name, pa));
+			dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
 			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
 			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
 				cb_idx = mpt_stm_index;
@@ -357,6 +437,34 @@
 			pa = 0;					/* No reply flush! */
 		}
 
+		if ((int)ioc->chip_type > (int)FC929) {
+			/* Verify mf, mf are reasonable.
+			 */
+			if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
+				|| (mf < ioc->req_frames)) ) {
+				printk(MYIOC_s_WARN_FMT 
+					"mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, mf, req_idx);
+				cb_idx = 0;
+				pa = 0;
+				freeme = 0;
+			}
+			if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
+				|| (mr < ioc->reply_frames)) ) {
+				printk(MYIOC_s_WARN_FMT 
+					"mpt_interrupt: Invalid rf (%p)!\n", ioc->name, mr);
+				cb_idx = 0;
+				pa = 0;
+				freeme = 0;
+			}
+			if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
+				printk(MYIOC_s_WARN_FMT 
+					"mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
+				cb_idx = 0;
+				pa = 0;
+				freeme = 0;
+			}
+		}
+
 		/*  Check for (valid) IO callback!  */
 		if (cb_idx) {
 			/*  Do the callback!  */
@@ -374,15 +482,18 @@
 			/*  Put Request back on FreeQ!  */
 			spin_lock_irqsave(&ioc->FreeQlock, flags);
 			Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+#ifdef MFCNT
+			ioc->mfcnt--;
+#endif
 			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		}
 
 		count++;
-		dirqprintk((KERN_INFO MYNAM ": %s: ISR processed frame #%d\n", ioc->name, count));
+		dirqprintk((MYIOC_s_INFO_FMT "ISR processed frame #%d\n", ioc->name, count));
 		mb();
 
 		if (count >= MPT_MAX_REPLIES_PER_ISR) {
-			dirqprintk((KERN_INFO MYNAM ": %s: ISR processed %d replies.",
+			dirqprintk((MYIOC_s_INFO_FMT "ISR processed %d replies.",
 					ioc->name, count));
 			dirqprintk((" Giving this ISR a break!\n"));
 			return;
@@ -409,17 +520,17 @@
 	int freereq = 1;
 	u8 func;
 
-	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply() called\n", ioc->name));
+	dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
 
 	if ((mf == NULL) ||
 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
-		printk(KERN_ERR MYNAM ": %s: ERROR - NULL or BAD request frame ptr! (=%p)\n",
+		printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
 				ioc->name, mf);
 		return 1;
 	}
 
 	if (reply == NULL) {
-		dprintk((KERN_ERR MYNAM ": %s: ERROR - Unexpected NULL Event (turbo?) reply!\n",
+		dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
 				ioc->name));
 		return 1;
 	}
@@ -430,7 +541,7 @@
 	}
 
 	func = reply->u.hdr.Function;
-	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, Function=%02Xh\n",
+	dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
 			ioc->name, func));
 
 	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
@@ -441,30 +552,77 @@
 		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
 		if (results != evHandlers) {
 			/* CHECKME! Any special handling needed here? */
-			dprintk((KERN_WARNING MYNAM ": %s: Hmmm... Called %d event handlers, sum results = %d\n",
+			dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
 					ioc->name, evHandlers, results));
 		}
 
 		/*
-		 *  Hmmm...  It seems that EventNotificationReply is an exception
-		 *  to the rule of one reply per request.
+		 *	Hmmm...  It seems that EventNotificationReply is an exception
+		 *	to the rule of one reply per request.
 		 */
 		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
 			freereq = 0;
+
 #ifdef CONFIG_PROC_FS
 //		LogEvent(ioc, pEvReply);
 #endif
+
 	} else if (func == MPI_FUNCTION_EVENT_ACK) {
-		dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, EventAck reply received\n",
+		dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
 				ioc->name));
+	} else if (func == MPI_FUNCTION_CONFIG) {
+		CONFIGPARMS *pCfg;
+		unsigned long flags;
+
+		dprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
+				ioc->name, mf, reply));
+
+		pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
+
+		if (pCfg) {
+			/* disable timer and remove from linked list */
+			del_timer(&pCfg->timer);
+
+			spin_lock_irqsave(&ioc->FreeQlock, flags);
+			Q_DEL_ITEM(&pCfg->linkage);
+			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+			/*
+			 *	If IOC Status is SUCCESS, save the header
+			 *	and set the status code to GOOD.
+			 */
+			pCfg->status = MPT_CONFIG_ERROR;
+			if (reply) {
+				ConfigReply_t	*pReply = (ConfigReply_t *)reply;
+				u16		 status;
+
+				status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+				dprintk((KERN_NOTICE "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
+				     status, le32_to_cpu(pReply->IOCLogInfo)));
+
+				pCfg->status = status;
+				if (status == MPI_IOCSTATUS_SUCCESS) {
+					pCfg->hdr->PageVersion = pReply->Header.PageVersion;
+					pCfg->hdr->PageLength = pReply->Header.PageLength;
+					pCfg->hdr->PageNumber = pReply->Header.PageNumber;
+					pCfg->hdr->PageType = pReply->Header.PageType;
+				}
+			}
+
+			/*
+			 *	Wake up the original calling thread
+			 */
+			pCfg->wait_done = 1;
+			wake_up(&mpt_waitq);
+		}
 	} else {
-		printk(KERN_ERR MYNAM ": %s: ERROR - Unexpected msg function (=%02Xh) reply received!\n",
+		printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
 				ioc->name, func);
 	}
 
 	/*
-	 *  Conditionally tell caller to free the original
-	 *  EventNotification/EventAck/unexpected request frame!
+	 *	Conditionally tell caller to free the original
+	 *	EventNotification/EventAck/unexpected request frame!
 	 */
 	return freereq;
 }
@@ -480,21 +638,22 @@
  *	protocol-specific driver must do this before it will be able to
  *	use any IOC resources, such as obtaining request frames.
  *
- *	NOTES: The SCSI protocol driver currently calls this routine twice
- *	in order to register separate callbacks; one for "normal" SCSI IO
- *	and another for MptScsiTaskMgmt requests.
+ *	NOTES: The SCSI protocol driver currently calls this routine thrice
+ *	in order to register separate callbacks; one for "normal" SCSI IO;
+ *	one for MptScsiTaskMgmt requests; one for Scan/DV requests.
  *
  *	Returns a positive integer valued "handle" in the
- *	range (and S.O.D. order) {7,6,...,1} if successful.
+ *	range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
  *	Any non-positive return value (including zero!) should be considered
  *	an error by the caller.
  */
 int
 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
 {
-	int r = -1;
 	int i;
 
+	last_drv_idx = -1;
+
 #ifndef MODULE
 	/*
 	 *  Handle possibility of the mptscsih_detect() routine getting
@@ -512,7 +671,7 @@
 #endif
 
 	/*
-	 *  Search for empty callback slot in this order: {7,6,...,1}
+	 *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
 	 *  (slot/handle 0 is reserved!)
 	 */
 	for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
@@ -520,7 +679,7 @@
 			MptCallbacks[i] = cbfunc;
 			MptDriverClass[i] = dclass;
 			MptEvHandlers[i] = NULL;
-			r = i;
+			last_drv_idx = i;
 			if (cbfunc != mpt_base_reply) {
 				MOD_INC_USE_COUNT;
 			}
@@ -528,7 +687,7 @@
 		}
 	}
 
-	return r;
+	return last_drv_idx;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -546,6 +705,11 @@
 		MptCallbacks[cb_idx] = NULL;
 		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
 		MptEvHandlers[cb_idx] = NULL;
+
+		last_drv_idx++;
+		if (isense_idx != -1 && isense_idx <= cb_idx)
+			isense_idx++;
+
 		if (cb_idx != mpt_base_index) {
 			MOD_DEC_USE_COUNT;
 		}
@@ -639,7 +803,8 @@
  *	@handle: Handle of registered MPT protocol driver
  *	@iocid: IOC unique identifier (integer)
  *
- *	Returns pointer to a MPT request frame or %NULL if none are available.
+ *	Returns pointer to a MPT request frame or %NULL if none are available
+ *	or IOC is not active.
  */
 MPT_FRAME_HDR*
 mpt_get_msg_frame(int handle, int iocid)
@@ -650,6 +815,16 @@
 
 	/* validate handle and ioc identifier */
 	iocp = mpt_adapters[iocid];
+
+#ifdef MFCNT
+	if (!iocp->active)
+		printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
+#endif
+
+	/* If interrupts are not attached, do not return a request frame */
+	if (!iocp->active)
+		return NULL;
+
 	spin_lock_irqsave(&iocp->FreeQlock, flags);
 	if (! Q_IS_EMPTY(&iocp->FreeQ)) {
 		int req_offset;
@@ -662,8 +837,20 @@
 		mf->u.frame.hwhdr.msgctxu.fld.req_idx =
 				cpu_to_le16(req_offset / iocp->req_sz);
 		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+#ifdef MFCNT
+		iocp->mfcnt++;
+#endif
 	}
 	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+
+#ifdef MFCNT
+	if (mf == NULL)
+		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
+	mfcounter++;
+	if (mfcounter == PRINT_MF_COUNT)
+		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
+#endif
+
 	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
 			iocp->name, handle, iocid, mf));
 	return mf;
@@ -687,7 +874,7 @@
 
 	iocp = mpt_adapters[iocid];
 	if (iocp != NULL) {
-		dma_addr_t mf_dma_addr;
+		u32 mf_dma_addr;
 		int req_offset;
 
 		/* ensure values are reset properly! */
@@ -700,23 +887,23 @@
 #ifdef MPT_DEBUG_MSG_FRAME
 		{
 			u32	*m = mf->u.frame.hwhdr.__hdr;
-			int	 i, n;
+			int	 ii, n;
 
 			printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
 					iocp->name, m);
 			n = iocp->req_sz/4 - 1;
 			while (m[n] == 0)
 				n--;
-			for (i=0; i<=n; i++) {
-				if (i && ((i%8)==0))
+			for (ii=0; ii<=n; ii++) {
+				if (ii && ((ii%8)==0))
 					printk("\n" KERN_INFO " ");
-				printk(" %08x", le32_to_cpu(m[i]));
+				printk(" %08x", le32_to_cpu(m[ii]));
 			}
 			printk("\n");
 		}
 #endif
 
-		mf_dma_addr = iocp->req_frames_dma + req_offset;
+		mf_dma_addr = iocp->req_frames_low_dma + req_offset;
 		CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
 	}
 }
@@ -742,6 +929,9 @@
 		/*  Put Request back on FreeQ!  */
 		spin_lock_irqsave(&iocp->FreeQlock, flags);
 		Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+#ifdef MFCNT
+		iocp->mfcnt--;
+#endif
 		spin_unlock_irqrestore(&iocp->FreeQlock, flags);
 	}
 }
@@ -754,8 +944,9 @@
  *	@iocid: IOC unique identifier (integer)
  *	@reqBytes: Size of the request in bytes
  *	@req: Pointer to MPT request frame
+ *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay.
  *
- *	This routine is used exclusively by mptscsih to send MptScsiTaskMgmt
+ *	This routine is used exclusively to send MptScsiTaskMgmt
  *	requests since they are required to be sent via doorbell handshake.
  *
  *	NOTE: It is the callers responsibility to byte-swap fields in the
@@ -764,41 +955,30 @@
  *	Returns 0 for success, non-zero for failure.
  */
 int
-mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req)
+mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag)
 {
 	MPT_ADAPTER	*iocp;
 	int		 r = 0;
 
 	iocp = mpt_adapters[iocid];
 	if (iocp != NULL) {
-		u8		*req_as_bytes;
-		u32		 ioc_raw_state;
-		int		 i;
-
-		/* YIKES!  We already know something is amiss.
-		 * Do upfront check on IOC state.
-		 */
-		ioc_raw_state = GetIocState(iocp, 0);
-		if ((ioc_raw_state & MPI_DOORBELL_ACTIVE) ||
-		    ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL)) {
-			printk(KERN_WARNING MYNAM ": %s: Bad IOC state (%08x) WARNING!\n",
-					iocp->name, ioc_raw_state);
-			if ((r = mpt_do_ioc_recovery(iocp, MPT_HOSTEVENT_IOC_RECOVER)) != 0) {
-				printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
-						r, iocp->name);
-				return r;
-			}
-		}
+		u8	*req_as_bytes;
+		int	 ii;
+
+		/* State is known to be good upon entering
+		 * this function so issue the bus reset
+		 * request.
+		 */
 
 		/*
 		 * Emulate what mpt_put_msg_frame() does /wrt to sanity
 		 * setting cb_idx/req_idx.  But ONLY if this request
 		 * is in proper (pre-alloc'd) request buffer range...
 		 */
-		i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
-		if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) {
+		ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
+		if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
 			MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
-			mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(i);
+			mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
 			mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
 		}
 
@@ -810,36 +990,40 @@
 				 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
 
 		/* Wait for IOC doorbell int */
-		if ((i = WaitForDoorbellInt(iocp, 2)) < 0) {
-			return i;
+		if ((ii = WaitForDoorbellInt(iocp, 2, sleepFlag)) < 0) {
+			return ii;
 		}
 
+		/* Read doorbell and check for active bit */
+		if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+				return -5;
+
 		dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
-				iocp->name, i));
+				iocp->name, ii));
 
 		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
 
-		if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
+		if ((r = WaitForDoorbellAck(iocp, 1, sleepFlag)) < 0) {
 			return -2;
 		}
 
 		/* Send request via doorbell handshake */
 		req_as_bytes = (u8 *) req;
-		for (i = 0; i < reqBytes/4; i++) {
+		for (ii = 0; ii < reqBytes/4; ii++) {
 			u32 word;
 
-			word = ((req_as_bytes[(i*4) + 0] <<  0) |
-				(req_as_bytes[(i*4) + 1] <<  8) |
-				(req_as_bytes[(i*4) + 2] << 16) |
-				(req_as_bytes[(i*4) + 3] << 24));
+			word = ((req_as_bytes[(ii*4) + 0] <<  0) |
+				(req_as_bytes[(ii*4) + 1] <<  8) |
+				(req_as_bytes[(ii*4) + 2] << 16) |
+				(req_as_bytes[(ii*4) + 3] << 24));
 			CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
-			if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
+			if ((r = WaitForDoorbellAck(iocp, 1, sleepFlag)) < 0) {
 				r = -3;
 				break;
 			}
 		}
 
-		if ((r = WaitForDoorbellInt(iocp, 2)) >= 0)
+		if ((r = WaitForDoorbellInt(iocp, 10, sleepFlag)) >= 0)
 			r = 0;
 		else
 			r = -4;
@@ -871,8 +1055,8 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- * 	mpt_adapter_find_next - Find next MPT adapter pointer.
- * 	@prev: Pointer to previous MPT adapter
+ *	mpt_adapter_find_next - Find next MPT adapter pointer.
+ *	@prev: Pointer to previous MPT adapter
  *
  *	Returns next MPT adapter pointer or %NULL if there are no more.
  */
@@ -888,13 +1072,13 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	mpt_pci_scan - Scan PCI devices for MPT adapters.
  *
  *	Returns count of MPT adapters found, keying off of PCI vendor and
  *	device_id's.
  */
-int __init
+static int __init
 mpt_pci_scan(void)
 {
 	struct pci_dev *pdev;
@@ -906,7 +1090,7 @@
 	dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
 
 	/*
-	 *  NOTE: The 929 (I believe) will appear as 2 separate PCI devices,
+	 *  NOTE: The 929 and 1030 will appear as 2 separate PCI devices,
 	 *  one for each channel.
 	 */
 	pci_for_each_dev(pdev) {
@@ -917,9 +1101,9 @@
 		if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&
+		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
 #if 0
 		    /* FIXME! C103x family */
-		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&
 #endif
@@ -929,7 +1113,7 @@
 		}
 
 		/* GRRRRR
-		 * 929 dual function devices may be presented in Func 1,0 order,
+		 * dual function devices (929, 1030) may be presented in Func 1,0 order,
 		 * but we'd really really rather have them in Func 0,1 order.
 		 * Do some kind of look ahead here...
 		 */
@@ -937,11 +1121,11 @@
 			pdev2 = pci_peek_next_dev(pdev);
 			if (pdev2 && (pdev2->vendor == 0x1000) &&
 			    (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
-			    (pdev2->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
+			    (pdev2->device == pdev->device) &&
 			    (pdev2->bus->number == pdev->bus->number) &&
 			    !(pdev2->devfn & 1)) {
 				dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
-			 		pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
+					pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
 				found++;
 				if ((r = mpt_adapter_install(pdev2)) == 0)
 					count++;
@@ -969,9 +1153,7 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	if (procmpt_create() != 0)
-		printk(KERN_WARNING MYNAM ": WARNING! - %s creation failed!\n",
-				MPT_PROCFS_MPTBASEDIR);
+	(void) procmpt_create();
 #endif
 
 	return count;
@@ -1004,7 +1186,7 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	mpt_adapter_install - Install a PCI intelligent MPT adapter.
  *	@pdev: Pointer to pci_dev structure
  *
@@ -1030,7 +1212,7 @@
 	unsigned long	 port;
 	u32		 msize;
 	u32		 psize;
-	int		 i;
+	int		 ii;
 	int		 r = -ENODEV;
 	int		 len;
 
@@ -1040,41 +1222,68 @@
 		return -ENOMEM;
 	}
 	memset(ioc, 0, sizeof(*ioc));
-	ioc->req_sz = MPT_REQ_SIZE;			/* avoid div by zero! */
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
+	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
+	ioc->reply_sz = ioc->req_sz;
 
 	ioc->pcidev = pdev;
+	ioc->diagPending = 0;
+	spin_lock_init(&ioc->diagLock);
+
+	/* Initialize the event logging.
+	 */
+	ioc->eventTypes = 0;	/* None */
+	ioc->eventContext = 0;
+	ioc->eventLogSize = 0;
+	ioc->events = NULL;
+
+#ifdef MFCNT
+	ioc->mfcnt = 0;
+#endif
+
+	/* Initialize the FW and Data image pointers.
+	 */
+	ioc->FWImage = NULL;
+	ioc->FWImage_dma = 0;
+
+	/* Initilize SCSI Config Data structure
+	 */
+	memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
+
+	/* Initialize the running configQ head.
+	 */
+	Q_INIT(&ioc->configQ, Q_ITEM);
 
 	/* Find lookup slot. */
-	for (i=0; i < MPT_MAX_ADAPTERS; i++) {
-		if (mpt_adapters[i] == NULL) {
-			ioc->id = i;		/* Assign adapter unique id (lookup) */
+	for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
+		if (mpt_adapters[ii] == NULL) {
+			ioc->id = ii;		/* Assign adapter unique id (lookup) */
 			break;
 		}
 	}
-	if (i == MPT_MAX_ADAPTERS) {
-		printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", i);
+	if (ii == MPT_MAX_ADAPTERS) {
+		printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);
 		kfree(ioc);
 		return -ENFILE;
 	}
 
 	mem_phys = msize = 0;
 	port = psize = 0;
-	for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
-		if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) {
+	for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
+		if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
 			/* Get I/O space! */
-			port = pdev->PCI_BASEADDR_START(i);
-			psize = PCI_BASEADDR_SIZE(pdev,i);
+			port = pdev->PCI_BASEADDR_START(ii);
+			psize = PCI_BASEADDR_SIZE(pdev,ii);
 		} else {
 			/* Get memmap */
-			mem_phys = pdev->PCI_BASEADDR_START(i);
-			msize = PCI_BASEADDR_SIZE(pdev,i);
+			mem_phys = pdev->PCI_BASEADDR_START(ii);
+			msize = PCI_BASEADDR_SIZE(pdev,ii);
 			break;
 		}
 	}
 	ioc->mem_size = msize;
 
-	if (i == DEVICE_COUNT_RESOURCE) {
+	if (ii == DEVICE_COUNT_RESOURCE) {
 		printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
 		kfree(ioc);
 		return -EINVAL;
@@ -1098,6 +1307,8 @@
 	}
 	dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
 
+	dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
+			&ioc->facts, &ioc->pfacts[0]));
 	if (PortIo) {
 		u8 *pmem = (u8*)port;
 		ioc->mem_phys = port;
@@ -1107,6 +1318,13 @@
 		ioc->chip = (SYSIF_REGS*)mem;
 	}
 
+	/* Save Port IO values incase we need to do downloadboot */
+	{
+		u8 *pmem = (u8*)port;
+		ioc->pio_mem_phys = port;
+		ioc->pio_chip = (SYSIF_REGS*)pmem;
+	}
+
 	ioc->chip_type = FCUNK;
 	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
 		ioc->chip_type = FC909;
@@ -1120,12 +1338,19 @@
 		ioc->chip_type = FC919;
 		ioc->prod_name = "LSIFC919";
 	}
-#if 0
-	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) {
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
 		ioc->chip_type = C1030;
 		ioc->prod_name = "LSI53C1030";
+		{
+			/* 1030 Chip Fix. Disable Split transactions
+			 * for PCIX. Set bits 4 - 6 to zero.
+			 */
+			u16 pcixcmd = 0;
+			pci_read_config_word(pdev, 0x6a, &pcixcmd);
+			pcixcmd &= 0xFF8F;
+			pci_write_config_word(pdev, 0x6a, pcixcmd);
+		}
 	}
-#endif
 
 	myname = "iocN";
 	len = strlen(myname);
@@ -1145,8 +1370,13 @@
 		r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
 
 		if (r < 0) {
-			printk(KERN_ERR MYNAM ": %s: ERROR - Unable to allocate interrupt %d!\n",
+#ifndef __sparc__
+			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
 					ioc->name, pdev->irq);
+#else
+			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
+					ioc->name, __irq_itoa(pdev->irq));
+#endif
 			iounmap(mem);
 			kfree(ioc);
 			return -EBUSY;
@@ -1156,7 +1386,11 @@
 
 		pci_set_master(pdev);			/* ?? */
 
+#ifndef __sparc__
 		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
+#else
+		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
+#endif
 	}
 
 	/* tack onto tail of our MPT adapter list */
@@ -1166,12 +1400,12 @@
 	mpt_adapters[ioc->id] = ioc;
 
 	/* NEW!  20010220 -sralston
-	 * Check for "929 bound ports" to reduce redundant resets.
+	 * Check for "bound ports" (929, 1030) to reduce redundant resets.
 	 */
-	if (ioc->chip_type == FC929)
-		mpt_detect_929_bound_ports(ioc, pdev);
+	if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030))
+		mpt_detect_bound_ports(ioc, pdev);
 
-	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
+	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
 		printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n",
 				ioc->name, r);
 	}
@@ -1180,10 +1414,11 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	mpt_do_ioc_recovery - Initialize or recover MPT adapter.
  *	@ioc: Pointer to MPT adapter structure
  *	@reason: Event word / reason
+ *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay.
  *
  *	This routine performs all the steps necessary to bring the IOC
  *	to a OPERATIONAL state.
@@ -1191,16 +1426,21 @@
  *	This routine also pre-fetches the LAN MAC address of a Fibre Channel
  *	MPT adapter.
  *
- *	Returns 0 for success.
+ *	Returns:
+ *		 0 for success
+ *		-1 if failed to get board READY
+ *		-2 if READY but IOCFacts Failed
+ *		-3 if READY but PrimeIOCFifos Failed
+ *		-4 if READY but IOCInit Failed
  */
 static int
-mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason)
+mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 {
 	int	 hard_reset_done = 0;
 	int	 alt_ioc_ready = 0;
 	int	 hard;
 	int	 r;
-	int	 i;
+	int	 ii;
 	int	 handlers;
 
 	printk(KERN_INFO MYNAM ": Initiating %s %s\n",
@@ -1211,156 +1451,106 @@
 	ioc->active = 0;
 	/* NOTE: Access to IOC's request FreeQ is now blocked! */
 
-// FIXME? Cleanup all IOC requests here! (or below?)
-// But watch out for event associated request?
+	if (ioc->alt_ioc) {
+		/* Disable alt-IOC's reply interrupts for a bit ... */
+		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
+		ioc->alt_ioc->active = 0;
+		/* NOTE: Access to alt-IOC's request FreeQ is now blocked! */
+	}
 
-	hard = HardReset;
-	if (ioc->alt_ioc && (reason == MPT_HOSTEVENT_IOC_BRINGUP))
+	hard = 1;
+	if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
 		hard = 0;
 
-	if ((hard_reset_done = MakeIocReady(ioc, hard)) < 0) {
+	if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
 		printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
 				ioc->name);
 		return -1;
 	}
 
-// NEW!
-#if 0						// Kiss-of-death!?!
-	if (ioc->alt_ioc) {
-// Grrr... Hold off any alt-IOC interrupts (and events) while
-// handshaking to <this> IOC, needed because?
-		/* Disable alt-IOC's reply interrupts for a bit ... */
-		alt_ioc_intmask = CHIPREG_READ32(&ioc->alt_ioc->chip->IntMask);
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
-		ioc->alt_ioc->active = 0;
-		/* NOTE: Access to alt-IOC's request FreeQ is now blocked! */
-	}
-#endif
-
+	/* hard_reset_done = 0 if a soft reset was performed
+	 * and 1 if a hard reset was performed.
+	 */
 	if (hard_reset_done && ioc->alt_ioc) {
-		if ((r = MakeIocReady(ioc->alt_ioc, 0)) == 0)
+		if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
 			alt_ioc_ready = 1;
 		else
-			printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n",
+			printk(KERN_WARNING MYNAM
+					": alt-%s: (%d) Not ready WARNING!\n",
 					ioc->alt_ioc->name, r);
 	}
 
+	/* Get IOC facts! */
+	if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
+		return -2;
 	if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
-		/* Get IOC facts! */
-		if ((r = GetIocFacts(ioc)) != 0)
-			return -2;
 		MptDisplayIocCapabilities(ioc);
 	}
 
-	/*
-	 * Call each currently registered protocol IOC reset handler
-	 * with pre-reset indication.
-	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
-	 * MptResetHandlers[] registered yet.
-	 */
-	if (hard_reset_done) {
-		r = handlers = 0;
-		for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
-			if (MptResetHandlers[i]) {
-				dprintk((KERN_INFO MYNAM ": %s: Calling IOC pre_reset handler #%d\n",
-						ioc->name, i));
-				r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_PRE_RESET);
-				handlers++;
-
-				if (alt_ioc_ready) {
-					dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC pre_reset handler #%d\n",
-							ioc->alt_ioc->name, i));
-					r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
-					handlers++;
-				}
-			}
-		}
-		/* FIXME?  Examine results here? */
-	}
-
-	// May need to check/upload firmware & data here!
-
-	if ((r = SendIocInit(ioc)) != 0)
-		return -3;
-// NEW!
 	if (alt_ioc_ready) {
-		if ((r = SendIocInit(ioc->alt_ioc)) != 0) {
-			alt_ioc_ready = 0;
-			printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n",
-					ioc->alt_ioc->name, r);
-		}
-	}
-
-	/*
-	 * Call each currently registered protocol IOC reset handler
-	 * with post-reset indication.
-	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
-	 * MptResetHandlers[] registered yet.
-	 */
-	if (hard_reset_done) {
-		r = handlers = 0;
-		for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
-			if (MptResetHandlers[i]) {
-				dprintk((KERN_INFO MYNAM ": %s: Calling IOC post_reset handler #%d\n",
-						ioc->name, i));
-				r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_POST_RESET);
-				handlers++;
-
-				if (alt_ioc_ready) {
-					dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC post_reset handler #%d\n",
-							ioc->alt_ioc->name, i));
-					r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
-					handlers++;
-				}
-			}
+		if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0)
+			return -2;
+		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+			MptDisplayIocCapabilities(ioc->alt_ioc);
 		}
-		/* FIXME?  Examine results here? */
 	}
 
 	/*
 	 * Prime reply & request queues!
-	 * (mucho alloc's)
+	 * (mucho alloc's) Must be done prior to
+	 * init as upper addresses are needed for init.
 	 */
 	if ((r = PrimeIocFifos(ioc)) != 0)
+		return -3;
+
+	// May need to check/upload firmware & data here!
+	if ((r = SendIocInit(ioc, sleepFlag)) != 0)
 		return -4;
 // NEW!
 	if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
 		printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
 				ioc->alt_ioc->name, r);
+		alt_ioc_ready = 0;
 	}
 
-// FIXME! Cleanup all IOC (and alt-IOC?) requests here!
+	if (alt_ioc_ready) {
+		if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
+			alt_ioc_ready = 0;
+			printk(KERN_WARNING MYNAM
+				": alt-%s: (%d) init failure WARNING!\n",
+					ioc->alt_ioc->name, r);
+		}
+	}
 
-	if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
-	    (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
-		/*
-		 *  Pre-fetch the ports LAN MAC address!
-		 *  (LANPage1_t stuff)
-		 */
-		(void) GetLanConfigPages(ioc);
-#ifdef MPT_DEBUG
-		{
-			u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
-			dprintk((KERN_INFO MYNAM ": %s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-					ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
+	if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
+		if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
+			dprintk((MYIOC_s_INFO_FMT
+				"firmware upload required!\n", ioc->name));
+
+			r = mpt_do_upload(ioc, sleepFlag);
+			if (r != 0)
+				printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+			/* Handle the alt IOC too */
+			if (alt_ioc_ready){
+				r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
+				if (r != 0)
+					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+			}
 		}
-#endif
 	}
 
+
 	/* Enable! (reply interrupt) */
 	CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
 	ioc->active = 1;
 
-// NEW!
-#if 0						// Kiss-of-death!?!
-	if (alt_ioc_ready && (r==0)) {
+	if (ioc->alt_ioc) {
 		/* (re)Enable alt-IOC! (reply interrupt) */
 		dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 				ioc->alt_ioc->name));
 		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
 		ioc->alt_ioc->active = 1;
 	}
-#endif
 
 	/* NEW!  20010120 -sralston
 	 *  Enable MPT base driver management of EventNotification
@@ -1368,19 +1558,95 @@
 	 */
 	if (!ioc->facts.EventState)
 		(void) SendEventNotification(ioc, 1);	/* 1=Enable EventNotification */
-// NEW!
-// FIXME!?!
-//	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) {
-//		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
-//	}
+
+	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
+		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
+
+	/* (Bugzilla:fibrebugs, #513)
+	 * Bug fix (part 2)!  20010905 -sralston
+	 *	Add additional "reason" check before call to GetLanConfigPages
+	 *	(combined with GetIoUnitPage2 call).  This prevents a somewhat
+	 *	recursive scenario; GetLanConfigPages times out, timer expired
+	 *	routine calls HardResetHandler, which calls into here again,
+	 *	and we try GetLanConfigPages again...
+	 */
+	if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+		if ((int)ioc->chip_type <= (int)FC929) {
+			/*
+			 *  Pre-fetch FC port WWN and stuff...
+			 *  (FCPortPage0_t stuff)
+			 */
+			for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+				(void) GetFcPortPage0(ioc, ii);
+			}
+
+			if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
+			    (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
+				/*
+				 *  Pre-fetch the ports LAN MAC address!
+				 *  (LANPage1_t stuff)
+				 */
+				(void) GetLanConfigPages(ioc);
+#ifdef MPT_DEBUG
+				{
+					u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
+					dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+							ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
+				}
+#endif
+			}
+		} else {
+			/* Get NVRAM and adapter maximums from SPP 0 and 2
+			 */
+			mpt_GetScsiPortSettings(ioc, 0);
+
+			/* Get version and length of SDP 1 
+			 */
+			mpt_readScsiDevicePageHeaders(ioc, 0);
+
+			/* Find IM volumes 
+			 */
+			if (ioc->facts.MsgVersion >= 0x0102)
+				mpt_findImVolumes(ioc);
+		}
+
+		GetIoUnitPage2(ioc);
+	}
+
+	/*
+	 * Call each currently registered protocol IOC reset handler
+	 * with post-reset indication.
+	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
+	 * MptResetHandlers[] registered yet.
+	 */
+	if (hard_reset_done) {
+		r = handlers = 0;
+		for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+			if (MptResetHandlers[ii]) {
+				dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
+						ioc->name, ii));
+				r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+				handlers++;
+
+				if (alt_ioc_ready) {
+					dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+							ioc->name, ioc->alt_ioc->name, ii));
+					r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+					handlers++;
+				}
+			}
+		}
+		/* FIXME?  Examine results here? */
+	}
 
 	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mpt_detect_929_bound_ports - Search for PCI bus/dev_function
- *	which matches PCI bus/dev_function (+/-1) for newly discovered 929.
+ *	mpt_detect_bound_ports - Search for PCI bus/dev_function
+ *	which matches PCI bus/dev_function (+/-1) for newly discovered 929
+ *	or 1030.
  *	@ioc: Pointer to MPT adapter structure
  *	@pdev: Pointer to (struct pci_dev) structure
  *
@@ -1388,22 +1654,22 @@
  *	using alt_ioc pointer fields in their %MPT_ADAPTER structures.
  */
 static void
-mpt_detect_929_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
+mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 {
 	MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
 	unsigned int match_lo, match_hi;
 
 	match_lo = pdev->devfn-1;
 	match_hi = pdev->devfn+1;
-	dprintk((KERN_INFO MYNAM ": %s: PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
+	dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
 			ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
 
 	while (ioc_srch != NULL) {
 		struct pci_dev *_pcidev = ioc_srch->pcidev;
 
-		if ( (_pcidev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
-		     (_pcidev->bus->number == pdev->bus->number) &&
-		     (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+		if ((_pcidev->device == pdev->device) &&
+		    (_pcidev->bus->number == pdev->bus->number) &&
+		    (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
 			/* Paranoia checks */
 			if (ioc->alt_ioc != NULL) {
 				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
@@ -1418,8 +1684,6 @@
 					ioc->name, ioc_srch->name));
 			ioc_srch->alt_ioc = ioc;
 			ioc->alt_ioc = ioc_srch;
-			ioc->sod_reset = ioc->alt_ioc->sod_reset;
-			ioc->last_kickstart = ioc->alt_ioc->last_kickstart;
 			break;
 		}
 		ioc_srch = mpt_adapter_find_next(ioc_srch);
@@ -1440,10 +1704,10 @@
 		u32 state;
 
 		/* Disable the FW */
-		state = GetIocState(this, 1);
+		state = mpt_GetIocState(this, 1);
 		if (state == MPI_IOC_STATE_OPERATIONAL) {
-			if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET) != 0)
-				(void) KickStart(this, 1);
+			if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP) != 0)
+				(void) KickStart(this, 1, NO_SLEEP);
 		}
 
 		/* Disable adapter interrupts! */
@@ -1475,12 +1739,37 @@
 		}
 
 		if (freeup && this->sense_buf_pool != NULL) {
-			sz = (this->req_depth * 256);
+			sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
 			pci_free_consistent(this->pcidev, sz,
 					this->sense_buf_pool, this->sense_buf_pool_dma);
 			this->sense_buf_pool = NULL;
 			this->alloc_total -= sz;
 		}
+
+		if (freeup && this->events != NULL){
+			sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+			kfree(this->events);
+			this->events = NULL;
+			this->alloc_total -= sz;
+		}
+
+		if (freeup && this->FWImage != NULL) {
+			sz = this->facts.FWImageSize;
+			pci_free_consistent(this->pcidev, sz,
+					this->FWImage, this->FWImage_dma);
+			this->FWImage = NULL;
+			this->alloc_total -= sz;
+		}
+
+		if (freeup && this->spi_data.nvram != NULL) {
+			kfree(this->spi_data.nvram);
+			this->spi_data.nvram = NULL;
+		}
+
+		if (freeup && this->spi_data.pIocPg3 != NULL) {
+			kfree(this->spi_data.pIocPg3);
+			this->spi_data.pIocPg3 = NULL;
+		}
 	}
 }
 
@@ -1575,23 +1864,30 @@
 /*
  *	MakeIocReady - Get IOC to a READY state, using KickStart if needed.
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	@kick: Force hard KickStart of IOC
+ *	@force: Force hard KickStart of IOC
+ *	@sleepFlag: Specifies whether the process can sleep
  *
- *	Returns 0 for already-READY, 1 for hard reset success,
- *	else negative for failure.
+ *	Returns:
+ *		 1 - DIAG reset and READY
+ *		 0 - READY initially OR soft reset and READY 
+ *		-1 - Any failure on KickStart 
+ *		-2 - Msg Unit Reset Failed
+ *		-3 - IO Unit Reset Failed
+ *		-4 - IOC owned by a PEER
  */
 static int
-MakeIocReady(MPT_ADAPTER *ioc, int force)
+MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
 {
 	u32	 ioc_state;
 	int	 statefault = 0;
-	int 	 cntdn;
+	int	 cntdn;
 	int	 hard_reset_done = 0;
 	int	 r;
-	int	 i;
+	int	 ii;
+	int	 whoinit;
 
 	/* Get current [raw] IOC state  */
-	ioc_state = GetIocState(ioc, 0);
+	ioc_state = mpt_GetIocState(ioc, 0);
 	dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
 
 	/*
@@ -1600,7 +1896,7 @@
 	 */
 	if (ioc_state & MPI_DOORBELL_ACTIVE) {
 		statefault = 1;
-		printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n",
+		printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
 				ioc->name);
 	}
 
@@ -1613,7 +1909,7 @@
 	 */
 	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
 		statefault = 2;
-		printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n",
+		printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
 				ioc->name);
 		printk(KERN_WARNING "           FAULT code = %04xh\n",
 				ioc_state & MPI_DOORBELL_DATA_MASK);
@@ -1623,28 +1919,49 @@
 	 *	Hmmm...  Did it get left operational?
 	 */
 	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
-		statefault = 3;
-		dprintk((KERN_WARNING MYNAM ": %s: Hmmm... IOC operational unexpected\n",
+		dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
 				ioc->name));
+
+		/* Check WhoInit.
+		 * If PCI Peer, exit.
+		 * Else, if no fault conditions are present, issue a MessageUnitReset
+		 * Else, fall through to KickStart case
+		 */
+		whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
+		dprintk((KERN_WARNING MYNAM
+			": whoinit 0x%x\n statefault %d force %d\n",
+			whoinit, statefault, force));
+		if (whoinit == MPI_WHOINIT_PCI_PEER)
+			return -4;
+		else {
+			if ((statefault == 0 ) && (force == 0)) {
+				if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
+					return 0;
+			}
+			statefault = 3;
+		}
 	}
 
-	hard_reset_done = KickStart(ioc, statefault||force);
+	hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
 	if (hard_reset_done < 0)
 		return -1;
 
 	/*
 	 *  Loop here waiting for IOC to come READY.
 	 */
-	i = 0;
+	ii = 0;
 	cntdn = HZ * 15;
-	while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
+	if (sleepFlag != CAN_SLEEP)
+		cntdn *= 10;	/* 1500 iterations @ 1msec per */
+
+	while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
 		if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
 			/*
 			 *  BIOS or previous driver load left IOC in OP state.
 			 *  Reset messaging FIFOs.
 			 */
-			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) {
-				printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name);
+			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
+				printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
 				return -2;
 			}
 		} else if (ioc_state == MPI_IOC_STATE_RESET) {
@@ -1652,25 +1969,30 @@
 			 *  Something is wrong.  Try to get IOC back
 			 *  to a known state.
 			 */
-			if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) {
-				printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name);
+			if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
+				printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
 				return -3;
 			}
 		}
 
-		i++; cntdn--;
+		ii++; cntdn--;
 		if (!cntdn) {
-			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (i+5)/HZ);
+			printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
+					ioc->name, (ii+5)/HZ);
 			return -ETIME;
 		}
 
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+		} else {
+			mdelay (1);	/* 1 msec delay */
+		}
+
 	}
 
 	if (statefault < 3) {
-		printk(KERN_WARNING MYNAM ": %s: Whew!  Recovered from %s\n",
+		printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
 				ioc->name,
 				statefault==1 ? "stuck handshake" : "IOC FAULT");
 	}
@@ -1680,21 +2002,21 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	GetIocState - Get the current state of a MPT adapter.
+ *	mpt_GetIocState - Get the current state of a MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@cooked: Request raw or cooked IOC state
  *
  *	Returns all IOC Doorbell register bits if cooked==0, else just the
  *	Doorbell bits in MPI_IOC_STATE_MASK.
  */
-static u32
-GetIocState(MPT_ADAPTER *ioc, int cooked)
+u32
+mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
 {
 	u32 s, sc;
 
 	/*  Get!  */
 	s = CHIPREG_READ32(&ioc->chip->Doorbell);
-	dprintk((KERN_INFO MYNAM ": %s: raw state = %08x\n", ioc->name, s));
+//	dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
 	sc = s & MPI_IOC_STATE_MASK;
 
 	/*  Save!  */
@@ -1707,11 +2029,13 @@
 /*
  *	GetIocFacts - Send IOCFacts request to MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@sleepFlag: Specifies whether the process can sleep
+ *	@reason: If recovery, only update facts.
  *
  *	Returns 0 for success, non-zero for failure.
  */
 static int
-GetIocFacts(MPT_ADAPTER *ioc)
+GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 {
 	IOCFacts_t		 get_facts;
 	IOCFactsReply_t		*facts;
@@ -1741,14 +2065,13 @@
 	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
 	/* Assert: All other get_facts fields are zero! */
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending get IocFacts request\n", ioc->name));
+	dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
 
 	/* No non-zero fields in the get_facts request are greater than
 	 * 1 byte in size, so we can just fire it off as is.
 	 */
-	r = HandShakeReqAndReply(ioc,
-			req_sz, (u32*)&get_facts,
-			reply_sz, (u16*)facts, 3);
+	r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
+			reply_sz, (u16*)facts, 3 /*seconds*/, sleepFlag);
 	if (r != 0)
 		return r;
 
@@ -1761,14 +2084,17 @@
 	 */
 	/* Did we get a valid reply? */
 	if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
-		/*
-		 * If not been here, done that, save off first WhoInit value
-		 */
-		if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
-			ioc->FirstWhoInit = facts->WhoInit;
+		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+			/*
+			 * If not been here, done that, save off first WhoInit value
+			 */
+			if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
+				ioc->FirstWhoInit = facts->WhoInit;
+		}
 
 		facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
 		facts->MsgContext = le32_to_cpu(facts->MsgContext);
+		facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
 		facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
 		facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
 		status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
@@ -1776,7 +2102,23 @@
 
 		facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
 		facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
-		facts->FWVersion = le16_to_cpu(facts->FWVersion);
+
+		/*
+		 * FC f/w version changed between 1.1 and 1.2 
+		 *	Old: u16{Major(4),Minor(4),SubMinor(8)}
+		 *	New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
+		 */
+		if (facts->MsgVersion < 0x0102) {
+			/*
+			 *	Handle old FC f/w style, convert to new...
+			 */
+			u16	 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
+			facts->FWVersion.Word =
+					((oldv<<12) & 0xFF000000) |
+					((oldv<<8)  & 0x000FFF00);
+		} else
+			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
+
 		facts->ProductID = le16_to_cpu(facts->ProductID);
 		facts->CurrentHostMfaHighAddr =
 				le32_to_cpu(facts->CurrentHostMfaHighAddr);
@@ -1791,52 +2133,42 @@
 		 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
 		 * to 14 in MPI-1.01.0x.
 		 */
-		if (facts->MsgLength >= sizeof(IOCFactsReply_t)/sizeof(u32) && facts->MsgVersion > 0x0100) {
+		if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
+		    facts->MsgVersion > 0x0100) {
 			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
-			facts->DataImageSize = le32_to_cpu(facts->DataImageSize);
 		}
 
-		if (facts->RequestFrameSize) {
-			/*
-			 * Set values for this IOC's REQUEST queue size & depth...
-			 */
-			ioc->req_sz = MIN(MPT_REQ_SIZE, facts->RequestFrameSize * 4);
-
-			/*
-			 *  Set values for this IOC's REPLY queue size & depth...
-			 *
-			 * BUG? FIX?  20000516 -nromer & sralston 
-			 *  GRRR...  The following did not translate well from MPI v0.09:
-			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->ReplySize * 4);
-			 *  to 0.10:
-			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->BlockSize * 4);
-			 *  Was trying to minimally optimize to smallest possible reply size
-			 *  (and greatly reduce kmalloc size).  But LAN may need larger reply?
-			 *
-			 *  So for now, just set reply size to request size.  FIXME?
-			 */
-			ioc->reply_sz = ioc->req_sz;
-		} else {
+		if (!facts->RequestFrameSize) {
 			/*  Something is wrong!  */
-			printk(KERN_ERR MYNAM ": %s: ERROR - IOC reported invalid 0 request size!\n",
+			printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
 					ioc->name);
-			ioc->req_sz = MPT_REQ_SIZE;
-			ioc->reply_sz = MPT_REPLY_SIZE;
 			return -55;
 		}
-		ioc->req_depth = MIN(MPT_REQ_DEPTH, facts->GlobalCredits);
-		ioc->reply_depth = MIN(MPT_REPLY_DEPTH, facts->ReplyQueueDepth);
 
-		dprintk((KERN_INFO MYNAM ": %s: reply_sz=%3d, reply_depth=%4d\n",
+		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+			/*
+			 * Set values for this IOC's request & reply frame sizes,
+			 * and request & reply queue depths...
+			 */
+			ioc->req_sz = MIN(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
+			ioc->req_depth = MIN(MPT_DEFAULT_REQ_DEPTH, facts->GlobalCredits);
+			ioc->reply_sz = ioc->req_sz;
+			ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
+
+			/* 1030 - should we use a smaller DEFAULT_REPLY_DEPTH?
+			 * FIX
+			 */
+			dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
 				ioc->name, ioc->reply_sz, ioc->reply_depth));
-		dprintk((KERN_INFO MYNAM ": %s: req_sz  =%3d, req_depth  =%4d\n",
+			dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
 				ioc->name, ioc->req_sz, ioc->req_depth));
 
-		/* Get port facts! */
-		if ( (r = GetPortFacts(ioc, 0)) != 0 )
-			return r;
+			/* Get port facts! */
+			if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
+				return r;
+		}
 	} else {
-		printk(KERN_ERR MYNAM ": %s: ERROR - Invalid IOC facts reply!\n",
+		printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
 				ioc->name);
 		return -66;
 	}
@@ -1849,15 +2181,16 @@
  *	GetPortFacts - Send PortFacts request to MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@portnum: Port number
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	Returns 0 for success, non-zero for failure.
  */
 static int
-GetPortFacts(MPT_ADAPTER *ioc, int portnum)
+GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 {
 	PortFacts_t		 get_pfacts;
 	PortFactsReply_t	*pfacts;
-	int			 i;
+	int			 ii;
 	int			 req_sz;
 	int			 reply_sz;
 
@@ -1883,16 +2216,16 @@
 	get_pfacts.PortNumber = portnum;
 	/* Assert: All other get_pfacts fields are zero! */
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending get PortFacts(%d) request\n",
+	dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
 			ioc->name, portnum));
 
 	/* No non-zero fields in the get_pfacts request are greater than
 	 * 1 byte in size, so we can just fire it off as is.
 	 */
-	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_pfacts,
-				reply_sz, (u16*)pfacts, 3);
-	if (i != 0)
-		return i;
+	ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
+				reply_sz, (u16*)pfacts, 3 /*seconds*/, sleepFlag);
+	if (ii != 0)
+		return ii;
 
 	/* Did we get a valid reply? */
 
@@ -1914,13 +2247,14 @@
 /*
  *	SendIocInit - Send IOCInit request to MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
  *
  *	Returns 0 for success, non-zero for failure.
  */
 static int
-SendIocInit(MPT_ADAPTER *ioc)
+SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 {
 	IOCInit_t		 ioc_init;
 	MPIDefaultReply_t	 init_reply;
@@ -1937,20 +2271,35 @@
 	ioc_init.Function = MPI_FUNCTION_IOC_INIT;
 /*	ioc_init.Flags = 0;				*/
 
-	/*ioc_init.MaxDevices = 16;*/
-	ioc_init.MaxDevices = 255;
-/*	ioc_init.MaxBuses = 16;				*/
-	ioc_init.MaxBuses = 1;
+	if ((int)ioc->chip_type <= (int)FC929) {
+		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
+	}
+	else {
+		ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
+	}
+	ioc_init.MaxBuses = MPT_MAX_BUS;
 
 /*	ioc_init.MsgFlags = 0;				*/
 /*	ioc_init.MsgContext = cpu_to_le32(0x00000000);	*/
 	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
-	ioc_init.HostMfaHighAddr = cpu_to_le32(0);	/* Say we 32-bit! for now */
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init));
+#ifdef __ia64__
+	/* Save the upper 32-bits of the request
+	 * (reply) and sense buffers.
+	 */
+	ioc_init.HostMfaHighAddr = cpu_to_le32((u32)(ioc->req_frames_dma >> 32));
+	ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)(ioc->sense_buf_pool_dma >> 32));
+#else
+	/* Force 32-bit addressing */
+	ioc_init.HostMfaHighAddr = cpu_to_le32(0);
+	ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
+#endif
 
-	r = HandShakeReqAndReply(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
-			sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10);
+	dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
+			ioc->name, &ioc_init));
+
+	r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
+				sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
 	if (r != 0)
 		return r;
 
@@ -1958,7 +2307,7 @@
 	 * since we don't even look at it's contents.
 	 */
 
-	if ((r = SendPortEnable(ioc, 0)) != 0)
+	if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
 		return r;
 
 	/* YIKES!  SUPER IMPORTANT!!!
@@ -1967,21 +2316,27 @@
 	 */
 	count = 0;
 	cntdn = HZ * 60;					/* chg'd from 30 to 60 seconds */
-	state = GetIocState(ioc, 1);
+	if (sleepFlag != CAN_SLEEP)
+		cntdn *= 10;					/* scale for 1msec delays */
+	state = mpt_GetIocState(ioc, 1);
 	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+		} else {
+			mdelay(1);
+		}
 
 		if (!cntdn) {
-			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_OP state timeout(%d)!\n",
+			printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
 					ioc->name, (count+5)/HZ);
 			return -9;
 		}
 
-		state = GetIocState(ioc, 1);
+		state = mpt_GetIocState(ioc, 1);
 		count++;
 	}
-	dhsprintk((KERN_INFO MYNAM ": %s: INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+	dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
 			ioc->name, count));
 
 	return r;
@@ -1992,17 +2347,18 @@
  *	SendPortEnable - Send PortEnable request to MPT adapter port.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@portnum: Port number to enable
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	Send PortEnable to bring IOC to OPERATIONAL state.
  *
  *	Returns 0 for success, non-zero for failure.
  */
 static int
-SendPortEnable(MPT_ADAPTER *ioc, int portnum)
+SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 {
 	PortEnable_t		 port_enable;
 	MPIDefaultReply_t	 reply_buf;
-	int	 i;
+	int	 ii;
 	int	 req_sz;
 	int	 reply_sz;
 
@@ -2019,13 +2375,21 @@
 /*	port_enable.MsgFlags = 0;		*/
 /*	port_enable.MsgContext = 0;		*/
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending Port(%d)Enable (req @ %p)\n",
+	dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
 			ioc->name, portnum, &port_enable));
 
-	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&port_enable,
-			reply_sz, (u16*)&reply_buf, 65);
-	if (i != 0)
-		return i;
+	/* RAID FW may take a long time to enable
+	 */
+	if ((int)ioc->chip_type <= (int)FC929) {
+		ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+				reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
+	} else {
+		ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+				reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+	}
+
+	if (ii != 0)
+		return ii;
 
 	/* We do not even look at the reply, so we need not
 	 * swap the multi-byte fields.
@@ -2036,19 +2400,341 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
+ *	mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@sleepFlag: Specifies whether the process can sleep
+ *
+ *	Returns 0 for success, >0 for handshake failure
+ *		<0 for fw upload failure.
+ *
+ *	Remark: If bound IOC and a successful FWUpload was performed
+ *	on the bound IOC, the second image is discarded
+ *	and memory is free'd. Both channels must upload to prevent
+ *	IOC from running in degraded mode.
+ */
+static int
+mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
+{
+	u8			 request[sizeof(FWUpload_t) +  24];
+	u8			 reply[sizeof(FWUploadReply_t)];
+	FWUpload_t		*prequest;
+	FWUploadReply_t		*preply;
+	FWUploadTCSGE_t		*ptcsge = NULL;
+	MptSge_t		*psge;
+	u8			*mem;
+	dma_addr_t		 dma_addr;
+	int			 sgeoffset;
+	int			 i, sz, req_sz, reply_sz;
+	int			 cmdStatus, freeMem = 0;
+
+	/* If the image size is 0 or if the pointer is
+	 * not NULL (error), we are done.
+	 */
+	if (((sz = ioc->facts.FWImageSize) == 0) || ioc->FWImage)
+		return 0;
+
+	/* Allocate memory
+	 */
+	mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->FWImage_dma);
+	if (mem == NULL)
+		return -1;
+
+	memset(mem, 0, sz);
+	ioc->alloc_total += sz;
+	ioc->FWImage = mem;
+	dprintk((KERN_INFO MYNAM ": FW Image  @ %p[%p], sz=%d bytes\n",
+			mem, (void *)(ulong)ioc->FWImage_dma, sz));
+
+	dma_addr = ioc->FWImage_dma;
+
+	prequest = (FWUpload_t *)&request;
+	preply = (FWUploadReply_t *)&reply;
+
+	/*  Destination...  */
+	req_sz = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION)
+			+ sizeof(FWUploadTCSGE_t) + sizeof(MptSge_t);
+	memset(prequest, 0, req_sz);
+
+	reply_sz = sizeof(reply);
+	memset(preply, 0, reply_sz);
+
+	prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
+	prequest->Function = MPI_FUNCTION_FW_UPLOAD;
+	prequest->MsgContext = 0;		/* anything */
+
+	ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
+	ptcsge->Reserved = 0;
+	ptcsge->ContextSize = 0;
+	ptcsge->DetailsLength = 12;
+	ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
+	ptcsge->Reserved1 = 0;
+	ptcsge->ImageOffset = 0;
+	ptcsge->ImageSize = cpu_to_le32(sz);
+
+	sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
+	psge = (MptSge_t *) &request[sgeoffset];
+	psge->FlagsLength = cpu_to_le32(MPT_SGE_FLAGS_SSIMPLE_READ | (u32) sz);
+
+	cpu_to_leXX(dma_addr, psge->Address);
+
+	dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p)\n",
+			ioc->name, prequest));
+
+	i = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)prequest,
+				reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
+
+	cmdStatus = -EFAULT;
+	if (i == 0) {
+		/* Handshake transfer was complete and successful.
+		 * Check the Reply Frame.
+		 */
+		int status, transfer_sz;
+		status = le16_to_cpu(preply->IOCStatus);
+		if (status == MPI_IOCSTATUS_SUCCESS) {
+			transfer_sz = le32_to_cpu(preply->ActualImageSize);
+			if (transfer_sz == sz)
+				cmdStatus = 0;
+		}
+	}
+	dprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+			ioc->name, cmdStatus));
+
+	/* Check to see if we have a copy of this image in
+	 * host memory already.
+	 */
+	if (cmdStatus == 0) {
+		if (ioc->alt_ioc && ioc->alt_ioc->FWImage)
+			freeMem = 1;
+	}
+
+	/* We already have a copy of this image or
+	 * we had some type of an error  - either the handshake
+	 * failed (i != 0) or the command did not complete successfully.
+	 */
+	if (cmdStatus || freeMem) {
+		dprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
+			ioc->name, cmdStatus ? "incomplete" : "duplicate"));
+
+		pci_free_consistent(ioc->pcidev, sz,
+					ioc->FWImage, ioc->FWImage_dma);
+		ioc->FWImage = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	return cmdStatus;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_downloadboot - DownloadBoot code
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@flag: Specify which part of IOC memory is to be uploaded.
+ *	@sleepFlag: Specifies whether the process can sleep
+ *
+ *	FwDownloadBoot requires Programmed IO access.
+ *
+ *	Returns 0 for success
+ *		-1 FW Image size is 0
+ *		-2 No valid FWImage Pointer
+ *		<0 for fw upload failure.
+ */
+static int
+mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+{
+	MpiFwHeader_t		*FwHdr = NULL;
+	MpiExtImageHeader_t 	*ExtHdr;
+	int			 fw_sz;
+	u32			 diag0val;
+#ifdef MPT_DEBUG
+	u32			 diag1val = 0;
+#endif
+	int			 count = 0;
+	u32			*ptru32 = NULL;
+	u32			 diagRwData;
+	u32			 nextImage;
+
+	dprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n",
+				ioc->name));
+#ifdef MPT_DEBUG
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (ioc->alt_ioc)
+		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+	dprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
+				ioc->name, diag0val, diag1val));
+#endif
+
+	dprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
+				ioc->name, ioc->facts.FWImageSize, ioc->FWImage));
+	if (ioc->alt_ioc)
+		dprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
+				ioc->name, ioc->alt_ioc->FWImage));
+
+	/* Get dma_addr and data transfer size.
+	 */
+	if ((fw_sz = ioc->facts.FWImageSize) == 0)
+		return -1;
+
+	/* Get the DMA from ioc or ioc->alt_ioc */
+	if (ioc->FWImage)
+		FwHdr = (MpiFwHeader_t *)ioc->FWImage;
+	else if (ioc->alt_ioc && ioc->alt_ioc->FWImage)
+		FwHdr = (MpiFwHeader_t *)ioc->alt_ioc->FWImage;
+
+	dprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
+			ioc->name, FwHdr));
+
+	if (!FwHdr)
+		return -2;
+
+	/* Write magic sequence to WriteSequence register
+	 * until enter diagnostic mode
+	 */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	while ((diag0val & MPI_DIAG_DRWE) == 0) {
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+
+		/* wait 100 msec */
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(100 * HZ / 1000);
+		} else {
+			mdelay (100);
+		}
+
+		count++;
+		if (count > 20) {
+			printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
+					ioc->name, diag0val);
+			return -EFAULT;
+
+		}
+
+		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+#ifdef MPT_DEBUG
+		if (ioc->alt_ioc)
+			diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+		dprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
+				ioc->name, diag0val, diag1val));
+#endif
+		dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
+				ioc->name, diag0val));
+	}
+
+	/* Set the DiagRwEn and Disable ARM bits */
+	diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+
+#ifdef MPT_DEBUG
+	if (ioc->alt_ioc)
+		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+	dprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
+			ioc->name, diag0val, diag1val));
+#endif
+
+	/* Write the LoadStartAddress to the DiagRw Address Register
+	 * using Programmed IO
+	 */
+
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
+	dprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
+		ioc->name, FwHdr->LoadStartAddress));
+
+	nextImage = FwHdr->NextImageHeaderOffset;
+
+	/* round up count to a 32bit alignment */
+	ptru32 = (u32 *) FwHdr;
+	count = (FwHdr->ImageSize + 3)/4;
+
+	dprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
+				ioc->name, count, ptru32));
+	while (count-- ) {
+		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
+		ptru32++;
+	}
+
+	dprintk((MYIOC_s_INFO_FMT "FW Image done! \n", ioc->name));
+		
+	while (nextImage) {
+
+		/* Set the pointer to the extended image
+		 */
+		ExtHdr = (MpiExtImageHeader_t *) ((char *) FwHdr + nextImage);
+
+		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, ExtHdr->LoadStartAddress);
+
+		count = (ExtHdr->ImageSize + 3 )/4;
+
+		ptru32 = (u32 *) ExtHdr;
+		dprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
+				ioc->name, count, ptru32));
+		while (count-- ) {
+			CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
+			ptru32++;
+		}
+		nextImage = ExtHdr->NextImageHeaderOffset;
+	}
+
+
+	/* Write the IopResetVectorRegAddr */
+	dprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
+
+	/* Write the IopResetVectorValue */
+	dprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
+
+	/* Clear the internal flash bad bit - autoincrementing register,
+	 * so must do two writes.
+	 */
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+	diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+	diagRwData |= 0x4000000;
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+
+	/* clear the RW enable and DISARM bits */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+
+	/* Write 0xFF to reset the sequencer */
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
  *	KickStart - Perform hard reset of MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@force: Force hard reset
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	This routine places MPT adapter in diagnostic mode via the
  *	WriteSequence register, and then performs a hard reset of adapter
  *	via the Diagnostic register.
  *
- *	Returns 0 for soft reset success, 1 for hard reset success,
- *	else a negative value for failure.
+ *	Inputs:   sleepflag - CAN_SLEEP (non-interrupt thread)
+ *			or NO_SLEEP (interrupt thread, use mdelay)
+ *		  force - 1 if doorbell active, board fault state
+ *				board operational, IOC_RECOVERY or
+ *				IOC_BRINGUP and there is an alt_ioc.
+ *			  0 else
+ *
+ *	Returns:
+ *		 1 - hard reset, READY	
+ *		 0 - no reset due to History bit, READY	
+ *		-1 - no reset due to History bit but not READY	
+ *		     OR reset but failed to come READY
+ *		-2 - no reset, could not enter DIAG mode 
+ *		-3 - reset but bad FW bit 
  */
 static int
-KickStart(MPT_ADAPTER *ioc, int force)
+KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 {
 	int hard_reset_done = 0;
 	u32 ioc_state;
@@ -2056,183 +2742,295 @@
 
 	dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
 
-	hard_reset_done = mpt_fc9x9_reset(ioc, force);
-#if 0
-	if (ioc->chip_type == FC909 || ioc->chip-type == FC919) {
-		hard_reset_done = mpt_fc9x9_reset(ioc, force);
-	} else if (ioc->chip_type == FC929) {
-		unsigned long delta;
-
-		delta = jiffies - ioc->last_kickstart;
-		dprintk((KERN_INFO MYNAM ": %s: 929 KickStart, last=%ld, delta = %ld\n",
-				ioc->name, ioc->last_kickstart, delta));
-		if ((ioc->sod_reset == 0) || (delta >= 10*HZ))
-			hard_reset_done = mpt_fc9x9_reset(ioc, ignore);
-		else {
-			dprintk((KERN_INFO MYNAM ": %s: Skipping KickStart (delta=%ld)!\n",
-					ioc->name, delta));
-			return 0;
-		}
-	/* TODO! Add C1030!
-	} else if (ioc->chip_type == C1030) {
-	 */
-	} else {
-		printk(KERN_ERR MYNAM ": %s: ERROR - Bad chip_type (0x%x)\n",
-				ioc->name, ioc->chip_type);
-		return -5;
-	}
-#endif
-
+	hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
 	if (hard_reset_done < 0)
 		return hard_reset_done;
 
-	dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset successful\n",
+	dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
 			ioc->name));
 
 	for (cnt=0; cnt<HZ*20; cnt++) {
-		if ((ioc_state = GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
-			dprintk((KERN_INFO MYNAM ": %s: KickStart successful! (cnt=%d)\n",
+		if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
+			dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
 					ioc->name, cnt));
 			return hard_reset_done;
 		}
-		/* udelay(10000) ? */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+		} else {
+			mdelay (10);
+		}
 	}
 
-	printk(KERN_ERR MYNAM ": %s: ERROR - Failed to come READY after reset!\n",
+	printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
 			ioc->name);
 	return -1;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mpt_fc9x9_reset - Perform hard reset of FC9x9 adapter.
+ *	mpt_diag_reset - Perform hard reset of the adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
- *
- *	This routine places FC9x9 adapter in diagnostic mode via the
- *	WriteSequence register, and then performs a hard reset of adapter
- *	via the Diagnostic register.
- *
- *	Returns 0 for success, non-zero for failure.
+ *	@ignore: Set if to honor and clear to ignore
+ *		the reset history bit
+ *	@sleepflag: CAN_SLEEP if called in a non-interrupt thread,
+ *		else set to NO_SLEEP (use mdelay instead)
+ *
+ *	This routine places the adapter in diagnostic mode via the
+ *	WriteSequence register and then performs a hard reset of adapter
+ *	via the Diagnostic register. Adapter should be in ready state
+ *	upon successful completion.
+ *
+ *	Returns:  1  hard reset successful
+ *		  0  no reset performed because reset history bit set
+ *		 -2  enabling diagnostic mode failed
+ *		 -3  diagnostic reset failed
  */
 static int
-mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore)
+mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 {
 	u32 diag0val;
+	u32 doorbell;
 	int hard_reset_done = 0;
+	int count = 0;
+#ifdef MPT_DEBUG
+	u32 diag1val = 0;
+#endif
 
-	/* Use "Diagnostic reset" method! (only thing available!) */
+	/* Clear any existing interrupts */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
+	/* Use "Diagnostic reset" method! (only thing available!) */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+
 #ifdef MPT_DEBUG
-{
-	u32 diag1val = 0;
 	if (ioc->alt_ioc)
 		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-	dprintk((KERN_INFO MYNAM ": %s: DBG1: diag0=%08x, diag1=%08x\n",
+	dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
 			ioc->name, diag0val, diag1val));
-}
 #endif
-	if (diag0val & MPI_DIAG_DRWE) {
-		dprintk((KERN_INFO MYNAM ": %s: DiagWriteEn bit already set\n",
-				ioc->name));
-	} else {
-		/* Write magic sequence to WriteSequence register */
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
-		dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#1]\n",
-				ioc->name));
-	}
 
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	/* Do the reset if we are told to ignore the reset history
+	 * or if the reset history is 0
+	 */
+	if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
+		while ((diag0val & MPI_DIAG_DRWE) == 0) {
+			/* Write magic sequence to WriteSequence register
+			 * Loop until in diagnostic mode
+			 */
+			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+
+			/* wait 100 msec */
+			if (sleepFlag == CAN_SLEEP) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(100 * HZ / 1000);
+			} else {
+				mdelay (100);
+			}
+
+			count++;
+			if (count > 20) {
+				printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
+						ioc->name, diag0val);
+				return -2;
+
+			}
+
+			diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+
+			dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
+					ioc->name, diag0val));
+		}
+
 #ifdef MPT_DEBUG
-{
-	u32 diag1val = 0;
-	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-	dprintk((KERN_INFO MYNAM ": %s: DbG2: diag0=%08x, diag1=%08x\n",
-			ioc->name, diag0val, diag1val));
-}
+		if (ioc->alt_ioc)
+			diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+		dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
+				ioc->name, diag0val, diag1val));
 #endif
-	if (!ignore && (diag0val & MPI_DIAG_RESET_HISTORY)) {
-		dprintk((KERN_INFO MYNAM ": %s: Skipping due to ResetHistory bit set!\n",
-				ioc->name));
-	} else {
+		/* Write the PreventIocBoot bit */
+		if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
+			diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
+			CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+		}
+
+		/*
+		 * Disable the ARM (Bug fix)
+		 * 
+		 */
+		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
+		mdelay (1);
+
 		/*
 		 * Now hit the reset bit in the Diagnostic register
-		 * (THE BIG HAMMER!)
+		 * (THE BIG HAMMER!) (Clears DRWE bit).
 		 */
-		CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER);
+		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
 		hard_reset_done = 1;
-		dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset performed\n",
+		dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
 				ioc->name));
 
-		/* want udelay(100) */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
+		/*
+		 * Call each currently registered protocol IOC reset handler
+		 * with pre-reset indication.
+		 * NOTE: If we're doing _IOC_BRINGUP, there can be no
+		 * MptResetHandlers[] registered yet.
+		 */
+		{
+			int	 ii;
+			int	 r = 0;
+
+			for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+				if (MptResetHandlers[ii]) {
+					dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
+							ioc->name, ii));
+					r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
+					if (ioc->alt_ioc) {
+						dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
+								ioc->name, ioc->alt_ioc->name, ii));
+						r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
+					}
+				}
+			}
+			/* FIXME?  Examine results here? */
+		}
+
+		if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
+			/* If the DownloadBoot operation fails, the
+			 * IOC will be left unusable. This is a fatal error
+			 * case.  _diag_reset will return < 0
+			 */
+			for (count = 0; count < 30; count ++) {
+				diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+#ifdef MPT_DEBUG
+				if (ioc->alt_ioc)
+					diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+				dprintk((MYIOC_s_INFO_FMT 
+					"DbG2b: diag0=%08x, diag1=%08x\n",
+					ioc->name, diag0val, diag1val));
+#endif
+				if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+					break;
+				}
+
+				/* wait 1 sec */
+				if (sleepFlag == CAN_SLEEP) {
+					set_current_state(TASK_INTERRUPTIBLE);
+					schedule_timeout(HZ);
+				} else {
+					mdelay (1000);
+				}
+			}
+			if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+				printk(KERN_WARNING MYNAM 
+					": firmware downloadboot failure (%d)!\n", count);
+			}
+
+		} else {
+			/* Wait for FW to reload and for board
+			 * to go to the READY state.
+			 * Maximum wait is 30 seconds.
+			 * If fail, no error will check again
+			 * with calling program.
+			 */
+			for (count = 0; count < 30; count ++) {
+				doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+				doorbell &= MPI_IOC_STATE_MASK;
+
+				if (doorbell == MPI_IOC_STATE_READY) {
+					break;
+				}
+
+				/* wait 1 sec */
+				if (sleepFlag == CAN_SLEEP) {
+					set_current_state(TASK_INTERRUPTIBLE);
+					schedule_timeout(HZ);
+				} else {
+					mdelay (1000);
+				}
+			}
+		}
+	}
 
-		/* Write magic sequence to WriteSequence register */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+#ifdef MPT_DEBUG
+	if (ioc->alt_ioc)
+		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+	dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
+		ioc->name, diag0val, diag1val));
+#endif
+
+	/* Clear RESET_HISTORY bit!  Place board in the
+	 * diagnostic mode to update the diag register.
+	 */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	count = 0;
+	while ((diag0val & MPI_DIAG_DRWE) == 0) {
+		/* Write magic sequence to WriteSequence register
+		 * Loop until in diagnostic mode
+		 */
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
-		dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#2]\n",
-				ioc->name));
-	}
 
-	/* Clear RESET_HISTORY bit! */
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, 0x0);
+		/* wait 100 msec */
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(100 * HZ / 1000);
+		} else {
+			mdelay (100);
+		}
 
+		count++;
+		if (count > 20) {
+			printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
+					ioc->name, diag0val);
+			break;
+		}
+		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	}
+	diag0val &= ~MPI_DIAG_RESET_HISTORY;
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
-{
-	u32 diag1val = 0;
-	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-	dprintk((KERN_INFO MYNAM ": %s: DbG3: diag0=%08x, diag1=%08x\n",
-			ioc->name, diag0val, diag1val));
-}
-#endif
 	if (diag0val & MPI_DIAG_RESET_HISTORY) {
-		printk(KERN_WARNING MYNAM ": %s: WARNING - ResetHistory bit failed to clear!\n",
+		printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
 				ioc->name);
 	}
 
+	/* Disable Diagnostic Mode
+	 */
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
+
+	/* Check FW reload status flags.
+	 */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
+		printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
+				ioc->name, diag0val);
+		return -3;
+	}
+
 #ifdef MPT_DEBUG
-{
-	u32 diag1val = 0;
 	if (ioc->alt_ioc)
 		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-	dprintk((KERN_INFO MYNAM ": %s: DbG4: diag0=%08x, diag1=%08x\n",
+	dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
 			ioc->name, diag0val, diag1val));
-}
 #endif
-	if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
-		printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED! (%02xh)\n",
-				ioc->name, diag0val);
-		return -3;
-	}
 
 	/*
 	 * Reset flag that says we've enabled event notification
 	 */
 	ioc->facts.EventState = 0;
 
-	/* NEW!  20010220 -sralston
-	 * Try to avoid redundant resets of the 929.
-	 */
-	ioc->sod_reset++;
-	ioc->last_kickstart = jiffies;
-	if (ioc->alt_ioc) {
-		ioc->alt_ioc->sod_reset = ioc->sod_reset;
-		ioc->alt_ioc->last_kickstart = ioc->last_kickstart;
-	}
+	if (ioc->alt_ioc)
+		ioc->alt_ioc->facts.EventState = 0;
 
 	return hard_reset_done;
 }
@@ -2249,16 +3047,45 @@
  *	Returns 0 for success, non-zero for failure.
  */
 static int
-SendIocReset(MPT_ADAPTER *ioc, u8 reset_type)
+SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 {
 	int r;
+	u32 state;
+	int cntdn, count;
 
 	dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
 			ioc->name, reset_type));
 	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
-	if ((r = WaitForDoorbellAck(ioc, 2)) < 0)
+	if ((r = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0)
 		return r;
 
+	/* FW ACK'd request, wait for READY state 
+	 */
+	cntdn = HZ * 15;
+	count = 0;
+	if (sleepFlag != CAN_SLEEP)
+		cntdn *= 10;	/* 1500 iterations @ 1msec per */
+
+	while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
+		cntdn--;
+		count++;
+		if (!cntdn) {
+			if (sleepFlag != CAN_SLEEP)
+				count *= 10;
+
+			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
+					ioc->name, (count+5)/HZ);
+			return -ETIME;
+		}
+
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+		} else {
+			mdelay (1);	/* 1 msec delay */
+		}
+	}
+
 	/* TODO!
 	 *  Cleanup all event stuff for this IOC; re-issue EventNotification
 	 *  request if needed.
@@ -2275,7 +3102,8 @@
  *	@ioc: Pointer to MPT_ADAPTER structure
  *
  *	This routine allocates memory for the MPT reply and request frame
- *	pools, and primes the IOC reply FIFO with reply frames.
+ *	pools (if necessary), and primes the IOC reply FIFO with
+ *	reply frames.
  *
  *	Returns 0 for success, non-zero for failure.
  */
@@ -2284,6 +3112,7 @@
 {
 	MPT_FRAME_HDR *mf;
 	unsigned long b;
+	unsigned long flags;
 	dma_addr_t aligned_mem_dma;
 	u8 *mem, *aligned_mem;
 	int i, sz;
@@ -2299,8 +3128,8 @@
 		memset(mem, 0, sz);
 		ioc->alloc_total += sz;
 		ioc->reply_alloc = mem;
-		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%08x], sz=%d bytes\n",
-			 ioc->name, mem, ioc->reply_alloc_dma, sz));
+		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
+			 	ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, sz));
 
 		b = (unsigned long) mem;
 		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
@@ -2308,15 +3137,20 @@
 		ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
 		ioc->reply_frames_dma =
 			(ioc->reply_alloc_dma + (aligned_mem - mem));
-		aligned_mem_dma = ioc->reply_frames_dma;
-		dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%08x]\n",
-			 ioc->name, aligned_mem, aligned_mem_dma));
-
-		for (i = 0; i < ioc->reply_depth; i++) {
-			/*  Write each address to the IOC!  */
-			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
-			aligned_mem_dma += ioc->reply_sz;
-		}
+
+		ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
+	}
+
+	/* Post Reply frames to FIFO
+	 */
+	aligned_mem_dma = ioc->reply_frames_dma;
+	dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
+		 	ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
+
+	for (i = 0; i < ioc->reply_depth; i++) {
+		/*  Write each address to the IOC!  */
+		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
+		aligned_mem_dma += ioc->reply_sz;
 	}
 
 
@@ -2336,8 +3170,8 @@
 		memset(mem, 0, sz);
 		ioc->alloc_total += sz;
 		ioc->req_alloc = mem;
-		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%08x], sz=%d bytes\n",
-			 ioc->name, mem, ioc->req_alloc_dma, sz));
+		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
+			 	ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, sz));
 
 		b = (unsigned long) mem;
 		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
@@ -2345,18 +3179,18 @@
 		ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
 		ioc->req_frames_dma =
 			(ioc->req_alloc_dma + (aligned_mem - mem));
-		aligned_mem_dma = ioc->req_frames_dma;
 
-		dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%08x]\n",
-			 ioc->name, aligned_mem, aligned_mem_dma));
+		ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
 
-		for (i = 0; i < ioc->req_depth; i++) {
-			mf = (MPT_FRAME_HDR *) aligned_mem;
-
-			/*  Queue REQUESTs *internally*!  */
-			Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
-			aligned_mem += ioc->req_sz;
+#ifdef __ia64__
+		/* Check: upper 32-bits of the request and reply frame
+		 * physical addresses must be the same.
+		 * ia64 check only
+		 */
+		if ((ioc->req_frames_dma >> 32) != (ioc->reply_frames_dma >> 32)){
+			goto out_fail;
 		}
+#endif
 
 #if defined(CONFIG_MTRR) && 0
 		/*
@@ -2367,20 +3201,38 @@
 		ioc->mtrr_reg = mtrr_add(ioc->req_alloc_dma,
 					 sz,
 					 MTRR_TYPE_WRCOMB, 1);
-		dprintk((KERN_INFO MYNAM ": %s: MTRR region registered (base:size=%08x:%x)\n",
-				ioc->name, ioc->req_alloc_dma,
-				sz ));
+		dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
+				ioc->name, ioc->req_alloc_dma, sz));
 #endif
+	}
+
+	/* Initialize Request frames linked list
+	 */
+	aligned_mem_dma = ioc->req_frames_dma;
+	aligned_mem = (u8 *) ioc->req_frames;
+	dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%p]\n",
+		 	ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
 
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
+	for (i = 0; i < ioc->req_depth; i++) {
+		mf = (MPT_FRAME_HDR *) aligned_mem;
+
+		/*  Queue REQUESTs *internally*!  */
+		Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+		aligned_mem += ioc->req_sz;
 	}
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
 
 	if (ioc->sense_buf_pool == NULL) {
-		sz = (ioc->req_depth * 256);
+		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
 		ioc->sense_buf_pool =
 				pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
 		if (ioc->sense_buf_pool == NULL)
 			goto out_fail;
 
+		ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
 		ioc->alloc_total += sz;
 	}
 
@@ -2408,7 +3260,7 @@
 #if defined(CONFIG_MTRR) && 0
 		if (ioc->mtrr_reg > 0) {
 			mtrr_del(ioc->mtrr_reg, 0, 0);
-			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n",
+			dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
 					ioc->name));
 		}
 #endif
@@ -2417,7 +3269,7 @@
 		ioc->alloc_total -= sz;
 	}
 	if (ioc->sense_buf_pool != NULL) {
-		sz = (ioc->req_depth * 256);
+		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
 		pci_free_consistent(ioc->pcidev,
 				sz,
 				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
@@ -2427,8 +3279,8 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	HandShakeReqAndReply - Send MPT request to and receive reply from
+/**
+ *	mpt_handshake_req_reply_wait - Send MPT request to and receive reply from
  *	IOC via doorbell handshake method.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@reqBytes: Size of the request in bytes
@@ -2436,6 +3288,7 @@
  *	@replyBytes: Expected size of the reply in bytes
  *	@u16reply: Pointer to area where reply should be written
  *	@maxwait: Max wait time for a reply (in seconds)
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	NOTES: It is the callers responsibility to byte-swap fields in the
  *	request which are greater than 1 byte in size.  It is also the
@@ -2444,8 +3297,9 @@
  *
  *	Returns 0 for success, non-zero for failure.
  */
-static int
-HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait)
+int
+mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
+				int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
 {
 	MPIDefaultReply_t *mptReply;
 	int failcnt = 0;
@@ -2471,57 +3325,61 @@
 	/*
 	 * Wait for IOC's doorbell handshake int
 	 */
-	if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
+	if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
 
-	dhsprintk((KERN_INFO MYNAM ": %s: HandShake request start, WaitCnt=%d%s\n",
+	dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
 			ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
+	/* Read doorbell and check for active bit */
+	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+			return -1;
+
 	/*
 	 * Clear doorbell int (WRITE 0 to IntStatus reg),
 	 * then wait for IOC to ACKnowledge that it's ready for
 	 * our handshake request.
 	 */
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-	if (!failcnt && (t = WaitForDoorbellAck(ioc, 2)) < 0)
+	if (!failcnt && (t = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0)
 		failcnt++;
 
 	if (!failcnt) {
-		int	 i;
+		int	 ii;
 		u8	*req_as_bytes = (u8 *) req;
 
 		/*
 		 * Stuff request words via doorbell handshake,
 		 * with ACK from IOC for each.
 		 */
-		for (i = 0; !failcnt && i < reqBytes/4; i++) {
-			u32 word = ((req_as_bytes[(i*4) + 0] <<  0) |
-				    (req_as_bytes[(i*4) + 1] <<  8) |
-				    (req_as_bytes[(i*4) + 2] << 16) |
-				    (req_as_bytes[(i*4) + 3] << 24));
+		for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
+			u32 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
+				    (req_as_bytes[(ii*4) + 1] <<  8) |
+				    (req_as_bytes[(ii*4) + 2] << 16) |
+				    (req_as_bytes[(ii*4) + 3] << 24));
 
 			CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
-			if ((t = WaitForDoorbellAck(ioc, 2)) < 0)
+			if ((t = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0)
 				failcnt++;
 		}
 
 		dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
 		DBG_DUMP_REQUEST_FRAME_HDR(req)
 
-		dhsprintk((KERN_INFO MYNAM ": %s: HandShake request post done, WaitCnt=%d%s\n",
+		dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
 				ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
 
 		/*
 		 * Wait for completion of doorbell handshake reply from the IOC
 		 */
-		if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait)) < 0)
+		if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
 			failcnt++;
 
 		/*
 		 * Copy out the cached reply...
 		 */
-		for(i=0; i < MIN(replyBytes/2,mptReply->MsgLength*2); i++)
-			u16reply[i] = ioc->hs_reply[i];
+		for (ii=0; ii < MIN(replyBytes/2,mptReply->MsgLength*2); ii++)
+			u16reply[ii] = ioc->hs_reply[ii];
 	} else {
 		return -99;
 	}
@@ -2535,6 +3393,7 @@
  *	in it's IntStatus register.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@howlong: How long to wait (in seconds)
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	This routine waits (up to ~2 seconds max) for IOC doorbell
  *	handshake ACKnowledge.
@@ -2542,28 +3401,40 @@
  *	Returns a negative value on failure, else wait loop count.
  */
 static int
-WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong)
+WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 {
 	int cntdn = HZ * howlong;
 	int count = 0;
 	u32 intstat;
 
-	while (--cntdn) {
-		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
-		if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
-			break;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		count++;
+	if (sleepFlag == CAN_SLEEP) {
+		while (--cntdn) {
+			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+				break;
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+			count++;
+		}
+	} else {
+		cntdn *= 10; /* convert to msec */
+		while (--cntdn) {
+			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+				break;
+			mdelay (1);
+			count++;
+		}
+		count /= 10;
 	}
 
 	if (cntdn) {
-		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell ACK (cnt=%d)\n",
+		dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
 				ioc->name, count));
 		return count;
 	}
 
-	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell ACK timeout(%d)!\n",
+	printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
 			ioc->name, (count+5)/HZ);
 	return -1;
 }
@@ -2574,34 +3445,47 @@
  *	in it's IntStatus register.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@howlong: How long to wait (in seconds)
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
  *
  *	Returns a negative value on failure, else wait loop count.
  */
 static int
-WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong)
+WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 {
 	int cntdn = HZ * howlong;
 	int count = 0;
 	u32 intstat;
 
-	while (--cntdn) {
-		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
-		if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
-			break;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		count++;
+	if (sleepFlag == CAN_SLEEP) {
+		while (--cntdn) {
+			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+				break;
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+			count++;
+		}
+	} else {
+		cntdn *= 10; /* convert to msec */
+		while (--cntdn) {
+			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+				break;
+			mdelay(1);
+			count++;
+		}
+		count /= 10;
 	}
 
 	if (cntdn) {
-		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell INT (cnt=%d)\n",
+		dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
 				ioc->name, count));
 		return count;
 	}
 
-	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell INT timeout(%d)!\n",
+	printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
 			ioc->name, (count+5)/HZ);
 	return -1;
 }
@@ -2611,6 +3495,7 @@
  *	WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@howlong: How long to wait (in seconds)
+ *	@sleepFlag: Specifies whether the process can sleep
  *
  *	This routine polls the IOC for a handshake reply, 16 bits at a time.
  *	Reply is cached to IOC private area large enough to hold a maximum
@@ -2619,13 +3504,13 @@
  *	Returns a negative value on failure, else size of reply in WORDS.
  */
 static int
-WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong)
+WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 {
 	int u16cnt = 0;
 	int failcnt = 0;
 	int t;
 	u16 *hs_reply = ioc->hs_reply;
- 	volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
+	volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
 	u16 hword;
 
 	hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
@@ -2634,12 +3519,12 @@
 	 * Get first two u16's so we can look at IOC's intended reply MsgLength
 	 */
 	u16cnt=0;
-	if ((t = WaitForDoorbellInt(ioc, howlong)) < 0) {
+	if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
 		failcnt++;
 	} else {
 		hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
 		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-		if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
+		if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
 			failcnt++;
 		else {
 			hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
@@ -2647,7 +3532,7 @@
 		}
 	}
 
-	dhsprintk((KERN_INFO MYNAM ": %s: First handshake reply word=%08x%s\n",
+	dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
 			ioc->name, le32_to_cpu(*(u32 *)hs_reply),
 			failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
@@ -2656,7 +3541,7 @@
 	 * reply 16 bits at a time.
 	 */
 	for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
-		if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
+		if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
 			failcnt++;
 		hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
 		/* don't overflow our IOC hs_reply[] buffer! */
@@ -2665,12 +3550,12 @@
 		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 	}
 
-	if (!failcnt && (t = WaitForDoorbellInt(ioc, 2)) < 0)
+	if (!failcnt && (t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
 		failcnt++;
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
 	if (failcnt) {
-		printk(KERN_ERR MYNAM ": %s: ERROR - Handshake reply failure!\n",
+		printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
 				ioc->name);
 		return -failcnt;
 	}
@@ -2681,130 +3566,631 @@
 	else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
 		return -102;
 	}
-#endif
+#endif
+
+	dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
+	DBG_DUMP_REPLY_FRAME(mptReply)
+
+	dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
+			ioc->name, u16cnt/2));
+	return u16cnt/2;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetLanConfigPages - Fetch LANConfig pages.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Return: 0 for success
+ *	-ENOMEM if no memory available
+ *		-EPERM if not allowed due to ISR context
+ *		-EAGAIN if no msg frames currently available
+ *		-EFAULT for non-successful reply or no reply (timeout)
+ */
+static int
+GetLanConfigPages(MPT_ADAPTER *ioc)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	LANPage0_t		*ppage0_alloc;
+	dma_addr_t		 page0_dma;
+	LANPage1_t		*ppage1_alloc;
+	dma_addr_t		 page1_dma;
+	int			 rc = 0;
+	int			 data_sz;
+	int			 copy_sz;
+
+	/* Get LAN Page 0 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 0;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
+	cfg.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = 0;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength > 0) {
+		data_sz = hdr.PageLength * 4;
+		ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
+		rc = -ENOMEM;
+		if (ppage0_alloc) {
+			memset((u8 *)ppage0_alloc, 0, data_sz);
+			cfg.physAddr = page0_dma;
+			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+			if ((rc = mpt_config(ioc, &cfg)) == 0) {
+				/* save the data */
+				copy_sz = MIN(sizeof(LANPage0_t), data_sz);
+				memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
+
+			}
+
+			pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
+
+			/* FIXME!
+			 *	Normalize endianness of structure data,
+			 *	by byte-swapping all > 1 byte fields!
+			 */
+
+		}
+
+		if (rc)
+			return rc;
+	}
+
+	/* Get LAN Page 1 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 1;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
+	cfg.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return 0;
+
+	data_sz = hdr.PageLength * 4;
+	rc = -ENOMEM;
+	ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
+	if (ppage1_alloc) {
+		memset((u8 *)ppage1_alloc, 0, data_sz);
+		cfg.physAddr = page1_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+		if ((rc = mpt_config(ioc, &cfg)) == 0) {
+			/* save the data */
+			copy_sz = MIN(sizeof(LANPage1_t), data_sz);
+			memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
+		}
+
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
+
+		/* FIXME!
+		 *	Normalize endianness of structure data,
+		 *	by byte-swapping all > 1 byte fields!
+		 */
+
+	}
+
+	return rc;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetFcPortPage0 - Fetch FCPort config Page0.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@portnum: IOC Port number
+ *
+ *	Return: 0 for success
+ *	-ENOMEM if no memory available
+ *		-EPERM if not allowed due to ISR context
+ *		-EAGAIN if no msg frames currently available
+ *		-EFAULT for non-successful reply or no reply (timeout)
+ */
+static int
+GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	FCPortPage0_t		*ppage0_alloc;
+	FCPortPage0_t		*pp0dest;
+	dma_addr_t		 page0_dma;
+	int			 data_sz;
+	int			 copy_sz;
+	int			 rc;
+
+	/* Get FCPort Page 0 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 0;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+	cfg.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = portnum;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return 0;
+
+	data_sz = hdr.PageLength * 4;
+	rc = -ENOMEM;
+	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
+	if (ppage0_alloc) {
+		memset((u8 *)ppage0_alloc, 0, data_sz);
+		cfg.physAddr = page0_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+		if ((rc = mpt_config(ioc, &cfg)) == 0) {
+			/* save the data */
+			pp0dest = &ioc->fc_port_page0[portnum];
+			copy_sz = MIN(sizeof(FCPortPage0_t), data_sz);
+			memcpy(pp0dest, ppage0_alloc, copy_sz);
+
+			/*
+			 *	Normalize endianness of structure data,
+			 *	by byte-swapping all > 1 byte fields!
+			 */
+			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
+			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
+			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
+			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
+			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
+			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
+			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
+			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
+			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
+			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
+			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
+			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
+			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
+			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
+			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
+			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+
+		}
+
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
+	}
+
+	return rc;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetIoUnitPage2 - Retrieve BIOS version and boot order information.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Returns: 0 for success
+ *	-ENOMEM if no memory available
+ *		-EPERM if not allowed due to ISR context
+ *		-EAGAIN if no msg frames currently available
+ *		-EFAULT for non-successful reply or no reply (timeout)
+ */
+static int
+GetIoUnitPage2(MPT_ADAPTER *ioc)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	IOUnitPage2_t		*ppage_alloc;
+	dma_addr_t		 page_dma;
+	int			 data_sz;
+	int			 rc;
+
+	/* Get the page header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 2;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
+	cfg.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = 0;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return 0;
+
+	/* Read the config page */
+	data_sz = hdr.PageLength * 4;
+	rc = -ENOMEM;
+	ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
+	if (ppage_alloc) {
+		memset((u8 *)ppage_alloc, 0, data_sz);
+		cfg.physAddr = page_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+		/* If Good, save data */
+		if ((rc = mpt_config(ioc, &cfg)) == 0)
+			ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
+
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
+	}
+
+	return rc;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*	mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
+ *	@ioc: Pointer to a Adapter Strucutre
+ *	@portnum: IOC port number
+ *
+ *	Return: -EFAULT if read of config page header fails
+ *			or if no nvram
+ *	If read of SCSI Port Page 0 fails,
+ *		NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
+ *		Adapter settings: async, narrow
+ *		Return 1
+ *	If read of SCSI Port Page 2 fails,
+ *		Adapter settings valid
+ *		NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
+ *		Return 1
+ *	Else
+ *		Both valid
+ *		Return 0
+ *	CHECK - what type of locking mechanisms should be used????
+ */
+static int
+mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
+{
+	u8			*pbuf = NULL;
+	dma_addr_t		 buf_dma;
+	CONFIGPARMS		 cfg;
+	ConfigPageHeader_t	 header;
+	int			 ii;
+	int			 data, rc = 0;
+
+	/* Allocate memory 
+	 */
+	if (!ioc->spi_data.nvram) {
+		int	 sz;
+		u8	*mem;
+		sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
+		mem = kmalloc(sz, GFP_KERNEL);
+		if (mem == NULL)
+			return -EFAULT;
+
+		ioc->spi_data.nvram = (int *) mem;
+
+		dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
+			ioc->name, ioc->spi_data.nvram, sz));
+	}
+
+	/* Invalidate NVRAM information
+	 */
+	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+		ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
+	}
+
+	/* Read SPP0 header, allocate memory, then read page.
+	 */
+	header.PageVersion = 0;
+	header.PageLength = 0;
+	header.PageNumber = 0;
+	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
+	cfg.hdr = &header;
+	cfg.physAddr = -1;
+	cfg.pageAddr = portnum;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.timeout = 0;	/* use default */
+	if (mpt_config(ioc, &cfg) != 0)
+		 return -EFAULT;
+
+	if (header.PageLength > 0) {
+		pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
+		if (pbuf) {
+			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+			cfg.physAddr = buf_dma;
+			if (mpt_config(ioc, &cfg) != 0) {
+				ioc->spi_data.maxBusWidth = MPT_NARROW;
+				ioc->spi_data.maxSyncOffset = 0;
+				ioc->spi_data.minSyncFactor = MPT_ASYNC;
+				ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
+				rc = 1;
+			} else {
+				/* Save the Port Page 0 data
+				 */
+				SCSIPortPage0_t  *pPP0 = (SCSIPortPage0_t  *) pbuf;
+				pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
+				pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
+
+				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
+				data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
+				if (data) {
+					ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
+					data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
+					ioc->spi_data.minSyncFactor = (u8) (data >> 8);
+				} else {
+					ioc->spi_data.maxSyncOffset = 0;
+					ioc->spi_data.minSyncFactor = MPT_ASYNC;
+				}
+
+				ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
+
+				/* Update the minSyncFactor based on bus type.
+				 */
+				if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
+					(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
+
+					if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+						ioc->spi_data.minSyncFactor = MPT_ULTRA;
+				}
+			}
+			if (pbuf) {
+				pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
+				pbuf = NULL;
+			}
+		}
+	}
+
+	/* SCSI Port Page 2 - Read the header then the page.
+	 */
+	header.PageVersion = 0;
+	header.PageLength = 0;
+	header.PageNumber = 2;
+	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
+	cfg.hdr = &header;
+	cfg.physAddr = -1;
+	cfg.pageAddr = portnum;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	if (mpt_config(ioc, &cfg) != 0)
+		return -EFAULT;
+
+	if (header.PageLength > 0) {
+		/* Allocate memory and read SCSI Port Page 2
+		 */
+		pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
+		if (pbuf) {
+			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
+			cfg.physAddr = buf_dma;
+			if (mpt_config(ioc, &cfg) != 0) {
+				/* Nvram data is left with INVALID mark
+				 */
+				rc = 1;
+			} else {
+				SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
+				MpiDeviceInfo_t	*pdevice = NULL;
+
+				/* Save the Port Page 2 data
+				 * (reformat into a 32bit quantity)
+				 */
+				for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+					pdevice = &pPP2->DeviceSettings[ii];
+					data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
+						(pdevice->SyncFactor << 8) | pdevice->Timeout;
+					ioc->spi_data.nvram[ii] = data;
+				}
+			}
+
+			pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
+			pbuf = NULL;
+		}
+	}
 
-	dmfprintk((KERN_INFO MYNAM ": %s: Got Handshake reply:\n", ioc->name));
-	DBG_DUMP_REPLY_FRAME(mptReply)
+	/* Update Adapter limits with those from NVRAM
+	 * Comment: Don't need to do this. Target performance
+	 * parameters will never exceed the adapters limits.
+	 */
 
-	dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell REPLY (sz=%d)\n",
-			ioc->name, u16cnt/2));
-	return u16cnt/2;
+	return rc;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	GetLanConfigPages - Fetch LANConfig pages.
- *	@ioc: Pointer to MPT_ADAPTER structure
+/*	mpt_readScsiDevicePageHeaders - save version and length of SDP1
+ *	@ioc: Pointer to a Adapter Strucutre
+ *	@portnum: IOC port number
  *
- *	Returns 0 for success, non-zero for failure.
+ *	Return: -EFAULT if read of config page header fails
+ *		or 0 if success.
  */
 static int
-GetLanConfigPages(MPT_ADAPTER *ioc)
+mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
 {
-	Config_t		 config_req;
-	ConfigReply_t		 config_reply;
-	LANPage0_t		*page0;
-	dma_addr_t		 page0_dma;
-	LANPage1_t		*page1;
-	dma_addr_t		 page1_dma;
-	int			 i;
-	int			 req_sz;
-	int			 reply_sz;
-	int			 data_sz;
+	CONFIGPARMS		 cfg;
+	ConfigPageHeader_t	 header;
 
-/* LANPage0 */
-	/*  Immediate destination (reply area)...  */
-	reply_sz = sizeof(config_reply);
-	memset(&config_reply, 0, reply_sz);
-
-	/*  Ultimate destination...  */
-	page0 = &ioc->lan_cnfg_page0;
-	data_sz = sizeof(*page0);
-	memset(page0, 0, data_sz);
-
-	/*  Request area (config_req on the stack right now!)  */
-	req_sz = sizeof(config_req);
-	memset(&config_req, 0, req_sz);
-	config_req.Function = MPI_FUNCTION_CONFIG;
-	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-	/*	config_req.Header.PageVersion = 0;	*/
-	/*	config_req.Header.PageLength = 0;	*/
-	config_req.Header.PageNumber = 0;
-	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
-	/*	config_req.PageAddress = 0;		*/
-	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
-			((MPI_SGE_FLAGS_LAST_ELEMENT |
-			  MPI_SGE_FLAGS_END_OF_BUFFER |
-			  MPI_SGE_FLAGS_END_OF_LIST |
-			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
-			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
-			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
-			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
-			(u32)data_sz
-	);
-	page0_dma = pci_map_single(ioc->pcidev, page0, data_sz, PCI_DMA_FROMDEVICE);
-	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page0_dma);
+	/* Read the SCSI Device Page 1 header
+	 */
+	header.PageVersion = 0;
+	header.PageLength = 0;
+	header.PageNumber = 1;
+	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+	cfg.hdr = &header;
+	cfg.physAddr = -1;
+	cfg.pageAddr = portnum;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.timeout = 0;
+	if (mpt_config(ioc, &cfg) != 0)
+		 return -EFAULT;
+
+	ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
+	ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+
+	header.PageVersion = 0;
+	header.PageLength = 0;
+	header.PageNumber = 0;
+	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+	if (mpt_config(ioc, &cfg) != 0)
+		 return -EFAULT;
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_0\n",
-			ioc->name));
+	ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
+	ioc->spi_data.sdp0length = cfg.hdr->PageLength;
 
-	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
-				reply_sz, (u16*)&config_reply, 3);
-	pci_unmap_single(ioc->pcidev, page0_dma, data_sz, PCI_DMA_FROMDEVICE);
-	if (i != 0)
-		return i;
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes 
+ *	@ioc: Pointer to a Adapter Strucutre
+ *	@portnum: IOC port number
+ *
+ *	Return:
+ *	0 on success
+ *	-EFAULT if read of config page header fails or data pointer not NULL
+ *	-ENOMEM if pci_alloc failed
+ */
+static int
+mpt_findImVolumes(MPT_ADAPTER *ioc)
+{
+	IOCPage2_t		*pIoc2 = NULL;
+	IOCPage3_t		*pIoc3 = NULL;
+	ConfigPageIoc2RaidVol_t	*pIocRv = NULL;
+	u8			*mem;
+	dma_addr_t		 ioc2_dma;
+	dma_addr_t		 ioc3_dma;
+	CONFIGPARMS		 cfg;
+	ConfigPageHeader_t	 header;
+	int			 jj;
+	int			 rc = 0;
+	int			 iocpage2sz;
+	int			 iocpage3sz = 0;
+	u8			 nVols, nPhys;
+	u8			 vid, vbus, vioc;
+
+	if (ioc->spi_data.pIocPg3)
+		return -EFAULT;	
+
+	/* Read IOCP2 header then the page.
+	 */
+	header.PageVersion = 0;
+	header.PageLength = 0;
+	header.PageNumber = 2;
+	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+	cfg.hdr = &header;
+	cfg.physAddr = -1;
+	cfg.pageAddr = 0;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.timeout = 0;
+	if (mpt_config(ioc, &cfg) != 0)
+		 return -EFAULT;
+
+	if (header.PageLength == 0)
+		return -EFAULT;
+
+	iocpage2sz = header.PageLength * 4;
+	pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
+	if (!pIoc2)
+		return -ENOMEM;
+
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.physAddr = ioc2_dma;
+	if (mpt_config(ioc, &cfg) != 0)
+		goto done_and_free;
+
+	/* Identify RAID Volume Id's */
+	nVols = pIoc2->NumActiveVolumes;
+	if ( nVols == 0) {
+		/* No RAID Volumes.  Done.
+		 */
+	} else {
+		/* At least 1 RAID Volume
+		 */
+		pIocRv = pIoc2->RaidVolume;
+		ioc->spi_data.isRaid = 0;
+		for (jj = 0; jj < nVols; jj++, pIocRv++) {
+			vid = pIocRv->VolumeID;
+			vbus = pIocRv->VolumeBus;
+			vioc = pIocRv->VolumeIOC;
+
+			/* find the match
+			 */
+			if (vbus == 0) {
+				ioc->spi_data.isRaid |= (1 << vid);
+			} else {
+				/* Error! Always bus 0
+				 */
+			}
+		}
+	}
 
-	/*  Now byte swap the necessary LANPage0 fields  */
+	/* Identify Hidden Physical Disk Id's */
+	nPhys = pIoc2->NumActivePhysDisks;
+	if (nPhys == 0) {
+		/* No physical disks. Done.
+		 */
+	} else {
+		/* There is at least one physical disk.
+		 * Read and save IOC Page 3
+		 */
+		header.PageVersion = 0;
+		header.PageLength = 0;
+		header.PageNumber = 3;
+		header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+		cfg.hdr = &header;
+		cfg.physAddr = -1;
+		cfg.pageAddr = 0;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+		cfg.dir = 0;
+		cfg.timeout = 0;
+		if (mpt_config(ioc, &cfg) != 0)
+			goto done_and_free;
 
-/* LANPage1 */
-	/*  Immediate destination (reply area)...  */
-	reply_sz = sizeof(config_reply);
-	memset(&config_reply, 0, reply_sz);
-
-	/*  Ultimate destination...  */
-	page1 = &ioc->lan_cnfg_page1;
-	data_sz = sizeof(*page1);
-	memset(page1, 0, data_sz);
-
-	/*  Request area (config_req on the stack right now!)  */
-	req_sz = sizeof(config_req);
-	memset(&config_req, 0, req_sz);
-	config_req.Function = MPI_FUNCTION_CONFIG;
-	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-	/*	config_req.Header.PageVersion = 0;	*/
-	/*	config_req.Header.PageLength = 0;	*/
-	config_req.Header.PageNumber = 1;
-	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
-	/*	config_req.PageAddress = 0;		*/
-	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
-			((MPI_SGE_FLAGS_LAST_ELEMENT |
-			  MPI_SGE_FLAGS_END_OF_BUFFER |
-			  MPI_SGE_FLAGS_END_OF_LIST |
-			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
-			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
-			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
-			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
-			(u32)data_sz
-	);
-	page1_dma = pci_map_single(ioc->pcidev, page1, data_sz, PCI_DMA_FROMDEVICE);
-	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page1_dma);
+		if (header.PageLength == 0)
+			goto done_and_free;
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_1\n",
-			ioc->name));
+		/* Read Header good, alloc memory
+		 */
+		iocpage3sz = header.PageLength * 4;
+		pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
+		if (!pIoc3)
+			goto done_and_free;
 
-	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
-				reply_sz, (u16*)&config_reply, 3);
-	pci_unmap_single(ioc->pcidev, page1_dma, data_sz, PCI_DMA_FROMDEVICE);
-	if (i != 0)
-		return i;
+		/* Read the Page and save the data
+		 * into malloc'd memory.
+		 */
+		cfg.physAddr = ioc3_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+		if (mpt_config(ioc, &cfg) == 0) {
+			mem = kmalloc(iocpage3sz, GFP_KERNEL);
+			if (mem) {
+				memcpy(mem, (u8 *)pIoc3, iocpage3sz);
+				ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+			}
+		}
+	}
 
-	/*  Now byte swap the necessary LANPage1 fields  */
+done_and_free:
+	if (pIoc2) {
+		pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
+		pIoc2 = NULL;
+	}
 
-	return 0;
+	if (pIoc3) {
+		pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
+		pIoc3 = NULL;
+	}
+
+	return rc;
 }
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	SendEventNotification - Send EventNotification (on or off) request
  *	to MPT adapter.
  *	@ioc: Pointer to MPT_ADAPTER structure
@@ -2817,13 +4203,13 @@
 
 	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
 	if (evnp == NULL) {
-		dprintk((KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate a event request frame!\n",
+		dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
 				ioc->name));
 		return 0;
 	}
 	memset(evnp, 0, sizeof(*evnp));
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+	dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
 
 	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
 	evnp->ChainOffset = 0;
@@ -2847,13 +4233,13 @@
 	EventAck_t	*pAck;
 
 	if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
-		printk(KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate event ACK request frame!\n",
+		printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
 				ioc->name);
 		return -1;
 	}
 	memset(pAck, 0, sizeof(*pAck));
 
-	dprintk((KERN_INFO MYNAM ": %s: Sending EventAck\n", ioc->name));
+	dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
 
 	pAck->Function     = MPI_FUNCTION_EVENT_ACK;
 	pAck->ChainOffset  = 0;
@@ -2866,25 +4252,212 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS		/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_config - Generic function to issue config message
+ *	@ioc - Pointer to an adapter structure
+ *	@cfg - Pointer to a configuration structure. Struct contains
+ *		action, page address, direction, physical address
+ *		and pointer to a configuration page header
+ *		Page header is updated.
+ *
+ *	Returns 0 for success
+ *	-EPERM if not allowed due to ISR context
+ *	-EAGAIN if no msg frames currently available
+ *	-EFAULT for non-successful reply or no reply (timeout)
+ */
+int
+mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
+{
+	Config_t	*pReq;
+	MPT_FRAME_HDR	*mf;
+	MptSge_t	*psge;
+	unsigned long	 flags;
+	int		 ii, rc;
+	int		 flagsLength;
+	int		 in_isr;
+
+	/* (Bugzilla:fibrebugs, #513)
+	 * Bug fix (part 1)!  20010905 -sralston
+	 *	Prevent calling wait_event() (below), if caller happens
+	 *	to be in ISR context, because that is fatal!
+	 */
+	in_isr = in_interrupt();
+	if (in_isr) {
+		dprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
+				ioc->name));
+		return -EPERM;
+	}
+
+	/* Get and Populate a free Frame
+	 */
+	if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
+		dprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
+				ioc->name));
+		return -EAGAIN;
+	}
+	pReq = (Config_t *)mf;
+	pReq->Action = pCfg->action;
+	pReq->Reserved = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_CONFIG;
+	pReq->Reserved1[0] = 0;
+	pReq->Reserved1[1] = 0;
+	pReq->Reserved1[2] = 0;
+	pReq->MsgFlags = 0;
+	for (ii=0; ii < 8; ii++)
+		pReq->Reserved2[ii] = 0;
+
+	pReq->Header.PageVersion = pCfg->hdr->PageVersion;
+	pReq->Header.PageLength = pCfg->hdr->PageLength;
+	pReq->Header.PageNumber = pCfg->hdr->PageNumber;
+	pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+	pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
+
+	/* Add a SGE to the config request.
+	 */
+	flagsLength = ((MPI_SGE_FLAGS_LAST_ELEMENT |
+			MPI_SGE_FLAGS_END_OF_BUFFER |
+			MPI_SGE_FLAGS_END_OF_LIST |
+			MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+			MPT_SGE_ADDRESS_SIZE ) << MPI_SGE_FLAGS_SHIFT) |
+			pCfg->hdr->PageLength * 4;
+
+	if (pCfg->dir)
+		flagsLength |= (MPI_SGE_FLAGS_DIRECTION << MPI_SGE_FLAGS_SHIFT);
+
+	psge = (MptSge_t *) &pReq->PageBufferSGE;
+	psge->FlagsLength = cpu_to_le32(flagsLength);
+	cpu_to_leXX(pCfg->physAddr, psge->Address);
+
+	dprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+		ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+
+	/* Append pCfg pointer to end of mf
+	 */
+	*((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
+
+	/* Initalize the timer
+	 */
+	init_timer(&pCfg->timer);
+	pCfg->timer.data = (unsigned long) ioc;
+	pCfg->timer.function = mpt_timer_expired;
+	pCfg->wait_done = 0;
+
+	/* Set the timer; ensure 10 second minimum */
+	if (pCfg->timeout < 10)
+		pCfg->timer.expires = jiffies + HZ*10;
+	else
+		pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
+
+	/* Add to end of Q, set timer and then issue this command */
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+	add_timer(&pCfg->timer);
+	mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
+	wait_event(mpt_waitq, pCfg->wait_done);
+
+	/* mf has been freed - do not access */
+
+	rc = pCfg->status;
+
+	return rc;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
+ *	mpt_timer_expired - Call back for timer process.
+ *	Used only internal config functionality.
+ *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
+ */
+static void
+mpt_timer_expired(unsigned long data)
+{
+	MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
+
+	dprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
+
+	/* Perform a FW reload */
+	if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
+		printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
+
+	/* No more processing.
+	 * Hard reset clean-up will wake up
+	 * process and free all resources.
+	 */
+	dprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
+
+	return;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_ioc_reset - Base cleanup for hard reset
+ *	@ioc: Pointer to the adapter structure
+ *	@reset_phase: Indicates pre- or post-reset functionality
+ *
+ *	Remark: Free's resources with internally generated commands.
  */
+static int
+mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	CONFIGPARMS *pCfg;
+	unsigned long flags;
+
+	dprintk((KERN_WARNING MYNAM
+			": IOC %s_reset routed to MPT base driver!\n",
+			reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"));
+
+	if (reset_phase == MPT_IOC_PRE_RESET) {
+		/* If the internal config Q is not empty -
+		 * delete timer. MF resources will be freed when
+		 * the FIFO's are primed.
+		 */
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		if (! Q_IS_EMPTY(&ioc->configQ)){
+			pCfg = (CONFIGPARMS *)ioc->configQ.head;
+			do {
+				del_timer(&pCfg->timer);
+				pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
+			} while (pCfg != (CONFIGPARMS *)&ioc->configQ);
+		}
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+	} else {
+		CONFIGPARMS *pNext;
+
+		/* Search the configQ for internal commands. 
+		 * Flush the Q, and wake up all suspended threads.
+		 */
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		if (! Q_IS_EMPTY(&ioc->configQ)){
+			pCfg = (CONFIGPARMS *)ioc->configQ.head;
+			do {
+				pNext = (CONFIGPARMS *) pCfg->linkage.forw;
 
-#define PROC_MPT_READ_RETURN(page,start,off,count,eof,len) \
-{ \
-	len -= off;			\
-	if (len < count) {		\
-		*eof = 1;		\
-		if (len <= 0)		\
-			return 0;	\
-	} else				\
-		len = count;		\
-	*start = page + off;		\
-	return len;			\
+				Q_DEL_ITEM(&pCfg->linkage);
+
+				pCfg->status = MPT_CONFIG_ERROR;
+				pCfg->wait_done = 1;
+				wake_up(&mpt_waitq);
+
+				pCfg = pNext;
+			} while (pCfg != (CONFIGPARMS *)&ioc->configQ);
+		}
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+	}
+
+	return 1;		/* currently means nothing really */
 }
 
+
+#ifdef CONFIG_PROC_FS		/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
+ */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
@@ -2894,71 +4467,62 @@
 static int
 procmpt_create(void)
 {
-	MPT_ADAPTER *ioc;
-	struct proc_dir_entry *ent;
-	int errcnt = 0;
+	MPT_ADAPTER		*ioc;
+	struct proc_dir_entry	*ent;
+	int	 ii;
 
 	/*
-	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
-	 * 	(single level) to multi level (e.g. "driver/message/fusion")
-	 * 	something here needs to change.  -sralston
+	 *	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
+	 *	(single level) to multi level (e.g. "driver/message/fusion")
+	 *	something here needs to change.  -sralston
 	 */
-	procmpt_root_dir = CREATE_PROCDIR_ENTRY(MPT_PROCFS_MPTBASEDIR, NULL);
-	if (procmpt_root_dir == NULL)
+	mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
+	if (mpt_proc_root_dir == NULL)
 		return -ENOTDIR;
 
-	if ((ioc = mpt_adapter_find_first()) != NULL) {
-		ent = create_proc_read_entry(MPT_PROCFS_SUMMARY_NODE, 0, NULL, procmpt_read_summary, NULL);
-		if (ent == NULL) {
-			printk(KERN_WARNING MYNAM ": WARNING - Could not create %s entry!\n",
-					MPT_PROCFS_SUMMARY_PATHNAME);
-			errcnt++;
+	for (ii=0; ii < MPT_PROC_ENTRIES; ii++) {
+		ent = create_proc_entry(mpt_proc_list[ii].name,
+				S_IFREG|S_IRUGO, mpt_proc_root_dir);
+		if (!ent) {
+			printk(KERN_WARNING MYNAM
+					": WARNING - Could not create /proc/mpt/%s entry\n",
+					mpt_proc_list[ii].name);
+			continue;
 		}
+		ent->read_proc = mpt_proc_list[ii].f;
+		ent->data      = NULL;
 	}
 
+	ioc = mpt_adapter_find_first();
 	while (ioc != NULL) {
-		char pname[32];
-		int namelen;
+		struct proc_dir_entry	*dent;
 		/*
 		 *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
 		 */
-		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
-		if ((ent = CREATE_PROCDIR_ENTRY(pname, NULL)) != NULL) {
+		if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
 			/*
-			 *  And populate it with: "summary" and "dbg" file entries.
+			 *  And populate it with mpt_ioc_proc_list[] entries.
 			 */
-			(void) sprintf(pname+namelen, "/summary");
-			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_summary, ioc);
-			if (ent == NULL) {
-				errcnt++;
-				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
-						ioc->name, pname);
-			}
-//#ifdef MPT_DEBUG
-			/* DEBUG aid! */
-			(void) sprintf(pname+namelen, "/dbg");
-			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_dbg, ioc);
-			if (ent == NULL) {
-				errcnt++;
-				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
-						ioc->name, pname);
+			for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
+				ent = create_proc_entry(mpt_ioc_proc_list[ii].name,
+						S_IFREG|S_IRUGO, dent);
+				if (!ent) {
+					printk(KERN_WARNING MYNAM
+							": WARNING - Could not create /proc/mpt/%s/%s entry!\n",
+							ioc->name,
+							mpt_ioc_proc_list[ii].name);
+					continue;
+				}
+				ent->read_proc = mpt_ioc_proc_list[ii].f;
+				ent->data      = ioc;
 			}
-//#endif
 		} else {
-			errcnt++;
-			printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
-					ioc->name, pname);
-
+			printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n",
+					ioc->name, mpt_ioc_proc_list[ii].name);
 		}
-
 		ioc = mpt_adapter_find_next(ioc);
 	}
 
-	if (errcnt) {
-//		remove_proc_entry("mpt", 0);
-		return -ENOTDIR;
-	}
-
 	return 0;
 }
 
@@ -2971,44 +4535,44 @@
 static int
 procmpt_destroy(void)
 {
-	MPT_ADAPTER *ioc;
+	MPT_ADAPTER	*ioc;
+	int		 ii;
 
-	if (!procmpt_root_dir)
+	if (!mpt_proc_root_dir)
 		return 0;
 
 	/*
-	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
-	 * 	(single level) to multi level (e.g. "driver/message/fusion")
-	 * 	something here needs to change.  -sralston
+	 *	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
+	 *	(single level) to multi level (e.g. "driver/message/fusion")
+	 *	something here needs to change.  -sralston
 	 */
 
 	ioc = mpt_adapter_find_first();
-	if (ioc != NULL) {
-		remove_proc_entry(MPT_PROCFS_SUMMARY_NODE, 0);
-	}
-
 	while (ioc != NULL) {
 		char pname[32];
 		int namelen;
+
+		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+
 		/*
 		 *  Tear down each "/proc/mpt/iocN" subdirectory.
 		 */
-		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
-		(void) sprintf(pname+namelen, "/summary");
-		remove_proc_entry(pname, 0);
-//#ifdef MPT_DEBUG
-		(void) sprintf(pname+namelen, "/dbg");
-		remove_proc_entry(pname, 0);
-//#endif
-		(void) sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
-		remove_proc_entry(pname, 0);
+		for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
+			(void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name);
+			remove_proc_entry(pname, NULL);
+		}
+
+		remove_proc_entry(ioc->name, mpt_proc_root_dir);
 
 		ioc = mpt_adapter_find_next(ioc);
 	}
 
-	if (atomic_read((atomic_t *)&procmpt_root_dir->count) == 0) {
-		remove_proc_entry(MPT_PROCFS_MPTBASEDIR, 0);
-		procmpt_root_dir = NULL;
+	for (ii=0; ii < MPT_PROC_ENTRIES; ii++)
+		remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir);
+
+	if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) {
+		remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
+		mpt_proc_root_dir = NULL;
 		return 0;
 	}
 
@@ -3016,23 +4580,23 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	procmpt_read_summary - Handle read request from /proc/mpt/summary
+/*
+ *	procmpt_summary_read - Handle read request from /proc/mpt/summary
  *	or from /proc/mpt/iocN/summary.
- *	@page: Pointer to area to write information
+ *	@buf: Pointer to area to write information
  *	@start: Pointer to start pointer
- *	@off: Offset to start writing
- *	@count: 
+ *	@offset: Offset to start writing
+ *	@request:
  *	@eof: Pointer to EOF integer
- *	@data: Pointer 
+ *	@data: Pointer
  *
- *	Returns numbers of characters written to process performing the read.
+ *	Returns number of characters written to process performing the read.
  */
 static int
-procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data)
+procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 {
 	MPT_ADAPTER *ioc;
-	char *out = page;
+	char *out = buf;
 	int len;
 
 	if (data == NULL)
@@ -3040,84 +4604,196 @@
 	else
 		ioc = data;
 
-// Too verbose!
-//	out += sprintf(out, "Attached Fusion MPT I/O Controllers:%s\n", ioc ? "" : " none");
-
 	while (ioc) {
 		int	more = 0;
 
-// Too verbose!
-//		mpt_print_ioc_facts(ioc, out, &more, 0);
 		mpt_print_ioc_summary(ioc, out, &more, 0, 1);
 
 		out += more;
-		if ((out-page) >= count) {
+		if ((out-buf) >= request) {
 			break;
 		}
 
 		if (data == NULL)
 			ioc = mpt_adapter_find_next(ioc);
 		else
-			ioc = NULL;				/* force exit for iocN */
+			ioc = NULL;		/* force exit for iocN */
 	}
-	len = out - page;
+	len = out - buf;
 
-	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
+	MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
 }
 
-// debug aid!
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	procmpt_read_dbg - Handle read request from /proc/mpt/iocN/dbg.
- *	@page: Pointer to area to write information
+/*
+ *	procmpt_version_read - Handle read request from /proc/mpt/version.
+ *	@buf: Pointer to area to write information
  *	@start: Pointer to start pointer
- *	@off: Offset to start writing
- *	@count: 
+ *	@offset: Offset to start writing
+ *	@request:
  *	@eof: Pointer to EOF integer
- *	@data: Pointer 
+ *	@data: Pointer
  *
- *	Returns numbers of characters written to process performing the read.
+ *	Returns number of characters written to process performing the read.
  */
 static int
-procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
+procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 {
-	MPT_ADAPTER *ioc;
-	char *out = page;
-	int len;
+	int	 ii;
+	int	 scsi, lan, ctl, targ, dmp;
+	char	*drvname;
+	int	 len;
+
+	len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
+	len += sprintf(buf+len, "  Fusion MPT base driver\n");
+
+	scsi = lan = ctl = targ = dmp = 0;
+	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+		drvname = NULL;
+		if (MptCallbacks[ii]) {
+			switch (MptDriverClass[ii]) {
+			case MPTSCSIH_DRIVER:
+				if (!scsi++) drvname = "SCSI host";
+				break;
+			case MPTLAN_DRIVER:
+				if (!lan++) drvname = "LAN";
+				break;
+			case MPTSTM_DRIVER:
+				if (!targ++) drvname = "SCSI target";
+				break;
+			case MPTCTL_DRIVER:
+				if (!ctl++) drvname = "ioctl";
+				break;
+			case MPTDMP_DRIVER:
+				if (!dmp++) drvname = "DMP";
+				break;
+			}
+
+			if (drvname)
+				len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
+			/*
+			 *	Handle isense special case, because it
+			 *	doesn't do a formal mpt_register call.
+			 */
+			if (isense_idx == ii)
+				len += sprintf(buf+len, "  Fusion MPT isense driver\n");
+		} else
+			break;
+	}
 
-	ioc = data;
+	MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
+}
 
-	while (ioc) {
-		int	more = 0;
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
+ *	@buf: Pointer to area to write information
+ *	@start: Pointer to start pointer
+ *	@offset: Offset to start writing
+ *	@request:
+ *	@eof: Pointer to EOF integer
+ *	@data: Pointer
+ *
+ *	Returns number of characters written to process performing the read.
+ */
+static int
+procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
+{
+	MPT_ADAPTER	*ioc = data;
+	int		 len;
+	char		 expVer[32];
+	int		 sz;
+	int		 p;
 
-		mpt_print_ioc_facts(ioc, out, &more, 0);
+	mpt_get_fw_exp_ver(expVer, ioc);
 
-		out += more;
-		if ((out-page) >= count) {
-			break;
+	len = sprintf(buf, "%s:", ioc->name);
+	if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
+		len += sprintf(buf+len, "  (f/w download boot flag set)");
+//	if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
+//		len += sprintf(buf+len, "  CONFIG_CHECKSUM_FAIL!");
+
+	len += sprintf(buf+len, "\n  ProductID = 0x%04x (%s)\n",
+			ioc->facts.ProductID,
+			ioc->prod_name);
+	len += sprintf(buf+len, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
+	if (ioc->facts.FWImageSize)
+		len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
+	len += sprintf(buf+len, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
+	len += sprintf(buf+len, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
+	len += sprintf(buf+len, "  EventState = 0x%02x\n", ioc->facts.EventState);
+
+	len += sprintf(buf+len, "  CurrentHostMfaHighAddr = 0x%08x\n",
+			ioc->facts.CurrentHostMfaHighAddr);
+	len += sprintf(buf+len, "  CurrentSenseBufferHighAddr = 0x%08x\n",
+			ioc->facts.CurrentSenseBufferHighAddr);
+
+	len += sprintf(buf+len, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
+	len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
+
+	len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
+					ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
+	/*
+	 *  Rounding UP to nearest 4-kB boundary here...
+	 */
+	sz = (ioc->req_sz * ioc->req_depth) + 128;
+	sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+	len += sprintf(buf+len, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
+					ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
+	len += sprintf(buf+len, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
+					4*ioc->facts.RequestFrameSize,
+					ioc->facts.GlobalCredits);
+
+	len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
+					ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
+	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+	len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
+					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
+	len += sprintf(buf+len, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
+					ioc->facts.CurReplyFrameSize,
+					ioc->facts.ReplyQueueDepth);
+
+	len += sprintf(buf+len, "  MaxDevices = %d\n",
+			(ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
+	len += sprintf(buf+len, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
+
+	/* per-port info */
+	for (p=0; p < ioc->facts.NumberOfPorts; p++) {
+		len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
+				p+1,
+				ioc->facts.NumberOfPorts);
+		if ((int)ioc->chip_type <= (int)FC929) {
+			if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+				u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
+				len += sprintf(buf+len, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+						a[5], a[4], a[3], a[2], a[1], a[0]);
+			}
+			len += sprintf(buf+len, "    WWN = %08X%08X:%08X%08X\n",
+					ioc->fc_port_page0[p].WWNN.High,
+					ioc->fc_port_page0[p].WWNN.Low,
+					ioc->fc_port_page0[p].WWPN.High,
+					ioc->fc_port_page0[p].WWPN.Low);
 		}
-		ioc = NULL;
 	}
-	len = out - page;
 
-	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
+	MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
 }
+
 #endif		/* CONFIG_PROC_FS } */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void
 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
 {
-	if ((ioc->facts.FWVersion & 0xF000) == 0xE000)
+	buf[0] ='\0';
+	if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
 		sprintf(buf, " (Exp %02d%02d)",
-			(ioc->facts.FWVersion & 0x0F00) >> 8,	/* Month */
-			ioc->facts.FWVersion & 0x001F);		/* Day */
-	else
-		buf[0] ='\0';
+			(ioc->facts.FWVersion.Word >> 16) & 0x00FF,	/* Month */
+			(ioc->facts.FWVersion.Word >> 8) & 0x1F);	/* Day */
 
-	/* insider hack! */
-	if (ioc->facts.FWVersion & 0x0080) {
-		strcat(buf, " [MDBG]");
+		/* insider hack! */
+		if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
+			strcat(buf, " [MDBG]");
 	}
 }
 
@@ -3130,8 +4806,8 @@
  *	@len: Offset at which to start writing in buffer
  *	@showlan: Display LAN stuff?
  *
- * 	This routine writes (english readable) ASCII text, which represents
- * 	a summary of IOC information, to a buffer.
+ *	This routine writes (english readable) ASCII text, which represents
+ *	a summary of IOC information, to a buffer.
  */
 void
 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
@@ -3144,11 +4820,11 @@
 	/*
 	 *  Shorter summary of attached ioc's...
 	 */
-	y = sprintf(buffer+len, "%s: %s, %s%04xh%s, Ports=%d, MaxQ=%d",
+	y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
 			ioc->name,
 			ioc->prod_name,
 			MPT_FW_REV_MAGIC_ID_STRING,	/* "FwRev=" or somesuch */
-			ioc->facts.FWVersion,
+			ioc->facts.FWVersion.Word,
 			expVer,
 			ioc->facts.NumberOfPorts,
 			ioc->req_depth);
@@ -3159,8 +4835,11 @@
 			a[5], a[4], a[3], a[2], a[1], a[0]);
 	}
 
-	if (ioc->pci_irq < 100)
-		y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
+#ifndef __sparc__
+	y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
+#else
+	y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
+#endif
 
 	if (!ioc->active)
 		y += sprintf(buffer+len+y, " (disabled)");
@@ -3171,75 +4850,66 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	Reset Handling
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_print_ioc_facts - Write ASCII summary of IOC facts to a buffer.
+ *	mpt_HardResetHandler - Generic reset handler, issue SCSI Task
+ *	Management call based on input arg values.  If TaskMgmt fails,
+ *	return associated SCSI request.
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	@buffer: Pointer to buffer where IOC facts should be written
- *	@size: Pointer to number of bytes we wrote (set by this routine)
- *	@len: Offset at which to start writing in buffer
+ *	@sleepFlag: Indicates if sleep or schedule must be called.
+ *
+ *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
+ *	or a non-interrupt thread.  In the former, must not call schedule().
  *
- * 	This routine writes (english readable) ASCII text, which represents
- * 	a summary of the IOC facts, to a buffer.
+ *	Remark: A return of -1 is a FATAL error case, as it means a
+ *	FW reload/initialization failed.
+ *
+ *	Returns 0 for SUCCESS or -1 if FAILED.
  */
-void
-mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buffer, int *size, int len)
+int
+mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 {
-	char expVer[32];
-	char iocName[16];
-	int sz;
-	int y;
-	int p;
-
-	mpt_get_fw_exp_ver(expVer, ioc);
+	int		 rc;
+	unsigned long	 flags;
 
-	strcpy(iocName, ioc->name);
-	y = sprintf(buffer+len, "%s:\n", iocName);
+	dprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
+#ifdef MFCNT
+	printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
+	printk("MF count 0x%x !\n", ioc->mfcnt);
+#endif
 
-	y += sprintf(buffer+len+y, "  ProductID = 0x%04x\n", ioc->facts.ProductID);
-	for (p=0; p < ioc->facts.NumberOfPorts; p++) {
-		y += sprintf(buffer+len+y, "  PortNumber = %d (of %d)\n",
-			p+1,
-			ioc->facts.NumberOfPorts);
-		if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
-			u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
-			y += sprintf(buffer+len+y, "  LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-				a[5], a[4], a[3], a[2], a[1], a[0]);
-		}
-	}
-	y += sprintf(buffer+len+y, "  FWVersion = 0x%04x%s\n", ioc->facts.FWVersion, expVer);
-	y += sprintf(buffer+len+y, "  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
-	y += sprintf(buffer+len+y, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
-	y += sprintf(buffer+len+y, "  EventState = 0x%02x\n", ioc->facts.EventState);
-	y += sprintf(buffer+len+y, "  CurrentHostMfaHighAddr = 0x%08x\n",
-		 	ioc->facts.CurrentHostMfaHighAddr);
-	y += sprintf(buffer+len+y, "  CurrentSenseBufferHighAddr = 0x%08x\n",
-			ioc->facts.CurrentSenseBufferHighAddr);
-	y += sprintf(buffer+len+y, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
-	y += sprintf(buffer+len+y, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
+	/* Reset the adapter. Prevent more than 1 call to
+	 * mpt_do_ioc_recovery at any instant in time.
+	 */
+	spin_lock_irqsave(&ioc->diagLock, flags);
+	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
+		spin_unlock_irqrestore(&ioc->diagLock, flags);
+		return 0;
+	} else {
+		ioc->diagPending = 1;
+	}
+	spin_unlock_irqrestore(&ioc->diagLock, flags);
 
-	y += sprintf(buffer+len+y, "  RequestFrames @ 0x%p (Dma @ 0x%08x)\n",
-					ioc->req_alloc, ioc->req_alloc_dma);
-	/*
-	 *  Rounding UP to nearest 4-kB boundary here...
+	/* FIXME: If do_ioc_recovery fails, repeat....
 	 */
-	sz = (ioc->req_sz * ioc->req_depth) + 128;
-	sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
-	y += sprintf(buffer+len+y, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
-					ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
-	y += sprintf(buffer+len+y, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
-					4*ioc->facts.RequestFrameSize,
-					ioc->facts.GlobalCredits);
 
-	y += sprintf(buffer+len+y, "  ReplyFrames   @ 0x%p (Dma @ 0x%08x)\n",
-					ioc->reply_alloc, ioc->reply_alloc_dma);
-	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
-	y += sprintf(buffer+len+y, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
-					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
-	y += sprintf(buffer+len+y, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
-					ioc->facts.CurReplyFrameSize,
-					ioc->facts.ReplyQueueDepth);
+	if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
+		printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
+			rc, ioc->name);
+	}
 
-	*size = y;
+	spin_lock_irqsave(&ioc->diagLock, flags);
+	ioc->diagPending = 0;
+	if (ioc->alt_ioc)
+		ioc->alt_ioc->diagPending = 0;
+	spin_unlock_irqrestore(&ioc->diagLock, flags);
+
+	dprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
+
+	return rc;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3268,7 +4938,7 @@
 		ds = "External Bus Reset";
 		break;
 	case MPI_EVENT_RESCAN:
-		ds = "Bus Rescan Event"; 
+		ds = "Bus Rescan Event";
 		/* Ok, do we need to do anything here? As far as
 		   I can tell, this is when a new device gets added
 		   to the loop. */
@@ -3296,6 +4966,9 @@
 		else
 			ds = "Events(OFF) Change";
 		break;
+	case MPI_EVENT_INTEGRATED_RAID:
+		ds = "Integrated Raid";
+		break;
 	/*
 	 *  MPT base "custom" events may be added here...
 	 */
@@ -3307,7 +4980,7 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	ProcessEventNotification - Route a received EventNotificationReply to
  *	all currently regeistered event handlers.
  *	@ioc: Pointer to MPT_ADAPTER structure
@@ -3322,7 +4995,7 @@
 	u16 evDataLen;
 	u32 evData0 = 0;
 //	u32 evCtx;
-	int i;
+	int ii;
 	int r = 0;
 	int handlers = 0;
 	char *evStr;
@@ -3339,15 +5012,15 @@
 	}
 
 	evStr = EventDescriptionStr(event, evData0);
-	dprintk((KERN_INFO MYNAM ": %s: MPT event (%s=%02Xh) detected!\n",
+	dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
 			ioc->name,
 			evStr,
 			event));
 
 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
 	printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
-	for (i = 0; i < evDataLen; i++)
-		printk(" %08x", le32_to_cpu(pEventReply->Data[i]));
+	for (ii = 0; ii < evDataLen; ii++)
+		printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
 	printk("\n");
 #endif
 
@@ -3365,6 +5038,8 @@
 	case MPI_EVENT_LINK_STATUS_CHANGE:	/* 07 */
 	case MPI_EVENT_LOOP_STATE_CHANGE:	/* 08 */
 	case MPI_EVENT_LOGOUT:			/* 09 */
+	case MPI_EVENT_INTEGRATED_RAID:		/* 0B */
+	case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:	/* 0C */
 	default:
 		break;
 	case MPI_EVENT_EVENT_CHANGE:		/* 0A */
@@ -3382,13 +5057,36 @@
 	}
 
 	/*
+	 * Should this event be logged? Events are written sequentially.
+	 * When buffer is full, start again at the top.
+	 */
+	if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
+		int idx;
+
+		idx = ioc->eventContext % ioc->eventLogSize;
+
+		ioc->events[idx].event = event;
+		ioc->events[idx].eventContext = ioc->eventContext;
+
+		for (ii = 0; ii < 2; ii++) {
+			if (ii < evDataLen)
+				ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
+			else
+				ioc->events[idx].data[ii] =  0;
+		}
+
+		ioc->eventContext++;
+	}
+
+
+	/*
 	 *  Call each currently registered protocol event handler.
 	 */
-	for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
-		if (MptEvHandlers[i]) {
-			dprintk((KERN_INFO MYNAM ": %s: Routing Event to event handler #%d\n",
-					ioc->name, i));
-			r += (*(MptEvHandlers[i]))(ioc, pEventReply);
+	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+		if (MptEvHandlers[ii]) {
+			dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+					ioc->name, ii));
+			r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
 			handlers++;
 		}
 	}
@@ -3398,7 +5096,9 @@
 	 *  If needed, send (a single) EventAck.
 	 */
 	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
-		if ((i = SendEventAck(ioc, pEventReply)) != 0) {
+		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
+			printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+					ioc->name, ii);
 		}
 	}
 
@@ -3427,7 +5127,7 @@
 
 	switch(log_info) {
 /* FCP Initiator */
-    	case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
 		desc = "Received an out of order frame - unsupported";
 		break;
 	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME:
@@ -3483,7 +5183,7 @@
 		desc = "Not sent because login to remote node not validated";
 		break;
 	case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND:
-		desc = "Cleared from the outbound after a logout";
+		desc = "Cleared from the outbound queue after a logout";
 		break;
 	case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN:
 		desc = "Cleared waiting for data after a logout";
@@ -3516,7 +5216,7 @@
 		break;
 	}
 
-	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x): SubCl={%s}",
+	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
 			ioc->name, log_info, subcl_str[subcl]);
 	if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET)
 		printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET);
@@ -3539,7 +5239,7 @@
 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
 	/* FIXME! */
-	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x)\n", ioc->name, log_info);
+	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x)\n", ioc->name, log_info);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3553,7 +5253,7 @@
  *	Specialized driver registration routine for the isense driver.
  */
 int
-mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable)
+mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
 {
 	int r = 0;
 
@@ -3562,6 +5262,7 @@
 		mpt_ASCQ_TableSz = ascqtbl_sz;
 		mpt_ScsiOpcodesPtr = opsTable;
 		printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
+		isense_idx = last_drv_idx;
 		r = 1;
 	}
 	MOD_INC_USE_COUNT;
@@ -3582,11 +5283,15 @@
 	mpt_ASCQ_TableSz = 0;
 	mpt_ScsiOpcodesPtr = NULL;
 	printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
+	isense_idx = -1;
 	MOD_DEC_USE_COUNT;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+EXPORT_SYMBOL(mpt_adapters);
+EXPORT_SYMBOL(mpt_proc_root_dir);
+EXPORT_SYMBOL(DmpService);
 EXPORT_SYMBOL(mpt_register);
 EXPORT_SYMBOL(mpt_deregister);
 EXPORT_SYMBOL(mpt_event_register);
@@ -3597,12 +5302,16 @@
 EXPORT_SYMBOL(mpt_put_msg_frame);
 EXPORT_SYMBOL(mpt_free_msg_frame);
 EXPORT_SYMBOL(mpt_send_handshake_request);
+EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
 EXPORT_SYMBOL(mpt_adapter_find_first);
 EXPORT_SYMBOL(mpt_adapter_find_next);
 EXPORT_SYMBOL(mpt_verify_adapter);
+EXPORT_SYMBOL(mpt_GetIocState);
 EXPORT_SYMBOL(mpt_print_ioc_summary);
 EXPORT_SYMBOL(mpt_lan_index);
 EXPORT_SYMBOL(mpt_stm_index);
+EXPORT_SYMBOL(mpt_HardResetHandler);
+EXPORT_SYMBOL(mpt_config);
 
 EXPORT_SYMBOL(mpt_register_ascqops_strings);
 EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
@@ -3611,12 +5320,13 @@
 EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	fusion_init - Fusion MPT base driver initialization routine.
  *
  *	Returns 0 for success, non-zero for failure.
  */
-int __init fusion_init(void)
+int __init
+fusion_init(void)
 {
 	int i;
 
@@ -3636,12 +5346,22 @@
 		MptResetHandlers[i] = NULL;
 	}
 
+	DmpService = NULL;
+
 	/* NEW!  20010120 -sralston
 	 *  Register ourselves (mptbase) in order to facilitate
 	 *  EventNotification handling.
 	 */
 	mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
 
+	/* Register for hard reset handling callbacks.
+	 */
+	if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
+		dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
+	} else {
+		/* FIXME! */
+	}
+
 	if ((i = mpt_pci_scan()) < 0)
 		return i;
 
@@ -3649,13 +5369,14 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	fusion_exit - Perform driver unload cleanup.
  *
  *	This routine frees all resources associated with each MPT adapter
  *	and removes all %MPT_PROCFS_MPTBASEDIR entries.
  */
-static void fusion_exit(void)
+static void
+fusion_exit(void)
 {
 	MPT_ADAPTER *this;
 
@@ -3665,7 +5386,7 @@
 	 *  Moved this *above* removal of all MptAdapters!
 	 */
 #ifdef CONFIG_PROC_FS
-	procmpt_destroy();
+	(void) procmpt_destroy();
 #endif
 
 	while (! Q_IS_EMPTY(&MptAdapters)) {
@@ -3673,6 +5394,8 @@
 		Q_DEL_ITEM(this);
 		mpt_adapter_dispose(this);
 	}
+
+	mpt_reset_deregister(mpt_base_index);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

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