Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / message / fusion / mptbase.c
index fba96eb..79718c1 100644 (file)
@@ -1,55 +1,13 @@
 /*
  *  linux/drivers/message/fusion/mptbase.c
- *      High performance SCSI + LAN / Fibre Channel device drivers.
  *      This is the Fusion MPT base driver which supports multiple
  *      (SCSI + LAN) specialized protocol drivers.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      There are lots of people not mentioned below that deserve credit
- *      and thanks but won't get it here - sorry in advance that you
- *      got overlooked.
- *
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A special thanks to Noah Romer (LSI Logic) for tons of work
- *      and tough debugging on the LAN driver, especially early on;-)
- *      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,
- *      being a faithful sounding board on all sorts of issues & ideas,
- *      etc.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      Special thanks goes to the I2O LAN driver people at the
- *      University of Helsinki, who, unbeknownst to them, provided
- *      the inspiration and initial structure for this driver.
- *
- *      A really huge debt of gratitude is owed to Eddie C. Dost
- *      for gobs of hard work fixing and optimizing LAN code.
- *      THANK YOU!
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -89,7 +47,6 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>           /* needed for in_interrupt() proto */
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(MPT_LINUX_VERSION_COMMON);
 
 /*
  *  cmd line parameters
  */
+static int mpt_msi_enable;
+module_param(mpt_msi_enable, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
 #ifdef MFCNT
 static int mfcounter = 0;
 #define PRINT_MF_COUNT 20000
@@ -137,22 +100,14 @@ 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;
-
-
 #define WHOINIT_UNKNOWN                0xAA
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Private data...
  */
-                                       /* Adapter lookup table */
-       MPT_ADAPTER             *mpt_adapters[MPT_MAX_ADAPTERS];
-static MPT_ADAPTER_TRACKER      MptAdapters;
+                                       /* Adapter link list */
+LIST_HEAD(ioc_list);
                                        /* Callback lookup table */
 static MPT_CALLBACK             MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
                                        /* Protocol driver class lookup table */
@@ -163,10 +118,8 @@ static MPT_EVHANDLER                MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static MPT_RESETHANDLER                 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static struct mpt_pci_driver   *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 
-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);
 
@@ -176,21 +129,22 @@ static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
  */
 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
 static int     mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
-
+static int     mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
+                       u32 *req, int replyBytes, u16 *u16reply, int maxwait,
+                       int sleepFlag);
 static int     mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
-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_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+static void    mpt_adapter_disable(MPT_ADAPTER *ioc);
 static void    mpt_adapter_dispose(MPT_ADAPTER *ioc);
 
 static void    MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
 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_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
 static int     mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 static int     KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 static int     SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
@@ -199,8 +153,8 @@ 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);
+int            mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 static int     mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
 static int     mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
 static void    mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
@@ -208,10 +162,10 @@ static void       mpt_read_ioc_pg_4(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     mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
+static int     mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
 
 #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,
@@ -225,67 +179,177 @@ static void      mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
 static int     ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
 static void    mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
 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 void    mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void    mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static int     mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 
 /* module entry point */
-static int  __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit mptbase_remove(struct pci_dev *);
-static void mptbase_shutdown(struct device * );
 static int  __init    fusion_init  (void);
 static void __exit    fusion_exit  (void);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define CHIPREG_READ32(addr)           readl_relaxed(addr)
+#define CHIPREG_READ32_dmasync(addr)   readl(addr)
+#define CHIPREG_WRITE32(addr,val)      writel(val, addr)
+#define CHIPREG_PIO_WRITE32(addr,val)  outl(val, (unsigned long)addr)
+#define CHIPREG_PIO_READ32(addr)       inl((unsigned long)addr)
+
+static void
+pci_disable_io_access(struct pci_dev *pdev)
+{
+       u16 command_reg;
+
+       pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+       command_reg &= ~1;
+       pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
+static void
+pci_enable_io_access(struct pci_dev *pdev)
+{
+       u16 command_reg;
+
+       pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+       command_reg |= 1;
+       pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
 /*
- *  more Private data...
+ *  Process turbo (context) reply...
  */
-#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]))
+static void
+mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+       MPT_FRAME_HDR *mf = NULL;
+       MPT_FRAME_HDR *mr = NULL;
+       int req_idx = 0;
+       int cb_idx;
+
+       dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+                               ioc->name, pa));
+
+       switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+       case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
+               req_idx = pa & 0x0000FFFF;
+               cb_idx = (pa & 0x00FF0000) >> 16;
+               mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+               break;
+       case MPI_CONTEXT_REPLY_TYPE_LAN:
+               cb_idx = mpt_lan_index;
+               /*
+                *  Blind set of mf to NULL here was fatal
+                *  after lan_reply says "freeme"
+                *  Fix sort of combined with an optimization here;
+                *  added explicit check for case where lan_reply
+                *  was just returning 1 and doing nothing else.
+                *  For this case skip the callback, but set up
+                *  proper mf value first here:-)
+                */
+               if ((pa & 0x58000000) == 0x58000000) {
+                       req_idx = pa & 0x0000FFFF;
+                       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+                       mpt_free_msg_frame(ioc, mf);
+                       mb();
+                       return;
+                       break;
+               }
+               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+               break;
+       case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
+               cb_idx = mpt_stm_index;
+               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+               break;
+       default:
+               cb_idx = 0;
+               BUG();
+       }
 
-#endif
+       /*  Check for (valid) IO callback!  */
+       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+                       MptCallbacks[cb_idx] == NULL) {
+               printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+                               __FUNCTION__, ioc->name, cb_idx);
+               goto out;
+       }
 
-/****************************************************************************
- * Supported hardware
- */
+       if (MptCallbacks[cb_idx](ioc, mf, mr))
+               mpt_free_msg_frame(ioc, mf);
+ out:
+       mb();
+}
 
-static struct pci_device_id mptbase_pci_table[] = {
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
-               PCI_ANY_ID, PCI_ANY_ID },
-       {0}     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
+static void
+mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+       MPT_FRAME_HDR   *mf;
+       MPT_FRAME_HDR   *mr;
+       int              req_idx;
+       int              cb_idx;
+       int              freeme;
 
-#define CHIPREG_READ32(addr)           readl(addr)
-#define CHIPREG_WRITE32(addr,val)      writel(val, addr)
-#define CHIPREG_PIO_WRITE32(addr,val)  outl(val, (unsigned long)addr)
-#define CHIPREG_PIO_READ32(addr)       inl((unsigned long)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)!
+        */
+
+       /* 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 <<= 1);
+       mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
+                        (reply_dma_low - ioc->reply_frames_low_dma));
+
+       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);
+
+       dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+                       ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
+       DBG_DUMP_REPLY_FRAME(mr)
+
+        /*  Check/log IOC log info
+        */
+       ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+       if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+               u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+               if (ioc->bus_type == FC)
+                       mpt_fc_log_info(ioc, log_info);
+               else if (ioc->bus_type == SPI)
+                       mpt_spi_log_info(ioc, log_info);
+               else if (ioc->bus_type == SAS)
+                       mpt_sas_log_info(ioc, log_info);
+       }
+       if (ioc_stat & MPI_IOCSTATUS_MASK) {
+               if (ioc->bus_type == SPI &&
+                   cb_idx != mpt_stm_index &&
+                   cb_idx != mpt_lan_index)
+                       mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
+       }
+
+
+       /*  Check for (valid) IO callback!  */
+       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+                       MptCallbacks[cb_idx] == NULL) {
+               printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+                               __FUNCTION__, ioc->name, cb_idx);
+               freeme = 0;
+               goto out;
+       }
+
+       freeme = MptCallbacks[cb_idx](ioc, mf, mr);
+
+ out:
+       /*  Flush (non-TURBO) reply with a WRITE!  */
+       CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+
+       if (freeme)
+               mpt_free_msg_frame(ioc, mf);
+       mb();
+}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -299,8 +363,7 @@ MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
  *     (also referred to as a IO Controller or IOC).
  *     This routine must clear the interrupt from the adapter and does
  *     so by reading the reply FIFO.  Multiple replies may be processed
- *     per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
- *     which is currently set to 32 in mptbase.h.
+ *     per single call to this routine.
  *
  *     This routine handles register-level access of the adapter but
  *     dispatches (calls) a protocol-specific callback routine to handle
@@ -309,193 +372,21 @@ MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
 static irqreturn_t
 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
 {
-       MPT_ADAPTER     *ioc;
-       MPT_FRAME_HDR   *mf;
-       MPT_FRAME_HDR   *mr;
-       u32              pa;
-       int              req_idx;
-       int              cb_idx;
-       int              type;
-       int              freeme;
-
-       ioc = bus_id;
-
-#ifdef MPT_DEBUG_IRQ
-       /*
-        * 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 IRQ_NONE;
-               }
-       }
-#endif
+       MPT_ADAPTER *ioc = bus_id;
+       u32 pa;
 
        /*
         *  Drain the reply FIFO!
-        *
-        * NOTES: I've seen up to 10 replies processed in this loop, so far...
-        * Update: I've seen up to 9182 replies processed in this loop! ??
-        * Update: Limit ourselves to processing max of N replies
-        *      (bottom of loop).
         */
        while (1) {
-
-               if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
+               pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+               if (pa == 0xFFFFFFFF)
                        return IRQ_HANDLED;
-
-               cb_idx = 0;
-               freeme = 0;
-
-               /*
-                *  Check for non-TURBO reply!
-                */
-               if (pa & MPI_ADDRESS_REPLY_A_BIT) {
-                       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)!
-                        */
-
-                       /* 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));
-
-                       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((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
-                                       ioc->name, mr));
-                       DBG_DUMP_REPLY_FRAME(mr)
-
-                       /* NEW!  20010301 -sralston
-                        *  Check/log IOC log info
-                        */
-                       ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
-                       if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
-                               u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
-                               if ((int)ioc->chip_type <= (int)FC929)
-                                       mpt_fc_log_info(ioc, log_info);
-                               else
-                                       mpt_sp_log_info(ioc, log_info);
-                       }
-                       if (ioc_stat & MPI_IOCSTATUS_MASK) {
-                               if ((int)ioc->chip_type <= (int)FC929)
-                                               ;
-                               else
-                                       mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
-                       }
-               } else {
-                       /*
-                        *  Process turbo (context) reply...
-                        */
-                       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;
-                               mf = NULL;
-                               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
-                       } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
-                               cb_idx = mpt_lan_index;
-                               /*
-                                * BUG FIX!  20001218 -sralston
-                                *  Blind set of mf to NULL here was fatal
-                                *  after lan_reply says "freeme"
-                                *  Fix sort of combined with an optimization here;
-                                *  added explicit check for case where lan_reply
-                                *  was just returning 1 and doing nothing else.
-                                *  For this case skip the callback, but set up
-                                *  proper mf value first here:-)
-                                */
-                               if ((pa & 0x58000000) == 0x58000000) {
-                                       req_idx = pa & 0x0000FFFF;
-                                       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-                                       freeme = 1;
-                                       /*
-                                        *  IMPORTANT!  Invalidate the callback!
-                                        */
-                                       cb_idx = 0;
-                               } else {
-                                       mf = NULL;
-                               }
-                               mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
-                       } else {
-                               req_idx = pa & 0x0000FFFF;
-                               cb_idx = (pa & 0x00FF0000) >> 16;
-                               mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-                               mr = NULL;
-                       }
-                       pa = 0;                                 /* No reply flush! */
-               }
-
-#ifdef MPT_DEBUG_IRQ
-               if ((int)ioc->chip_type > (int)FC929) {
-                       /* Verify mf, mr 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, (void *)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, (void *)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;
-                       }
-               }
-#endif
-
-               /*  Check for (valid) IO callback!  */
-               if (cb_idx) {
-                       /*  Do the callback!  */
-                       freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
-               }
-
-               if (pa) {
-                       /*  Flush (non-TURBO) reply with a WRITE!  */
-                       CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
-               }
-
-               if (freeme) {
-                       unsigned long flags;
-
-                       /*  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);
-               }
-
-               mb();
-       }       /* drain reply FIFO */
+               else if (pa & MPI_ADDRESS_REPLY_A_BIT)
+                       mpt_reply(ioc, pa);
+               else
+                       mpt_turbo_reply(ioc, pa);
+       }
 
        return IRQ_HANDLED;
 }
@@ -509,7 +400,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
  *     @mf: Pointer to original MPT request frame
  *     @reply: Pointer to MPT reply frame (NULL if TurboReply)
  *
      *       Returns 1 indicating original alloc'd request frame ptr
*     Returns 1 indicating original alloc'd request frame ptr
  *     should be freed, or 0 if it shouldn't.
  */
 static int
@@ -518,28 +409,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
        int freereq = 1;
        u8 func;
 
-       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(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
-                               ioc->name, (void *)mf);
-               return 1;
-       }
-
-       if (reply == NULL) {
-               dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
-                               ioc->name));
-               return 1;
-       }
+       dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
 
+#if defined(MPT_DEBUG_MSG_FRAME)
        if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
                dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
                DBG_DUMP_REQUEST_FRAME_HDR(mf)
        }
+#endif
 
        func = reply->u.hdr.Function;
-       dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
+       dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
                        ioc->name, func));
 
        if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
@@ -550,7 +430,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
                if (results != evHandlers) {
                        /* CHECKME! Any special handling needed here? */
-                       dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+                       devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
                                        ioc->name, evHandlers, results));
                }
 
@@ -558,8 +438,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                 *      Hmmm...  It seems that EventNotificationReply is an exception
                 *      to the rule of one reply per request.
                 */
-               if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+               if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
                        freereq = 0;
+                       devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+                               ioc->name, pEvReply));
+               } else {
+                       devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+                               ioc->name, pEvReply));
+               }
 
 #ifdef CONFIG_PROC_FS
 //             LogEvent(ioc, pEvReply);
@@ -568,8 +454,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
        } else if (func == MPI_FUNCTION_EVENT_ACK) {
                dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
                                ioc->name));
-       } else if (func == MPI_FUNCTION_CONFIG ||
-                  func == MPI_FUNCTION_TOOLBOX) {
+       } else if (func == MPI_FUNCTION_CONFIG) {
                CONFIGPARMS *pCfg;
                unsigned long flags;
 
@@ -583,7 +468,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                        del_timer(&pCfg->timer);
 
                        spin_lock_irqsave(&ioc->FreeQlock, flags);
-                       Q_DEL_ITEM(&pCfg->linkage);
+                       list_del(&pCfg->linkage);
                        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
                        /*
@@ -601,10 +486,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 
                                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;
+                                       if ((pReply->Header.PageType &
+                                           MPI_CONFIG_PAGETYPE_MASK) ==
+                                           MPI_CONFIG_PAGETYPE_EXTENDED) {
+                                               pCfg->cfghdr.ehdr->ExtPageLength =
+                                                   le16_to_cpu(pReply->ExtPageLength);
+                                               pCfg->cfghdr.ehdr->ExtPageType =
+                                                   pReply->ExtPageType;
+                                       }
+                                       pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+
+                                       /* If this is a regular header, save PageLength. */
+                                       /* LMP Do this better so not using a reserved field! */
+                                       pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+                                       pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+                                       pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
                                }
                        }
 
@@ -614,6 +510,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                        pCfg->wait_done = 1;
                        wake_up(&mpt_waitq);
                }
+       } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+               /* we should be always getting a reply frame */
+               memcpy(ioc->persist_reply_frame, reply,
+                   min(MPT_DEFAULT_FRAME_SIZE,
+                   4*reply->u.reply.MsgLength));
+               del_timer(&ioc->persist_timer);
+               ioc->persist_wait_done = 1;
+               wake_up(&mpt_waitq);
        } else {
                printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
                                ioc->name, func);
@@ -653,22 +557,6 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
 
        last_drv_idx = -1;
 
-#ifndef MODULE
-       /*
-        *  Handle possibility of the mptscsih_detect() routine getting
-        *  called *before* fusion_init!
-        */
-       if (!FusionInitCalled) {
-               dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
-               /*
-                *  NOTE! We'll get recursion here, as fusion_init()
-                *  calls mpt_register()!
-                */
-               fusion_init();
-               FusionInitCalled++;
-       }
-#endif
-
        /*
         *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
         *  (slot/handle 0 is reserved!)
@@ -703,8 +591,6 @@ mpt_deregister(int cb_idx)
                MptEvHandlers[cb_idx] = NULL;
 
                last_drv_idx++;
-               if (isense_idx != -1 && isense_idx <= cb_idx)
-                       isense_idx++;
        }
 }
 
@@ -796,27 +682,22 @@ int
 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
 {
        MPT_ADAPTER     *ioc;
-       int             error=0;
 
        if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
-               error= -EINVAL;
-               return error;
+               return -EINVAL;
        }
 
        MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
 
        /* call per pci device probe entry point */
-       for(ioc = mpt_adapter_find_first(); ioc != NULL;
-         ioc = mpt_adapter_find_next(ioc)) {
+       list_for_each_entry(ioc, &ioc_list, list) {
                if(dd_cbfunc->probe) {
-                       error = dd_cbfunc->probe(ioc->pcidev,
+                       dd_cbfunc->probe(ioc->pcidev,
                          ioc->pcidev->driver->id_table);
-                       if(error != 0)
-                               return error;
                }
         }
 
-       return error;
+       return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -826,9 +707,19 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
 void
 mpt_device_driver_deregister(int cb_idx)
 {
+       struct mpt_pci_driver *dd_cbfunc;
+       MPT_ADAPTER     *ioc;
+
        if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return;
 
+       dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
+
+       list_for_each_entry(ioc, &ioc_list, list) {
+               if (dd_cbfunc->remove)
+                       dd_cbfunc->remove(ioc->pcidev);
+       }
+
        MptDeviceDriverHandlers[cb_idx] = NULL;
 }
 
@@ -838,60 +729,62 @@ mpt_device_driver_deregister(int cb_idx)
  *     mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
  *     allocated per MPT adapter.
  *     @handle: Handle of registered MPT protocol driver
- *     @iocid: IOC unique identifier (integer)
+ *     @ioc: Pointer to MPT adapter structure
  *
  *     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)
+mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 {
        MPT_FRAME_HDR *mf;
-       MPT_ADAPTER *iocp;
        unsigned long flags;
+       u16      req_idx;       /* Request index */
 
        /* validate handle and ioc identifier */
-       iocp = mpt_adapters[iocid];
 
 #ifdef MFCNT
-       if (!iocp->active)
+       if (!ioc->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)
+       if (!ioc->active)
                return NULL;
 
-       spin_lock_irqsave(&iocp->FreeQlock, flags);
-       if (! Q_IS_EMPTY(&iocp->FreeQ)) {
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+       if (!list_empty(&ioc->FreeQ)) {
                int req_offset;
 
-               mf = iocp->FreeQ.head;
-               Q_DEL_ITEM(&mf->u.frame.linkage);
+               mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
+                               u.frame.linkage.list);
+               list_del(&mf->u.frame.linkage.list);
+               mf->u.frame.linkage.arg1 = 0;
                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
-               req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+               req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
                                                                /* u16! */
-               mf->u.frame.hwhdr.msgctxu.fld.req_idx =
-                               cpu_to_le16(req_offset / iocp->req_sz);
+               req_idx = req_offset / ioc->req_sz;
+               mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
                mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+               ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
 #ifdef MFCNT
-               iocp->mfcnt++;
+               ioc->mfcnt++;
 #endif
        }
        else
                mf = NULL;
-       spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+       spin_unlock_irqrestore(&ioc->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);
+               printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
        mfcounter++;
        if (mfcounter == PRINT_MF_COUNT)
-               printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
+               printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
 #endif
 
        dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
-                       iocp->name, handle, iocid, mf));
+                       ioc->name, handle, ioc->id, mf));
        return mf;
 }
 
@@ -900,83 +793,74 @@ mpt_get_msg_frame(int handle, int iocid)
  *     mpt_put_msg_frame - Send a protocol specific MPT request frame
  *     to a IOC.
  *     @handle: Handle of registered MPT protocol driver
- *     @iocid: IOC unique identifier (integer)
+ *     @ioc: Pointer to MPT adapter structure
  *     @mf: Pointer to MPT request frame
  *
  *     This routine posts a MPT request frame to the request post FIFO of a
  *     specific MPT adapter.
  */
 void
-mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
-       MPT_ADAPTER *iocp;
+       u32 mf_dma_addr;
+       int req_offset;
+       u16      req_idx;       /* Request index */
 
-       iocp = mpt_adapters[iocid];
-       if (iocp != NULL) {
-               u32 mf_dma_addr;
-               int req_offset;
-
-               /* ensure values are reset properly! */
-               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;          /* byte */
-               req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
-                                                                       /* u16! */
-               mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
-               mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+       /* ensure values are reset properly! */
+       mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;          /* byte */
+       req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
+                                                               /* u16! */
+       req_idx = req_offset / ioc->req_sz;
+       mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
+       mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 
 #ifdef MPT_DEBUG_MSG_FRAME
-               {
-                       u32     *m = mf->u.frame.hwhdr.__hdr;
-                       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 (ii=0; ii<=n; ii++) {
-                               if (ii && ((ii%8)==0))
-                                       printk("\n" KERN_INFO " ");
-                               printk(" %08x", le32_to_cpu(m[ii]));
-                       }
-                       printk("\n");
+       {
+               u32     *m = mf->u.frame.hwhdr.__hdr;
+               int      ii, n;
+
+               printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
+                               ioc->name, m);
+               n = ioc->req_sz/4 - 1;
+               while (m[n] == 0)
+                       n--;
+               for (ii=0; ii<=n; ii++) {
+                       if (ii && ((ii%8)==0))
+                               printk("\n" KERN_INFO " ");
+                       printk(" %08x", le32_to_cpu(m[ii]));
                }
-#endif
-
-               mf_dma_addr = iocp->req_frames_low_dma + req_offset;
-               CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
-       } else {
-               printk (KERN_ERR
-                   "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);
+               printk("\n");
        }
+#endif
 
+       mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
+       dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
+       CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_free_msg_frame - Place MPT request frame back on FreeQ.
  *     @handle: Handle of registered MPT protocol driver
- *     @iocid: IOC unique identifier (integer)
+ *     @ioc: Pointer to MPT adapter structure
  *     @mf: Pointer to MPT request frame
  *
  *     This routine places a MPT request frame back on the MPT adapter's
  *     FreeQ.
  */
 void
-mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
-       MPT_ADAPTER *iocp;
        unsigned long flags;
 
-       iocp = mpt_adapters[iocid];
-       if (iocp != NULL) {
-               /*  Put Request back on FreeQ!  */
-               spin_lock_irqsave(&iocp->FreeQlock, flags);
-               Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+       /*  Put Request back on FreeQ!  */
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+       mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
+       list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
 #ifdef MFCNT
-               iocp->mfcnt--;
+       ioc->mfcnt--;
 #endif
-               spin_unlock_irqrestore(&iocp->FreeQlock, flags);
-       }
+       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1008,47 +892,12 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
        }
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mpt_add_chain - Place a chain SGE at address pAddr.
- *     @pAddr: virtual address for SGE
- *     @next: nextChainOffset value (u32's)
- *     @length: length of next SGL segment
- *     @dma_addr: Physical address
- *
- *     This routine places a MPT request frame back on the MPT adapter's
- *     FreeQ.
- */
-void
-mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
-{
-       if (sizeof(dma_addr_t) == sizeof(u64)) {
-               SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
-               u32 tmp = dma_addr & 0xFFFFFFFF;
-
-               pChain->Length = cpu_to_le16(length);
-               pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
-
-               pChain->NextChainOffset = next;
-
-               pChain->Address.Low = cpu_to_le32(tmp);
-               tmp = (u32) ((u64)dma_addr >> 32);
-               pChain->Address.High = cpu_to_le32(tmp);
-       } else {
-               SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
-               pChain->Length = cpu_to_le16(length);
-               pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
-               pChain->NextChainOffset = next;
-               pChain->Address = cpu_to_le32(dma_addr);
-       }
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_send_handshake_request - Send MPT request via doorbell
  *     handshake method.
  *     @handle: Handle of registered MPT protocol driver
- *     @iocid: IOC unique identifier (integer)
+ *     @ioc: Pointer to MPT adapter structure
  *     @reqBytes: Size of the request in bytes
  *     @req: Pointer to MPT request frame
  *     @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
@@ -1062,126 +911,191 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
  *     Returns 0 for success, non-zero for failure.
  */
 int
-mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag)
+mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
-       MPT_ADAPTER     *iocp;
        int              r = 0;
+       u8      *req_as_bytes;
+       int      ii;
 
-       iocp = mpt_adapters[iocid];
-       if (iocp != NULL) {
-               u8      *req_as_bytes;
-               int      ii;
+       /* State is known to be good upon entering
+        * this function so issue the bus reset
+        * request.
+        */
 
-               /* 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...
+        */
+       ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+       if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
+               MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
+               mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
+               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+       }
 
-               /*
-                * 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...
-                */
-               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(ii);
-                       mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
-               }
+       /* Make sure there are no doorbells */
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-               /* Make sure there are no doorbells */
-               CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+       CHIPREG_WRITE32(&ioc->chip->Doorbell,
+                       ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
+                        ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
 
-               CHIPREG_WRITE32(&iocp->chip->Doorbell,
-                               ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
-                                ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+       /* Wait for IOC doorbell int */
+       if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
+               return ii;
+       }
 
-               /* Wait for IOC doorbell int */
-               if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {
-                       return ii;
-               }
+       /* Read doorbell and check for active bit */
+       if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+               return -5;
 
-               /* 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",
+               ioc->name, ii));
 
-               dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
-                               iocp->name, ii));
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-               CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+       if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+               return -2;
+       }
 
-               if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
-                       return -2;
-               }
+       /* Send request via doorbell handshake */
+       req_as_bytes = (u8 *) req;
+       for (ii = 0; ii < reqBytes/4; ii++) {
+               u32 word;
 
-               /* Send request via doorbell handshake */
-               req_as_bytes = (u8 *) req;
-               for (ii = 0; ii < reqBytes/4; ii++) {
-                       u32 word;
-
-                       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, 5, sleepFlag)) < 0) {
-                               r = -3;
-                               break;
-                       }
+               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 ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+                       r = -3;
+                       break;
                }
+       }
 
-               if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
-                       r = 0;
-               else
-                       r = -4;
+       if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
+               r = 0;
+       else
+               r = -4;
 
-               /* Make sure there are no doorbells */
-               CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
-       }
+       /* Make sure there are no doorbells */
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
        return r;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_adapter_find_first - Find first MPT adapter pointer.
+ * mpt_host_page_access_control - provides mechanism for the host
+ * driver to control the IOC's Host Page Buffer access.
+ * @ioc: Pointer to MPT adapter structure
+ * @access_control_value: define bits below
+ *
+ * Access Control Value - bits[15:12]
+ * 0h Reserved
+ * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
+ * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
+ * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
  *
- *     Returns first MPT adapter pointer or %NULL if no MPT adapters
- *     are present.
+ * Returns 0 for success, non-zero for failure.
  */
-MPT_ADAPTER *
-mpt_adapter_find_first(void)
+
+static int
+mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
 {
-       MPT_ADAPTER *this;
+       int      r = 0;
 
-       if (! Q_IS_EMPTY(&MptAdapters))
-               this = MptAdapters.head;
-       else
-               this = NULL;
+       /* return if in use */
+       if (CHIPREG_READ32(&ioc->chip->Doorbell)
+           & MPI_DOORBELL_ACTIVE)
+           return -1;
+
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-       return this;
+       CHIPREG_WRITE32(&ioc->chip->Doorbell,
+               ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
+                <<MPI_DOORBELL_FUNCTION_SHIFT) |
+                (access_control_value<<12)));
+
+       /* Wait for IOC to clear Doorbell Status bit */
+       if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+               return -2;
+       }else
+               return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_adapter_find_next - Find next MPT adapter pointer.
- *     @prev: Pointer to previous MPT adapter
+ *     mpt_host_page_alloc - allocate system memory for the fw
+ *     If we already allocated memory in past, then resend the same pointer.
+ *     ioc@: Pointer to pointer to IOC adapter
+ *     ioc_init@: Pointer to ioc init config page
  *
- *     Returns next MPT adapter pointer or %NULL if there are no more.
+ *     Returns 0 for success, non-zero for failure.
  */
-MPT_ADAPTER *
-mpt_adapter_find_next(MPT_ADAPTER *prev)
+static int
+mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
 {
-       MPT_ADAPTER *next;
+       char    *psge;
+       int     flags_length;
+       u32     host_page_buffer_sz=0;
+
+       if(!ioc->HostPageBuffer) {
+
+               host_page_buffer_sz =
+                   le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
+
+               if(!host_page_buffer_sz)
+                       return 0; /* fw doesn't need any host buffers */
+
+               /* spin till we get enough memory */
+               while(host_page_buffer_sz > 0) {
+
+                       if((ioc->HostPageBuffer = pci_alloc_consistent(
+                           ioc->pcidev,
+                           host_page_buffer_sz,
+                           &ioc->HostPageBuffer_dma)) != NULL) {
+
+                               dinitprintk((MYIOC_s_INFO_FMT
+                                   "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
+                                   ioc->name,
+                                   ioc->HostPageBuffer,
+                                   ioc->HostPageBuffer_dma,
+                                   host_page_buffer_sz));
+                               ioc->alloc_total += host_page_buffer_sz;
+                               ioc->HostPageBuffer_sz = host_page_buffer_sz;
+                               break;
+                       }
 
-       if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
-               next = prev->forw;
-       else
-               next = NULL;
+                       host_page_buffer_sz -= (4*1024);
+               }
+       }
 
-       return next;
-}
+       if(!ioc->HostPageBuffer) {
+               printk(MYIOC_s_ERR_FMT
+                   "Failed to alloc memory for host_page_buffer!\n",
+                   ioc->name);
+               return -999;
+       }
 
+       psge = (char *)&ioc_init->HostPageBufferSGE;
+       flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+           MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+           MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+           MPI_SGE_FLAGS_HOST_TO_IOC |
+           MPI_SGE_FLAGS_END_OF_BUFFER;
+       if (sizeof(dma_addr_t) == sizeof(u64)) {
+           flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+       }
+       flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
+       flags_length |= ioc->HostPageBuffer_sz;
+       mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+       ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
+
+return 0;
+}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -1195,23 +1109,22 @@ mpt_adapter_find_next(MPT_ADAPTER *prev)
 int
 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
 {
-       MPT_ADAPTER *p;
-
-       *iocpp = NULL;
-       if (iocid >= MPT_MAX_ADAPTERS)
-               return -1;
+       MPT_ADAPTER *ioc;
 
-       p = mpt_adapters[iocid];
-       if (p == NULL)
-               return -1;
+       list_for_each_entry(ioc,&ioc_list,list) {
+               if (ioc->id == iocid) {
+                       *iocpp =ioc;
+                       return iocid;
+               }
+       }
 
-       *iocpp = p;
-       return iocid;
+       *iocpp = NULL;
+       return -1;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptbase_probe - Install a PCI intelligent MPT adapter.
+ *     mpt_attach - Install a PCI intelligent MPT adapter.
  *     @pdev: Pointer to pci_dev structure
  *
  *     This routine performs all the steps necessary to bring the IOC of
@@ -1226,53 +1139,58 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
  *
  *     TODO: Add support for polled controllers
  */
-static int __devinit
-mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int
+mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        MPT_ADAPTER     *ioc;
-       u8              *mem;
+       u8              __iomem *mem;
        unsigned long    mem_phys;
        unsigned long    port;
        u32              msize;
        u32              psize;
        int              ii;
        int              r = -ENODEV;
-       u64              mask = 0xffffffffffffffffULL;
        u8               revision;
        u8               pcixcmd;
+       static int       mpt_ids = 0;
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *dent, *ent;
+#endif
 
        if (pci_enable_device(pdev))
                return r;
-       
-       if (!pci_set_dma_mask(pdev, mask)) {
+
+       dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
+
+       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                dprintk((KERN_INFO MYNAM
                        ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
-       } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
+       } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
                return r;
        }
 
-       if (!pci_set_consistent_dma_mask(pdev, mask))
+       if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
                dprintk((KERN_INFO MYNAM
                        ": Using 64 bit consistent mask\n"));
        else
                dprintk((KERN_INFO MYNAM
                        ": Not using 64 bit consistent mask\n"));
 
-       ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+       ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
        if (ioc == NULL) {
                printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
                return -ENOMEM;
        }
-       memset(ioc, 0, sizeof(MPT_ADAPTER));
        ioc->alloc_total = sizeof(MPT_ADAPTER);
        ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
 
        ioc->pcidev = pdev;
-
        ioc->diagPending = 0;
        spin_lock_init(&ioc->diagLock);
+       spin_lock_init(&ioc->fc_rescan_work_lock);
+       spin_lock_init(&ioc->initializing_hba_lock);
 
        /* Initialize the event logging.
         */
@@ -1289,36 +1207,31 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Initilize SCSI Config Data structure
         */
-       memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
+       memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
 
        /* Initialize the running configQ head.
         */
-       Q_INIT(&ioc->configQ, Q_ITEM);
+       INIT_LIST_HEAD(&ioc->configQ);
+
+       /* Initialize the fc rport list head.
+        */
+       INIT_LIST_HEAD(&ioc->fc_rports);
 
        /* Find lookup slot. */
-       for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
-               if (mpt_adapters[ii] == NULL) {
-                       ioc->id = ii;           /* Assign adapter unique id (lookup) */
-                       break;
-               }
-       }
-       if (ii == MPT_MAX_ADAPTERS) {
-               printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);
-               kfree(ioc);
-               return -ENFILE;
-       }
+       INIT_LIST_HEAD(&ioc->list);
+       ioc->id = mpt_ids++;
 
        mem_phys = msize = 0;
        port = psize = 0;
        for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
-               if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
+               if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
                        /* Get I/O space! */
-                       port = pdev->PCI_BASEADDR_START(ii);
-                       psize = PCI_BASEADDR_SIZE(pdev,ii);
+                       port = pci_resource_start(pdev, ii);
+                       psize = pci_resource_len(pdev,ii);
                } else {
                        /* Get memmap */
-                       mem_phys = pdev->PCI_BASEADDR_START(ii);
-                       msize = PCI_BASEADDR_SIZE(pdev,ii);
+                       mem_phys = pci_resource_start(pdev, ii);
+                       msize = pci_resource_len(pdev,ii);
                        break;
                }
        }
@@ -1330,8 +1243,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return -EINVAL;
        }
 
-       dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
-       dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
+       dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
+       dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
 
        mem = NULL;
        /* Get logical ptr for PciMem0 space */
@@ -1343,37 +1256,36 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return -EINVAL;
        }
        ioc->memmap = mem;
-       dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+       dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
 
-       dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
+       dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
                        &ioc->facts, &ioc->pfacts[0]));
 
        ioc->mem_phys = mem_phys;
-       ioc->chip = (SYSIF_REGS*)mem;
+       ioc->chip = (SYSIF_REGS __iomem *)mem;
 
-       /* Save Port IO values incase we need to do downloadboot */
+       /* Save Port IO values in case we need to do downloadboot */
        {
                u8 *pmem = (u8*)port;
                ioc->pio_mem_phys = port;
-               ioc->pio_chip = (SYSIF_REGS*)pmem;
+               ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
        }
 
-       ioc->chip_type = FCUNK;
        if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
-               ioc->chip_type = FC909;
                ioc->prod_name = "LSIFC909";
+               ioc->bus_type = FC;
        }
-       if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
-               ioc->chip_type = FC929;
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
                ioc->prod_name = "LSIFC929";
+               ioc->bus_type = FC;
        }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
-               ioc->chip_type = FC919;
                ioc->prod_name = "LSIFC919";
+               ioc->bus_type = FC;
        }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
-               ioc->chip_type = FC929X;
                pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+               ioc->bus_type = FC;
                if (revision < XL_929) {
                        ioc->prod_name = "LSIFC929X";
                        /* 929X Chip Fix. Set Split transactions level
@@ -1392,8 +1304,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
-               ioc->chip_type = FC919X;
                ioc->prod_name = "LSIFC919X";
+               ioc->bus_type = FC;
                /* 919X Chip Fix. Set Split transactions level
                 * for PCIX. Set MOST bits to zero.
                 */
@@ -1401,9 +1313,23 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                pcixcmd &= 0x8F;
                pci_write_config_byte(pdev, 0x6a, pcixcmd);
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
+               ioc->prod_name = "LSIFC939X";
+               ioc->bus_type = FC;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
+               ioc->prod_name = "LSIFC949X";
+               ioc->bus_type = FC;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+               ioc->prod_name = "LSIFC949E";
+               ioc->bus_type = FC;
+       }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
-               ioc->chip_type = C1030;
                ioc->prod_name = "LSI53C1030";
+               ioc->bus_type = SPI;
                /* 1030 Chip Fix. Disable Split transactions
                 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
                 */
@@ -1415,13 +1341,42 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
-               ioc->chip_type = C1035;
                ioc->prod_name = "LSI53C1035";
+               ioc->bus_type = SPI;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
+               ioc->prod_name = "LSISAS1064";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
+               ioc->prod_name = "LSISAS1066";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
+               ioc->prod_name = "LSISAS1068";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
+               ioc->prod_name = "LSISAS1064E";
+               ioc->bus_type = SAS;
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
+               ioc->prod_name = "LSISAS1066E";
+               ioc->bus_type = SAS;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
+               ioc->prod_name = "LSISAS1068E";
+               ioc->bus_type = SAS;
+       }
+
+       if (ioc->errata_flag_1064)
+               pci_disable_io_access(pdev);
 
        sprintf(ioc->name, "ioc%d", ioc->id);
 
-       Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
        spin_lock_init(&ioc->FreeQlock);
 
        /* Disable all! */
@@ -1429,14 +1384,14 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->active = 0;
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-       /* tack onto tail of our MPT adapter list */
-       Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
-
        /* Set lookup ptr. */
-       mpt_adapters[ioc->id] = ioc;
+       list_add_tail(&ioc->list, &ioc_list);
 
        ioc->pci_irq = -1;
        if (pdev->irq) {
+               if (mpt_msi_enable && !pci_enable_msi(pdev))
+                       printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
+
                r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
 
                if (r < 0) {
@@ -1447,8 +1402,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                        printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
                                        ioc->name, __irq_itoa(pdev->irq));
 #endif
-                       Q_DEL_ITEM(ioc);
-                       mpt_adapters[ioc->id] = NULL;
+                       list_del(&ioc->list);
                        iounmap(mem);
                        kfree(ioc);
                        return -EBUSY;
@@ -1466,22 +1420,22 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 #endif
        }
 
-       /* NEW!  20010220 -sralston
-        * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
+       /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
         */
-       if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
-                       || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
-               mpt_detect_bound_ports(ioc, pdev);
+       mpt_detect_bound_ports(ioc, pdev);
 
-       if ((r = mpt_do_ioc_recovery(ioc,
-         MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 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);
 
-               Q_DEL_ITEM(ioc);
-               mpt_adapters[ioc->id] = NULL;
+               list_del(&ioc->list);
                free_irq(ioc->pci_irq, ioc);
+               if (mpt_msi_enable)
+                       pci_disable_msi(pdev);
+               if (ioc->alt_ioc)
+                       ioc->alt_ioc->alt_ioc = NULL;
                iounmap(mem);
                kfree(ioc);
                pci_set_drvdata(pdev, NULL);
@@ -1496,22 +1450,49 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                }
        }
 
+#ifdef CONFIG_PROC_FS
+       /*
+        *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
+        */
+       dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
+       if (dent) {
+               ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
+               if (ent) {
+                       ent->read_proc = procmpt_iocinfo_read;
+                       ent->data = ioc;
+               }
+               ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
+               if (ent) {
+                       ent->read_proc = procmpt_summary_read;
+                       ent->data = ioc;
+               }
+       }
+#endif
+
        return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptbase_remove - Remove a PCI intelligent MPT adapter.
+ *     mpt_detach - Remove a PCI intelligent MPT adapter.
  *     @pdev: Pointer to pci_dev structure
  *
  */
 
-static void __devexit
-mptbase_remove(struct pci_dev *pdev)
+void
+mpt_detach(struct pci_dev *pdev)
 {
        MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
+       char pname[32];
        int ii;
 
+       sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
+       remove_proc_entry(pname, NULL);
+       sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
+       remove_proc_entry(pname, NULL);
+       sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+       remove_proc_entry(pname, NULL);
+
        /* call per device driver remove entry point */
        for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
                if(MptDeviceDriverHandlers[ii] &&
@@ -1524,84 +1505,41 @@ mptbase_remove(struct pci_dev *pdev)
        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
 
        ioc->active = 0;
-       mpt_sync_irq(pdev->irq);
+       synchronize_irq(pdev->irq);
 
        /* Clear any lingering interrupt */
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
        CHIPREG_READ32(&ioc->chip->IntStatus);
 
-       Q_DEL_ITEM(ioc);
        mpt_adapter_dispose(ioc);
 
        pci_set_drvdata(pdev, NULL);
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mptbase_shutdown -
- *
- */
-static void
-mptbase_shutdown(struct device * dev)
-{
-       int ii;
-
-       /* call per device driver shutdown entry point */
-       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-               if(MptDeviceDriverHandlers[ii] &&
-                 MptDeviceDriverHandlers[ii]->shutdown) {
-                       MptDeviceDriverHandlers[ii]->shutdown(dev);
-               }
-       }
-
-}
-
-
 /**************************************************************************
  * Power Management
  */
 #ifdef CONFIG_PM
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptbase_suspend - Fusion MPT base driver suspend routine.
+ *     mpt_suspend - Fusion MPT base driver suspend routine.
  *
  *
  */
-static int
-mptbase_suspend(struct pci_dev *pdev, u32 state)
+int
+mpt_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        u32 device_state;
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
-       int ii;
 
-       switch(state)
-       {
-               case 1: /* S1 */
-                       device_state=1; /* D1 */;
-                       break;
-               case 3: /* S3 */
-               case 4: /* S4 */
-                       device_state=3; /* D3 */;
-                       break;
-               default:
-                       return -EAGAIN /*FIXME*/;
-                       break;
-       }
+       device_state=pci_choose_state(pdev, state);
 
        printk(MYIOC_s_INFO_FMT
        "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
                ioc->name, pdev, pci_name(pdev), device_state);
 
-       /* call per device driver suspend entry point */
-       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-               if(MptDeviceDriverHandlers[ii] &&
-                 MptDeviceDriverHandlers[ii]->suspend) {
-                       MptDeviceDriverHandlers[ii]->suspend(pdev, state);
-               }
-       }
-
-       pci_save_state(pdev, ioc->PciState);
+       pci_save_state(pdev);
 
        /* put ioc into READY_STATE */
        if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
@@ -1624,38 +1562,29 @@ mptbase_suspend(struct pci_dev *pdev, u32 state)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptbase_resume - Fusion MPT base driver resume routine.
+ *     mpt_resume - Fusion MPT base driver resume routine.
  *
  *
  */
-static int
-mptbase_resume(struct pci_dev *pdev)
+int
+mpt_resume(struct pci_dev *pdev)
 {
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        u32 device_state = pdev->current_state;
        int recovery_state;
-       int ii;
 
        printk(MYIOC_s_INFO_FMT
        "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
                ioc->name, pdev, pci_name(pdev), device_state);
 
        pci_set_power_state(pdev, 0);
-       pci_restore_state(pdev, ioc->PciState);
+       pci_restore_state(pdev);
        pci_enable_device(pdev);
 
        /* enable interrupts */
-       CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+       CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
        ioc->active = 1;
 
-       /* F/W not running */
-       if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
-               /* enable domain validation flags */
-               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                       ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
-               }
-       }
-
        printk(MYIOC_s_INFO_FMT
                "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
                ioc->name,
@@ -1673,18 +1602,25 @@ mptbase_resume(struct pci_dev *pdev)
                        "pci-resume: success\n", ioc->name);
        }
 
-       /* call per device driver resume entry point */
-       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-               if(MptDeviceDriverHandlers[ii] &&
-                 MptDeviceDriverHandlers[ii]->resume) {
-                       MptDeviceDriverHandlers[ii]->resume(pdev);
-               }
-       }
-
        return 0;
 }
 #endif
 
+static int
+mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
+{
+       if ((MptDriverClass[index] == MPTSPI_DRIVER &&
+            ioc->bus_type != SPI) ||
+           (MptDriverClass[index] == MPTFC_DRIVER &&
+            ioc->bus_type != FC) ||
+           (MptDriverClass[index] == MPTSAS_DRIVER &&
+            ioc->bus_type != SAS))
+               /* make sure we only call the relevant reset handler
+                * for the bus */
+               return 0;
+       return (MptResetHandlers[index])(ioc, reset_phase);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_do_ioc_recovery - Initialize or recover MPT adapter.
@@ -1711,7 +1647,7 @@ 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      rc=0;
        int      ii;
        int      handlers;
        int      ret = 0;
@@ -1746,7 +1682,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                                /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
                                dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
                                                ioc->alt_ioc->name));
-                               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+                               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                                ioc->alt_ioc->active = 1;
                        }
 
@@ -1761,31 +1697,37 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
         * and 1 if a hard reset was performed.
         */
        if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
-               if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
+               if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
                        alt_ioc_ready = 1;
                else
                        printk(KERN_WARNING MYNAM
-                                       ": alt-%s: (%d) Not ready WARNING!\n",
-                                       ioc->alt_ioc->name, r);
+                                       ": alt-%s: Not ready WARNING!\n",
+                                       ioc->alt_ioc->name);
+       }
+
+       for (ii=0; ii<5; ii++) {
+               /* Get IOC facts! Allow 5 retries */
+               if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
+                       break;
        }
 
-       /* Get IOC facts! Allow 1 retry */
-       if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
-               r = GetIocFacts(ioc, sleepFlag, reason);
 
-       if (r) {
+       if (ii == 5) {
+               dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
                ret = -2;
        } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
                MptDisplayIocCapabilities(ioc);
        }
 
        if (alt_ioc_ready) {
-               if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+               if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+                       dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
                        /* Retry - alt IOC was initialized once
                         */
-                       r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
+                       rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
                }
-               if (r) {
+               if (rc) {
+                       dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
                        alt_ioc_ready = 0;
                        reset_alt_ioc_active = 0;
                } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
@@ -1798,29 +1740,29 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
         * init as upper addresses are needed for init.
         * If fails, continue with alt-ioc processing
         */
-       if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
+       if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
                ret = -3;
 
        /* May need to check/upload firmware & data here!
         * If fails, continue with alt-ioc processing
         */
-       if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
+       if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
                ret = -4;
 // NEW!
-       if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
+       if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
                printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
-                               ioc->alt_ioc->name, r);
+                               ioc->alt_ioc->name, rc);
                alt_ioc_ready = 0;
                reset_alt_ioc_active = 0;
        }
 
        if (alt_ioc_ready) {
-               if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
+               if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
                        alt_ioc_ready = 0;
                        reset_alt_ioc_active = 0;
                        printk(KERN_WARNING MYNAM
                                ": alt-%s: (%d) init failure WARNING!\n",
-                                       ioc->alt_ioc->name, r);
+                                       ioc->alt_ioc->name, rc);
                }
        }
 
@@ -1832,39 +1774,43 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                        /* Controller is not operational, cannot do upload
                         */
                        if (ret == 0) {
-                               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) && (ioc->alt_ioc->upload_fw)){
-                               ddlprintk((MYIOC_s_INFO_FMT
-                                       "Alt-ioc firmware upload required!\n",
-                                       ioc->name));
-                               r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
-                               if (r != 0)
+                               rc = mpt_do_upload(ioc, sleepFlag);
+                               if (rc == 0) {
+                                       if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+                                               /*
+                                                * Maintain only one pointer to FW memory
+                                                * so there will not be two attempt to
+                                                * downloadboot onboard dual function
+                                                * chips (mpt_adapter_disable,
+                                                * mpt_diag_reset)
+                                                */
+                                               ioc->cached_fw = NULL;
+                                               ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload:  alt_%s has cached_fw=%p \n",
+                                                       ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+                                       }
+                               } else {
                                        printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+                                       ret = -5;
+                               }
                        }
                }
        }
 
        if (ret == 0) {
                /* Enable! (reply interrupt) */
-               CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+               CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
                ioc->active = 1;
        }
 
        if (reset_alt_ioc_active && ioc->alt_ioc) {
                /* (re)Enable alt-IOC! (reply interrupt) */
-               dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
+               dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
                                ioc->alt_ioc->name));
-               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                ioc->alt_ioc->active = 1;
        }
 
-       /* NEW!  20010120 -sralston
-        *  Enable MPT base driver management of EventNotification
+       /*  Enable MPT base driver management of EventNotification
         *  and EventAck handling.
         */
        if ((ret == 0) && (!ioc->facts.EventState))
@@ -1873,22 +1819,35 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
        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
+       /*      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 ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
-               if ((int)ioc->chip_type <= (int)FC929) {
+               if (ioc->bus_type == SAS) {
+
+                       /* clear persistency table */
+                       if(ioc->facts.IOCExceptions &
+                           MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+                               ret = mptbase_sas_persist_operation(ioc,
+                                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
+                               if(ret != 0)
+                                       return -1;
+                       }
+
+                       /* Find IM volumes
+                        */
+                       mpt_findImVolumes(ioc);
+
+               } else if (ioc->bus_type == FC) {
                        /*
                         *  Pre-fetch FC port WWN and stuff...
                         *  (FCPortPage0_t stuff)
                         */
                        for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-                               (void) GetFcPortPage0(ioc, ii);
+                               (void) mptbase_GetFcPortPage0(ioc, ii);
                        }
 
                        if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -1917,7 +1876,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
                        /* Find IM volumes
                         */
-                       if (ioc->facts.MsgVersion >= 0x0102)
+                       if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
                                mpt_findImVolumes(ioc);
 
                        /* Check, and possibly reset, the coalescing value
@@ -1937,19 +1896,19 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
         * MptResetHandlers[] registered yet.
         */
        if (hard_reset_done) {
-               r = handlers = 0;
+               rc = handlers = 0;
                for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
                        if ((ret == 0) && MptResetHandlers[ii]) {
                                dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
                                                ioc->name, ii));
-                               r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+                               rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
 
                        if (alt_ioc_ready && MptResetHandlers[ii]) {
-                               dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+                               drsprintk((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);
+                               rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
                }
@@ -1973,143 +1932,143 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 static void
 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((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));
+       struct pci_dev *peer=NULL;
+       unsigned int slot = PCI_SLOT(pdev->devfn);
+       unsigned int func = PCI_FUNC(pdev->devfn);
+       MPT_ADAPTER *ioc_srch;
+
+       dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
+           " searching for devfn match on %x or %x\n",
+               ioc->name, pci_name(pdev), pdev->bus->number,
+               pdev->devfn, func-1, func+1));
+
+       peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
+       if (!peer) {
+               peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
+               if (!peer)
+                       return;
+       }
 
-       while (ioc_srch != NULL) {
+       list_for_each_entry(ioc_srch, &ioc_list, list) {
                struct pci_dev *_pcidev = ioc_srch->pcidev;
-
-               if ((_pcidev->device == pdev->device) &&
-                   (_pcidev->bus->number == pdev->bus->number) &&
-                   (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+               if (_pcidev == peer) {
                        /* Paranoia checks */
                        if (ioc->alt_ioc != NULL) {
                                printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
-                                               ioc->name, ioc->alt_ioc->name);
+                                       ioc->name, ioc->alt_ioc->name);
                                break;
                        } else if (ioc_srch->alt_ioc != NULL) {
                                printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
-                                               ioc_srch->name, ioc_srch->alt_ioc->name);
+                                       ioc_srch->name, ioc_srch->alt_ioc->name);
                                break;
                        }
                        dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
-                                       ioc->name, ioc_srch->name));
+                               ioc->name, ioc_srch->name));
                        ioc_srch->alt_ioc = ioc;
                        ioc->alt_ioc = ioc_srch;
-                       break;
                }
-               ioc_srch = mpt_adapter_find_next(ioc_srch);
        }
+       pci_dev_put(peer);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_adapter_disable - Disable misbehaving MPT adapter.
  *     @this: Pointer to MPT adapter structure
- *     @free: Free up alloc'd reply, request, etc.
  */
 static void
-mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
+mpt_adapter_disable(MPT_ADAPTER *ioc)
 {
-       if (this != NULL) {
-               int sz=0;
-               u32 state;
-               int ret;
-
-               /* Disable the FW */
-               state = mpt_GetIocState(this, 1);
-               if (state == MPI_IOC_STATE_OPERATIONAL) {
-                       SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
-               }
-
-               if (this->cached_fw != NULL) {
-                       ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
+       int sz;
+       int ret;
 
-                       if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
-                               printk(KERN_WARNING MYNAM
-                                       ": firmware downloadboot failure (%d)!\n", ret);
-                       }
+       if (ioc->cached_fw != NULL) {
+               ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
+               if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
+                       printk(KERN_WARNING MYNAM
+                               ": firmware downloadboot failure (%d)!\n", ret);
                }
+       }
 
-               /* Disable adapter interrupts! */
-               CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
-               this->active = 0;
-               /* Clear any lingering interrupt */
-               CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
-               if (freeup && this->fifo_pool != NULL) {
-                       pci_free_consistent(this->pcidev,
-                               this->fifo_pool_sz,
-                               this->fifo_pool, this->fifo_pool_dma);
-                       this->reply_frames = NULL;
-                       this->reply_alloc = NULL;
-                       this->req_frames = NULL;
-                       this->req_alloc = NULL;
-                       this->chain_alloc = NULL;
-                       this->fifo_pool = NULL;
-                       this->alloc_total -= this->fifo_pool_sz;
-               }
-               if (freeup && this->sense_buf_pool != NULL) {
-                       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;
-               }
+       /* Disable adapter interrupts! */
+       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+       ioc->active = 0;
+       /* Clear any lingering interrupt */
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-               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 (ioc->alloc != NULL) {
+               sz = ioc->alloc_sz;
+               dexitprintk((KERN_INFO MYNAM ": %s.free  @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->alloc, ioc->alloc_sz));
+               pci_free_consistent(ioc->pcidev, sz,
+                               ioc->alloc, ioc->alloc_dma);
+               ioc->reply_frames = NULL;
+               ioc->req_frames = NULL;
+               ioc->alloc = NULL;
+               ioc->alloc_total -= sz;
+       }
 
-               if (freeup && this->cached_fw != NULL) {
-                       int ii = 0;
+       if (ioc->sense_buf_pool != NULL) {
+               sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+               pci_free_consistent(ioc->pcidev, sz,
+                               ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+               ioc->sense_buf_pool = NULL;
+               ioc->alloc_total -= sz;
+       }
 
-                       while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) {
-                               sz = this->cached_fw[ii]->size;
-                               pci_free_consistent(this->pcidev, sz,
-                                       this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma);
-                               this->cached_fw[ii]->fw = NULL;
-                               this->alloc_total -= sz;
+       if (ioc->events != NULL){
+               sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+               kfree(ioc->events);
+               ioc->events = NULL;
+               ioc->alloc_total -= sz;
+       }
 
-                               kfree(this->cached_fw[ii]);
-                               this->cached_fw[ii] = NULL;
-                               this->alloc_total -= sizeof(fw_image_t);
+       if (ioc->cached_fw != NULL) {
+               sz = ioc->facts.FWImageSize;
+               pci_free_consistent(ioc->pcidev, sz,
+                       ioc->cached_fw, ioc->cached_fw_dma);
+               ioc->cached_fw = NULL;
+               ioc->alloc_total -= sz;
+       }
 
-                               ii++;
-                       }
+       kfree(ioc->spi_data.nvram);
+       kfree(ioc->raid_data.pIocPg3);
+       ioc->spi_data.nvram = NULL;
+       ioc->raid_data.pIocPg3 = NULL;
 
-                       kfree(this->cached_fw);
-                       this->cached_fw = NULL;
-                       sz = this->num_fw_frags * sizeof(void *);
-                       this->alloc_total -= sz;
-               }
+       if (ioc->spi_data.pIocPg4 != NULL) {
+               sz = ioc->spi_data.IocPg4Sz;
+               pci_free_consistent(ioc->pcidev, sz, 
+                       ioc->spi_data.pIocPg4,
+                       ioc->spi_data.IocPg4_dma);
+               ioc->spi_data.pIocPg4 = NULL;
+               ioc->alloc_total -= sz;
+       }
 
-               if (freeup && this->spi_data.nvram != NULL) {
-                       kfree(this->spi_data.nvram);
-                       this->spi_data.nvram = NULL;
-               }
+       if (ioc->ReqToChain != NULL) {
+               kfree(ioc->ReqToChain);
+               kfree(ioc->RequestNB);
+               ioc->ReqToChain = NULL;
+       }
 
-               if (freeup && this->spi_data.pIocPg3 != NULL) {
-                       kfree(this->spi_data.pIocPg3);
-                       this->spi_data.pIocPg3 = NULL;
-               }
+       kfree(ioc->ChainToChain);
+       ioc->ChainToChain = NULL;
 
-               if (freeup && this->spi_data.pIocPg4 != NULL) {
-                       sz = this->spi_data.IocPg4Sz;
-                       pci_free_consistent(this->pcidev, sz,
-                               this->spi_data.pIocPg4,
-                               this->spi_data.IocPg4_dma);
-                       this->spi_data.pIocPg4 = NULL;
-                       this->alloc_total -= sz;
+       if (ioc->HostPageBuffer != NULL) {
+               if((ret = mpt_host_page_access_control(ioc,
+                   MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
+                       printk(KERN_ERR MYNAM
+                          ": %s: host page buffers free failed (%d)!\n",
+                           __FUNCTION__, ret);
                }
+               dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+               pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+                               ioc->HostPageBuffer,
+                               ioc->HostPageBuffer_dma);
+               ioc->HostPageBuffer = NULL;
+               ioc->HostPageBuffer_sz = 0;
+               ioc->alloc_total -= ioc->HostPageBuffer_sz;
        }
 }
 
@@ -2117,49 +2076,53 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
 /*
  *     mpt_adapter_dispose - Free all resources associated with a MPT
  *     adapter.
- *     @this: Pointer to MPT adapter structure
+ *     @ioc: Pointer to MPT adapter structure
  *
  *     This routine unregisters h/w resources and frees all alloc'd memory
  *     associated with a MPT adapter structure.
  */
 static void
-mpt_adapter_dispose(MPT_ADAPTER *this)
+mpt_adapter_dispose(MPT_ADAPTER *ioc)
 {
-       if (this != NULL) {
-               int sz_first, sz_last;
+       int sz_first, sz_last;
 
-               sz_first = this->alloc_total;
+       if (ioc == NULL)
+               return;
 
-               if (this->alt_ioc != NULL) {
-                       this->alt_ioc->alt_ioc = NULL;
-                       this->alt_ioc = NULL;
-               }
+       sz_first = ioc->alloc_total;
 
-               mpt_adapter_disable(this, 1);
+       mpt_adapter_disable(ioc);
 
-               if (this->pci_irq != -1) {
-                       free_irq(this->pci_irq, this);
-                       this->pci_irq = -1;
-               }
+       if (ioc->pci_irq != -1) {
+               free_irq(ioc->pci_irq, ioc);
+               if (mpt_msi_enable)
+                       pci_disable_msi(ioc->pcidev);
+               ioc->pci_irq = -1;
+       }
 
-               if (this->memmap != NULL)
-                       iounmap((u8 *) this->memmap);
+       if (ioc->memmap != NULL) {
+               iounmap(ioc->memmap);
+               ioc->memmap = NULL;
+       }
 
 #if defined(CONFIG_MTRR) && 0
-               if (this->mtrr_reg > 0) {
-                       mtrr_del(this->mtrr_reg, 0, 0);
-                       dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
-               }
+       if (ioc->mtrr_reg > 0) {
+               mtrr_del(ioc->mtrr_reg, 0, 0);
+               dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+       }
 #endif
 
-               /*  Zap the adapter lookup ptr!  */
-               mpt_adapters[this->id] = NULL;
+       /*  Zap the adapter lookup ptr!  */
+       list_del(&ioc->list);
 
-               sz_last = this->alloc_total;
-               dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
-                               this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
-               kfree(this);
-       }
+       sz_last = ioc->alloc_total;
+       dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+                       ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+
+       if (ioc->alt_ioc)
+               ioc->alt_ioc->alt_ioc = NULL;
+
+       kfree(ioc);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2246,19 +2209,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
        }
 
        /* Is it already READY? */
-       if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
-               if ((int)ioc->chip_type <= (int)FC929)
-                       return 0;
-               else {
-                       /* Workaround from broken 1030 FW.
-                        * Force a diagnostic reset if fails.
-                        */
-                       if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
-                               return 0;
-                       else
-                               statefault = 4;
-               }
-       }
+       if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
+               return 0;
 
        /*
         *      Check to see if IOC is in FAULT state.
@@ -2275,7 +2227,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
         *      Hmmm...  Did it get left operational?
         */
        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
-               dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+               dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
                                ioc->name));
 
                /* Check WhoInit.
@@ -2284,8 +2236,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
                 * 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",
+               dinitprintk((KERN_INFO MYNAM
+                       ": whoinit 0x%x statefault %d force %d\n",
                        whoinit, statefault, force));
                if (whoinit == MPI_WHOINIT_PCI_PEER)
                        return -4;
@@ -2306,7 +2258,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
         *  Loop here waiting for IOC to come READY.
         */
        ii = 0;
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
+       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;     /* 5 seconds */
 
        while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
                if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
@@ -2332,13 +2284,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
                ii++; cntdn--;
                if (!cntdn) {
                        printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
-                                       ioc->name, (ii+5)/HZ);
+                                       ioc->name, (int)((ii+5)/HZ));
                        return -ETIME;
                }
 
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       msleep_interruptible(1);
                } else {
                        mdelay (1);     /* 1 msec delay */
                }
@@ -2396,7 +2347,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
        int                      r;
        int                      req_sz;
        int                      reply_sz;
-       u32                      status;
+       int                      sz;
+       u32                      status, vv;
+       u8                       shiftFactor=1;
 
        /* IOC *must* NOT be in RESET state! */
        if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2419,7 +2372,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
        get_facts.Function = MPI_FUNCTION_IOC_FACTS;
        /* Assert: All other get_facts fields are zero! */
 
-       dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
+       dinitprintk((MYIOC_s_INFO_FMT
+           "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
+           ioc->name, req_sz, reply_sz));
 
        /* 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.
@@ -2451,7 +2406,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                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;
+               status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
                /* CHECKME! IOCStatus, IOCLogInfo */
 
                facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
@@ -2481,6 +2436,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                                le32_to_cpu(facts->CurrentSenseBufferHighAddr);
                facts->CurReplyFrameSize =
                                le16_to_cpu(facts->CurReplyFrameSize);
+               facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
 
                /*
                 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
@@ -2492,6 +2448,13 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                        facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
                }
 
+               sz = facts->FWImageSize;
+               if ( sz & 0x01 )
+                       sz += 1;
+               if ( sz & 0x02 )
+                       sz += 2;
+               facts->FWImageSize = sz;
+
                if (!facts->RequestFrameSize) {
                        /*  Something is wrong!  */
                        printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2499,6 +2462,18 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                        return -55;
                }
 
+               r = sz = facts->BlockSize;
+               vv = ((63 / (sz * 4)) + 1) & 0x03;
+               ioc->NB_for_64_byte_frame = vv;
+               while ( sz )
+               {
+                       shiftFactor++;
+                       sz = sz >> 1;
+               }
+               ioc->NBShiftFactor  = shiftFactor;
+               dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+                                       ioc->name, vv, shiftFactor, r));
+
                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
                        /*
                         * Set values for this IOC's request & reply frame sizes,
@@ -2509,9 +2484,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
                        ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
 
-                       dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
+                       dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
                                ioc->name, ioc->reply_sz, ioc->reply_depth));
-                       dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
+                       dinitprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
                                ioc->name, ioc->req_sz, ioc->req_depth));
 
                        /* Get port facts! */
@@ -2519,8 +2494,10 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                                return r;
                }
        } else {
-               printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
-                               ioc->name);
+               printk(MYIOC_s_ERR_FMT
+                    "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
+                    ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
+                    RequestFrameSize)/sizeof(u32)));
                return -66;
        }
 
@@ -2567,7 +2544,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
        get_pfacts.PortNumber = portnum;
        /* Assert: All other get_pfacts fields are zero! */
 
-       dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
+       dinitprintk((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
@@ -2618,67 +2595,78 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
        memset(&init_reply, 0, sizeof(init_reply));
 
        ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
-/*     ioc_init.ChainOffset = 0;                       */
        ioc_init.Function = MPI_FUNCTION_IOC_INIT;
-/*     ioc_init.Flags = 0;                             */
 
        /* If we are in a recovery mode and we uploaded the FW image,
         * then this pointer is not NULL. Skip the upload a second time.
         * Set this flag if cached_fw set for either IOC.
         */
-       ioc->upload_fw = 0;
-       ioc_init.Flags = 0;
-       if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
-               if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
-                       ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
-               else
-                       ioc->upload_fw = 1;
-       }
-       ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
-                  ioc->name, ioc_init.Flags, ioc->upload_fw));
+       if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
+               ioc->upload_fw = 1;
+       else
+               ioc->upload_fw = 0;
+       ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+                  ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
-       if ((int)ioc->chip_type <= (int)FC929) {
+       if(ioc->bus_type == SAS)
+               ioc_init.MaxDevices = ioc->facts.MaxDevices;
+       else if(ioc->bus_type == FC)
                ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
-       } else {
+       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);  */
+       dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+                  ioc->name, ioc->facts.MsgVersion));
+       if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+               // set MsgVersion and HeaderVersion host driver was built with
+               ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
+               ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
+
+               if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
+                       ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
+               } else if(mpt_host_page_alloc(ioc, &ioc_init))
+                       return -99;
+       }
        ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
-               
-       ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
 
        if (sizeof(dma_addr_t) == sizeof(u64)) {
                /* Save the upper 32-bits of the request
                 * (reply) and sense buffers.
                 */
-               ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
+               ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
                ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)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);
        }
-               
+
        ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
        ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
+       ioc->facts.MaxDevices = ioc_init.MaxDevices;
+       ioc->facts.MaxBuses = ioc_init.MaxBuses;
 
-       dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
+       dhsprintk((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)
+       if (r != 0) {
+               printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
                return r;
+       }
 
        /* No need to byte swap the multibyte fields in the reply
         * since we don't even look at it's contents.
         */
 
-       if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
+       dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
+                       ioc->name, &ioc_init));
+
+       if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
+               printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
                return r;
+       }
 
        /* YIKES!  SUPER IMPORTANT!!!
         *  Poll IocState until _OPERATIONAL while IOC is doing
@@ -2689,22 +2677,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
        state = mpt_GetIocState(ioc, 1);
        while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       msleep_interruptible(1);
                } else {
                        mdelay(1);
                }
 
                if (!cntdn) {
                        printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
-                                       ioc->name, (count+5)/HZ);
+                                       ioc->name, (int)((count+5)/HZ));
                        return -9;
                }
 
                state = mpt_GetIocState(ioc, 1);
                count++;
        }
-       dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+       dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
                        ioc->name, count));
 
        return r;
@@ -2726,7 +2713,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 {
        PortEnable_t             port_enable;
        MPIDefaultReply_t        reply_buf;
-       int      ii;
+       int      rc;
        int      req_sz;
        int      reply_sz;
 
@@ -2743,160 +2730,57 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 /*     port_enable.MsgFlags = 0;               */
 /*     port_enable.MsgContext = 0;             */
 
-       dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
+       dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
                        ioc->name, portnum, &port_enable));
 
        /* 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);
+       if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+           > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
+           (ioc->bus_type == SAS)) {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+               (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+               300 /*seconds*/, sleepFlag);
        } else {
-               ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
-                               reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+               (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+               30 /*seconds*/, sleepFlag);
        }
-
-       if (ii != 0)
-               return ii;
-
-       /* We do not even look at the reply, so we need not
-        * swap the multi-byte fields.
-        */
-
-       return 0;
+       return rc;
 }
 
 /*
- * Inputs: size - total FW bytes
- * Outputs: frags - number of fragments needed
- * Return NULL if failed.
+ *     ioc: Pointer to MPT_ADAPTER structure
+ *      size - total FW bytes
  */
-void *
-mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
+void
+mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
 {
-       fw_image_t      **cached_fw;
-       u8              *mem;
-       dma_addr_t      fw_dma;
-       int             alloc_total = 0;
-       int             bytes_left, bytes, num_frags;
-       int             sz, ii;
-
-       /* cached_fw
-        */
-       sz = ioc->num_fw_frags * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL)
-               return NULL;
-
-       memset(mem, 0, sz);
-       cached_fw = (fw_image_t **)mem;
-       alloc_total += sz;
-
-       /* malloc fragment memory
-        * fw_image_t struct and dma for fw data
-        */
-       bytes_left = size;
-       ii = 0;
-       num_frags = 0;
-       bytes = bytes_left;
-       while((bytes_left) && (num_frags < ioc->num_fw_frags)) {
-               if (cached_fw[ii] == NULL) {
-                       mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC);
-                       if (mem == NULL)
-                               break;
-
-                       memset(mem, 0, sizeof(fw_image_t));
-                       cached_fw[ii] = (fw_image_t *)mem;
-                       alloc_total += sizeof(fw_image_t);
-               }
-
-               mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma);
-               if (mem == NULL) {
-                       if (bytes > 0x10000)
-                               bytes = 0x10000;
-                       else if (bytes > 0x8000)
-                               bytes = 0x8000;
-                       else if (bytes > 0x4000)
-                               bytes = 0x4000;
-                       else if (bytes > 0x2000)
-                               bytes = 0x2000;
-                       else if (bytes > 0x1000)
-                               bytes = 0x1000;
-                       else
-                               break;
-
-                       continue;
-               }
-
-               cached_fw[ii]->fw = mem;
-               cached_fw[ii]->fw_dma = fw_dma;
-               cached_fw[ii]->size = bytes;
-               memset(mem, 0, bytes);
-               alloc_total += bytes;
-
-               bytes_left -= bytes;
-
-               num_frags++;
-               ii++;
-       }
-
-       if (bytes_left ) {
-               /* Major Failure.
-                */
-               mpt_free_fw_memory(ioc, cached_fw);
-               return NULL;
+       if (ioc->cached_fw)
+               return;  /* use already allocated memory */
+       if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+               ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
+               ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
+       } else {
+               if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
+                       ioc->alloc_total += size;
        }
-
-       *frags = num_frags;
-       *alloc_sz = alloc_total;
-
-       return (void *) cached_fw;
 }
-
 /*
  * If alt_img is NULL, delete from ioc structure.
  * Else, delete a secondary image in same format.
  */
 void
-mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img)
+mpt_free_fw_memory(MPT_ADAPTER *ioc)
 {
-       fw_image_t **cached_fw;
-       int ii;
        int sz;
-       int alloc_freed = 0;
-
-       if (alt_img != NULL)
-               cached_fw = alt_img;
-       else
-               cached_fw = ioc->cached_fw;
-
-       if (cached_fw == NULL)
-               return;
-
-       ii = 0;
-       while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) {
-               sz = cached_fw[ii]->size;
-               if (sz > 0) {
-                       pci_free_consistent(ioc->pcidev, sz,
-                                               cached_fw[ii]->fw, cached_fw[ii]->fw_dma);
-               }
-               cached_fw[ii]->fw = NULL;
-               alloc_freed += sz;
-
-               kfree(cached_fw[ii]);
-               cached_fw[ii] = NULL;
-               alloc_freed += sizeof(fw_image_t);
-
-               ii++;
-       }
-
-       kfree(cached_fw);
-       cached_fw = NULL;
-       sz = ioc->num_fw_frags * sizeof(void *);
-       alloc_freed += sz;
 
-       if (alt_img == NULL)
-               ioc->alloc_total -= alloc_freed;
+       sz = ioc->facts.FWImageSize;
+       dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+                ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+       pci_free_consistent(ioc->pcidev, sz,
+                       ioc->cached_fw, ioc->cached_fw_dma);
+       ioc->cached_fw = NULL;
 
        return;
 }
@@ -2925,34 +2809,25 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
        FWUploadReply_t         *preply;
        FWUploadTCSGE_t         *ptcsge;
        int                      sgeoffset;
+       u32                      flagsLength;
        int                      ii, sz, reply_sz;
-       int                      cmdStatus, freeMem = 0;
-       int                      num_frags, alloc_sz;
+       int                      cmdStatus;
 
-       /* If the image size is 0 or if the pointer is
-        * not NULL (error), we are done.
+       /* If the image size is 0, we are done.
         */
-       if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
+       if ((sz = ioc->facts.FWImageSize) == 0)
                return 0;
 
-       ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
-       ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
+       mpt_alloc_fw_memory(ioc, sz);
 
-       ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
-                       ioc->facts.FWImageSize, &num_frags, &alloc_sz);
+       dinitprintk((KERN_INFO MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+                ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 
        if (ioc->cached_fw == NULL) {
                /* Major Failure.
                 */
-               mpt_free_fw_memory(ioc, NULL);
-               ioc->cached_fw = NULL;
-               
                return -ENOMEM;
        }
-       ioc->alloc_total += alloc_sz;
-
-       ddlprintk((KERN_INFO MYNAM ": FW Image  @ %p, sz=%d bytes\n",
-                (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize));
 
        prequest = (FWUpload_t *)&request;
        preply = (FWUploadReply_t *)&reply;
@@ -2965,39 +2840,27 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 
        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);
 
-       for (ii = 0; ii < (num_frags-1); ii++) {
-               mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT | 
-                       MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST |
-                       (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma);
-
-               sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-       }
-
-       mpt_add_sge(&request[sgeoffset],
-                       MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
-                       ioc->cached_fw[ii]->fw_dma);
+       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
+       mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
 
        sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-
-       dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n",
-                       ioc->name, prequest, sgeoffset));
+       dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
+                       prequest, sgeoffset));
+       DBG_DUMP_FW_REQUEST_FRAME(prequest)
 
        ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
                                reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
 
+       dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
+
        cmdStatus = -EFAULT;
        if (ii == 0) {
                /* Handshake transfer was complete and successful.
@@ -3011,28 +2874,15 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
                                cmdStatus = 0;
                }
        }
-       ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+       dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
                        ioc->name, cmdStatus));
 
-       /* Check to see if we have a copy of this image in
-        * host memory already.
-        */
-       if (cmdStatus == 0) {
-               ioc->upload_fw = 0;
-               if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
-                       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) {
+       if (cmdStatus) {
 
-               ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
-                       ioc->name, cmdStatus ? "incomplete" : "duplicate"));
-               mpt_free_fw_memory(ioc, NULL);
-               ioc->cached_fw = NULL;
+               ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
+                       ioc->name));
+               mpt_free_fw_memory(ioc);
        }
 
        return cmdStatus;
@@ -3053,262 +2903,195 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
  *             <0 for fw upload failure.
  */
 static int
-mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
 {
-       MpiFwHeader_t           *FwHdr;
-       MpiExtImageHeader_t     *ExtHdr;
-       fw_image_t              **pCached=NULL;
-       int                      fw_sz;
+       MpiExtImageHeader_t     *pExtImage;
+       u32                      fwSize;
        u32                      diag0val;
-#ifdef MPT_DEBUG
-       u32                      diag1val = 0;
-#endif
-       int                      count = 0;
-       u32                     *ptru32;
+       int                      count;
+       u32                     *ptrFw;
        u32                      diagRwData;
        u32                      nextImage;
-       u32                      ext_offset;
        u32                      load_addr;
-       int                      max_idx, fw_idx, ext_idx;
-       int                      left_u32s;
-
-       ddlprintk((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);
-       ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
-                               ioc->name, diag0val, diag1val));
-#endif
+       u32                      ioc_state=0;
 
-       ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
-                               ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
-       if (ioc->alt_ioc)
-               ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
-                               ioc->name, ioc->alt_ioc->cached_fw));
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
+                               ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
 
-       /* Get dma_addr and data transfer size.
-        */
-       if ((fw_sz = ioc->facts.FWImageSize) == 0)
-               return -1;
+       CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+       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);
 
-       /* Get the DMA from ioc or ioc->alt_ioc */
-       if (ioc->cached_fw != NULL)
-               pCached = (fw_image_t **)ioc->cached_fw;
-       else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL))
-               pCached = (fw_image_t **)ioc->alt_ioc->cached_fw;
-       else
-               return -2;
+       CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
 
-       ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
-                       ioc->name, pCached));
+       /* wait 1 msec */
+       if (sleepFlag == CAN_SLEEP) {
+               msleep_interruptible(1);
+       } else {
+               mdelay (1);
+       }
 
-       /* 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, 0xFF);
-               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);
+       CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
 
-               /* wait 100 msec */
+       for (count = 0; count < 30; count ++) {
+               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+               if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+                       ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
+                               ioc->name, count));
+                       break;
+               }
+               /* wait .1 sec */
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(100 * HZ / 1000);
+                       msleep_interruptible (100);
                } 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);
-               ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
-                               ioc->name, diag0val, diag1val));
-#endif
-               ddlprintk((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);
+       if ( count == 30 ) {
+               ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
+               "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
+               ioc->name, diag0val));
+               return -3;
+       }
 
-       ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
-                       ioc->name, diag0val, diag1val));
-#endif
+       CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+       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);
 
-       /* max_idx = 1 + maximum valid buffer index
-        */
-       max_idx = 0;
-       while (pCached[max_idx])
-               max_idx++;
+       /* Set the DiagRwEn and Disable ARM bits */
+       CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
-       fw_idx = 0;
-       FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw;
-       ptru32 = (u32 *) FwHdr;
-       count = (FwHdr->ImageSize + 3)/4;
-       nextImage = FwHdr->NextImageHeaderOffset;
+       fwSize = (pFwHeader->ImageSize + 3)/4;
+       ptrFw = (u32 *) pFwHeader;
 
        /* Write the LoadStartAddress to the DiagRw Address Register
         * using Programmed IO
         */
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
+       if (ioc->errata_flag_1064)
+               pci_enable_io_access(ioc->pcidev);
+
+       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
        ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
-               ioc->name, FwHdr->LoadStartAddress));
-
-       ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
-                               ioc->name, count, ptru32));
-       left_u32s = pCached[fw_idx]->size/4;
-       while (count--) {
-               if (left_u32s == 0) {
-                       fw_idx++;
-                       if (fw_idx >= max_idx) {
-                               /* FIXME
-                               ERROR CASE
-                               */
-                               ;
-                       }
-                       ptru32 = (u32 *) pCached[fw_idx]->fw;
-                       left_u32s = pCached[fw_idx]->size / 4;
-               }
-               left_u32s--;
-               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
-               ptru32++;
+               ioc->name, pFwHeader->LoadStartAddress));
+
+       ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
+                               ioc->name, fwSize*4, ptrFw));
+       while (fwSize--) {
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
        }
 
-       /* left_u32s, fw_idx and ptru32 are all valid
-        */
+       nextImage = pFwHeader->NextImageHeaderOffset;
        while (nextImage) {
-               ext_idx = 0;
-               ext_offset = nextImage;
-               while (ext_offset > pCached[ext_idx]->size) {
-                       ext_idx++;
-                       if (ext_idx >= max_idx) {
-                               /* FIXME
-                               ERROR CASE
-                               */
-                               ;
-                       }
-                       ext_offset -= pCached[ext_idx]->size;
-               }
-               ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset);
-               left_u32s = pCached[ext_idx]->size - ext_offset;
-
-               if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) {
-                       ExtHdr = (MpiExtImageHeader_t *) ptru32;
-                       count = (ExtHdr->ImageSize + 3 )/4;
-                       nextImage = ExtHdr->NextImageHeaderOffset;
-                       load_addr = ExtHdr->LoadStartAddress;
-               } else {
-                       u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw;
-
-                       switch (left_u32s) {
-                       case 5:
-                               count = *(ptru32 + 2);
-                               nextImage = *(ptru32 + 3);
-                               load_addr = *(ptru32 + 4);
-                               break;
-                       case 4:
-                               count = *(ptru32 + 2);
-                               nextImage = *(ptru32 + 3);
-                               load_addr = *ptmp;
-                               break;
-                       case 3:
-                               count = *(ptru32 + 2);
-                               nextImage = *ptmp;
-                               load_addr = *(ptmp + 1);
-                               break;
-                       case 2:
-                               count = *ptmp;
-                               nextImage = *(ptmp + 1);
-                               load_addr = *(ptmp + 2);
-                               break;
-
-                       case 1:
-                               count = *(ptmp + 1);
-                               nextImage = *(ptmp + 2);
-                               load_addr = *(ptmp + 3);
-                               break;
+               pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
 
-                       default:
-                               count = 0;
-                               nextImage = 0;
-                               load_addr = 0;
-                               /* FIXME
-                               ERROR CASE
-                               */
-                               ;
+               load_addr = pExtImage->LoadStartAddress;
 
-                       }
-                       count = (count +3)/4;
-               }
+               fwSize = (pExtImage->ImageSize + 3) >> 2;
+               ptrFw = (u32 *)pExtImage;
 
-               ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
-                                               ioc->name, count, ptru32));
+               ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+                                               ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
 
-               while (count--) {
-                       if (left_u32s == 0) {
-                               fw_idx++;
-                               if (fw_idx >= max_idx) {
-                                       /* FIXME
-                                       ERROR CASE
-                                       */
-                                       ;
-                               }
-                               ptru32 = (u32 *) pCached[fw_idx]->fw;
-                               left_u32s = pCached[fw_idx]->size / 4;
-                       }
-                       left_u32s--;
-                       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
-                       ptru32++;
+               while (fwSize--) {
+                       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
                }
+               nextImage = pExtImage->NextImageHeaderOffset;
        }
 
        /* Write the IopResetVectorRegAddr */
-       ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
+       ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name,      pFwHeader->IopResetRegAddr));
+       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
 
        /* Write the IopResetVectorValue */
-       ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
+       ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
+       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
 
        /* Clear the internal flash bad bit - autoincrementing register,
         * so must do two writes.
         */
-       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);
+       if (ioc->bus_type == SPI) {
+               /*
+                * 1030 and 1035 H/W errata, workaround to access
+                * the ClearFlashBadSignatureBit
+                */
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+               diagRwData |= 0x40000000;
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+
+       } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
+               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+               CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
+                   MPI_DIAG_CLEAR_FLASH_BAD_SIG);
+
+               /* wait 1 msec */
+               if (sleepFlag == CAN_SLEEP) {
+                       msleep_interruptible (1);
+               } else {
+                       mdelay (1);
+               }
+       }
+
+       if (ioc->errata_flag_1064)
+               pci_disable_io_access(ioc->pcidev);
 
-       /* 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);
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
+               "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
+               ioc->name, diag0val));
+       diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+               ioc->name, diag0val));
        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
        /* Write 0xFF to reset the sequencer */
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
-       return 0;
+       if (ioc->bus_type == SAS) {
+               ioc_state = mpt_GetIocState(ioc, 0);
+               if ( (GetIocFacts(ioc, sleepFlag,
+                               MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
+                       ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
+                                       ioc->name, ioc_state));
+                       return -EFAULT;
+               }
+       }
+
+       for (count=0; count<HZ*20; count++) {
+               if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
+                       ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
+                                       ioc->name, count, ioc_state));
+                       if (ioc->bus_type == SAS) {
+                               return 0;
+                       }
+                       if ((SendIocInit(ioc, sleepFlag)) != 0) {
+                               ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+                                       ioc->name));
+                               return -EFAULT;
+                       }
+                       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+                                       ioc->name));
+                       return 0;
+               }
+               if (sleepFlag == CAN_SLEEP) {
+                       msleep_interruptible (10);
+               } else {
+                       mdelay (10);
+               }
+       }
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
+               ioc->name, ioc_state));
+       return -EFAULT;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3330,9 +3113,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
  *                       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  
+ *              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
@@ -3341,19 +3124,18 @@ static int
 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 {
        int hard_reset_done = 0;
-       u32 ioc_state;
-       int cntdn, cnt = 0;
+       u32 ioc_state=0;
+       int cnt,cntdn;
 
-       dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
-       if ((int)ioc->chip_type > (int)FC929) {
+       dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+       if (ioc->bus_type == SPI) {
                /* Always issue a Msg Unit Reset first. This will clear some
                 * SCSI bus hang conditions.
                 */
                SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
 
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ);
+                       msleep_interruptible (1000);
                } else {
                        mdelay (1000);
                }
@@ -3363,26 +3145,26 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
        if (hard_reset_done < 0)
                return hard_reset_done;
 
-       dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
+       dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
                        ioc->name));
 
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20;    /* 20 seconds */
+       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;     /* 2 seconds */
        for (cnt=0; cnt<cntdn; cnt++) {
-               if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
-                       dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
-                                       ioc->name, cnt));
+               ioc_state = mpt_GetIocState(ioc, 1);
+               if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
+                       dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
+                                       ioc->name, cnt));
                        return hard_reset_done;
                }
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       msleep_interruptible (10);
                } else {
                        mdelay (10);
                }
        }
 
-       printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
-                       ioc->name);
+       printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
+                       ioc->name, ioc_state);
        return -1;
 }
 
@@ -3446,8 +3228,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 
                        /* wait 100 msec */
                        if (sleepFlag == CAN_SLEEP) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(100 * HZ / 1000);
+                               msleep_interruptible (100);
                        } else {
                                mdelay (100);
                        }
@@ -3472,18 +3253,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
                                ioc->name, diag0val, diag1val));
 #endif
-               /* Write the PreventIocBoot bit */
-               if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
-                       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);
+               mdelay(1);
 
                /*
                 * Now hit the reset bit in the Diagnostic register
@@ -3508,44 +3283,37 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                                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);
+                                       r += mpt_signal_reset(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);
+                                               r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
                                        }
                                }
                        }
                        /* FIXME?  Examine results here? */
                }
 
-               if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
+               if (ioc->cached_fw) {
                        /* 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);
+                                       msleep_interruptible (1000);
                                } else {
                                        mdelay (1000);
                                }
                        }
-                       if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+                       if ((count = mpt_downloadboot(ioc,
+                               (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
                                printk(KERN_WARNING MYNAM
                                        ": firmware downloadboot failure (%d)!\n", count);
                        }
@@ -3567,8 +3335,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 
                                /* wait 1 sec */
                                if (sleepFlag == CAN_SLEEP) {
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                                       schedule_timeout(HZ);
+                                       msleep_interruptible (1000);
                                } else {
                                        mdelay (1000);
                                }
@@ -3593,6 +3360,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                /* Write magic sequence to WriteSequence register
                 * Loop until in diagnostic mode
                 */
+               CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
                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);
@@ -3601,8 +3369,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 
                /* wait 100 msec */
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(100 * HZ / 1000);
+                       msleep_interruptible (100);
                } else {
                        mdelay (100);
                }
@@ -3672,7 +3439,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
        u32 state;
        int cntdn, count;
 
-       dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+       drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
                        ioc->name, reset_type));
        CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
@@ -3691,13 +3458,12 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
                                count *= 10;
 
                        printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
-                                       ioc->name, (count+5)/HZ);
+                                       ioc->name, (int)((count+5)/HZ));
                        return -ETIME;
                }
 
                if (sleepFlag == CAN_SLEEP) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       msleep_interruptible(1);
                } else {
                        mdelay (1);     /* 1 msec delay */
                }
@@ -3715,35 +3481,45 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     PrimeIocFifos - Initialize IOC request and reply FIFOs.
- *     @ioc: Pointer to MPT_ADAPTER structure
- *
- *     This routine allocates memory for the MPT reply and request frame
- *     pools (if necessary), and primes the IOC reply FIFO with
- *     reply frames.
- *
- *     Returns 0 for success, non-zero for failure.
+ *     initChainBuffers - Allocate memory for and initialize
+ *     chain buffers, chain buffer control arrays and spinlock.
+ *     @hd: Pointer to MPT_SCSI_HOST structure
+ *     @init: If set, initialize the spin lock.
  */
 static int
-PrimeIocFifos(MPT_ADAPTER *ioc)
+initChainBuffers(MPT_ADAPTER *ioc)
 {
-       MPT_FRAME_HDR *mf;
-       unsigned long b;
-       unsigned long flags;
-       dma_addr_t aligned_mem_dma;
-       u8 *aligned_mem;
-       int i, sz;
-       int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
-       int scale, num_sge, num_chain;
+       u8              *mem;
+       int             sz, ii, num_chain;
+       int             scale, num_sge, numSGE;
+
+       /* ReqToChain size must equal the req_depth
+        * index = req_idx
+        */
+       if (ioc->ReqToChain == NULL) {
+               sz = ioc->req_depth * sizeof(int);
+               mem = kmalloc(sz, GFP_ATOMIC);
+               if (mem == NULL)
+                       return -1;
 
-       /* request buffer size,  rounding UP to nearest 4-kB boundary */
-       request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
-       request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+               ioc->ReqToChain = (int *) mem;
+               dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc  @ %p, sz=%d bytes\n",
+                               ioc->name, mem, sz));
+               mem = kmalloc(sz, GFP_ATOMIC);
+               if (mem == NULL)
+                       return -1;
 
-       /* reply buffer size */
-       reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+               ioc->RequestNB = (int *) mem;
+               dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc  @ %p, sz=%d bytes\n",
+                               ioc->name, mem, sz));
+       }
+       for (ii = 0; ii < ioc->req_depth; ii++) {
+               ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
+       }
 
-       /* chain buffer size, copied from from mptscsih_initChainBuffers()
+       /* ChainToChain size must equal the total number
+        * of chain buffers to be allocated.
+        * index = chain_idx
         *
         * Calculate the number of chain buffers needed(plus 1) per I/O
         * then multiply the the maximum number of simultaneous cmds
@@ -3751,77 +3527,137 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
         * num_sge = num sge in request frame + last chain buffer
         * scale = num sge per chain buffer if no chain element
         */
-
        scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
        if (sizeof(dma_addr_t) == sizeof(u64))
                num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
        else
-               num_sge =  1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+               num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+
+       if (sizeof(dma_addr_t) == sizeof(u64)) {
+               numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+                       (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+       } else {
+               numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+                       (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+       }
+       dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
+               ioc->name, num_sge, numSGE));
+
+       if ( numSGE > MPT_SCSI_SG_DEPTH )
+               numSGE = MPT_SCSI_SG_DEPTH;
+
+       num_chain = 1;
+       while (numSGE - num_sge > 0) {
+               num_chain++;
+               num_sge += (scale - 1);
+       }
+       num_chain++;
+
+       dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
+               ioc->name, numSGE, num_sge, num_chain));
+
+       if (ioc->bus_type == SPI)
+               num_chain *= MPT_SCSI_CAN_QUEUE;
+       else
+               num_chain *= MPT_FC_CAN_QUEUE;
+
+       ioc->num_chain = num_chain;
+
+       sz = num_chain * sizeof(int);
+       if (ioc->ChainToChain == NULL) {
+               mem = kmalloc(sz, GFP_ATOMIC);
+               if (mem == NULL)
+                       return -1;
+
+               ioc->ChainToChain = (int *) mem;
+               dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
+                               ioc->name, mem, sz));
+       } else {
+               mem = (u8 *) ioc->ChainToChain;
+       }
+       memset(mem, 0xFF, sz);
+       return num_chain;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     PrimeIocFifos - Initialize IOC request and reply FIFOs.
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *
+ *     This routine allocates memory for the MPT reply and request frame
+ *     pools (if necessary), and primes the IOC reply FIFO with
+ *     reply frames.
+ *
+ *     Returns 0 for success, non-zero for failure.
+ */
+static int
+PrimeIocFifos(MPT_ADAPTER *ioc)
+{
+       MPT_FRAME_HDR *mf;
+       unsigned long flags;
+       dma_addr_t alloc_dma;
+       u8 *mem;
+       int i, reply_sz, sz, total_size, num_chain;
 
-       num_chain = 1;
-       while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
-               num_chain++;
-               num_sge += (scale - 1);
-       }
-       num_chain++;
+       /*  Prime reply FIFO...  */
 
-       if ((int)ioc->chip_type > (int) FC929)
-               num_chain *= MPT_SCSI_CAN_QUEUE;
-       else
-               num_chain *= MPT_FC_CAN_QUEUE;
+       if (ioc->reply_frames == NULL) {
+               if ( (num_chain = initChainBuffers(ioc)) < 0)
+                       return -1;
 
-       chain_buffer_sz = num_chain * ioc->req_sz;
+               total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
+               dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
+                               ioc->name, ioc->reply_sz, ioc->reply_depth));
+               dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
+                               ioc->name, reply_sz, reply_sz));
+
+               sz = (ioc->req_sz * ioc->req_depth);
+               dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+                               ioc->name, ioc->req_sz, ioc->req_depth));
+               dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
+                               ioc->name, sz, sz));
+               total_size += sz;
+
+               sz = num_chain * ioc->req_sz; /* chain buffer pool size */
+               dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
+                               ioc->name, ioc->req_sz, num_chain));
+               dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
+                               ioc->name, sz, sz, num_chain));
+
+               total_size += sz;
+               mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
+               if (mem == NULL) {
+                       printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
+                               ioc->name);
+                       goto out_fail;
+               }
 
-       if(ioc->fifo_pool == NULL) {
+               dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
+                               ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
 
-               ioc->fifo_pool_sz = request_buffer_sz +
-                       reply_buffer_sz + chain_buffer_sz;
+               memset(mem, 0, total_size);
+               ioc->alloc_total += total_size;
+               ioc->alloc = mem;
+               ioc->alloc_dma = alloc_dma;
+               ioc->alloc_sz = total_size;
+               ioc->reply_frames = (MPT_FRAME_HDR *) mem;
+               ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
 
-               ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
-               ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
+               dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
+                       ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
 
-               if( ioc->fifo_pool == NULL)
-                       goto out_fail;
+               alloc_dma += reply_sz;
+               mem += reply_sz;
 
-               ioc->alloc_total += ioc->fifo_pool_sz;
-               memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
-
-               /* reply fifo pointers */
-               ioc->reply_alloc = ioc->fifo_pool;
-               ioc->reply_alloc_dma = ioc->fifo_pool_dma;
-               /* request fifo pointers */
-               ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
-               ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
-               /* chain buffer pointers */
-               ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
-               ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
-               ioc->chain_alloc_sz = chain_buffer_sz;
-
-               /*  Prime reply FIFO...  */
-               dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
-                               ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
-
-               b = (unsigned long) ioc->reply_alloc;
-               b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-               aligned_mem = (u8 *) b;
-               ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
-               ioc->reply_frames_dma =
-                       (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
-
-               ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
-       
                /*  Request FIFO - WE manage this!  */
-               dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
-                               ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
 
-               b = (unsigned long) ioc->req_alloc;
-               b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-               aligned_mem = (u8 *) b;
-               ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
-               ioc->req_frames_dma =
-                       (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
+               ioc->req_frames = (MPT_FRAME_HDR *) mem;
+               ioc->req_frames_dma = alloc_dma;
 
-               ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
+               dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
+                               ioc->name, mem, (void *)(ulong)alloc_dma));
+
+               ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
 
 #if defined(CONFIG_MTRR) && 0
                /*
@@ -3829,79 +3665,94 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
                 *  (at least as much as we can; "size and base must be
                 *  multiples of 4 kiB"
                 */
-               ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
-                                        ioc->fifo_pool_sz,
+               ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
+                                        sz,
                                         MTRR_TYPE_WRCOMB, 1);
                dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
-                               ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
+                               ioc->name, ioc->req_frames_dma, sz));
 #endif
 
-       } /* ioc->fifo_pool == NULL */
-       
-       /* 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->req_depth; i++) {
+                       alloc_dma += ioc->req_sz;
+                       mem += ioc->req_sz;
+               }
 
-       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->ChainBuffer = mem;
+               ioc->ChainBufferDMA = alloc_dma;
 
+               dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
+                       ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
 
-       /* 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));
+               /* Initialize the free chain Q.
+               */
 
-       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;
+               INIT_LIST_HEAD(&ioc->FreeChainQ);
 
-               /*  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);
+               /* Post the chain buffers to the FreeChainQ.
+               */
+               mem = (u8 *)ioc->ChainBuffer;
+               for (i=0; i < num_chain; i++) {
+                       mf = (MPT_FRAME_HDR *) mem;
+                       list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
+                       mem += ioc->req_sz;
+               }
+
+               /* Initialize Request frames linked list
+                */
+               alloc_dma = ioc->req_frames_dma;
+               mem = (u8 *) ioc->req_frames;
 
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
+               INIT_LIST_HEAD(&ioc->FreeQ);
+               for (i = 0; i < ioc->req_depth; i++) {
+                       mf = (MPT_FRAME_HDR *) mem;
+
+                       /*  Queue REQUESTs *internally*!  */
+                       list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+
+                       mem += ioc->req_sz;
+               }
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
-       if (ioc->sense_buf_pool == NULL) {
                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)
+                       pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+               if (ioc->sense_buf_pool == NULL) {
+                       printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
+                               ioc->name);
                        goto out_fail;
+               }
 
                ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
                ioc->alloc_total += sz;
+               dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
+                       ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
+
+       }
+
+       /* Post Reply frames to FIFO
+        */
+       alloc_dma = ioc->alloc_dma;
+       dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
+               ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
+       for (i = 0; i < ioc->reply_depth; i++) {
+               /*  Write each address to the IOC!  */
+               CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
+               alloc_dma += ioc->reply_sz;
        }
 
        return 0;
 
 out_fail:
-       if (ioc->fifo_pool != NULL) {
+       if (ioc->alloc != NULL) {
+               sz = ioc->alloc_sz;
                pci_free_consistent(ioc->pcidev,
-                               ioc->fifo_pool_sz,
-                               ioc->fifo_pool, ioc->fifo_pool_dma);
+                               sz,
+                               ioc->alloc, ioc->alloc_dma);
                ioc->reply_frames = NULL;
-               ioc->reply_alloc = NULL;
                ioc->req_frames = NULL;
-               ioc->req_alloc = NULL;
-               ioc->chain_alloc = NULL;
-               ioc->fifo_pool = NULL;
-               ioc->alloc_total -= ioc->fifo_pool_sz;
-#if defined(CONFIG_MTRR) && 0
-               if (ioc->mtrr_reg > 0) {
-                       mtrr_del(ioc->mtrr_reg, 0, 0);
-                       dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
-                                       ioc->name));
-               }
-#endif
+               ioc->alloc_total -= sz;
        }
        if (ioc->sense_buf_pool != NULL) {
                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
@@ -3932,9 +3783,9 @@ out_fail:
  *
  *     Returns 0 for success, non-zero for failure.
  */
-int
+static int
 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
-                               int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+               int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
 {
        MPIDefaultReply_t *mptReply;
        int failcnt = 0;
@@ -3963,8 +3814,8 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
        if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
                failcnt++;
 
-       dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
-                       ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+       dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
+                       ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
        /* Read doorbell and check for active bit */
        if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
@@ -3998,7 +3849,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
                                failcnt++;
                }
 
-               dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
+               dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
                DBG_DUMP_REQUEST_FRAME_HDR(req)
 
                dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
@@ -4010,6 +3861,9 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
                if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
                        failcnt++;
 
+               dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
+                               ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
+
                /*
                 * Copy out the cached reply...
                 */
@@ -4040,17 +3894,16 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 {
        int cntdn;
        int count = 0;
-       u32 intstat;
+       u32 intstat=0;
 
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+       cntdn = 1000 * howlong;
 
        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);
+                       msleep_interruptible (1);
                        count++;
                }
        } else {
@@ -4064,13 +3917,13 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
        }
 
        if (cntdn) {
-               dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
+               dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
                                ioc->name, count));
                return count;
        }
 
-       printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
-                       ioc->name, (count+5)/HZ);
+       printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
+                       ioc->name, count, intstat);
        return -1;
 }
 
@@ -4091,16 +3944,15 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 {
        int cntdn;
        int count = 0;
-       u32 intstat;
+       u32 intstat=0;
 
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+       cntdn = 1000 * howlong;
        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);
+                       msleep_interruptible(1);
                        count++;
                }
        } else {
@@ -4114,13 +3966,13 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
        }
 
        if (cntdn) {
-               dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
-                               ioc->name, count));
+               dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
+                               ioc->name, count, howlong));
                return count;
        }
 
-       printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
-                       ioc->name, (count+5)/HZ);
+       printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
+                       ioc->name, count, intstat);
        return -1;
 }
 
@@ -4166,8 +4018,8 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
                }
        }
 
-       dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
-                       ioc->name, le32_to_cpu(*(u32 *)hs_reply),
+       dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
+                       ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
                        failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
        /*
@@ -4202,11 +4054,11 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
        }
 #endif
 
-       dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
+       dhsprintk((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));
+       dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
+                       ioc->name, t, u16cnt/2));
        return u16cnt/2;
 }
 
@@ -4239,7 +4091,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
        hdr.PageLength = 0;
        hdr.PageNumber = 0;
        hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
-       cfg.hdr = &hdr;
+       cfg.cfghdr.hdr = &hdr;
        cfg.physAddr = -1;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;
@@ -4283,7 +4135,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
        hdr.PageLength = 0;
        hdr.PageNumber = 1;
        hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
-       cfg.hdr = &hdr;
+       cfg.cfghdr.hdr = &hdr;
        cfg.physAddr = -1;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;
@@ -4323,7 +4175,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     GetFcPortPage0 - Fetch FCPort config Page0.
+ *     mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @portnum: IOC Port number
  *
@@ -4333,8 +4185,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
  *             -EAGAIN if no msg frames currently available
  *             -EFAULT for non-successful reply or no reply (timeout)
  */
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
 {
        ConfigPageHeader_t       hdr;
        CONFIGPARMS              cfg;
@@ -4344,13 +4196,15 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        int                      data_sz;
        int                      copy_sz;
        int                      rc;
+       int                      count = 400;
+
 
        /* 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.cfghdr.hdr = &hdr;
        cfg.physAddr = -1;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;
@@ -4367,6 +4221,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        rc = -ENOMEM;
        ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
        if (ppage0_alloc) {
+
+ try_again:
                memset((u8 *)ppage0_alloc, 0, data_sz);
                cfg.physAddr = page0_dma;
                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4398,6 +4254,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
                        pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
                        pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
 
+                       /*
+                        * if still doing discovery,
+                        * hang loose a while until finished
+                        */
+                       if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+                               if (count-- > 0) {
+                                       msleep_interruptible(100);
+                                       goto try_again;
+                               }
+                               printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+                                                       " complete.\n",
+                                               ioc->name);
+                       }
                }
 
                pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -4406,6 +4275,217 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        return rc;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @sas_address: 64bit SAS Address for operation.
+ *     @target_id: specified target for operation
+ *     @bus: specified bus for operation
+ *     @persist_opcode: see below
+ *
+ *     MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+ *             devices not currently present.
+ *     MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+ *
+ *     NOTE: Don't use not this function during interrupt time.
+ *
+ *     Returns: 0 for success, non-zero error
+ */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int
+mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
+{
+       SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
+       SasIoUnitControlReply_t         *sasIoUnitCntrReply;
+       MPT_FRAME_HDR                   *mf = NULL;
+       MPIHeader_t                     *mpi_hdr;
+
+
+       /* insure garbage is not sent to fw */
+       switch(persist_opcode) {
+
+       case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+       case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+               break;
+
+       default:
+               return -1;
+               break;
+       }
+
+       printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+
+       /* Get a MF for this command.
+        */
+       if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+               printk("%s: no msg frames!\n",__FUNCTION__);
+               return -1;
+        }
+
+       mpi_hdr = (MPIHeader_t *) mf;
+       sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+       memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+       sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+       sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+       sasIoUnitCntrReq->Operation = persist_opcode;
+
+       init_timer(&ioc->persist_timer);
+       ioc->persist_timer.data = (unsigned long) ioc;
+       ioc->persist_timer.function = mpt_timer_expired;
+       ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
+       ioc->persist_wait_done=0;
+       add_timer(&ioc->persist_timer);
+       mpt_put_msg_frame(mpt_base_index, ioc, mf);
+       wait_event(mpt_waitq, ioc->persist_wait_done);
+
+       sasIoUnitCntrReply =
+           (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+       if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
+               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+                   __FUNCTION__,
+                   sasIoUnitCntrReply->IOCStatus,
+                   sasIoUnitCntrReply->IOCLogInfo);
+               return -1;
+       }
+
+       printk("%s: success\n",__FUNCTION__);
+       return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static void
+mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+    MpiEventDataRaid_t * pRaidEventData)
+{
+       int     volume;
+       int     reason;
+       int     disk;
+       int     status;
+       int     flags;
+       int     state;
+
+       volume  = pRaidEventData->VolumeID;
+       reason  = pRaidEventData->ReasonCode;
+       disk    = pRaidEventData->PhysDiskNum;
+       status  = le32_to_cpu(pRaidEventData->SettingsStatus);
+       flags   = (status >> 0) & 0xff;
+       state   = (status >> 8) & 0xff;
+
+       if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+               return;
+       }
+
+       if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
+            reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
+           (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
+               printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
+                       ioc->name, disk);
+       } else {
+               printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
+                       ioc->name, volume);
+       }
+
+       switch(reason) {
+       case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+               printk(MYIOC_s_INFO_FMT "  volume has been created\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+
+               printk(MYIOC_s_INFO_FMT "  volume has been deleted\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
+               printk(MYIOC_s_INFO_FMT "  volume settings have been changed\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+               printk(MYIOC_s_INFO_FMT "  volume is now %s%s%s%s\n",
+                       ioc->name,
+                       state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
+                        ? "optimal"
+                        : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
+                         ? "degraded"
+                         : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
+                          ? "failed"
+                          : "state unknown",
+                       flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
+                        ? ", enabled" : "",
+                       flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
+                        ? ", quiesced" : "",
+                       flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
+                        ? ", resync in progress" : "" );
+               break;
+
+       case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
+               printk(MYIOC_s_INFO_FMT "  volume membership of PhysDisk %d has changed\n",
+                       ioc->name, disk);
+               break;
+
+       case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+               printk(MYIOC_s_INFO_FMT "  PhysDisk has been created\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+               printk(MYIOC_s_INFO_FMT "  PhysDisk has been deleted\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
+               printk(MYIOC_s_INFO_FMT "  PhysDisk settings have been changed\n",
+                       ioc->name);
+               break;
+
+       case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+               printk(MYIOC_s_INFO_FMT "  PhysDisk is now %s%s%s\n",
+                       ioc->name,
+                       state == MPI_PHYSDISK0_STATUS_ONLINE
+                        ? "online"
+                        : state == MPI_PHYSDISK0_STATUS_MISSING
+                         ? "missing"
+                         : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
+                          ? "not compatible"
+                          : state == MPI_PHYSDISK0_STATUS_FAILED
+                           ? "failed"
+                           : state == MPI_PHYSDISK0_STATUS_INITIALIZING
+                            ? "initializing"
+                            : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
+                             ? "offline requested"
+                             : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
+                              ? "failed requested"
+                              : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
+                               ? "offline"
+                               : "state unknown",
+                       flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
+                        ? ", out of sync" : "",
+                       flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
+                        ? ", quiesced" : "" );
+               break;
+
+       case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
+               printk(MYIOC_s_INFO_FMT "  Domain Validation needed for PhysDisk %d\n",
+                       ioc->name, disk);
+               break;
+
+       case MPI_EVENT_RAID_RC_SMART_DATA:
+               printk(MYIOC_s_INFO_FMT "  SMART data received, ASC/ASCQ = %02xh/%02xh\n",
+                       ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
+               break;
+
+       case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
+               printk(MYIOC_s_INFO_FMT "  replacement of PhysDisk %d has started\n",
+                       ioc->name, disk);
+               break;
+       }
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     GetIoUnitPage2 - Retrieve BIOS version and boot order information.
@@ -4432,7 +4512,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
        hdr.PageLength = 0;
        hdr.PageNumber = 2;
        hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
-       cfg.hdr = &hdr;
+       cfg.cfghdr.hdr = &hdr;
        cfg.physAddr = -1;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;
@@ -4522,7 +4602,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
        header.PageLength = 0;
        header.PageNumber = 0;
        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = portnum;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4542,6 +4622,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
                                ioc->spi_data.minSyncFactor = MPT_ASYNC;
                                ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
                                rc = 1;
+                               ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
+                                       ioc->name, ioc->spi_data.minSyncFactor));
                        } else {
                                /* Save the Port Page 0 data
                                 */
@@ -4549,15 +4631,19 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
                                pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
                                pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
 
-                               if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
+                               if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
                                        ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-
+                                       ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+                                               ioc->name, pPP0->Capabilities));
+                               }
                                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);
+                                       ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
+                                               ioc->name, ioc->spi_data.minSyncFactor));
                                } else {
                                        ioc->spi_data.maxSyncOffset = 0;
                                        ioc->spi_data.minSyncFactor = MPT_ASYNC;
@@ -4570,8 +4656,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
                                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)
+                                       if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
                                                ioc->spi_data.minSyncFactor = MPT_ULTRA;
+                                               ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
+                                                       ioc->name, ioc->spi_data.minSyncFactor));
+                                       }
                                }
                        }
                        if (pbuf) {
@@ -4586,7 +4675,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
        header.PageLength = 0;
        header.PageNumber = 2;
        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = portnum;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4609,6 +4698,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
                                SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
                                MpiDeviceInfo_t *pdevice = NULL;
 
+                               /*
+                                * Save "Set to Avoid SCSI Bus Resets" flag
+                                */
+                               ioc->spi_data.bus_reset =
+                                   (le32_to_cpu(pPP2->PortFlags) &
+                               MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
+                                   0 : 1 ;
+
                                /* Save the Port Page 2 data
                                 * (reformat into a 32bit quantity)
                                 */
@@ -4654,7 +4751,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
        header.PageLength = 0;
        header.PageNumber = 1;
        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = portnum;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4663,8 +4760,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
        if (mpt_config(ioc, &cfg) != 0)
                 return -EFAULT;
 
-       ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
-       ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+       ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
+       ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
 
        header.PageVersion = 0;
        header.PageLength = 0;
@@ -4673,8 +4770,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
        if (mpt_config(ioc, &cfg) != 0)
                 return -EFAULT;
 
-       ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
-       ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+       ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
+       ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
 
        dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
                        ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
@@ -4716,7 +4813,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
        header.PageLength = 0;
        header.PageNumber = 2;
        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4738,10 +4835,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
        if (mpt_config(ioc, &cfg) != 0)
                goto done_and_free;
 
-       if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
+       if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
                mem = kmalloc(iocpage2sz, GFP_ATOMIC);
                if (mem) {
-                       ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
+                       ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
                } else {
                        goto done_and_free;
                }
@@ -4758,7 +4855,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
                /* At least 1 RAID Volume
                 */
                pIocRv = pIoc2->RaidVolume;
-               ioc->spi_data.isRaid = 0;
+               ioc->raid_data.isRaid = 0;
                for (jj = 0; jj < nVols; jj++, pIocRv++) {
                        vid = pIocRv->VolumeID;
                        vbus = pIocRv->VolumeBus;
@@ -4767,7 +4864,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
                        /* find the match
                         */
                        if (vbus == 0) {
-                               ioc->spi_data.isRaid |= (1 << vid);
+                               ioc->raid_data.isRaid |= (1 << vid);
                        } else {
                                /* Error! Always bus 0
                                 */
@@ -4790,7 +4887,7 @@ done_and_free:
        return rc;
 }
 
-int
+static int
 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 {
        IOCPage3_t              *pIoc3;
@@ -4802,10 +4899,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 
        /* Free the old page
         */
-       if (ioc->spi_data.pIocPg3) {
-               kfree(ioc->spi_data.pIocPg3);
-               ioc->spi_data.pIocPg3 = NULL;
-       }
+       kfree(ioc->raid_data.pIocPg3);
+       ioc->raid_data.pIocPg3 = NULL;
 
        /* There is at least one physical disk.
         * Read and save IOC Page 3
@@ -4814,7 +4909,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
        header.PageLength = 0;
        header.PageNumber = 3;
        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4842,7 +4937,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
                mem = kmalloc(iocpage3sz, GFP_ATOMIC);
                if (mem) {
                        memcpy(mem, (u8 *)pIoc3, iocpage3sz);
-                       ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+                       ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
                }
        }
 
@@ -4866,7 +4961,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
        header.PageLength = 0;
        header.PageNumber = 4;
        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4918,7 +5013,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
        header.PageLength = 0;
        header.PageNumber = 1;
        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-       cfg.hdr = &header;
+       cfg.cfghdr.hdr = &header;
        cfg.physAddr = -1;
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4998,22 +5093,22 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
 {
        EventNotification_t     *evnp;
 
-       evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
+       evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
        if (evnp == NULL) {
-               dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+               devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
                                ioc->name));
                return 0;
        }
        memset(evnp, 0, sizeof(*evnp));
 
-       dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+       devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
 
        evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
        evnp->ChainOffset = 0;
        evnp->MsgFlags = 0;
        evnp->Switch = EvSwitch;
 
-       mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
+       mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
 
        return 0;
 }
@@ -5025,142 +5120,37 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
  *     @evnp: Pointer to original EventNotification request
  */
 static int
-SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
-{
-       EventAck_t      *pAck;
-
-       if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
-               printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
-                               ioc->name);
-               return -1;
-       }
-       memset(pAck, 0, sizeof(*pAck));
-
-       dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
-
-       pAck->Function     = MPI_FUNCTION_EVENT_ACK;
-       pAck->ChainOffset  = 0;
-       pAck->MsgFlags     = 0;
-       pAck->Event        = evnp->Event;
-       pAck->EventContext = evnp->EventContext;
-
-       mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
-
-       return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     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;
-       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) {
-               dcprintk((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) {
-               dcprintk((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->ExtPageLength = 0;
-       pReq->ExtPageType = 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.
-        */
-       if (pCfg->dir)
-               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
-       else
-               flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
-
-       flagsLength |= pCfg->hdr->PageLength * 4;
-
-       mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
-
-       dcprintk((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;
+SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
+{
+       EventAck_t      *pAck;
 
-       /* 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);
+       if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+               printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
+                       "request frame for Event=%x EventContext=%x EventData=%x!\n",
+                       ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
+                       le32_to_cpu(evnp->Data[0]));
+               return -1;
+       }
+       memset(pAck, 0, sizeof(*pAck));
 
-       add_timer(&pCfg->timer);
-       mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
-       wait_event(mpt_waitq, pCfg->wait_done);
+       dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
 
-       /* mf has been freed - do not access */
+       pAck->Function     = MPI_FUNCTION_EVENT_ACK;
+       pAck->ChainOffset  = 0;
+       pAck->MsgFlags     = 0;
+       pAck->Event        = evnp->Event;
+       pAck->EventContext = evnp->EventContext;
 
-       rc = pCfg->status;
+       mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
 
-       return rc;
+       return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_toolbox - Generic function to issue toolbox message
+ *     mpt_config - Generic function to issue config message
  *     @ioc - Pointer to an adapter structure
- *     @cfg - Pointer to a toolbox structure. Struct contains
+ *     @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.
@@ -5171,63 +5161,85 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
  *     -EFAULT for non-successful reply or no reply (timeout)
  */
 int
-mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
+mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 {
-       ToolboxIstwiReadWriteRequest_t  *pReq;
+       Config_t        *pReq;
+       ConfigExtendedPageHeader_t  *pExtHdr = NULL;
        MPT_FRAME_HDR   *mf;
        unsigned long    flags;
-       int              rc;
+       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
+       /*      Prevent calling wait_event() (below), if caller happens
         *      to be in ISR context, because that is fatal!
         */
        in_isr = in_interrupt();
        if (in_isr) {
-               dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
+               dcprintk((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) {
-               dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
+       if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+               dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
                                ioc->name));
                return -EAGAIN;
        }
-       pReq = (ToolboxIstwiReadWriteRequest_t  *)mf;
-       pReq->Tool = pCfg->action;
+       pReq = (Config_t *)mf;
+       pReq->Action = pCfg->action;
        pReq->Reserved = 0;
        pReq->ChainOffset = 0;
-       pReq->Function = MPI_FUNCTION_TOOLBOX;
-       pReq->Reserved1 = 0;
-       pReq->Reserved2 = 0;
+       pReq->Function = MPI_FUNCTION_CONFIG;
+
+       /* Assume page type is not extended and clear "reserved" fields. */
+       pReq->ExtPageLength = 0;
+       pReq->ExtPageType = 0;
        pReq->MsgFlags = 0;
-       pReq->Flags = pCfg->dir;
-       pReq->BusNum = 0;
-       pReq->Reserved3 = 0;
-       pReq->NumAddressBytes = 0x01;
-       pReq->Reserved4 = 0;
-       pReq->DataLength = 0x04;
-       pReq->DeviceAddr = 0xB0;
-       pReq->Addr1 = 0;
-       pReq->Addr2 = 0;
-       pReq->Addr3 = 0;
-       pReq->Reserved5 = 0;
+
+       for (ii=0; ii < 8; ii++)
+               pReq->Reserved2[ii] = 0;
+
+       pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
+       pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
+       pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
+       pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+
+       if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+               pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
+               pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
+               pReq->ExtPageType = pExtHdr->ExtPageType;
+               pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+
+               /* Page Length must be treated as a reserved field for the extended header. */
+               pReq->Header.PageLength = 0;
+       }
+
+       pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
 
        /* Add a SGE to the config request.
         */
+       if (pCfg->dir)
+               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+       else
+               flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
 
-       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
+       if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+               flagsLength |= pExtHdr->ExtPageLength * 4;
 
-       mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
+               dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+                       ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
+       }
+       else {
+               flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
+
+               dcprintk((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));
+       }
 
-       dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
-               ioc->name, pReq->Tool));
+       mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
 
        /* Append pCfg pointer to end of mf
         */
@@ -5248,11 +5260,11 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 
        /* 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);
+       list_add_tail(&pCfg->linkage, &ioc->configQ);
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
        add_timer(&pCfg->timer);
-       mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
+       mpt_put_msg_frame(mpt_base_index, ioc, mf);
        wait_event(mpt_waitq, pCfg->wait_done);
 
        /* mf has been freed - do not access */
@@ -5315,13 +5327,8 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                 * 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);
-               }
+               list_for_each_entry(pCfg, &ioc->configQ, linkage)
+                       del_timer(&pCfg->timer);
                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
        } else {
@@ -5331,19 +5338,12 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                 * 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;
-
-                               Q_DEL_ITEM(&pCfg->linkage);
-
-                               pCfg->status = MPT_CONFIG_ERROR;
-                               pCfg->wait_done = 1;
-                               wake_up(&mpt_waitq);
+               list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
+                       list_del(&pCfg->linkage);
 
-                               pCfg = pNext;
-                       } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
+                       pCfg->status = MPT_CONFIG_ERROR;
+                       pCfg->wait_done = 1;
+                       wake_up(&mpt_waitq);
                }
                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
        }
@@ -5366,61 +5366,19 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 static int
 procmpt_create(void)
 {
-       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
-        */
        mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
        if (mpt_proc_root_dir == NULL)
                return -ENOTDIR;
 
-       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;
-       }
+       ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
+       if (ent)
+               ent->read_proc = procmpt_summary_read;
 
-       ioc = mpt_adapter_find_first();
-       while (ioc != NULL) {
-               struct proc_dir_entry   *dent;
-               /*
-                *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
-                */
-               if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
-                       /*
-                        *  And populate it with mpt_ioc_proc_list[] entries.
-                        */
-                       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;
-                       }
-               } else {
-                       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);
-       }
+       ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
+       if (ent)
+               ent->read_proc = procmpt_version_read;
 
        return 0;
 }
@@ -5431,49 +5389,12 @@ procmpt_create(void)
  *
  *     Returns 0 for success, non-zero for failure.
  */
-static int
+static void
 procmpt_destroy(void)
 {
-       MPT_ADAPTER     *ioc;
-       int              ii;
-
-       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
-        */
-
-       ioc = mpt_adapter_find_first();
-       while (ioc != NULL) {
-               char pname[32];
-               int namelen;
-
-               namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
-
-               /*
-                *  Tear down each "/proc/mpt/iocN" subdirectory.
-                */
-               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);
-       }
-
-       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;
-       }
-
-       return -1;
+       remove_proc_entry("version", mpt_proc_root_dir);
+       remove_proc_entry("summary", mpt_proc_root_dir);
+       remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5496,26 +5417,25 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo
        char *out = buf;
        int len;
 
-       if (data == NULL)
-               ioc = mpt_adapter_find_first();
-       else
-               ioc = data;
-
-       while (ioc) {
-               int     more = 0;
+       if (data) {
+               int more = 0;
 
+               ioc = data;
                mpt_print_ioc_summary(ioc, out, &more, 0, 1);
 
                out += more;
-               if ((out-buf) >= request) {
-                       break;
-               }
+       } else {
+               list_for_each_entry(ioc, &ioc_list, list) {
+                       int     more = 0;
 
-               if (data == NULL)
-                       ioc = mpt_adapter_find_next(ioc);
-               else
-                       ioc = NULL;             /* force exit for iocN */
+                       mpt_print_ioc_summary(ioc, out, &more, 0, 1);
+
+                       out += more;
+                       if ((out-buf) >= request)
+                               break;
+               }
        }
+
        len = out - buf;
 
        MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
@@ -5537,20 +5457,26 @@ static int
 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 {
        int      ii;
-       int      scsi, lan, ctl, targ, dmp;
+       int      scsi, fc, sas, 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;
+       scsi = fc = sas = 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";
+                       case MPTSPI_DRIVER:
+                               if (!scsi++) drvname = "SPI host";
+                               break;
+                       case MPTFC_DRIVER:
+                               if (!fc++) drvname = "FC host";
+                               break;
+                       case MPTSAS_DRIVER:
+                               if (!sas++) drvname = "SAS host";
                                break;
                        case MPTLAN_DRIVER:
                                if (!lan++) drvname = "LAN";
@@ -5561,19 +5487,10 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo
                        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");
                }
        }
 
@@ -5628,7 +5545,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo
        len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
 
        len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
-                                       (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
+                                       (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
        /*
         *  Rounding UP to nearest 4-kB boundary here...
         */
@@ -5640,8 +5557,8 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo
                                        4*ioc->facts.RequestFrameSize,
                                        ioc->facts.GlobalCredits);
 
-       len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
-                                       (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
+       len += sprintf(buf+len, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
+                                       (void *)ioc->alloc, (void *)(ulong)ioc->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);
@@ -5658,7 +5575,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo
                len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
                                p+1,
                                ioc->facts.NumberOfPorts);
-               if ((int)ioc->chip_type <= (int)FC929) {
+               if (ioc->bus_type == FC) {
                        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",
@@ -5805,11 +5722,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
                        if (MptResetHandlers[ii]) {
                                dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
                                                ioc->name, ii));
-                               r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
+                               r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
                                if (ioc->alt_ioc) {
                                        dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
                                                        ioc->name, ioc->alt_ioc->name, ii));
-                                       r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
+                                       r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
                                }
                        }
                }
@@ -5834,11 +5751,13 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
        return rc;
 }
 
+# define EVENT_DESCR_STR_SZ            100
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *
-EventDescriptionStr(u8 event, u32 evData0)
+static void
+EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 {
-       char *ds;
+       char *ds = NULL;
 
        switch(event) {
        case MPI_EVENT_NONE:
@@ -5875,9 +5794,9 @@ EventDescriptionStr(u8 event, u32 evData0)
                if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
                        ds = "Loop State(LIP) Change";
                else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
-                       ds = "Loop State(LPE) Change";                  /* ??? */
+                       ds = "Loop State(LPE) Change";          /* ??? */
                else
-                       ds = "Loop State(LPB) Change";                  /* ??? */
+                       ds = "Loop State(LPB) Change";          /* ??? */
                break;
        case MPI_EVENT_LOGOUT:
                ds = "Logout";
@@ -5889,8 +5808,193 @@ EventDescriptionStr(u8 event, u32 evData0)
                        ds = "Events(OFF) Change";
                break;
        case MPI_EVENT_INTEGRATED_RAID:
-               ds = "Integrated Raid";
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+                       ds = "Integrated Raid: Volume Created";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_DELETED :
+                       ds = "Integrated Raid: Volume Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Volume Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
+                       ds = "Integrated Raid: Volume Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
+                       ds = "Integrated Raid: Volume Physdisk Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
+                       ds = "Integrated Raid: Physdisk Created";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
+                       ds = "Integrated Raid: Physdisk Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
+                       ds = "Integrated Raid: Domain Validation Needed";
+                       break;
+               case MPI_EVENT_RAID_RC_SMART_DATA :
+                       ds = "Integrated Raid; Smart Data";
+                       break;
+               case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
+                       ds = "Integrated Raid: Replace Action Started";
+                       break;
+               default:
+                       ds = "Integrated Raid";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
+               ds = "SCSI Device Status Change";
+               break;
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+       {
+               u8 id = (u8)(evData0);
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Added: id=%d", id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Deleted: id=%d", id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: SMART Data: id=%d",
+                           id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: No Persistancy "
+                           "Added: id=%d", id);
+                       break;
+               default:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Unknown: id=%d", id);
+                       break;
+               }
+               break;
+       }
+       case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
+               ds = "Bus Timer Expired";
+               break;
+       case MPI_EVENT_QUEUE_FULL:
+               ds = "Queue Full";
+               break;
+       case MPI_EVENT_SAS_SES:
+               ds = "SAS SES Event";
+               break;
+       case MPI_EVENT_PERSISTENT_TABLE_FULL:
+               ds = "Persistent Table Full";
+               break;
+       case MPI_EVENT_SAS_PHY_LINK_STATUS:
+       {
+               u8 LinkRates = (u8)(evData0 >> 8);
+               u8 PhyNumber = (u8)(evData0);
+               LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
+                       MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
+               switch (LinkRates) {
+               case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Rate Unknown",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Phy Disabled",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Failed Speed Nego",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Sata OOB Completed",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Rate 1.5 Gbps",PhyNumber);
+                       break;
+               case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
+                          " Rate 3.0 Gpbs",PhyNumber);
+                       break;
+               default:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d", PhyNumber);
+                       break;
+               }
+               break;
+       }
+       case MPI_EVENT_SAS_DISCOVERY_ERROR:
+               ds = "SAS Discovery Error";
                break;
+       case MPI_EVENT_IR_RESYNC_UPDATE:
+       {
+               u8 resync_complete = (u8)(evData0 >> 16);
+               snprintf(evStr, EVENT_DESCR_STR_SZ,
+                   "IR Resync Update: Complete = %d:",resync_complete);
+               break;
+       }
+       case MPI_EVENT_IR2:
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
+                       ds = "IR2: LD State Changed";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
+                       ds = "IR2: PD State Changed";
+                       break;
+               case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
+                       ds = "IR2: Bad Block Table Full";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_INSERTED:
+                       ds = "IR2: PD Inserted";
+                       break;
+               case MPI_EVENT_IR2_RC_PD_REMOVED:
+                       ds = "IR2: PD Removed";
+                       break;
+               case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
+                       ds = "IR2: Foreign CFG Detected";
+                       break;
+               case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
+                       ds = "IR2: Rebuild Medium Error";
+                       break;
+               default:
+                       ds = "IR2";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_SAS_DISCOVERY:
+       {
+               if (evData0)
+                       ds = "SAS Discovery: Start";
+               else
+                       ds = "SAS Discovery: Stop";
+               break;
+       }
+       case MPI_EVENT_LOG_ENTRY_ADDED:
+               ds = "SAS Log Entry Added";
+               break;
+
        /*
         *  MPT base "custom" events may be added here...
         */
@@ -5898,7 +6002,8 @@ EventDescriptionStr(u8 event, u32 evData0)
                ds = "Unknown";
                break;
        }
-       return ds;
+       if (ds)
+               strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5920,7 +6025,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        int ii;
        int r = 0;
        int handlers = 0;
-       char *evStr;
+       char evStr[EVENT_DESCR_STR_SZ];
        u8 event;
 
        /*
@@ -5933,13 +6038,13 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
                evData0 = le32_to_cpu(pEventReply->Data[0]);
        }
 
-       evStr = EventDescriptionStr(event, evData0);
-       dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+       EventDescriptionStr(event, evData0, evStr);
+       devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
                        ioc->name,
-                       evStr,
-                       event));
+                       event,
+                       evStr));
 
-#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
        printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
        for (ii = 0; ii < evDataLen; ii++)
                printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
@@ -5950,20 +6055,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
         *  Do general / base driver event processing
         */
        switch(event) {
-       case MPI_EVENT_NONE:                    /* 00 */
-       case MPI_EVENT_LOG_DATA:                /* 01 */
-       case MPI_EVENT_STATE_CHANGE:            /* 02 */
-       case MPI_EVENT_UNIT_ATTENTION:          /* 03 */
-       case MPI_EVENT_IOC_BUS_RESET:           /* 04 */
-       case MPI_EVENT_EXT_BUS_RESET:           /* 05 */
-       case MPI_EVENT_RESCAN:                  /* 06 */
-       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 */
                if (evDataLen) {
                        u8 evState = evData0 & 0xFF;
@@ -5976,6 +6067,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
                        }
                }
                break;
+       case MPI_EVENT_INTEGRATED_RAID:
+               mptbase_raid_process_event_data(ioc,
+                   (MpiEventDataRaid_t *)pEventReply->Data);
+               break;
+       default:
+               break;
        }
 
        /*
@@ -5985,7 +6082,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
                int idx;
 
-               idx = ioc->eventContext % ioc->eventLogSize;
+               idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
 
                ioc->events[idx].event = event;
                ioc->events[idx].eventContext = ioc->eventContext;
@@ -6006,7 +6103,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *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",
+                       devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
                                        ioc->name, ii));
                        r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
                        handlers++;
@@ -6018,9 +6115,11 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
         *  If needed, send (a single) EventAck.
         */
        if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+               devtverboseprintk((MYIOC_s_WARN_FMT
+                       "EventAck required\n",ioc->name));
                if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
-                       printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
-                                       ioc->name, ii);
+                       devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+                                       ioc->name, ii));
                }
        }
 
@@ -6044,15 +6143,14 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
                "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
        };
        u8 subcl = (log_info >> 24) & 0x7;
-//     u32 SubCl = log_info & 0x27000000;
 
-       printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
+       printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
                        ioc->name, log_info, subcl_str[subcl]);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
+ *     mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @mr: Pointer to MPT reply frame
  *     @log_info: U32 LogInfo word from the IOC
@@ -6060,7 +6158,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
  *     Refer to lsi/sp_log.h.
  */
 static void
-mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
+mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
        u32 info = log_info & 0x00FF0000;
        char *desc = "unknown";
@@ -6099,7 +6197,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
        case 0x00080000:
                desc = "Outbound DMA Overrun";
                break;
-       
+
        case 0x00090000:
                desc = "Task Management";
                break;
@@ -6115,12 +6213,117 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
        case 0x000C0000:
                desc = "Untagged Table Size";
                break;
-       
+
        }
 
        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
 }
 
+/* strings for sas loginfo */
+       static char *originator_str[] = {
+               "IOP",                                          /* 00h */
+               "PL",                                           /* 01h */
+               "IR"                                            /* 02h */
+       };
+       static char *iop_code_str[] = {
+               NULL,                                           /* 00h */
+               "Invalid SAS Address",                          /* 01h */
+               NULL,                                           /* 02h */
+               "Invalid Page",                                 /* 03h */
+               NULL,                                           /* 04h */
+               "Task Terminated"                               /* 05h */
+       };
+       static char *pl_code_str[] = {
+               NULL,                                           /* 00h */
+               "Open Failure",                                 /* 01h */
+               "Invalid Scatter Gather List",                  /* 02h */
+               "Wrong Relative Offset or Frame Length",        /* 03h */
+               "Frame Transfer Error",                         /* 04h */
+               "Transmit Frame Connected Low",                 /* 05h */
+               "SATA Non-NCQ RW Error Bit Set",                /* 06h */
+               "SATA Read Log Receive Data Error",             /* 07h */
+               "SATA NCQ Fail All Commands After Error",       /* 08h */
+               "SATA Error in Receive Set Device Bit FIS",     /* 09h */
+               "Receive Frame Invalid Message",                /* 0Ah */
+               "Receive Context Message Valid Error",          /* 0Bh */
+               "Receive Frame Current Frame Error",            /* 0Ch */
+               "SATA Link Down",                               /* 0Dh */
+               "Discovery SATA Init W IOS",                    /* 0Eh */
+               "Config Invalid Page",                          /* 0Fh */
+               "Discovery SATA Init Timeout",                  /* 10h */
+               "Reset",                                        /* 11h */
+               "Abort",                                        /* 12h */
+               "IO Not Yet Executed",                          /* 13h */
+               "IO Executed",                                  /* 14h */
+               "Persistant Reservation Out Not Affiliation Owner", /* 15h */
+               "Open Transmit DMA Abort",                      /* 16h */
+               NULL,                                           /* 17h */
+               NULL,                                           /* 18h */
+               NULL,                                           /* 19h */
+               NULL,                                           /* 1Ah */
+               NULL,                                           /* 1Bh */
+               NULL,                                           /* 1Ch */
+               NULL,                                           /* 1Dh */
+               NULL,                                           /* 1Eh */
+               NULL,                                           /* 1Fh */
+               "Enclosure Management"                          /* 20h */
+       };
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mpt_sas_log_info - Log information returned from SAS IOC.
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @log_info: U32 LogInfo reply word from the IOC
+ *
+ *     Refer to lsi/mpi_log_sas.h.
+ */
+static void
+mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
+{
+union loginfo_type {
+       u32     loginfo;
+       struct {
+               u32     subcode:16;
+               u32     code:8;
+               u32     originator:4;
+               u32     bus_type:4;
+       }dw;
+};
+       union loginfo_type sas_loginfo;
+       char *code_desc = NULL;
+
+       sas_loginfo.loginfo = log_info;
+       if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
+           (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
+               return;
+       if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
+           (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
+               code_desc = iop_code_str[sas_loginfo.dw.code];
+       }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
+           (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
+               code_desc = pl_code_str[sas_loginfo.dw.code];
+       }
+
+       if (code_desc != NULL)
+               printk(MYIOC_s_INFO_FMT
+                       "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+                       " SubCode(0x%04x)\n",
+                       ioc->name,
+                       log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       code_desc,
+                       sas_loginfo.dw.subcode);
+       else
+               printk(MYIOC_s_INFO_FMT
+                       "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+                       " SubCode(0x%04x)\n",
+                       ioc->name,
+                       log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       sas_loginfo.dw.code,
+                       sas_loginfo.dw.subcode);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
@@ -6207,7 +6410,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
                break;
 
        case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
-               /* This error is checked in scsi_io_done(). Skip. 
+               /* This error is checked in scsi_io_done(). Skip.
                desc = "SCSI Data Underrun";
                */
                break;
@@ -6249,53 +6452,14 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
- *     OpCode strings from the (optional) isense module.
- *     @ascqTable: Pointer to ASCQ_Table_t structure
- *     @ascqtbl_sz: Number of entries in ASCQ_Table
- *     @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
- *
- *     Specialized driver registration routine for the isense driver.
- */
-int
-mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
-{
-       int r = 0;
-
-       if (ascqTable && ascqtbl_sz && opsTable) {
-               mpt_v_ASCQ_TablePtr = ascqTable;
-               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;
-       }
-       return r;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
- *     OpCode strings from the isense driver.
- *
- *     Specialized driver deregistration routine for the isense driver.
- */
-void
-mpt_deregister_ascqops_strings(void)
-{
-       mpt_v_ASCQ_TablePtr = NULL;
-       mpt_ASCQ_TableSz = 0;
-       mpt_ScsiOpcodesPtr = NULL;
-       printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
-       isense_idx = -1;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-EXPORT_SYMBOL(mpt_adapters);
+EXPORT_SYMBOL(mpt_attach);
+EXPORT_SYMBOL(mpt_detach);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mpt_resume);
+EXPORT_SYMBOL(mpt_suspend);
+#endif
+EXPORT_SYMBOL(ioc_list);
 EXPORT_SYMBOL(mpt_proc_root_dir);
-EXPORT_SYMBOL(DmpService);
 EXPORT_SYMBOL(mpt_register);
 EXPORT_SYMBOL(mpt_deregister);
 EXPORT_SYMBOL(mpt_event_register);
@@ -6308,11 +6472,7 @@ EXPORT_SYMBOL(mpt_get_msg_frame);
 EXPORT_SYMBOL(mpt_put_msg_frame);
 EXPORT_SYMBOL(mpt_free_msg_frame);
 EXPORT_SYMBOL(mpt_add_sge);
-EXPORT_SYMBOL(mpt_add_chain);
 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);
@@ -6320,32 +6480,12 @@ EXPORT_SYMBOL(mpt_lan_index);
 EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
-EXPORT_SYMBOL(mpt_toolbox);
 EXPORT_SYMBOL(mpt_findImVolumes);
-EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
+EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
 
-EXPORT_SYMBOL(mpt_register_ascqops_strings);
-EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
-EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
-EXPORT_SYMBOL(mpt_ASCQ_TableSz);
-EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
-
-
-static struct pci_driver mptbase_driver = {
-       .name           = "mptbase",
-       .id_table       = mptbase_pci_table,
-       .probe          = mptbase_probe,
-       .remove         = __devexit_p(mptbase_remove),
-       .driver         = {
-               .shutdown = mptbase_shutdown,
-        },
-#ifdef CONFIG_PM
-       .suspend        = mptbase_suspend,
-       .resume         = mptbase_resume,
-#endif
-};
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -6357,17 +6497,10 @@ static int __init
 fusion_init(void)
 {
        int i;
-       int r;
-
-       if (FusionInitCalled++) {
-               dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
-               return 0;
-       }
 
        show_mptmod_ver(my_NAME, my_VERSION);
        printk(KERN_INFO COPYRIGHT "\n");
 
-       Q_INIT(&MptAdapters, MPT_ADAPTER);                      /* set to empty */
        for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
                MptCallbacks[i] = NULL;
                MptDriverClass[i] = MPTUNKNOWN_DRIVER;
@@ -6375,10 +6508,7 @@ fusion_init(void)
                MptResetHandlers[i] = NULL;
        }
 
-       DmpService = NULL;
-
-       /* NEW!  20010120 -sralston
-        *  Register ourselves (mptbase) in order to facilitate
+       /*  Register ourselves (mptbase) in order to facilitate
         *  EventNotification handling.
         */
        mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
@@ -6391,15 +6521,10 @@ fusion_init(void)
                /* FIXME! */
        }
 
-       r = pci_module_init(&mptbase_driver);
-       if(r)
-               return(r);
-
 #ifdef CONFIG_PROC_FS
        (void) procmpt_create();
 #endif
-
-       return r;
+       return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -6413,18 +6538,14 @@ static void __exit
 fusion_exit(void)
 {
 
-       dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+       dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+
+       mpt_reset_deregister(mpt_base_index);
 
-       /* Whups?  20010120 -sralston
-        *  Moved this *above* removal of all MptAdapters!
-        */
 #ifdef CONFIG_PROC_FS
-       (void) procmpt_destroy();
+       procmpt_destroy();
 #endif
-       pci_unregister_driver(&mptbase_driver);
-       mpt_reset_deregister(mpt_base_index);
 }
 
-
 module_init(fusion_init);
 module_exit(fusion_exit);